web-dev-qa-db-ja.com

WordpressはMySQLの行ロックエラーをどのように処理しますか?

カスタムテーブルの行を更新するWordPressプラグインがあるのに、その更新で行ロックが発生した場合、どうなりますか?例えば。 2人のユーザーが同時にTABLE1の更新を起動します。一方の設定はAGE = 1、もう一方の設定はAGE = 2です。

  • 行ロックはありますか?
  • MySQLはこれを「優雅に」処理し、2つのアップデートのうちの1つは単に「失われる」のでしょうか。
  • Wordpressはそれを優雅に扱いますか?
  • プラグインでそれを気にする必要がありますか?

私はすべての変更を追跡する必要はないので、データはそれほど重要ではありません。しかし、発生する可能性があるエラーを処理する必要があります。

5
Samudra

MySQLの観点から厳密に

短バージョン

MyISAMストレージエンジン

  • テーブルロック
  • 書面は先着順、先着順
  • 読み取りが開始から書き込みを遅くする

InnoDBストレージエンジン

  • 行ロック
  • トランザクション(ノンブロッキング)
  • インデックスの更新時にデッドロックが発生する可能性があります

長期版

基礎となるテーブルが MyISAMストレージエンジン を使用している場合、行ロックは不可能です。各DML文(INSERT、UPDATEおよびDELETE)によって、全表ロックが発生します。

50のDB接続がmydb.mytableのonw行を更新しようとした場合

  • 1テーブルロック、1更新、49 DB接続待ち
  • 1テーブルロック、1更新、48 DB接続待ち
  • 1テーブルロック、1更新、47 DB接続待ち
  • ...
  • 1テーブルロック、1更新、02 DB接続待ち
  • 1テーブルロック、1更新、01 DB接続待機

写真をゲット? 1つのテーブルでボトルネックが発生する可能性がある場所を確認できます。今、トラフィックの多いWordPressサイトを想像してください。 SELECTはDML文よりも優先されます(例外はMyISAMテーブルに対する同時INSERTです。ただし、MyISAMテーブルにはSELECTとINSERTのみがあり、それらの間にギャップはありません)。 DMLステートメントの間に数百、あるいは数十ものSELECTがあると、前述のボトルネックをさらに遅くする可能性があります。

人の多い人が多いWordPressサイトでのMyISAMの節約の恩恵は、デッドロックが起こり得ないことです。

基礎となるテーブルが InnoDBストレージエンジン を使用する場合、行ロックは(同じ行でも)読み取りをブロックすることはできませんが、書き込み中にデッドロックは発生する可能性があります。 /etc/my.cnfにAUTOCOMMIT=0を設定すると、各DML文(INSERT、UPDATE、およびDELETE)は1行のトランザクションとして実行されます。個々の行ロックが発行されます。したがって、50のDB接続が50の異なる行を通過した後で悲劇的なことが起こることはありません。

デッドロックはどこに入りますか?

InnoDBテーブルのPRIMARY KEYは クラスタ化インデックス(内部的にgen_clust_indexとして知られています) に含まれているので、行データはインデックスエントリと密接に結び付いています。 PRIMARY KEYの一部ではない列に対して作成されたインデックスは、2つの基本項目、1)列値、および2)gen_clust_indexキーでカタログ化されます。時には、InnoDBでインデックス付きの列を更新すると、冗談めかしてインデックスの便秘と呼ばれるものが発生する可能性があります。これは、互いに近くに保管されている索引項目に2つ以上のロックが生成されたときに発生します。これは非常に人身売買の多いWebサイトで可能です。

私はかつて開発者がなぜDBA StackExchangeでこれが起こるのかを知るのを手伝った。その開発者はその後コードを変更しました。ここにそれらの記事がありました:

あなたの質問

アップデートの1つは、ストレージエンジンに関係なく失われます。列の最後のUPDATEだけが最終値を設定します。

結論

この記事はどちらのStorage Engineにも適していません。これらは単にテーブルへの書き込み時に起こりうることと起こることについての事実です。

9
RolandoMySQLDBA