21

各クライアントが同時に動作するため、クライアントが切断された直後にMySQLサーバーがトランザクションをロールバックするようにする必要があります。問題は次のように再現できます (innodb テーブル タイプを使用)

クライアント A:

START TRANSACTION;
SELECT MAX(ID) FROM tblone FOR UPDATE;
#... then disconnect your connection to the server

クライアント B:

START TRANSACTION;
SELECT MAX(ID) FROM tblone FOR UPDATE;
#... lock wait time out will occur here

MySQLのサーバーオプションを設定し、両方のクライアントでinnodb_rollback_on_timeoutmysqlのクライアントを使用していました。mysql --skip-reconnectネットワーク上で1台のサーバーと2台のクライアントを使用してこれを試しました。ラインの後、ネットワークを物理的に切断しました(ケーブルを抜きました)SELECT ... FOR UPDATE;。他のクライアントがすぐにトランザクションで使用できるようにするtblone(ロック、更新) 必要があります。そのためには、クライアント A が切断された後、サーバーがクライアント A のトランザクションをロールバックする必要があると思います。

4

2 に答える 2

23

クライアントを物理的に切断している場合、通常の切断を送信していません (ロールバックが発生する可能性があります)。また、MySQL プロトコルはあまり頻繁に処理されないため、サーバーはクライアントが存在しないことを認識できません。クライアントとサーバーが内部でやり取りする他のデータベース システムと比較すると、これはプロトコルの欠陥だと思います。

ともかく。変更できる変数は 2 つあります。基本的に同じことを行いますが、クライアントが異なります。

1 つ目はwait_timeoutで、Java や php などのアプリケーション クライアントによって使用されます。

もう1つはinteractive_timeoutで、mysqlクライアントによって使用されます(テストのように)

どちらの場合も、サーバーは数秒後に接続を切断し、その際にすべてのトランザクションをロールバックしてすべてのロックを解放します。

于 2012-04-08T05:57:47.977 に答える
1

これは、いくつかのコメントについて議論するためのものです。これはコメントの一部と一致しないことに注意してください。効果がより目に見えるので、SELECT..FOR UPDATE の代わりに INSERT を使用します。

いくつかの異なるケースを見てみましょう:

(1) SQLなし + タイムアウト

START TRANSACTION;
do some SQL statement(s)
do no SQL for more than the timeout (before COMMITing)

以下に詳述するケースのため、これは避けてください。解決策: InnoDB に依存して長いトランザクションを処理しないでください。

(2) 実行時間の長いクエリ

START TRANSACTION;
do some SQL statement(s)
run an SQL query that takes more than the timeout
COMMIT;

すべては順調です。サーバー (mysqld) がクエリを実行し続けている限り、タイムアウトは適用されません。つまり、タイムアウト「クロック」は、各 SQL ステートメントの最後で最初からやり直されます。

(3) (自動再接続)

START TRANSACTION;
INSERT ... VALUES (123);
    time passes; no SQL performed for longer than the timeout
    disconnect occurs
INSERT ... VALUES (456);
    auto-reconnect (because you have it ENabled);
    the INSERT proceeds
COMMIT;

123 はロールバックされます。456が挿入されます。(同様に、SELECT..FOR UPDATE はロックを失います。) よくありません。解決策は、「自動再接続」をオフにすることです。代わりに、エラーをチェックし、切断エラーをトランザクションの致命的なエラーとして扱います。(その後、トランザクションをやり直します。)

INSERT 456 は、によって制御される新しいトランザクションで実行されautocommitます。

(4) (自動再接続なし)

START TRANSACTION;
INSERT ... VALUES (123);
    time passes; no SQL for longer than the timeout
    disconnect occurs
INSERT ... VALUES (456);
    NO auto-reconnect (because you have it DISabled)
COMMIT;

123 はロールバックされます。456 の INSERT は、「接続が失われました」のようなエラーを受け取ります。取引をやり直してください。

于 2021-06-02T14:45:13.347 に答える