1

次のような mysql デッドロック エラーが発生することがあります。

'ロックを取得しようとしたときにデッドロックが見つかりました。トランザクションを再開してみてください」

複数のphpプロセスが同時に実行され、テーブルから行を選択しているキューテーブルがあります。ただし、プロセスごとに、フェッチごとに一意の行のバッチを取得する必要があるため、重複する行が選択されないようにします。

だから私はこのクエリを実行します:(これはデッドロックエラーが発生するクエリです)

    $this->db->query("START TRANSACTION;");

    $sql = "   SELECT   mailer_queue_id
                FROM    mailer_queues
                WHERE   process_id IS NULL
                LIMIT   250 
                FOR UPDATE;";
    ...


    $sql = "UPDATE  mailer_queues
            SET     process_id = 33044,
                    status = 'COMPLETED'
            WHERE   mailer_queue_id 
                IN  (1,2,3...);";

    ...

    if($this->db->affected_rows() > 0) {
        $this->db->query("COMMIT;");       
    } else{
        $this->db->query("ROLLBACK;");      
    }

私もよ:

同時にテーブルに行を挿入する(トランザクション/ロックなし)

テーブル内の行を同時に更新する(トランザクション/ロックなし)

同時にテーブルから行を削除する(トランザクション/ロックなし)

同様に、私の更新と削除は、process_idが割り当てられている行のみを更新および削除します...そして、「SELECT行... FOR UPDATE」というトランザクションを実行する場所は、process_id = nullです。理論的には、それらが重複することはありません。

これらのデッドロックを回避する適切な方法があるかどうか疑問に思っていますか?

あるトランザクションがテーブルの選択/更新中にテーブルを長時間ロックし、別のプロセスが同じトランザクションを実行しようとしてタイムアウトしたためにデッドロックが発生する可能性はありますか?

どんな助けでも大歓迎です

4

3 に答える 3

6

デッドロックは、2 つ以上のプロセスが、ロックされるリソースがオーバーラップするような方法でロックを要求するときに発生しますが、異なる順序で発生するため、各プロセスは別のプロセスによってロックされるリソースを待機し、他のプロセスはロックを待機します。元のプロセスが開いていること。

現実世界で言えば、建設現場を考えてみましょう。ドライバーが 1 本とネジが 1 本あります。2 人の作業員がネジを打ち込む必要があります。作業員 1 はドライバーを、作業員 2 はネジをつかみます。作業員 1 もネジを取りに行きますが、作業員 2 が持っているため取れません。作業員 2 はドライバーが必要ですが、作業員 1 が持っているため、ドライバーを取得できません。そのため、彼らは必要な 2 つのリソースのうちの 1 つを持っているため、行き詰まり、先に進むことができず、どちらも礼儀正しく「後退」することはありません。

トランザクション外の変更が発生した場合、1 つ (または複数) の更新/削除が、トランザクション内で予約しているロックされた領域と重複している可能性があります。

于 2011-11-07T16:54:28.997 に答える
4

トランザクションを開始する前にLOCKTABLESを試して、テーブルを明示的に制御できるようにすることをお勧めします。ロックは、特定のテーブルのすべてのアクティビティが完了するまで待機します。

于 2011-11-07T19:40:03.050 に答える