web-dev-qa-db-ja.com

ALTER TABLE-ADD COLUMNはテーブルをロックしますか?

ALTER TABLE ... ADD COLUMN DDLステートメント について質問があります。

MariaDB v10.2を使用するAmazon RDSインスタンスで、INSERTステートメントが完了し、行がテーブルのALTER TABLE ... ADD COLUMNの前に(SELECTで確認済みとして)テーブルに正しく挿入されていることに気付きました終了します。

ALTER TABLE操作が完了するまで、書き込みを実行するDMLステートメントをキューに入れるべきではありませんか?

この質問を投稿するのは、稼働中の稼働中の本番データベース、使用頻度の高いデータベース、数百万行のテーブルでALTER TABLE ... ADD COLUMNを実行できるかどうかを確認するためのテストを求められたためです。私は非常に不適切なことを見つけました。 ALTER TABLEがテーブルにロックを設定しなくても、( metadata lock を設定する接続により)接続がテーブルを使用しなくなるまで待機する必要があります。ずっと後で起こります。
編集:どうやら、この評価はあまりにも悲観的でした。私はmysqlslapを使用していくつかのテストを行っており、テーブルに対して重い操作を実行しています(INSERTUPDATEDELETEステートメント、およびSELECTALTER TABLE ... ADD COLUMNの実行中に150のシミュレートされた同時接続でLIKEを使用したステートメント)プロファイリングではメタデータロックが表示されますが、待機時間は短く(各1秒)、テーブルの変更は約30分で完了します(SQLステートメントが実行されていない10分)。これは満足のいくものですが、一方で、DDLステートメントが非ブロッキングであると想定しても安全かどうかを知りたいのです。

Instant ADD COLUMN機能がInnoDB にあり、テーブルに(特定の制約の下で)列を瞬時に追加できるが、以前は使用できなかったことに注意する価値があるでしょう) v10.3.2)

6
dr_

はい、テーブルをロックします。 MySQL 8のドキュメントから

以前に言及した例外は、テーブルとテーブル定義キャッシュから古いテーブル構造をクリアする準備ができた時点で、ALTER TABLEが読み取り(書き込みだけでなく)をブロックすることです。この時点で、排他ロックを取得する必要があります。 これを行うには、現在のリーダーが終了するまで待機し、新しい読み取りと書き込みをブロックします。

そして リンクしたドキュメント から、それはかなり明示的です

インスタントADD COLUMNを使用すると、テーブルを再構築する必要がない欠点なしに、構造化ストレージのすべての利点を享受できます。

あなたが述べたように、あなたは10.2にいます。したがって、列を追加するにはテーブル全体を再構築する必要があるようです。

ロックを受け取れないとどうなるか

INSERTステートメントが完了し、テーブルのALTER TABLE ... ADD COLUMNが完了する前に、行がテーブルに正しく挿入されている(SELECTで確認済み)ことに気付きました。

はい、それは一般にロック中に発生することですが、常に発生しないことに注意してください。時々、ステートメントとトランザクションは待機をあきらめる。時々、バックエンドとプールは、スタックして待機しているときに刈り取られます。ダウンタイム中にこれを行い、タイムアウトを設定し、タイムアウトの期限が切れたときにライブラリからのエラーをキャッチする方が常に安全です。トランザクションを使用している限り、何かがトリガーされ、タイムアウトする前にロックを取得できない場合、ロールバックされます。すべてがコーシャになります。

3
Evan Carroll

実際には特定の変更テーブルに依存しますが、いずれにしても、GitHubからのghostやperconaによるpt-online-schema-changeなどのオンラインスキーマ変更ツールを調べることをお勧めします。

どちらのツールも別のテーブルで変更を行い、最後に元のテーブルに切り替えます。古いロールバックを保持して高速にロールバックすることもできます。

特に負荷の高いテーブルの場合は、はるかに安全なルートです。

2
cohenjo