web-dev-qa-db-ja.com

MySQL 5.6-ALGORITHM = inplaceが使用されている場合でもテーブルがロックされる

次のALTERコマンドを、6000万行の大きなテーブルのMySQL 5.6データベースで実行しています。

ALTER TABLE `large_table` ADD COLUMN `note` longtext NULL, 
ALGORITHM=INPLACE, LOCK=NONE;

ALGORITHM=INPLACELOCK=NONEの両方を指定しても、テーブルはロックされ、移行が完了するまで基本的にアプリを停止します。

In_useコマンドの出力でSHOW OPEN TABLES列の値を確認して、テーブルが実際にロックされていることを確認しました。 1に設定されました。

MySQLのドキュメントで収集したものから、この操作はテーブルをロックするべきではありません。そして、MySQLは、ロックなしでは続行できない場合、コマンドを失敗させるはずです。データベースをMySQL 5.7にアップグレードしてそれがより良いかどうかを確認しましたが、5.7でも同じ問題に直面しています。

これは予想される動作ですか?ここで何が問題になっているのかを知るにはどうすればよいですか?

10
jeffreyveon

そのテーブルで他のDDLをほぼ同時に行わなかったと思いますか?

将来のために:

8.0.12にはALTER TABLE .. ALGORITHM=INSTANTADD COLUMNがあります。 Discussion および ALTER Reference および Online DDL Reference

INSTANTアルゴリズムを使用して列を追加する場合、次の制限が適用されます。

  • 列の追加は、ALGORITHM = INSTANTをサポートしない他のALTER TABLEアクションと同じステートメントで組み合わせることができません。
  • 列は、テーブルの最後の列としてのみ追加できます。他の列の間の他の位置への列の追加はサポートされていません。
  • ROW_FORMAT = COMPRESSEDを使用するテーブルに列を追加することはできません。
  • FULLTEXTインデックスを含むテーブルに列を追加することはできません。
  • 列は一時テーブルに追加できません。一時テーブルはALGORITHM = COPYのみをサポートします。
  • データディクショナリテーブルスペースにあるテーブルに列を追加することはできません。
  • 列を追加するとき、行サイズの制限は評価されません。ただし、行サイズの制限は、テーブルに行を挿入および更新するDML操作中にチェックされます。

同じALTER TABLEステートメントに複数の列を追加できます。

アップグレードできない場合は、Perconaのpt-online-schema-changeまたは新しい競合製品gh-ost(binlogを使用)を検討してください。

4
Rick James

MySQL 5.6のロックに関する問題もALGORITHM=INPLACE, LOCK=NONE; 使用されている。最初に次のことを確認します。


テーブルの制約をチェックします

テーブルにON ... CASCADEまたはON ... SET NULL制約がある場合、ALTER TABLE句LOCK = NONEは許可されません。

ソース: https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html


テーブルに外部キー関係がありますか?

外部キー関係にあるテーブルでのオンラインDDL操作は、外部キー関係にある他のテーブルで実行されているトランザクションがコミットまたはロールバックするのを待機しません。トランザクションは、更新するテーブルの排他的メタデータロックと外部キー関連テーブルの共有メタデータロックを保持します(外部キーチェックに必要)。共有メタデータロックは、オンラインDDL操作の続行を許可しますが、テーブル定義を更新するために排他的メタデータロックが必要な場合、最終フェーズで操作をブロックします。このシナリオでは、他のトランザクションがオンラインDDL操作の完了を待機するため、デッドロックが発生する可能性があります。

ソース: https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html

ここでメタデータのロックについてお読みください: https://dev.mysql.com/doc/refman/5.6/en/metadata-locking.html


最初に古いtimeformatからテーブルを変更します

MySQL 5.6より前からDATETIMEまたはTIMESTAMPフィールドを使用してテーブルを作成した場合、それらをMySQL 5.6の新しい形式にアップグレードする必要があります。

MySQL 5.6より前に作成されたInnoDBテーブルは、一時的な列(DATE、DATETIME、またはTIMESTAMP)を含み、ALTER TABLE ... ALGORITHM = COPYを使用して再構築されていないテーブルのALTER TABLE ... ALGORITHM = INPLACEをサポートしません。この場合、ALTER TABLE ... ALGORITHM = INPLACE操作は次のエラーを返します。

エラー1846(0A000):ALGORITHM = INPLACEはサポートされていません。理由:列タイプINPLACEを変更できません。 ALGORITHM = COPYを試してください。

ソース: https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-limitations.html


テーブルにパーティションがあるかどうかを確認します

パーティション化により、変更テーブルのルールの適用方法が変わります。テーブルの分割ステータスを確認する

show table status;

InnoDBと等しくない「エンジン」を探す

ソース: https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html#online-ddl-partitioning


最後に、Rick Jamesが彼の回答で述べたように、5.6から8.0へのアップグレードは、他の改善を提供するため、オプションになる可能性があります。

2
Chris