次のスニペットがあるとします。
-- error checking omitted for brevity
begin tran
exec database1..my_stored_procedure
exec database2..my_other_stored_procedure
if (@@error <> 0)
rollback
commit
トランザクション情報はどのデータベースのトランザクションログに挿入されますか?
database1
のトランザクションログを再生しようとしても、そのDBにのみ影響を与えたとしても意味がないため、両方のログですべてのデータが取得されると思います。また、database1
が存在しないサーバーではdatabase2
のトランザクションログを再生できず、その逆も同様です。
..しかし、私は修正にオープンです!
トランザクションログは、ご想像のとおり、実行中のSQLステートメントを記録していません。代わりに、各データベースの生データへの変更を個別に記録しています。
あるデータベースのストアドプロシージャが、別のデータベースのトランザクションログで完全に機能している可能性があります。
... database1..my_stored_procedure AS
BEGIN
INSERT INTO database2..table1 (col1) values (1);
^^ changes written to database2's tlog
INSERT INTO database2..table2 (col1) values (2);
^^ changes written to database2's tlog
END
^^ when this transaction is committed, COMMIT is recorded in database2's tlog
または、両方に変更を加えるために。
... database2..my_other_stored_procedure AS
BEGIN
INSERT INTO database1..table1 (col1) values (1);
^^ changes written to database1's tlog
INSERT INTO database2..table1 (col1) values (2);
^^ changes written to database2's tlog
END
^^ when this transaction is committed, COMMIT is recorded in BOTH database1's and database2's tlog
トランザクションログに記録されるのは実際のデータ変更であり、それらを発生させたSQLステートメントではありません。各トランザクションログファイルへのエントリは完全に独立しています。ただし、トランザクションがコミットされると、COMMITが2つのログファイルに同時に書き込まれる場合を除きます。
複数のデータベースにわたって多数のストアドプロシージャを実行する大規模なトランザクションがある場合も、同じロジックが適用されます。トランザクションをCOMMITすると、COMMITはトランザクションに参加したすべてのデータベースのログに記録されます。
Database2のバックアップを復元し、database1がないサーバーでトランザクションログを再生することは完全に可能です。
この動作により、SQL Serverでのプロシージャとビューのレイアウト方法にある程度の柔軟性が与えられます。多くのデータベース管理者は、ストアドプロシージャ、特にメンテナンスプロシージャを、アプリケーション/ユーザーデータベースとは完全に別のデータベース(Admin
など)に保持し、メンテナンス操作の結果をそのデータベースに書き込みます。ありがたいことに、Admin
全体にコピーする必要なく、ユーザーデータベースの1つを開発サーバーに復元することもできます。