web-dev-qa-db-ja.com

「ロック」Mysqlテーブルの「ロック待機タイムアウトを超えました。トランザクションを再開してみてください」を修正しますか?

スクリプトから、このようなクエリをローカルデータベースに数千回送信しました。

update some_table set some_column = some_value

Where部分を追加するのを忘れたため、同じ列がテーブル内のすべての行に対して同じ値に設定され、これが何千回も行われ、列にインデックスが付けられたため、対応するインデックスがおそらく何度も更新されました。

時間がかかりすぎたため、何かがおかしいことに気づいたので、スクリプトを殺しました。それからコンピューターを再起動しましたが、単純なクエリの実行には非常に長い時間がかかり、関連するインデックスを削除しようとすると、次のメッセージが表示されて失敗します。

Lock wait timeout exceeded; try restarting transaction

これはinnodbテーブルなので、おそらくトランザクションは暗黙的にスタックします。このテーブルを修正し、スタックしたトランザクションを削除するにはどうすればよいですか?

112
Tom

同様の問題があり、実行中のスレッドをチェックすることで解決しました。実行中のスレッドを表示するには、mysqlコマンドラインインターフェイスで次のコマンドを使用します。

SHOW PROCESSLIST;

Mysqlコマンドラインインターフェイスにアクセスできない場合は、phpMyAdminから送信することもできます。
これにより、対応するIDと実行時間を持つスレッドのリストが表示されるため、実行に時間がかかりすぎるスレッドを殺すことができます。 phpMyAdminでは、KILLを使用してスレッドを停止するためのボタンがあります。コマンドラインインターフェイスを使用している場合は、次の例のように、KILLコマンドに続いてスレッドIDを使用します。

KILL 115;

これにより、対応するスレッドの接続が終了します。

128
Mihai Crăiță

現在実行中のトランザクションを確認するには

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`

リスト内で最も古いため、トランザクションは最初のトランザクションの1つである必要があります。ここで、trx_mysql_thread_idから値を取得し、KILLコマンドを送信します。

KILL 1234;

どのトランザクションが自分のものかわからない場合は、最初のクエリを頻繁に繰り返して、どのトランザクションが持続するかを確認してください。

41
nlsrchtr

これは、データベースのサイズが大きくなり、そのデータベースで多くのトランザクションを行っていたときに起こりました。

真実は、おそらくクエリまたはDBのいずれかを最適化する方法がありますが、修正のための回避策としてこれら2つのクエリを試してください。

これを実行します:

SET GLOBAL innodb_lock_wait_timeout = 5000; 

そして、これ:

SET innodb_lock_wait_timeout = 5000; 
31
Max D

ロックのInnoDBステータスを確認する

SHOW ENGINE InnoDB STATUS;

MySQLのオープンテーブルをチェックします

SHOW OPEN TABLES WHERE In_use > 0;

保留中のInnoDBトランザクションを確認する

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`; 

ロックの依存関係をチェック-whatブロックするもの

SELECT * FROM `information_schema`.`innodb_locks`;

上記の結果を調査した後、何が何をロックしているかを確認できるはずです。

この問題の根本的な原因はコードにもある可能性があります。特にHibernateのようなJPAを使用する場合は、アノテーションの関連関数を確認してください。

たとえば、 here で説明されているように、次の注釈の誤用によりデータベースがロックされる可能性があります。

@Transactional(propagation = Propagation.REQUIRES_NEW) 
27
martoncsukas

MySQLを再起動すると、正常に動作します。

BUTそのようなクエリがスタックした場合、どこかに問題があることに注意してください:

  • クエリ内で(char、デカルト積など)
  • 編集する非常に多数のレコード
  • 複雑な結合またはテスト(MD5、サブストリング、LIKE %...%など)
  • データ構造の問題
  • 外部キーモデル(チェーン/ループロック)
  • インデックスの誤ったデータ

@syedrakibが言ったように、それは機能しますが、これは生産のための長生きする解決策ではありません。

注意:再起動を行うと、一貫性のない状態のデータに影響する場合があります。

また、EXPLAINキーワードを使用してMySQLがクエリを処理する方法を確認し、クエリ(インデックス、複雑なテストなど)を高速化するために何か可能性があるかどうかを確認できます。

7
Benj

トランザクションの接続を確立すると、トランザクションを実行する前にロックを取得します。ロックを取得できない場合は、しばらくしてみてください。それでもロックを取得できない場合は、ロック待機時間超過エラーがスローされます。ロックを取得できないのは、接続を閉じていないためです。そのため、2度目にロックを取得しようとすると、以前の接続がまだ閉じられておらず、ロックを保持しているため、ロックを取得できません。

解決策:接続を閉じるか、setAutoCommit(true)[設計に応じて]ロックを解除します。

5
user3388324

MysqlのGotoプロセス。

したがって、タスクがまだ機能していることがわかります。

特定のプロセスを強制終了するか、プロセスが完了するまで待ちます。

3
Shemeer M Ali

特定のレコードのグループを削除しようとしたときに、この問題が発生しました(Webサーバー上のODBC接続でMS Access 2007を使用)。通常、MySQLから特定のレコードを削除してから、更新されたレコードに置き換えます(複数の関連レコードをカスケード削除します。これにより、単一のレコード削除で関連レコードをすべて削除できます)。

テーブルのphpMyAdminで利用可能な操作(optimize、flushなど)を実行しようとしましたが、フラッシュしようとしたときに、RELOADエラーが必要になりました。データベースはWebサーバー上にあるため、データベースを再起動できませんでした。バックアップからの復元はオプションではありませんでした。

Web上のcPanel mySQLアクセスでこのグループのレコードに対して削除クエリを実行してみました。同じエラーメッセージが表示されました。

私のソリューション:Sun(Oracle)の無料のMySQL Query Browser(以前にコンピューターにインストールしたもの)を使用して、そこで削除クエリを実行しました。すぐに機能し、問題は解決しました。その後、MySQL接続へのODBC Accessを使用するAccessスクリプトを使用して、もう一度機能を実行することができました。

1
Mike Lane

修正しました。クエリのデータ型の挿入が一致していないことを確認してください。 「VARCHAR(255)」で「user browser agent data」を試行していて、このロックに問題があるという問題がありましたが、「TEXT(255)」に変更すると修正されました。そのため、ほとんどの場合、データ型の不一致です

0
Hiren Raj

同じ問題がありました。 SQLのデッドロックの問題だと思います。タスクマネージャからSQLプロセスを強制的に閉じることができます。それでも解決しない場合は、コンピューターを再起動してください。テーブルを削除してデータをリロードする必要はありません。

0
kriver

「更新」文で同じ問題に遭遇しました。私の解決策は、テーブルのphpMyAdminで利用可能な操作を実行するだけでした。テーブルを最適化、フラッシュ、デフラグしました(この順序ではありません)。テーブルを削除してバックアップから復元する必要はありません。 :)

0
The Science Boy