2016-11-22 3 views
1

idをプライマリキーとし、state(CHAR(1))は "x"または "y"となり、state_position(INT)です。これらの列には索引はありません。ストレージエンジンは無駄です。MySQL - ロックを取得しようとするとデッドロックが見つかりました

state_positionsは常に連続している必要があり、私は「X」の状態で5人のユーザーがいる場合は、特定の状態、すなわちのための重複位置は存在しないかもしれない、彼らのstate_positionsでなければなりません1,2,3,4,5

これは、デッドロックが発生し、私が実行しているクエリです:テスト用

insert into `tt_users` (`state`, `state_position`) 
values ('x', 
    (SELECT MAX(state_position) AS maxStatePosition 
    FROM tt_users AS u2 
    WHERE u2.state='x') + 1 
) 

、私は同時に、ユーザーを大量に挿入され、毎回私は、デッドロックエラーを得ました。

私はこの質問への答え - Working around MySQL error "Deadlock found when trying to get lock; try restarting transaction" - デッドロックは何が起こることができると言うので、デッドロックを防ぐために私のクエリで何をすべきか理解できませんでした。

私は仕事にこれを取得し、一貫して動作するために管理する唯一の方法は、この(言語はPHPです)です:

PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, true); 

はその後、手動でテーブルをロックし、私のクエリを実行:

SET autocommit=0; 

LOCK TABLES 
tt_users WRITE, 
tt_users AS u2 WRITE; 

insert into `tt_users` (`state`, `state_position`) 
values ('x', 
    (SELECT MAX(state_position) AS maxStatePosition 
    FROM tt_users AS u2 
    WHERE u2.state='x') + 1 
); 

COMMIT; 
UNLOCK TABLES; 
その後、

そして:私は4回同時にコードを実行されたこと方法で

PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 

、各インスタンスinser 2500人のユーザーが問題なく使用できます。

これを有効にする唯一の方法ですか、または手動でテーブルをロックしなくてもデッドロックを100%確実に防ぐことができますか?

UPDATE:@のwallykの答えパー

、私は次のことを試してみました:

1)トランザクションでクエリを置く - まだエラー
2デッドロック)WITH CONSISTENT SNAPSHOTとの取引を開始し、READ WRITEREAD ONLY。 3つのオプションすべてにPDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, true);を設定する必要があります。 WITH CONSISTENT SNAPSHOTREAD WRITEはまだ私にデッドロックエラーを与えましたが、READ ONLYは当然INSERTの実行を許可しませんでした。

今のところ、手動​​でテーブルをロックしているように見えるのは、動作する唯一のものです。

答えて

0

私はそれが役立つかどうか知りませんが、トランザクションにSQL文を囲むことは、内部で正しいロック・シーケンスを提供することができる:

start transaction; 
insert into `tt_users` (`state`, `state_position`) 
values ('x', 
    (SELECT MAX(state_position) AS maxStatePosition 
    FROM tt_users AS u2 
    WHERE u2.state='x') + 1 
); 
commit; 

問題が解決しない場合は、そのいくつかのオプションがありますstart transactionステートメントに追加できます。 hereを参照してください。

+0

ありがとう、私はこれらのすべてを試し、結果を得る。 – GTCrais

+0

あなたの提案を試した結果の質問を更新しました。残念ながら、それはうまくいきませんでした。 – GTCrais

関連する問題