MySQL 5.1同步到5.5卡库问题一则
今天在MySQL 5.1同步到5.5時遇到一則卡庫問題,在從庫上show slave status \G,報錯如下:
Error 'BIGINT UNSIGNED value is out of range in '(group.mg_group_var.grp_status_cnt + -(38))'' on query. Default database: 'group'. Query: 'update mg_group_var set grp_status_cnt=grp_status_cnt+(-38) where mgid = '302412' and grp_status_cnt>0'為何在主庫上能執(zhí)行,在從庫上就會失敗呢?
追查原因
在從庫上,show create table 查看表結(jié)構(gòu):
*************************** 1. row *************************** Table: mg_group_var Create Table: CREATE TABLE mg_group_var ( mgid bigint(20) NOT NULL, grp_status_cnt int(11) unsigned NOT NULL DEFAULT '0', grp_member_cnt int(11) unsigned NOT NULL DEFAULT '0', grp_apply_cnt int(6) DEFAULT NULL,發(fā)現(xiàn)grp_status_cnt 列為無符號的整數(shù)類型。 查詢一下grp_status_cnt的值:
mysql> select grp_status_cnt from mg_group_var where mgid = '302412'; +----------------+ | grp_status_cnt | +----------------+ | 27 | +----------------+ 27-38后得到的是負(fù)數(shù)。
官方手冊中有一段話:對于無符號數(shù),如果相減得到負(fù)數(shù),mysql會自動轉(zhuǎn)化為最大的正數(shù)。
驗證一下
在5.1上執(zhí)行如下語句:
mysql> SELECT CAST(0 AS UNSIGNED) - 1; +-------------------------+ | CAST(0 AS UNSIGNED) - 1 | +-------------------------+ | 18446744073709551615 | +-------------------------+但是在5.5上執(zhí)行的時候就會報錯:
mysql> SELECT CAST(0 AS UNSIGNED) - 1; ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '()cast(0 as unsigned) - 1)'按照官方文檔的解釋,在5.1上,當(dāng)相減得到負(fù)數(shù),馬上就被轉(zhuǎn)化為18446744073709551615,而它超出了無符號整數(shù)的范圍,所以被轉(zhuǎn)化為最大的int類型的無符號數(shù)4294967295(但是在5.5上,這個轉(zhuǎn)化報錯,因此導(dǎo)致同步中斷)。
(When an out-of-range value is assigned to an integer column, MySQL stores the value representing the corresponding endpoint of the column data type range. If you store 256 into a TINYINT or TINYINT UNSIGNED column, MySQL stores 127 or 255, respectively. )回到生產(chǎn)數(shù)據(jù)庫,在主庫上,執(zhí)行:
mysql> select grp_status_cnt from mg_group_var where grp_status_cnt > 300000000 limit 3; +----------------+ | grp_status_cnt | +----------------+ | 4294967295 | | 4294967295 | | 4294967272 | +----------------+可以發(fā)現(xiàn)這種溢出的情況很多,它們其實都是從負(fù)數(shù)轉(zhuǎn)化來的,這些數(shù)據(jù)從應(yīng)用的角度來說,都是錯誤的。
解決方法
解決從庫卡庫問題的辦法很多,常用的有如下幾種:
1.跳過指定的錯誤代碼
- 重啟mysql,設(shè)置slave_skip_errors=1069。這需要重啟數(shù)據(jù)庫,代價太大,所以不推薦。
- 用watch -n與mysql命令相結(jié)合,每秒跳過一個命令點:
但是watch的時間間隔最小只能到1s,因此只適合跳過少數(shù)卡庫的命令點。如果從庫卡庫累積的命令點非常多,此法就不可取了。
- 用pt-slave-restart工具跳過命令點。這也是推薦的跳過命令點的方法:
- 可以指定按照錯誤代碼匹配,例如1062,1069等;
- 可以指定按照錯誤文本進(jìn)行正則匹配;
- 智能的調(diào)整從庫同步狀態(tài)檢查的時間間隔,因此如果發(fā)現(xiàn)連續(xù)的卡庫問題,1s內(nèi)可以跳過非常多的sql語句。這些特點對于快速恢復(fù)服務(wù)是非常重要的。
2.跳命令點始終只能解決一時的問題,根本上還是應(yīng)修改代碼邏輯,確保不出現(xiàn)無符號減法的溢出。
3.對DBA來說,采用行格式復(fù)制,從根本上可以保證主從數(shù)據(jù)的一致性。畢竟跳過卡庫問題是簡單的,但是后續(xù)的數(shù)據(jù)修復(fù)過程卻是復(fù)雜的。
總結(jié)
以上是生活随笔為你收集整理的MySQL 5.1同步到5.5卡库问题一则的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决乱码的最佳实践
- 下一篇: 从零开始配置MySQL MMM