データベース(SQL Serverなど)にトランザクションをコミットしないとどうなりますか?


108

クエリがあるとします:

begin tran
-- some other sql code

その後、コミットまたはロールバックするのを忘れます。

別のクライアントがクエリを実行しようとすると、どうなりますか?

回答:


148

トランザクションをCOMMITまたはROLLBACKしない限り、トランザクションは「実行中」であり、ロックを保持している可能性があります。

クライアント(アプリケーションまたはユーザー)がコミットする前にデータベースへの接続を閉じると、実行中のトランザクションはすべてロールバックされて終了します。


1
うーん、これはある種のロックを作成していたと思います。接続を閉じると、この状態が実際に解除されるかどうかはわかりませんでした。問題は、コミットしようとするとエラーが発生することでした。今私は接続を閉じました、そしてそれはすべてうまくいきました。
Charbel

12
補足:Management Studioを使用している場合、クエリウィンドウを閉じると接続が閉じます
Joe Phillips

3
@BradleyDotNET:はい、間違いなく
marc_s

2
デフォルトでは、クエリウィンドウ/接続を閉じると、SQL Server Management Studioが自動コミットすることに注意してください。
Nuno

1
トランザクションがアクティブなときにクライアントが接続を閉じると、常にロールバックされるとは限らないことに注意してください。これはクライアントとデータベースによって異なります。たとえば、JavaアプリがOracle dbへの接続を閉じると、開いている接続はすべて自動的にコミットされます。
AviD 2016

38

実際にこれを試すことができ、これがどのように機能するかを理解するのに役立ちます。

Management Studioで2つのウィンドウ(タブ)を開きます。各ウィンドウには、SQLへの独自の接続があります。

これで、1つのウィンドウでトランザクションを開始し、挿入/更新/削除などを実行できますが、まだコミットはできません。次に、別のウィンドウで、トランザクションの外側からデータベースがどのように見えるかを確認できます。分離レベルによっては、最初のウィンドウがコミットされるまでテーブルがロックされる場合や、他のトランザクションがこれまでに何を行ったかなどがわかる場合があります。

さまざまな分離レベルとロックヒントなしで遊んで、結果にどのように影響するかを確認します。

また、トランザクションでエラーをスローするとどうなるかを確認してください。

このすべてがどのように機能するかを理解することは非常に重要です。そうしないと、SQLの機能に何度も悩まされることになります。

楽しんで!GJ。


わかりましたが、トランザクションは少なくともコミットを発行する前にログに記録されるように書き込まれますか?たとえば、トランザクションを開始し、挿入コマンドを実行して、コミットを実行する前に「何か他のことを行う」とします。挿入コマンドはログに書き込まれますか?コミットを実行する前にサーバーがクラッシュした場合、そのようにしてください。コミットしたところに戻ることができ、後でコミットを発行できます(「何か他のこと」を実行したときはいつでも)。
user1870400

16

トランザクションは、完全に実行するか、まったく実行しないことを目的としています。トランザクションを完了する唯一の方法はコミットすることです。それ以外の方法ではロールバックが発生します。

したがって、開始してコミットしない場合は、接続のクローズ時にロールバックされます(トランザクションが完了としてマークされずに中断されたため)。


それはあるべき姿ですが、常にそうであるとは限りません。
FalcoGer

... トランザクションをサポートしていないmySQLのMyISAMなどです。
Piskvorが

3

着信トランザクションの分離レベルに依存します。

SQLトランザクション分離の説明


6
トランザクションの動作は、分離レベルに依存しません。それらが引き起こすかもしれないロックの量はそうします。
marc_s

接続で読み取ることができるデータは、確実に分離レベルに依存していると確信しています。分離をREAD UNCOMMITTEDに設定している場合は、まだコミットされていないデータを読み取ることができ、実際にはトラックのある時点でロールバックされる可能性がありますが、これによりロックが確実になくなります。分離レベルとしてREAD COMMITTEDがある場合、コミットされていない行を読み取ることはできません。SNAPSHOTを使用しないと、2番目のクライアントがハングします。
Xhalent

2

トランザクションを開くと、何もロックされません。ただし、そのトランザクション内でクエリを実行すると、分離レベルに応じて、一部の行、テーブル、またはページがロックされるため、他のトランザクションからアクセスしようとする他のクエリに影響します。


1

トランザクションの例

トランTTを始める

SQLステートメント

エラーが発生した場合、ロールバックトランザクションtt、それ以外はコミットトランザクションtt

commit tran ttを実行していない限り、データは変更されません


1
MS SQLではトランザクションに名前を付ける必要がないだけでなく、誤った制御感覚を与える可能性があることに注意してください。 BEGIN TRAN X ... BEGIN TRAN Y ... ROLLBACK Yたとえば、機能しません。stackoverflow.com/questions/1273376/…を

0

潜在的なロックの問題に加えて、アクティブなトランザクションの最小LSNを超えて切り捨てることができず、スナップショットアイソレーションを使用している場合、tempdbのバージョンストアが大きくなるため、トランザクションログが大きくなり始める可能性があります。同様の理由。

を使用dbcc opentranして、最も古いオープントランザクションの詳細を確認できます。


0

コミットされていないトランザクションはサーバーをロックしたままにし、他のクエリはサーバーで実行されません。トランザクションをロールバックするか、コミットする必要があります。SSMSを終了するとトランザクションも終了し、他のクエリを実行できるようになります。


-4

動作は定義されていないため、コミットまたはロールバックを明示的に設定する必要があります。

http://docs.oracle.com/cd/B10500_01/java.920/a96654/basic.htm#1003303

「自動コミットモードが無効で、最後の変更を明示的にコミットまたはロールバックせずに接続を閉じると、暗黙的なCOMMIT操作が実行されます。」

Hsqldbがロールバックする

con.setAutoCommit(false);
stmt.executeUpdate("insert into USER values ('" +  insertedUserId + "','Anton','Alaf')");
con.close();

結果は

2011-11-14 14:20:22,519メインINFO [SqlAutoCommitExample:55] [AutoCommit enabled = false] 2011-11-14 14:20:22,546メインINFO [SqlAutoCommitExample:65] [データベースで0#ユーザーが見つかりました]


2
これはOracleにも当てはまるかもしれません(私には
わかり

最初の引用は、サーバーではなくJDBCドライバーに適用されます。
djechlin 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.