2

ロールバックが呼び出された場合、MySQL が行を挿入してから削除するのはなぜですか?

たとえば、次のコードの場合:

declare exit handler for not found rollback;
declare exit handler for sqlwarning rollback;
declare exit handler for sqlexception

BEGIN
select last_insert_id();
rollback;
END;

START TRANSACTION;

INSERT INTO test (text) VALUES ('this_insert_works');
INSERT INTO test (id, text) VALUES (3,'this_insert_fails');

ストア プロシージャの次のコードを実行し、最後の行なしで再度実行すると (動作します)、行が挿入されてから削除されたため、「auto_increment ID がありません」と表示されます。返された選択は、存在しない ID を返します。

どうすればこの動作を回避できますか?

4

1 に答える 1

3

この動作を避けることはできません。

2 つの同時実行トランザクションがあり、両方ともtestトランザクション内にいくつかのレコードを挿入するとします。それらのid値はどうなりますか? 一方をコミットして他方をロールバックするとどうなるでしょうか?

実行可能な唯一のオプションは、テーブルの auto_increment カウンターをインクリメントすることです。各トランザクションは互いの行を見ることができないため (ただし、行はそれぞれのトランザクション内に存在します)、これが両方が一意の ID を確実に取得する唯一の方法です。

この動作は望ましくないように見えるかもしれませんが、実際には非常に正当な理由があります。他の唯一のオプションは、トランザクションの内部を実行するときにテーブル全体をロックし、他のすべての接続が同時にそのテーブルに行を挿入するのを防ぐことです。これはパフォーマンスにとってひどいものです。INSERT

于 2012-11-11T03:25:49.297 に答える