故障處理報告–MYSQL5.7 online DDL BUG:
數據庫版本:
? MYSQL 5.7
背景:
? 早晨同事在執行MYSQL 數據表磁盤空間整理工作(回收數據文件空間碎片),期間執行了DDL操作,DDL操作報如下錯誤:
ERROR 1062(23000): Duplicate entry 'xxx' for key 'key_name'

排查過程:
-
查看數據是否重復
show create table table_name -- 略的表結構定義: create table 'table_name' ( ... 'order_code' varchar(64) COLLATE utf8mb4_bin default null, ... UNIQUE KEY 'order_idx' ('order_code') using btree, ) engine-Innodb ...發現報錯的Key 是一個unique key, 根據unqiue key 的定義,該字段不可能存在重復的entry。從下圖的查詢結果也能確定表中該字段的值均是唯一的。遂不可能是表中數據出現了問題。

When running an online DDL operation, the thread that runs the ALTER TABLE statement applies an
online log of DML operations that were run concurrently on the same table from other connection
threads. When the DMLoperations are applied, it is possible to encounter a duplicate key entry
error (ERROR 1062 (23000): Duplicate entry), even if the duplicate entry is only temporary and
would be reverted by a later entry in the online log. This is similar to the idea of a foreign
key constraint check in InnoDB in which constraints must hold during a transaction.
? 描述所說 online ddl 期間,其他會話執行的dml操作造成唯一鍵沖突的sql會記錄到 online log 中,在commit階段等變更結束之后再應用這些sql會導致報錯唯一鍵沖突。
注意: 資料來源于https://www.cnblogs.com/igoodful/p/14075649.html
-
根據理論尋找支持
? 此ERROR 1062(23000) 錯誤是由其它會話執行造成唯一鍵沖突,那么數據庫一定會返回給該會話ERROR 1062(23000)錯誤,通過應用日志查找該錯誤。經過查找錯誤日志,發現數據庫確實返回給了應用一個一摸一樣的唯一鍵沖突報錯:如下截圖:

? 然后繼續排查應用日志,是什么操作導致了唯一鍵的重復,最后通過開發排查是用戶短時間內將相同數據提交了兩遍。 所以在數據提交前最好數據驗證非常重要。
-
模擬BUG
? 第一步:Session A: 執行alter table DDL 操作;
? | 第二步:Session B: 在Session A 執行完畢前,構造并執行能觸發重復鍵的DML語句(update、insert),并提交;
? 第三步:Session A: 等待Session A 報錯,查看SessionA 報錯是否與Session B 一致。
總結:
? 不管任何數據庫,做重大的DDL操作,需要在業務低峰期操作或停業務操作(能不online,就不建議online操作),生產環境穩定為第一要素。




