DDL ジョブが失敗または中断されると、そのジョブは PENDING 状態に移行します。影響を受けるテーブルに対してその後実行されるすべての DDL 文は、保留中のジョブが解決されるまでエラーを返します。本トピックでは、失敗の原因を診断し、適切な回復操作を選択する方法について説明します。
対応方針ガイド
SHOW [FULL] DDL を実行してジョブの現在のステータスを照会し、REMARK フィールドに記載されたエラーメッセージを確認してください。根本原因に基づき、以下のいずれかの操作を選択します:
| 状況 | 操作 | 主な制約事項 |
|---|---|---|
| 根本原因が修正可能(例:重複データ) | データを修正した後、RECOVER DDL を実行してジョブを再開します | — |
| 根本原因が修正不可能であり、DDL 操作を完了できない | REMOVE DDL を実行してジョブを削除します | ジョブ内の DDL 文が REMOVE DDL を実行する前に適用されていないことを確認してください。すでに一部が適用済みの場合、SHOW が返すテーブルのステータスは、実際のテーブルのステータスと不一致になる可能性があります。 |
| テーブル自体を削除・再作成する必要がある | REMOVE DDL を実行した後、DROP TABLE IF EXISTS | IF EXISTS を必ず指定してください。テーブルが空であるか、データが不要であることを確認したうえで削除を行ってください。 |
操作例
以下の例では、重複値によりプライマリキーの追加に失敗したテーブルを用いて、各操作を順に説明します。
シナリオの準備
テーブルを作成し、重複した
id値を含む行を挿入します。mysql> create table test_pending (id int not null, age int) dbpartition by hash(id); Query OK, 0 rows affected (0.33 sec) mysql> insert into test_pending values(1,10),(1,20),(2,20),(3,30); Query OK, 4 rows affected (0.10 sec) mysql> select * from test_pending order by id; +------+------+ | id | age | +------+------+ | 1 | 10 | | 1 | 20 | | 2 | 20 | | 3 | 30 | +------+------+ 4 rows in set (0.10 sec)id列にプライマリキーを追加しようとします。列に重複値が含まれているため、この文は失敗します。mysql> alter table test_pending add primary key (id); ERROR 4636 (HY000): [f5be83373466000][10.81.69.55:3306][ddltest]ERR-CODE: [TDDL-4636][ERR_DDL_JOB_ERROR] Not all physical operations have been done successfully: expected 9, but done 8. Caused by: 1062:DDLTEST_1562056402230OYMK_7WW7_0001:Duplicate entry '1' for key 'PRIMARY' on `test_pending`;.SHOW FULL DDLを実行し、ジョブが PENDING 状態であることを確認するとともに、失敗の詳細情報を読み取ります。mysql> show full ddl\G *************************** 1. row *************************** JOB_ID: 1106733441212637184 PARENT_JOB_ID: 0 SERVER: 1:102:10.81.69.55 OBJECT_SCHEMA: ddltest OBJECT_NAME: test_pending NEW_OBJECT_NAME: JOB_TYPE: ALTER_TABLE PHASE: EXECUTE STATE: PENDING PROGRESS: 77% START_TIME: 2019-09-06 17:17:55.002 END_TIME: 2019-09-06 17:17:55.273 ELAPSED_TIME(MS): 271 DDL_STMT: alter table test_pending add primary key (id) REMARK: ERR-CODE: [TDDL-4636][ERR_DDL_JOB_ERROR] Not all physical operations have been done successfully: expected 9, but done 8. Caused by: 1062:DDLTEST_1562056402 230OYMK_7WW7_0001:Duplicate entry '1' for key 'PRIMARY' on `test_pending`;.REMARKフィールドには、以下の 2 つの部分が含まれます:Not all physical operations have been done successfully: expected 9, but done 8.— 論理テーブルに対して 9 件の物理 DDL 文が発行されました。そのうち 8 件が成功し、1 件が失敗したため、ジョブは PENDING 状態のままです。Caused by: 1062:DDLTEST_1562056402230OYMK_7WW7_0001:Duplicate entry '1' for key 'PRIMARY' on 'test_pending';— 物理データベースDDLTEST_1562056402230OYMK_7WW7_0001内の物理テーブルtest_pendingのid列に重複値1が存在するため、当該列をプライマリキーとして使用できません。
テーブルに不整合がないか確認します。
mysql> check table test_pending; +----------------------------------------+-------+----------+-------------------------------------------------------------------------------------------------------------+ | TABLE | OP | MSG_TYPE | MSG_TEXT | +----------------------------------------+-------+----------+-------------------------------------------------------------------------------------------------------------+ | ddltest_1562056402230oymk.test_pending | check | Error | Table 'DDLTEST_1562056402230OYMK_7WW7_0001.test_pending' find incorrect columns 'id', please recreate table | +----------------------------------------+-------+----------+-------------------------------------------------------------------------------------------------------------+ 1 row in set (0.04 sec)テーブルに対する後続の DDL 文がブロックされていることを確認します。
mysql> drop table test_pending; ERROR 4644 (HY000): [f5beae39d466000][10.81.69.55:3306][ddltest]ERR-CODE: [TDDL-4644][ERR_PENDING_DDL_JOB_EXISTS] Another DDL job '1106733441212637184' with operation 'ALTER_ TABLE' is pending on ddltest.test_pending in ddltest. Please use SHOW DDL to check it, and then recover or rollback it using RECOVER DDL or ROLLBACK DDL, or just remove it us ing REMOVE DDL if you confirm that the pending job can be discarded.
オプション 1:データを修正してジョブを回復
根本原因が修正可能な場合にこのオプションを使用します。本例では、重複行を削除した後、ジョブを再開します。
重複行を削除します。
DELETE文を実行するには、ご利用の PolarDB-X 1.0 インスタンスにログインします。ログイン時にエラーが発生した場合は、エラーメッセージに示されたバックエンドの ApsaraDB RDS for MySQL データベースに接続してください。mysql> delete from test_pending where id=1 and age=20; Query OK, 1 row affected (0.07 sec) mysql> select * from test_pending order by id; +------+------+ | id | age | +------+------+ | 1 | 10 | | 2 | 20 | | 3 | 30 | +------+------+ 3 rows in set (0.02 sec)ジョブ ID を指定して
RECOVER DDLを実行し、ジョブを再開します。mysql> recover ddl 1106733441212637184; Query OK, 0 rows affected (1.28 sec) mysql> show full ddl\G Empty set (0.00 sec) mysql> show create table test_pending\G *************************** 1. row *************************** Table: test_pending Create Table: CREATE TABLE `test_pending` ( `id` int(11) NOT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `auto_shard_key_id` (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`id`) 1 row in set (0.02 sec) mysql> check table test_pending; +----------------------------------------+-------+----------+----------+ | TABLE | OP | MSG_TYPE | MSG_TEXT | +----------------------------------------+-------+----------+----------+ | ddltest_1562056402230oymk.test_pending | check | status | OK | +----------------------------------------+-------+----------+----------+ 1 row in set (0.10 sec)SHOW FULL DDLの結果が空セットとなることは、ジョブが正常に完了したことを確認できます。また、id列へのプライマリキーの設定が反映され、CHECK TABLEの結果もOKとなります。
オプション 2:ジョブを削除してテーブルを削除
根本原因が解決できない場合、またはテーブルを削除・再作成する必要がある場合にこのオプションを使用します。実行前に、テーブルが空であるか、データが不要であることを確認してください。
REMOVE DDL を実行する前に、ジョブ内の DDL 文がテーブルに まだ適用されていないこと を確認してください。すでに一部が適用済みの場合、SHOW で返されるテーブルのステータスが、実際のテーブルのステータスと不整合になる可能性があります。
mysql> remove ddl 1106733441212637184;
Query OK, 1 row affected (0.02 sec)
mysql> drop table if exists test_pending;
Query OK, 0 rows affected (0.44 sec)
mysql> show tables like 'test_pending';
Empty set (0.01 sec)ジョブが削除され、テーブルも削除されました。SHOW TABLES の結果が空セットであることも確認できました。必要に応じて、テーブルを再作成できます。