0

最近、2 つのデータベースの大きなマージを試みました。データベース 2 からデータベース 1 にスキーマを再作成し、データベース 2 からデータベース 1 にすべてのデータを転送するスクリプトを作成しました。このスクリプトの実行とトランザクション処理には約 35 分かかります。

BEGIN TRANSACTION
...
IF(@@error<>0)
    COMMIT TRANSACTION
ELSE
    ROLLBACK TRANSACTION

完全なスクリプトは少し機密ですが、同じ構造を持ついくつかの SQL を次に示します: http://pastebin.com/GWJ3ZnkF

スクリプトを実行したところ、すべてのデータがエラーなしで転送されました。新しい結合データベースで動作するシステムをテストしました (古いデータベースへのアクセス権を削除しました)。

しかし、最後の作業として、古いデータベースをオフラインにして、誰もそのデータベースを使用していないことを確認したいと考えていました。これを行うために、次を使用しました。

ALTER DATABASE <dbname> SET OFFLINE WITH ROLLBACK IMMEDIATE

これはまずかった。この SQL コード行の後、コピーした結合データベースのすべてのデータが突然なくなりました。私は最初、それが本当に終わっていないと思っていたので、「すぐにロールバック」は私のトランザクションでロールバックを実行したように聞こえます..

しかし、なぜ?トランザクションはすでにコミットされていませんか?

また、同じスクリプトを数回再実行しようとしましたが、スクリプトが成功したと言っても、試行するたびにデータはコピーされませんでした。理由はわかりません...オフラインのロールバックを何らかの形で覚えていましたか?

接続に実際に何が起こっているのですか?

4

3 に答える 3

1

コミットされていない保留中のトランザクションがあり、強制的にロールバックして、作業の一部が失われたようです。残りは、スクリプトの構造によって説明されます。スクリプトが最初から最後まで単一のトランザクションを持っている可能性は低いです。最後のトランザクションのみがロールバックされたため、データベースは「半分コピー」された状態のままになりました。おそらく、スクリプトはさまざまなチェックを行い、この中間状態は、適切な作業を行わない「ELSE」ブランチにスクリプトを送信します (つまり、明らかに何もしません)。

とにかく、正確なスクリプトを投稿しなくても、すべて憶測です。

現時点では、データベースを一貫性のある状態 (データ コピー前の状態) に復元する必要があります。データを移動する前に作成したバックアップを使用します (バックアップを作成しましよね?)。追加のクレジットとして、スクリプトがべき等であり、半分更新されたデータベースで正しく動作することを確認してください

于 2012-06-11T08:07:43.327 に答える
0

未払いの取引がないことを再確認します。BEGIN TRANSACTIONファイルを調べてvs行の数を数えるか、ファイルCOMMIT TRANSACTIONの最後にステートメントを追加して、SELECT @@TRANCOUNT開いているトランザクションが残っていないことを確認してください。

データがコミットされている場合、接続を切断してもデータが失われることはありません。

于 2012-06-11T07:43:50.387 に答える