10

MySQL のコミットとトランザクションについて質問があります。MySQL クエリを実行する PHP ステートメントがいくつかあります。次のことを言うだけですか?

mysql_query("START TRANSACTION");
//more queries here
mysql_query("COMMIT");

これは正確に何をしますか?それはどのように役立ちますか?更新、削除、挿入については、これが他のクエリの読み取りをブロックすることもわかりました。

mysql_query("LOCK TABLES t1 WRITE, t2 WRITE");
//more queries here
mysql_query("UNLOCK TABLES t1, t2");

これは、性質に関​​係なく他のクエリをブロックするか、書き込み/選択のみをブロックしますか?

別の質問: 1 つのクエリが実行中で、他のクエリがブロックされているとします。別のクエリがブロックされたデータにアクセスしようとしますが、ブロックされていることがわかります。それはどのように進行しますか?データが再びブロック解除されるまで待って、クエリを再実行しますか? 失敗するだけで、繰り返す必要がありますか?もしそうなら、どうすれば確認できますか?

どうもありがとう!

デニス

4

1 に答える 1

19

InnoDB では、自動コミットのデフォルト設定 (「オン」) を変更していない場合、単一クエリのトランザクションを明示的に開始または終了する必要はありません。自動コミットがオンの場合、 InnoDB はすべての単一の SQL クエリをトランザクションに自動的に囲みます。これは と同等ですSTART TRANSACTION; query; COMMIT;

START TRANSACTION自動コミットをオンにして InnoDB で明示的に使用すると、START TRANSACTIONステートメントの後に実行されるクエリはすべて実行されるか、すべて失敗します。これは銀行環境で役立ちます。たとえば、あなたの銀行口座に 500 ドルを送金する場合、その金額が私の銀行残高から差し引かれ、あなたの銀行口座に追加された場合にのみ、その操作は成功するはずです。したがって、この場合、次のように実行します

START TRANSACTION;
UPDATE customers SET balance = balance - 500 WHERE customer = 'Daan';
UPDATE customers SET balance = balance + 500 WHERE customer = 'Dennis';
COMMIT;

これにより、1 つだけではなく、両方のクエリが正常に実行されるか、まったく実行されないことが保証されます。 この投稿には、いつトランザクションを使用する必要があるかについての詳細が記載されています。

InnoDB では、テーブル全体をロックする必要はほとんどありません。MyISAM とは異なり、InnoDB は行レベルのロックをサポートします。これは、クライアントがテーブル全体をロックする必要がないことを意味し、他のクライアントを待たせます。クライアントは、実際に必要な行のみをロックして、他のクライアントが必要な行に引き続きアクセスできるようにする必要があります。

InnoDB トランザクションの詳細については、こちらを参照してください。デッドロックに関する質問は、ドキュメントのセクション14.2.8.8および14.2.8.9で回答されています。クエリが失敗した場合、MySQL ドライバーは理由を示すエラー メッセージを返します。その後、アプリは必要に応じてクエリを再発行する必要があります。

最後に、コード例では、 を使用しmysql_queryました。新しいコードを書いている場合は、古くて遅くて非推奨mysql_の PHP ライブラリの使用をやめて、mysqli_代わりに または PDO を使用してください :)

于 2012-05-14T17:50:59.323 に答える