故障案例:MySQL唯一索引有重複值,官方卻說This is not a bug
* GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯系小編並注明來源。
問題 原因 故障解決方案 復現步驟 參考文獻
一、問題:
MySQL5.7.38主從架構,主節點唯一索引上(唯一索引不是主鍵)有重複值,全部從節點報1062,SQL執行緒狀態異常,根據SQL執行緒報的binlog位置點,insert 資料時有重複值,插入失敗
二、原因:
unique_checks=0時導致,在bug(106121)列表中官方解釋的原因:該引數關閉,維護唯一索引時,不會進行物理讀,只會進行記憶體讀,來確保唯一索引的唯一性,即如果記憶體中有衝突資料就報1062,如果記憶體中沒有衝突資料插入成功,不會進行io來將唯一索引相關的資料頁拉取到記憶體。
官方的回覆“IMHO this is not a bug”,我理解的意思“不要你覺得,我要我覺得,我就是這麼玩的”。
三、故障解決方案:
一、臨時解決方案
恢復主從: 在從節點開啟會話 set sql_log_bin=0 刪除表的唯一索引 重新啟動複製執行緒
缺點是:不能夠解決資料重複的問題,切換主從後會面臨更多重複資料的問題,如果從節點接收查請求且使用到了原唯一索引的欄位,那sql效率會嚴重下降,但是可以解決主從複製停止的問題
二、永久解決方案
業務自己去重,不要插入重複資料 引數unique_checks保持為1 關於重複的業務資料:與業務交流,確定重複資料的處理方式
四、復現步驟:
1. 表結構:
mysql> create database wl;
mysql> show create table wl.lgf\G
*************************** 1. row ***************************
Table: lgf
Create Table: CREATE TABLE `lgf` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `c` (`c`,`pad`)
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8
Python生成隨機資料,插入表,並另起會話觀察總資料量約10w條左右(保證聚簇索引中的前邊的資料與後邊的資料所在的葉子節點的頁相差很遠):
rand.py
import random
import os
while True:
i=str(random.randint(1000,8000000))
a=str(random.randint(1000000000000000,8000000000000000))
b=str(random.randint(1000000000000000,8000000000000000))
c=str(random.randint(100000,800000))
sql="insert ignore into lgf(id,k,c,pad) values(%s,%s,%s,%s) " % (i,c,a,b)
os.system('mysql -uroot -p123456 -h127.0.0.1 -P3306 -e "use wl;%s"' % (sql))
2. 查詢資料:
查詢前10條資料:
mysql> select * from wl.lgf order by id limit 10;
+------+--------+------------------+------------------+
| id | k | c | pad |
+------+--------+------------------+------------------+
| 1058 | 162327 | 1693367460515515 | 4503256156555111 |
| 1072 | 581438 | 7079984640802065 | 3180334749170868 |
| 1139 | 160022 | 5072986485096872 | 4163430310554381 |
| 1193 | 780611 | 4790797228737408 | 2940698105313885 |
| 1234 | 395757 | 4904177529354516 | 4353197763651083 |
| 1243 | 725513 | 5525166443023382 | 5731401212245669 |
| 1262 | 749163 | 1132694876665847 | 5159069792931202 |
| 1280 | 415220 | 2770815803363126 | 3979264947141008 |
| 1316 | 329253 | 6088415865037450 | 6035685143204331 |
| 1360 | 403078 | 3344825394389018 | 7962994492618902 |
+------+--------+------------------+------------------+
10 rows in set (0.00 sec)
id=1360 c=3344825394389018 pad=7962994492618902
3. 拼接SQL
c與pad的值與id=1360值相等,id=1000000000(表中無該id行)
insert into wl.lgf(id,c,pad) values(10000000,'3344825394389018','7962994492618902') ;
4. 重啟mysqld
目的是清除快取 為了清空MySQL快取容,還可結合以下幾個引數 修改my.cnf檔案,重啟MySQL例項
innodb_buffer_pool_load_at_startup = 0
innodb_buffer_pool_dump_at_shutdown = 0
5. 重新插入重複唯一索引資料:
mysql> set unique_checks=0;
mysql> use wl
mysql> insert into wl.lgf(id,c,pad) values(10000000,'3344825394389018','7962994492618902') ;
Query OK, 1 row affected (0.00 sec)
6. 查詢:force index指定主鍵查詢資料
mysql> select * from wl.lgf force index(primary) where c='3344825394389018' and pad='7962994492618902';
+----------+--------+------------------+------------------+
| id | k | c | pad |
+----------+--------+------------------+------------------+
| 1360 | 403078 | 3344825394389018 | 7962994492618902 |
| 10000000 | 0 | 3344825394389018 | 7962994492618902 |
+----------+--------+------------------+------------------+
2 rows in set (0.37 sec)
參考文件
MySQL Bugs: #106121: Unique key constraint invalid()
MySQL :: MySQL 8.0 Reference Manual :: 5.1.8 Server System Variables(https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_unique_checks)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024922/viewspace-2935735/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL <唯一索引>MySql索引
- 建立Oracle唯一約束,忽略已有的重複值Oracle
- MySQL 唯一索引和普通索引MySql索引
- MySQL 冗餘和重複索引薦MySql索引
- MySQL 處理插入過程中的主鍵唯一鍵重複值辦法MySql
- MySQL案例07:MySQL5.7併發複製隱式bugMySql
- 明明加了唯一索引,為什麼還是產生了重複資料?索引
- 明明加了唯一索引,為什麼還是產生重複資料?索引
- mysql唯一索引是什麼MySql索引
- 故障分析 | MySQL 從機故障重啟後主從同步報錯案例分析MySql主從同步
- MySQL實戰45講——普通索引和唯一索引MySql索引
- 處理MySQL複製環境Slave故障的一個案例MySql
- 【MySQL】可重複讀模式下 unique key失效案例MySql模式
- 說說MySQL索引相關MySql索引
- MySQL複合索引MySql索引
- SQL優化案例一則--複合索引沒有被使用SQL優化索引
- 故障分析 | MySQL 異地從庫複製延遲案例一則MySql
- 【MySQL】5.6/5.7並行複製bug導致的故障 ERROR 1755/1756MySql並行Error
- MySQL唯 一鍵約束場景下卻能插入重複行?MySql
- MySQL使用pt-duplicate-key-checker找出冗餘、重複索引MySql索引
- MySQL複合索引探究MySql索引
- MySQL建立複合索引MySql索引
- 唯一索引索引
- SQL最佳化案例一則--複合索引沒有被使用SQL索引
- mysql 新增時,唯一索引衝突時更新MySql索引
- mysql的唯一索引不會利用change bufferMySql索引
- 故障分析 | MySQL死鎖案例分析MySql
- MongoDB之索引(唯一索引)MongoDB索引
- 刪除oracle重複值Oracle
- SQL 處理重複值SQL
- 【MySQL】全索引掃描的bugMySql索引
- 如何選擇普通索引和唯一索引《死磕MySQL系列 五》索引MySql
- MYSQL中的普通索引,主健,唯一,全文索引區別MySql索引
- 常數複合索引應用案例索引
- 轉載-treedump索引讀取索引儲存的資料值--非唯一性索引索引
- 在陣列中找出唯一的重複元素陣列
- mysql xtrabackup 遭遇嚴重bugMySql
- 日常Bug排查-Nginx重複請求?Nginx