非常にトラフィックの多いWebサイトを使用しており、毎時間1000件の新しいレコードが挿入される可能性があります。
この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です。この問題の解決を開始するには、どのような初期構成設定とアプローチが推奨されますか?
さらに必要な情報がありましたらお知らせください。
ありがとう
パフォーマンスのボトルネックの問題ではなく、デッドロックを処理しています。
1時間に1000件の新しいレコードがある場合、MySQLの制限にはるかに遠く離れています。 MySQLは少なくとも50倍の負荷を処理できます。
デッドロックはアプリケーションコードが原因であり、データベースサーバーの障害ではありません。特定の状況を除き、MySQLサーバー側でデッドロックを修正することはできません。
InnoDB
は、MySQLプロンプトでSHOW ENGINE INNODB STATUS
を実行するか、mysql -uroot -p... -e "SHOW ENGINE INNODB STATUS"
を使用して、詳細なデッドロック情報を表示できます。
ただし、これは最後に発生したデッドロックのみを示し、デッドロックログはありません。
ありがたいことに、その問題を処理するツール pt-deadlock-logger があり、InnoDB
ステータスのポーリングを処理し、新しいデッドロックで更新される前にすべての詳細なデッドロック情報を保存します。 。
これは、トランザクションを実行するコードの一部と同じくらい簡単です。
insert into t1...
insert into t2...
commit;
コードの別の部分は、同じテーブルを異なる順序で変更します。
delete from t2 where...
delete from t1 where...
commit;
これらの両方のトランザクションが同時に実行されると、競合状態が発生する可能性があります。最初のトランザクションは、2番目のトランザクションによってロックされているため、t2
を変更できません。 t1
は最初のトランザクションによってロックされているため、2番目のトランザクションも同様にブロックされます。 MySQLは、INSERT/UPDATE/DELETEが失敗した「犠牲者」として1つのトランザクションを選択します。アプリケーションはそのエラーをキャッチし、ステートメントを再試行する必要があります-おそらく一時停止の後で、他のトランザクションが終了する時間があります。容量制限とは関係ありません。コードの配置方法によって悪化する可能性のある不運なタイミングのみです。トランザクション#2のDELETE、またはトランザクション#1のINSERTを切り替えると、競合は発生しません。各トランザクションは、必要なテーブルへのアクセスを待機します。
MySQL 5.6では、 innodb_print_all_deadlocks オプションを有効にして実行すると、MySQLエラーログですべてのデッドロック(最新のものだけでなく)に関する情報を収集できます。
[義務的な免責事項:私はOracleの従業員です。上記は私の個人的な見解であり、公式声明ではありません。]