PolarDB-X 1.0 においてグローバルセカンダリインデックス(GSI)への書き込みが失敗すると、テーブル全体がブロックされた状態になります。この状態では、そのテーブルに対してこれ以上の DML ステートメントを実行できず、アクティブなトランザクションもコミットできません。この動作を理解することで、予期しないトランザクションの失敗を回避し、GSI 周りで安全な書き込みパターンを設計できます。
前提条件
作業を開始する前に、以下の要件を満たしていることを確認してください。
ApsaraDB RDS for MySQL インスタンス(バージョン 5.7 以降)
PolarDB-X 1.0 インスタンス(バージョン 5.4.1 以降)
サンプルテーブル
本トピックの例では、通常の GSI(g_i_seller)と一意性 GSI(g_i_buyer)を定義した次のテーブルを使用します。
CREATE TABLE t_order(
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext DEFAULT NULL,
`order_detail` longtext DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `l_i_order` (`order_id`),
GLOBAL INDEX `g_i_seller` (`seller_id`) dbpartition by hash(`seller_id`) tbpartition by hash(`seller_id`),
GLOBAL UNIQUE INDEX `g_i_buyer` (`buyer_id`) COVERING (order_snapshot) dbpartition by hash(`buyer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`order_id`);GSI 書き込み失敗時の DML 動作
重要
GSI の書き込みに失敗すると、テーブルはブロック状態になります。この状態では、テーブルに対して DML ステートメントを実行できず、トランザクションもコミットできません。
以下の例は、この動作を示しています。
SET DRDS_TRANSACTION_POLICY='XA';
-- 成功:buyer_id='buyer_1' を持つ order_1 を挿入します。
-- 一意性 GSI g_i_buyer には buyer_id='buyer_1' が記録されます。
INSERT INTO t_order(order_id, buyer_id, seller_id) VALUES('order_1', 'buyer_1', 'seller_1');
-- GSI への書き込みに失敗しました。
INSERT IGNORE INTO t_order(order_id, buyer_id, seller_id) VALUES('order_2', 'buyer_1', 'seller_1');
-- ブロック中:GSI 書き込み失敗が解消されるまで、t_order に対して DML を実行できません。
INSERT IGNORE INTO t_order(order_id, buyer_id, seller_id) VALUES('order_2', 'buyer_2', 'seller_2');
-- ブロック中:トランザクションをコミットできません。
COMMIT;