[解決済み】MySQLの「ロックを取得しようとしたときにデッドロックが見つかりました。トランザクションを再起動してみてください」を回避する方法
質問
オンラインユーザーを記録する innoDB テーブルがあります。これは、ユーザーがページを更新するたびに更新され、どのページにいるか、サイトに最後にアクセスした日を記録しています。私は、古いレコードを削除するために15分ごとに実行されるクーロンを持っています。
昨夜、5分ほど「Deadlock found when trying to get lock; try restarting transaction」というメッセージが表示されましたが、このテーブルへのINSERTを実行したときに発生したようです。このエラーを回避する方法をどなたか教えていただけませんか?
=== EDIT ===編集
以下は実行中のクエリです。
サイトへの初回訪問。
INSERT INTO onlineusers SET
ip = 123.456.789.123,
datetime = now(),
userid = 321,
page = '/thispage',
area = 'thisarea',
type = 3
ページ更新の都度
UPDATE onlineusers SET
ips = 123.456.789.123,
datetime = now(),
userid = 321,
page = '/thispage',
area = 'thisarea',
type = 3
WHERE id = 888
15分ごとにクーロン。
DELETE FROM onlineusers WHERE datetime <= now() - INTERVAL 900 SECOND
そして、いくつかの統計(例えば、オンライン・メンバー、オンライン・ビジター)を記録するために、いくつかのカウントを行います。
どのように解決するのですか?
ほとんどのデッドロックに対処できる簡単なトリックとして、操作を特定の順序に並べ替えることがあります。
2つのトランザクションが2つのロックを逆の順番でロックしようとすると、デッドロックが発生します(例:
- connection 1: キー(1)をロックし、キー(2)をロックします。
- コネクション2:キー(2)をロック、キー(1)をロック。
両方が同時に実行された場合、接続1は鍵(1)をロックし、接続2は鍵(2)をロックし、それぞれの接続は相手が鍵を解放するのを待ちます -> デッドロックとなります。
ここで、接続が同じ順番でキーをロックするようにクエリを変更した場合、例えば、以下のようになります。
- 接続1:キー(1)をロックし、キー(2)をロックする。
- connection 2: ロックキー( 1 ), ロックキー( 2 );
を使えば、デッドロックになることはないでしょう。
そこで、こんな提案をしています。
-
deleteステートメントを除いて、一度に複数のキーにアクセスするようなクエリがないことを確認してください。
-
delete文が昇順で動作するように修正する。
変更
DELETE FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
への
DELETE FROM onlineusers
WHERE id IN (
SELECT id FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
ORDER BY id
) u;
もうひとつ覚えておきたいのは、MySQLのドキュメントによると、デッドロックが発生した場合、クライアントは自動的に再試行する必要があるようです。(例えば、この特定のエラーに対して、あきらめる前に3回リトライする)。
関連
-
[解決済み】Fatal error: mysqldをrootで実行する方法は、マニュアルの「セキュリティ」セクションをお読みください。
-
コマンドでmysqlに接続中、'mysql'が内部または外部コマンドとして認識されない エラーは解決されました。
-
[解決済み] MySQLで日付のみのパラメータを使用してタイムスタンプの日付を比較する方法は?
-
[解決済み] MySQL エラー 1241。オペランドには1つのカラムが含まれている必要があります。
-
[解決済み] 「他のデータベースへのクエリを無視する」コマンドライン
-
[解決済み] エラー 1049 (42000)。不明なデータベース
-
[解決済み] MySQLでコマンドラインを使用してユーザーアカウントのリストを取得するにはどうすればよいですか?
-
[解決済み] MySQLデータベースのテーブルのサイズを取得する方法は?
-
[解決済み] mysqlデータベースのサイズを取得する方法は?
-
[解決済み】トランザクションを使用していないのに「ロック待ちのタイムアウトを超えましたので、トランザクションを再起動してください」と表示される
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】カラムのデータが切り捨てられた?
-
[解決済み】mysqld_safe UNIX ソケットファイル用のディレクトリ '/var/run/mysqld' が存在しません。
-
[解決済み】MySQLのDESCRIBE [table]に相当するSQLiteはあるか?]
-
[解決済み] MySQLの グループ関数の無効な使用
-
[解決済み] WHEREで集計関数は使用できません "というエラーを回避する方法
-
[解決済み] whereステートメントによるmysqlの一括更新
-
[解決済み] MySQLのエラーコードです。MySQL WorkbenchでUPDATE中に1175が発生する
-
[解決済み] #1136 - 列数が 1 行目の値数と一致しません。
-
[解決済み] この操作を行うには、少なくとも1つのSUPER権限が必要です。
-
[解決済み] アプリでSSLを有効にしていない場合、AzureのMySQLサーバーへの接続に失敗するのはなぜですか?