このトピックでは、PENDING状態のジョブを処理するためのベストプラクティスについて説明します。
背景
このシナリオでは、新しいDDLジョブのエンジンが起動されます。 DDLジョブが失敗した場合、または例外のために中断された場合、ジョブはPENDING状態になります。 この場合、ジョブを処理して再開するための対策を講じる必要があります。 それ以外の場合、このジョブの後続のDDLステートメントは実行できず、エラーが返されます。
制御ポリシー機能の動作
SHOW [FULL] DDL
ステートメントを実行して、DDLジョブの詳細を照会し、失敗の原因を特定できます。REMARK
フィールドにエラーメッセージを表示できます。- 次のリストに、PENDING状態のジョブを処理する一般的な方法を示します。 ビジネス要件に基づいて方法を設定できます。
- 問題のトラブルシューティングと解決。 たとえば、問題がデータのエラーが原因であるかどうかを確認します。 問題が重複によって発生する場合は、重複を削除します。 問題が解決しない場合は、問題が制限によるものかどうかを確認します。 問題が制限によって引き起こされる場合は、制限を解除できるかどうかを確認してください。 問題を解決したら、
RECOVER DDL
ステートメントを実行して、PENDING状態でジョブを再開します。 - ジョブの失敗の原因となる問題を解決できない場合、ジョブ内のDDLステートメントは実行できません。 この場合、REMOVE DDL文を実行してジョブを削除できます。 REMOVE DDL文を実行する前に、ジョブ内のDDL文が実行されていないことを確認してください。 そうしないと、SHOWステートメントによって返されるテーブルのステータスが実際のテーブルのステータスと一致しない可能性があります。 DDLジョブを削除した後、テーブルを再度照会できます。
- DDLジョブが照会に失敗したテーブルを削除する場合は、
REMOVE DDL
ステートメントを実行してジョブを削除します。 次に、DROP TABLE IF EXISTS
ステートメントを実行して、テーブルを削除します。 テーブルを削除する前に、テーブルが空であるか、テーブルのデータが不要であることを確認してください。DROP TABLE
ステートメントでIF EXISTS
キーワードを使用する必要があります。 これにより、テーブルを強制的に削除できます。
- 問題のトラブルシューティングと解決。 たとえば、問題がデータのエラーが原因であるかどうかを確認します。 問題が重複によって発生する場合は、重複を削除します。 問題が解決しない場合は、問題が制限によるものかどうかを確認します。 問題が制限によって引き起こされる場合は、制限を解除できるかどうかを確認してください。 問題を解決したら、
例
次の例は、DDLジョブをPENDING状態で処理する方法を示しています。
- 主キーを指定せずにテーブルを作成します。 次に、重複する行をテーブルに挿入します。 結果は、id列の値1が重複することを示します。
mysql> create table test_pending (id int not null、age int) dbpartition by hash(id); クエリOK、影響を受ける0行 (0.33秒) mysql> test_pendingの値 (1,10) 、(1,20) 、(2,20) 、(3,30) に挿入します。クエリOK、影響を受ける4行 (0.10秒) mysql> select * from test_pending order by id; + ----- + ------ | id | 年齢 | + ----- + ------ | 1 | 10 | | 1 | 20 | | 2 | 20 | | 3 | 30 | + ----- + ------ セットの4列 (0.10秒)
- テーブルの主キーを設定します。 結果は、id列が正しく設定されていないことを示します。 この場合、id列の値が一意でないため、DDLステートメントは失敗します。
mysql> alter table test_pendingプライマリキーの追加 (id); エラー4636 (HY000): [f5be83373466000][10.81.69.55:3306][ddltest]ERR-CODE: [TDDL-4636][ERR_DDL_JOB_ERROR] すべての物理操作が正常に行われたわけではありません: 予想9、しかし行われた8。 原因: 1062:DDLTEST_1562056402230OYMK_7WW7_0001: 'test_pend' のキー 'PRIMARY' のエントリ '1' が重複しています。
SHOW FULL DDL
ステートメントを実行して、ジョブのステータスと失敗の原因を照会します。 結果は、物理テーブルに重複する列値が含まれているため、物理DDLステートメントが失敗したことを示します。mysql> ddl\Gをフル表示 *************************** 1。 行 *************************** JOB_ID: 1106733441212637184 PARENT_JOB_ID: 0 サーバー: 1:102:10.81.69.55 OBJECT_SCHEMA: ddltest OBJECT_NAME: test_pending NEW_OBJECT_NAME: JOB_TYPE: ALTER_TABLE フェーズ: 実行 州: 保留中 進歩: 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プライマリキーの追加 (id) REMARK: ERR-CODE: [TDDL-4636][ERR_DDL_JOB_ERROR] すべての物理操作が成功しているわけではありません。 原因: 1062:DDLTEST_1562056402 230OYMK_7WW7_0001: 「test_pending」のキー「PRIMARY」のエントリ「1」を複製する。
REMARKフィールドの内容:すべての物理操作が正常に行われたわけではありません: 期待された9ですが、完了した8です。
: 論理テーブルで9つの物理DDLステートメントを実行しようとします。 8つのステートメントが実行されますが、1つのステートメントが失敗します。 これにより、DDLジョブに障害が発生します。 DDLジョブはPENDING状態に入ります。原因: 1062:DDLTEST_1562056402 230OYMK_7WW7_0001: 「test_pending」上のキー「PRIMARY」のエントリ「1」の重複;
これは、障害の根本原因を示す。 id列の値1は、物理テーブルのtest_pending
に重複しています。 物理テーブルは、物理データベースDDLTEST_1562056402 230OYMK_7WW7_0001
に格納されます。 したがって、id列を主キーとして使用することはできません。
- テーブルのエラーを確認します。 結果は、返された論理テーブルのステータスが実際の論理テーブルのステータスと一致しないことを示しています。
mysql> チェックテーブルtest_pending; ^ a b | テーブル | OP | MSG_TYPE | MSG_TEXT | ^ a b | ddltest_1562056402230oymk.test_pending | チェック | エラー | テーブル 'DDLTEST_1562056402230OYMK_7WW7_0001.test_pending 'が正しくない列 'id' を見つけました。テーブルを再作成してください | ^ a b 1 列インセット (0.04 秒)
- ジョブ内の後続のステートメントが実行できるかどうかを確認します。 結果は、DROP TABLEステートメントを実行するとエラーが返されることを示しています。
mysql> ドロップテーブルtest_pending; エラー4644 (HY000): [f5beae39d466000][10.81.69.55:3306][ddltest]ERR-CODE: [TDDL-4644][ERR_PENDING_DDL_JOB_EXISTS] 操作 'ALTER_を持つ別のDDLジョブ '1106733441212637184' TABLE' はddltestのddltest.test_pendingで保留中です。 SHOW DDLを使用して確認し、recover DDLまたはrollback DDLを使用して回復またはロールバックするか、単に削除してください 保留中のジョブを破棄できることを確認した場合は、DDLを削除します。
- 次のいずれかの方法でジョブを処理します。 一般的な方法についての詳細な情報を参照のこと, "どこか" を参照. 次のコードは、各メソッドの効果を示しています。
- テーブルから重複を削除します。 次に、DDLジョブを再開して、テーブルの主キーを設定します。
- テーブルから重複を削除します。 この操作を実行する前に、データのコピーが1つだけ必要であることを確認してください。 DELETEステートメントを実行して重複を削除する場合は、PolarDB-X 1.0インスタンスにログインします。PolarDB-X 1.0インスタンスにログインしたときにエラーメッセージが返された場合は、エラーメッセージに基づいてバックエンドのApsaraDB RDS for MySQLデータベースに接続できます。
mysql> delete from test_pending where id=1 and age=20; クエリOK、影響を受ける1行 (0.07秒) mysql> select * from test_pending order by id; + ----- + ------ | id | 年齢 | + ----- + ------ | 1 | 10 | | 2 | 20 | | 3 | 30 | + ----- + ------ セットの3列 (0.02秒)
- 重複を削除した後、DDLジョブをPENDING状態で再開します。 結果は、DDLジョブが再開し、ジョブ失敗のレコードがクリアされ、テーブルのプライマリキーが設定されたことを示します。
mysql> ddl 1106733441212637184を回復します。クエリOK、影響を受ける0行 (1.28秒) mysql> フルddl\Gを表示する 空セット (0.00秒) mysql> show create table test_pending\G *************************** 1。 行 *************************** テーブル: test_pending テーブルの作成: Create Table 'test_pending' ( 'id' int (11) NOT NULL, `age` int(11) DEFAULT NULL, 主要なキー ('id') 、 KEY 'auto_shard_key_id ' ('id') BTREEを使用 ) ENGINE=InnoDB DEFAULT CHARSET=ハッシュによるutf8 dbpartition ('id') セットの1列 (0.02秒) mysql> チェックテーブルtest_pending; + ---------------------------------------- + ------------------------------ + | テーブル | OP | MSG_TYPE | MSG_TEXT | + ---------------------------------------- + ------------------------------ + | ddltest_1562056402230oymk.test_pending | チェック | ステータス | OK | + ---------------------------------------- + ------------------------------ + セットの1列 (0.10秒)
- 失敗したDDLジョブを削除し、テーブルを削除してから、テーブルを再度作成します。 テーブルを削除する前に、テーブルのデータが不要になったことを確認してください。
mysql> ddl 1106733441212637184を削除します。クエリOK、影響を受ける1行 (0.02秒) mysql> ドロップテーブルが存在する場合test_pending; クエリOK、影響を受ける0行 (0.44秒) mysql> 'test_pending' のようなテーブルを表示します。空セット (0.01秒)
- テーブルから重複を削除します。 次に、DDLジョブを再開して、テーブルの主キーを設定します。