100万行のテーブルに列を追加する場所に最近5時間かかった問題がありました。デフォルト値1の列を追加しました。これは夜間に行われたため、データベースでのアクティビティはそれほど多くありませんでしたが、これが開始されると、多くのロックがありました。
サーバー統計を見ると、CPU、メモリ、ハードドライブの容量はすべて、最大値の半分をはるかに下回っています。そのため、なぜこれほど長い時間がかかったのか、問題のテーブルには新しい列を含めて7列しかないのかわかりません。データ型は、int(11)、datetime、またはvarchar(45)です。
私はMySQL Cluster 7.3.3を使用しています。4つのデータノードがすべて同じデータセンターにあります。
カラムを追加するだけで5時間かかる理由を誰かがアドバイスできますか?
テーブル構造:
CREATE TABLE ddi_t (
id int(11) NOT NULL AUTO_INCREMENT,
ddi varchar(45) NOT NULL,
is_deleted tinyint(1) NOT NULL DEFAULT '0',
created_time datetime NOT NULL,
module_group_id int(11) DEFAULT NULL,
created_user_id int(11) DEFAULT NULL,
supplier_id int(11) DEFAULT '1',
PRIMARY KEY (id),
UNIQUE KEY uq_ddi_1 (ddi),
KEY fk_ddi_1_idx (module_group_id)
) ENGINE=ndbcluster AUTO_INCREMENT=935352 DEFAULT CHARSET=latin1
MySQL Clusterでの経験から、 pt-online-schema-change は、ライブスキーマの変更を適用するための非常に便利なツールであることがわかりました。
それはこのように機能します:
RENAME TABLE
操作[〜#〜] b [〜#〜]で[〜 #〜] a [〜#〜]すべての種類のスキーマ変更で機能するかどうかはわかりません。
テーブルが大きい場合は時間がかかりますが、テーブルは読み取り/書き込みクエリで引き続き使用できます。
pt-online-schema-change
を実行するmysqlユーザーは 特定の権限 を持っている必要がありますが、これはドキュメントで明確に説明されていません(これについて バグチケット を開きました)
列を追加するには、テーブル全体(クラスターごとではなくノードごと)に対する排他ロックが必要です。キューがないため、DBは書き込みが発生しなくなるまで待機してから、テーブルをロックします。アプリケーションが大量の書き込みを実行している場合は、そのロックを取得できない場合があります。
アプリが接続するノードを制御している場合(HAProxyなどを使用)、更新しようとしているノードから離れるようにすべてのトラフィックを誘導します。それ以外の場合は、このようなタスクを実行する前にアプリをシャットダウンする必要があります。
MySQL Clusterは、STORAGE DISKを使用していないカラムを追加するときに、ALTER TABLEアルゴリズム=インプレースをサポートします。ただし、テーブルに対するトラフィックがあるMySQLサーバーでこれを実行する場合、テーブルのロックを取得するために待機する必要がある可能性があります。ただし、実際にはこのALTER TABLEを別のMySQLサーバーで実行でき、完全にオンラインになり、他のクエリへの影響はありません。
問題は、MySQLサーバーがメタデータへの変更の発生方法についてかなり厳密なビューを持っていることです。NDBははるかに柔軟なビューをサポートしているため、別のMySQLサーバーから実行することで、MySQLサーバーの厳密なビューを回避できます。