1時間あたり数千回の挿入を処理するようにMySQL Innodbを構成するにはどうすればよいですか?


10

非常にトラフィックの多いWebサイトを使用しており、毎時間数千の新しいレコードが挿入される可能性があります。

この1つのエラーがサイトに障害をもたらしています。

PDOException: SQLSTATE[40001]: Serialization failure: 1213 
Deadlock found when trying to get lock; 
try restarting transaction: INSERT INTO {location_instance} 
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0, 
:db_insert_placeholder_1, :db_insert_placeholder_2, 
:db_insert_placeholder_3, :db_insert_placeholder_4); 
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] => 
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] => 
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )

MySQLがこのタイプの負荷を処理できなかった場合、私は非常に驚きます。それで、私の質問は、データベースの問題ですか?これだけのトラフィックを処理できるようにMySQLを構成するにはどうすればよいですか?

Webサイトに追加されるコンテンツの負荷をシミュレートするスクリプトを使用して、開発サーバーにWebサイトのコピーをセットアップしました。私はUbuntu、LAMPスタック、16GBのRAMを実行しています。

確かに、私はデータベースについてあまり知識がありません。実際、私は 'apt-get install'の終了後に付属するデフォルトのmy.cnfから始めています。テーブルはすべてInnodbです。この問題の解決を始めるには、どのような初期構成設定とアプローチが推奨されますか?

さらに必要な情報がありましたらお知らせください。

ありがとう


本番用のデフォルトのmy.cnfから始めていますか?男、もっと最適化する必要があります。私の答えであなたを詳しく説明します。:-)

回答:


11

パフォーマンスのボトルネックの問題ではなく、デッドロックを処理しています。

1時間に1000件の新しいレコードがある場合、MySQLの制限にはるかに遠く離れています。MySQLは少なくとも50倍の負荷を処理できます。

デッドロックはアプリケーションコードが原因であり、データベースサーバーの障害ではありません。特定の状況を除いて、MySQLサーバー側でデッドロックを修正することはできません。

InnoDBSHOW ENGINE INNODB STATUSMySQLプロンプトで実行するか、を使用して、詳細なデッドロック情報を表示できますmysql -uroot -p... -e "SHOW ENGINE INNODB STATUS"

ただし、これは最後に発生したデッドロックのみを示し、デッドロックログはありません。

ありがたいことに、その問題を処理するツールpt-deadlock-loggerがあり、ポーリングInnoDBステータスを処理し、新しいデッドロックで更新される前にすべての詳細なデッドロック情報を保存します。


知っておきたい!show statusコマンドで、ロックおよび関連するクエリとテーブルに関する情報を確認しています。これが私のコードにある場合、statusコマンドのこの情報を使用して問題のデバッグを開始するにはどうすればよいですか?PHP PDOクエリは非常に簡単です。接続、準備、実行、繰り返しです。役立つ場合は、コードやステータスメッセージを投稿させていただきます。
user658182

@ user658182スタックオーバーフローのこの投稿でデッドロックの処理方法を確認してください:ロックを取得しようとしたときに見つかったmysqlデッドロックを回避する方法
Valor

1
@ max-vernon構文編集に感謝します。明らかに英語です。母国語ではありません:-)。
Valor

1
-e "SHOW ENGINE INNODB STATUS"
グリフ

8

これは、トランザクションを実行するコードの一部と同じくらい簡単です。

insert into t1...
insert into t2...
commit;

コードの別の部分は、同じテーブルを異なる順序で変更します。

delete from t2 where...
delete from t1 where...
commit;

これらの両方のトランザクションが同時に実行されると、競合状態が発生する可能性があります。最初のトランザクションはt2、2番目のトランザクションによってロックされているため変更できません。一方、2番目のトランザクションはt1、最初のトランザクションによってロックされているため、同様にブロックされます。MySQLは、INSERT / UPDATE / DELETEが失敗した「犠牲者」として1つのトランザクションを選択します。アプリケーションはそのエラーをキャッチし、ステートメントを再試行する必要があります-おそらく一時停止の後で、他のトランザクションが終了する時間があります。容量の制限とは関係ありません。コードの配置方法によって悪化する可能性のある不運なタイミングのみです。トランザクション#2のDELETEまたはトランザクション#1のINSERTを切り替えると、競合は発生しません。各トランザクションは、必要なテーブルへのアクセスを待機します。

MySQL 5.6では、innodb_print_all_deadlocksオプションを有効にして実行すると、MySQLエラーログのすべてのデッドロック(最新のものだけでなく)に関する情報を収集できます。

[義務的免責事項:私はOracleの従業員です。上記は私の個人的な見解であり、公式声明ではありません。]

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.