この記事は、MySQL に関する関連知識を提供します。主に、MySQL がバッチでデッドロックを更新する方法について説明します。コード例もあります。興味のある友人は以下を参照してください。すべての人に役立つことを願っています。 .
テーブル構造は次のとおりです:
CREATE TABLE `user_item` ( `id` BIGINT(20) NOT NULL, `user_id` BIGINT(20) NOT NULL, `item_id` BIGINT(20) NOT NULL, `status` TINYINT(4) NOT NULL, PRIMARY KEY (`id`), KEY `idx_1` (`user_id`,`item_id`,`status`)) ENGINE=INNODB DEFAULT CHARSET=utf-8
SQL ステートメントは次のとおりです:
update user_item set status=1 where user_id=? and item_id=?
原因分析:
mysql的事务支持与存储引擎有关,MyISAM不支持事务,INNODB支持事务,更新时采用的是行级锁。这里采用的是INNODB做存储引擎,意味着会将update语句做为一个事务来处理。前面提到行级锁必须建立在索引的基础,这条更新语句用到了索引idx_1,所以这里肯定会加上行级锁。 行级锁并不是直接锁记录,而是锁索引,如果一条SQL语句用到了主键索引,mysql会锁住主键索引;如果一条语句操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引。
この更新ステートメントでは次の手順が実行されます:
非主キー インデックスが使用されるため、最初に idx_1 の行レベルのロックを取得する必要があります
その後、主キーの更新に従って続行するため、主キーの行レベルのロックを取得する必要があります。
更新後は、完了したら、すべてのロックを送信して解放します。
ステップ 1 と 2 の間にステートメントが突然挿入された場合: update user_item .....id=? と user_id=? の場合、このステートメントは最初に主キー インデックスをロックします。次に idx_1 をロックします。
厄介な状況が発生します。1 つのステートメントは idx_1 のロックを取得して主キー インデックスのロックを待機し、別のステートメントは主キーのロックを取得して idx_1 のロックを待機します。これにより、デッドロック、ロック。
解決策:
select id from user_item where user_id=? and item_id=?
update user_item set status=? where id=? and user_id=?
バッチ サイクルは最初のステップを繰り返します。最初と 2 番目のステップに従うだけです。
推奨される学習: 「MySQL ビデオ チュートリアル 」
以上がMySQL がデッドロックをバッチで更新する方法を詳しく説明した記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。