web-dev-qa-db-ja.com

クエリがテーブルレベルのロックを待機しないようにする方法

お客様のデータベースを追加のサーバーに移動した後、問題が発生しました。これはサイトのパフォーマンスにプラスの影響を与えるはずでしたが、MyISAMのテーブルロックに問題があります。 (MyISAMの代わりにInnoDBを使用することを聞いたことがありますが、近い将来エンジンを変更することはできません)。
モデレーターが記事サイトのコメントをアクティブ化するときに実行される更新クエリにそれを見つけることができます。これはプロセスです:

  • 更新クエリが処理されますSET status = 1 WHERE id = 5(インデックスが設定されている)
  • ページのキャッシュファイルが削除されます

この時点で、ページ全体が遅くなります。データベース自体は数分間ビジーです。私はプロセスリストを数回フェッチし、さまざまな選択クエリの約60のエントリを確認しました。これらはすべて状態テーブルレベルのロックを待機中でした。

1。なぜこの更新がテーブルで行われるのか理解できませんarticle_commentsは、テーブルarticleがテーブルレベルのロックを待機するためのselect-statementsに影響を与える可能性があります。プロセスリストでは、待機中のほとんどすべてのクエリがこのテーブルからのものでした。 selectよりもupdate/insertが優先され、これによりこのような問題が発生する可能性があるという事実を読みましたが、記事テーブル自体はコメントがアクティブになっても更新されないので、selectは待つべきではありません。私はそれを誤解しましたか?
2。この動作を防ぐため、または少なくともより良いバランスを得るために、InnoDBに変更する以外に何かありますか?データベースを新しいサーバーに移動する前にこの問題が発生しなかったという事実に非常に苛立ちました。いくつかの設定ミスがあると思いますが、特定する方法がわかりません。

10
32bitfloat

MyISAMストレージエンジンは、DML(INSERT、UPDATE、DELETE)に対してフルテーブルロックを実行することで猛烈に悪名高くなっています。 InnoDBは間違いなく長期的にその問題を解決します。

MyISAMとInnoDBを使用する場合の長所と短所について書いた

現在の質問に関して、考えられるシナリオは次のとおりです。

  • articlearticle_commentsはどちらもMyISAMテーブルです
  • article_commentsには、statusを列とする1つ以上のインデックスがあります
  • article_commentsのインデックスページの更新がMyISAMキーバッファーにキャッシュされます(サイズは key_buffer_size )。これにより、古いインデックスが作成されますMyISAMキーバッファーからのページ
  • articlearticle_commentsの間でJOINを実行するSELECTクエリがあります

私の提案するシナリオでは、article_commentsがDML(この場合はarticle)から解放されるのを待つ必要があるため、UPDATEテーブルに対するSELECTは書き込みを許可しないようにすることができます

8
RolandoMySQLDBA

この時点で、ページ全体が遅くなります。データベース自体は数分間ビジーです。

大きなQuery_cacheがあるようなにおいですか?

mysql> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 | -- Not over 50M
| query_cache_type             | DEMAND   | -- Only if using SQL_CACHE
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

書き込みが多い本番システムでは、query_cacheをオフにすることもできます。

All指定されたテーブルのquery_cacheのエントリは、そのテーブルにanyの書き込みが発生すると削除されます。 QCが大きいほど、このタスクは遅くなります。

MyISAMは「テーブルレベル」のロックを使用します。読み取りと書き込みを同時に(同じテーブルで)行うことはできません。粗野ですが効果的です。

7
Rick James