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


10

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

  • update-queryが処理されます SET status = 1 WHERE id = 5(インデックスが設定されます)
  • ページのキャッシュファイルが削除されます

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

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


1
一般的なロギングを有効にし、これらのテーブル間のJOINステートメントを監視します。SELECTすると、暗黙的なREAD LOCKが作成されます。MYISAMはROW LEVELロックをサポートしていないため、テーブルレベルでロックします。このロックは古いサーバーで起こっていたが、だれも見ていなかったのでしょうか?my.cnf行とホスト間の行を比較し、特にkey_bufferが適切に調整されていることを確認します。
randomx

古いサーバーで他にもいくつかのパフォーマンスの問題があり、プロセスリストを頻繁に監視していました。主に多くのスリープ中のプロセスがありましたが、待機中のプロセスに気づきませんでした(この情報は、通常、この新しいサーバーで初めて見ました)。同僚は古いmy.cnfをコピーして値を新しい既存のハードウェアに調整しましたが、エントリが多くありませんでした。「SHOW VARIABLES」の出力も比較しましたが、何を見ればよいのか本当にわかりませんでした。コメントありがとうございます。キーバッファは明日再確認します。
32ビットフロート2007

最近、同様の問題が発生しました。最初key_buffer_sizeはに設定されていました1GB10GB問題を減らすためにそれを増やします。
Haluk

@リックジェームス、ありがとう。今日あなたは私に多くのトラブルを救いました。アマゾンや他の場所にウィッシュリストはありますか?:) query_cache_limitを1024に設定しました。今はロックの問題はありません。私は最初にmysqlクライアントから変数でそれを行いました。グローバルquery_cache_limit = 1024を設定します。これをmy.cnfに書き込みます。このソリューションにより、ストレスなくinnodbの移行を計画する時間ができました。ありがとうございました。

回答:


8

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

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

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

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

私の提案するシナリオでは、articleテーブルに対するSELECTは、article_commentsDML(この場合はUPDATE)がなくなるまで待機する必要があるため、書き込みを許可しないようにすることができます。


あなたの答え(そしてリンク)をありがとう、あなたのシナリオは本物です。選択した記事の大部分が実際にコメント表に参加している(つまり、phpmyadminのプロセスリストにある不完全なステートメントを確認した)ことを知りませんでした。複数の待機中のクエリを防ぐための短期的な解決策を知っていますか?私はすでに特定のステートメントで "UPDATE LOW_PRIORITY"を使用してそれを試しましたが、それは顕著な変更を加えませんでした。将来的には本当にinnodbに変更する予定ですが、現在、改善する方法はあるのでしょうか。
32ビットフロート2007

究極のソリューション:テーブルをInnoDBに変換します。すべてのMyISAMをInnoDBに変換する方法については、私の投稿dba.stackexchange.com/a/9422/877を参照してください
RolandoMySQLDBA '18

7

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

大きな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をオフにすることもできます。

すべての時に与えられたテーブルのquery_cacheのエントリが消去されます任意の書き込みは、そのテーブルに発生します。QCが大きいほど、このタスクは遅くなります。

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


1
はい、そうです。キャッシュサイズは約64Mです。私にとって初めてのこの情報のおかげで、テーブルロックに気付かなかった古いサーバーでも同じ値が得られました。私たちはすでにInnoDBへの移行を開始しましたが、この事実は謎のままです...
32ビットフロート2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.