トランザクションがアトミックであるという事実をどのように消化するかについて私は本当に混乱しています。トランザクションが「クエリ」のセットである場合、それはどのようにアトミックになりますか。 「クエリ」という単語を一般的なSQLクエリに関連付けています。したがって、トランザクションは、同時に実行されるSQLクエリのセットに他なりません。しかし、各クエリが複数の操作を行うという事実は、後のクエリでエラーが発生した場合に、以前に実行されたクエリ(同じセット内)がどのようにロールバックするかについては実際にはわかりません。ここで何が欠けていますか?ありがとうございます!
回答
TL; DR;トランザクションログには、そのトランザクションのコミットレコードが含まれているかどうかに応じて、各トランザクションを再作成または元に戻すために必要なすべての情報が含まれます。
SQLデータベースでは、トランザクションアトミック性は事前書き込みログ(トランザクションログエントリは、実際のテーブルとインデックスが更新される前に書き込まれることを意味します)。
厳密な意味でのクエリ、つまりSELECT
ステートメントおよびデータベースの状態を変更しないその他の読み取り操作は、コミットまたはロールバックするものがないためログに記録されません。そのため、アトミック性の概念はここでは実際には適用されません。少なくともDBMSレベルでは。クエリ結果を消費するアプリケーションは、後続のクエリの1つが失敗してロールバックが発生した場合に、前のクエリの結果を破棄することでアトミック性を強制する必要がある場合があります。 >、UPDATE
、DELETE
、MERGE
)およびデータベースの状態を変更するその他のステートメント実行されると、変更は最初に先行書き込みログ(WAL)に書き込まれます。すべてのステートメントが成功し、コミット(明示的または暗黙的)が発行された場合、この事実もWALに記録され、ログが保持されます。これにより、変更が永続的になります。これらは、後でチェックポイントまたはログの再生中に実際のテーブルおよびインデックスセグメントに書き出される場合があります。
ただし、ステートメントの1つが失敗した場合、ログにコミットレコードはありません。このトランザクション、およびDBMSは、そのトランザクションの先行するログレコードを使用して、これまでに行われたテーブルとインデックスの変更を元に戻します。
同様に、DBMSプロセスがクラッシュしたり、電源が切れたりした場合、実行中のトランザクションのコミットレコード、およびすでに永続化されている可能性のあるテーブルまたはインデックスの変更は、ログの再生中に取り消されます。
コメント
- これは正しくありません'正しくありません:"厳密な意味でのクエリ、つまりSELECTステートメントやその他の読み取り操作データベースの状態を変更せず、コミットまたはロールバックするものがないため、ログに記録されません"-データベースの設定によっては、SELECTでも暗黙的なtrを開始できますansaction。 brentozar.com/archive/2018/02/ …
- I ' mは彼らが'トランザクション管理下にないと言っていない、私は' m何も変更せず、ログに記録されません。
回答
トランザクションは、次のようにカプセル化されている場合、アトミックです。これ:
BEGIN TRAN UPDATE dbo.Users SET Reputation = Reputation + 1 WHERE Id = 26837; UPDATE dbo.Posts SET Score = Score + 1 WHERE Id = 227563; COMMIT
その場合、2つの別々のテーブルの両方の更新が一緒にコミットされるか、一緒にロールバック(失敗)します。これは、コミットするトランザクションの最小単位です。
ただし、後でそのスコープ外で別のクエリを実行しようとすると、別のトランザクションになります。
次のようなことを試してみると:
BEGIN TRAN UPDATE dbo.Users SET Reputation = Reputation + 1 WHERE Id = 26837;
次に、アプリケーションで、C#コードなどの他の種類の作業を行ってから、データベースに戻ります。後でこれを行います:
UPDATE dbo.Posts SET Score = Score + 1 WHERE Id = 227563; COMMIT
その後、以前のユーザーの更新と後続の投稿の更新の両方が一緒に成功または失敗します。
ただし、実際には、次のようにトランザクションを開いたままにすることはできません。他の人がデータベースで作業するのをブロックするので、それは長期間にわたって行われます。そのため、「トランザクションを短くて甘くしてください」などのアドバイスがよく表示されます。つまり、参加して、作業を完了し、戻ってください。トランザクションを明示的に開いたままにしないでください。
コメント
- トランザクションは常にアトミックであり、そうですか?
- はい。ただし、データベースの設定によっては、暗黙的なトランザクションがオンになっている場合があります。つまり、' re '要求しなくてもBEGINTRANを取得します。これはベンダーによって異なります。たとえば、Oracleのデフォルトは暗黙的なトランザクションですが、SQLServerはそうではありません。SQL Serverで複数の異なるトランザクションを取得している可能性がある場合、Oracleのバックグラウンドから来た場合、' 1つのトランザクションしか取得していないと思うかもしれません。それぞれがアトミックです。