真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

回饋開源,我如何排查一個(gè)MySQLBug

X-Engine是阿里巴巴自研的高性能低成本存儲(chǔ)引擎,經(jīng)過(guò)多年的努力,我們?cè)诩瘓F(tuán)內(nèi)部以AliSQL(X-Engine)的形式(AliSQL是阿里的MySQL分支)支持了許多業(yè)務(wù),為用戶帶來(lái)了顯著的成本和性能收益。

成都創(chuàng)新互聯(lián)公司擁有一支富有激情的企業(yè)網(wǎng)站制作團(tuán)隊(duì),在互聯(lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)深耕十余年,專業(yè)且經(jīng)驗(yàn)豐富。十余年網(wǎng)站優(yōu)化營(yíng)銷經(jīng)驗(yàn),我們已為超過(guò)千家中小企業(yè)提供了成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站解決方案,按需定制開發(fā),設(shè)計(jì)滿意,售后服務(wù)無(wú)憂。所有客戶皆提供一年免費(fèi)網(wǎng)站維護(hù)!

時(shí)至今日,阿里巴巴數(shù)據(jù)庫(kù)團(tuán)隊(duì)已經(jīng)向MySQL官方提交了許多有價(jià)值的bug及修復(fù)方案。我們繼承了這一優(yōu)良傳統(tǒng),在生產(chǎn)、測(cè)試中遇到MySQL相關(guān)的問(wèn)題,總是積極地思考解決方案,并迅速與官方交流溝通,為開源社區(qū)的發(fā)展貢獻(xiàn)自己的力量。

下文將介紹我們剛發(fā)現(xiàn)的一個(gè)MySQL問(wèn)題及修復(fù)方案。遇到相同情況的朋友需要注意了,也許不符合規(guī)范的數(shù)據(jù)已經(jīng)寫入你們的數(shù)據(jù)庫(kù)了。

背景知識(shí)

如果MySQL參數(shù)sql_mode包含以下3項(xiàng):

NO_ZERO_DATE

NO_ZERO_IN_DATE

STRICT_TRANS_TABLES

向DATE類型列,插入'0000-00-00'或者年/月/日3部分任意一部分為0,都將失敗。

回饋開源,我如何排查一個(gè)MySQL Bug

異常:‘0000-00-00’竟然插入成功了

在MySQL 8.0.16上依次執(zhí)行以下語(yǔ)句:

set sql_mode='';

create table test (mydate DATE NOT NULL DEFAULT '0000-00-00');
set sql_mode=default;

show variables like "sql_mode";

insert into test values();

select * from test;

這里先將sql_mode設(shè)為空的目的是:建表時(shí)將mydate的default value設(shè)為'0000-00-00',否則會(huì)因default value不符合NO_ZERO_DATE而建表失敗。

建表成功后將sql_mode設(shè)回default,包含:

ONLY_FULL_GROUP_BY

NO_ZERO_DATE

NO_ZERO_IN_DATE

STRICT_TRANS_TABLES

ERROR_FOR_DIVISION_BY_ZERO

NO_ENGINE_SUBSTITUTION

然而,這時(shí)竟然成功向test庫(kù)里插入了一條'0000-00-00'的DATE。顯然,NO_ZERO_DATE的語(yǔ)義被打破了。

回饋開源,我如何排查一個(gè)MySQL Bug

抽絲剝繭,原來(lái)問(wèn)題出在這

首先,我們定位到MySQL插入路徑,檢查default value是否合法的函數(shù)。

回饋開源,我如何排查一個(gè)MySQL Bug

這個(gè)函數(shù)比較簡(jiǎn)單,找出用戶insert lists不包含的、且有default value的列,檢查它們的default value是否合法。write_set是一個(gè)bitmap,標(biāo)識(shí)了用戶insert lists里包含哪些列。

我用gdb在該函數(shù)處加了斷點(diǎn),執(zhí)行上述case,竟然發(fā)現(xiàn)write_set里全部bit被設(shè)為了1。這顯然不正常的現(xiàn)象,我的插入SQL語(yǔ)句insert into test values();insert list明明為空,write_set全為0才合理??磥?lái)有函數(shù)錯(cuò)誤地修改了它。

于是乎,我用gdb給write_set的地址加了一個(gè)watchpoint,重新執(zhí)行insert語(yǔ)句。這次定位到了修改write_set的地方:

回饋開源,我如何排查一個(gè)MySQL Bug

該函數(shù)在檢查default value是否合法前執(zhí)行,其作用是當(dāng)binlog_format為ROW且binlog_row_image為FULL時(shí),write_set會(huì)被全部設(shè)置為1。

參數(shù)binlog_format指定了binlog格式,有三個(gè)備選項(xiàng):

ROW代表主備之間通過(guò)log_event同步;

STATEMENT代表主備之間通過(guò)SQL語(yǔ)句同步;

MIXED則是混合格式,默認(rèn)用STATEMENT方式,一些特殊情況下用ROW方式。

由于主備通過(guò)STATEMENT同步(雖然它產(chǎn)生的binlog數(shù)量小),可能因上下文信息、環(huán)境不同等因素,導(dǎo)致結(jié)果不一致,因此安全起見(jiàn),binlog_format默認(rèn)為ROW。

參數(shù)binlog_row_image指定了ROW格式binlog要記錄哪些信息。它也有三個(gè)備選項(xiàng):

FULL表示binlog記錄變更前后的所有列;

MINIMAL表示binlog只記錄唯一標(biāo)識(shí)列和修改列;

NOBLOB表示BLOB是修改列或唯一標(biāo)識(shí)列,才記錄,其它列與FULL相同全部記錄。

binlog_row_image默認(rèn)為FULL。

當(dāng)binlog_format為ROW且binlog_row_image為FULL 時(shí),為了保證所有列都寫到binlog里,write_set竟然被全部設(shè)置為1。

write_set變量本是用來(lái)標(biāo)識(shí)用戶插入列,又被賦予了控制寫binlog的重任。多重語(yǔ)義交織,很容易出bug。這也給我們編碼帶來(lái)啟示:每個(gè)變量應(yīng)當(dāng)有確切的語(yǔ)義。

修復(fù)建議

導(dǎo)致這個(gè)bug的原因是write_set用處太多。因此可以創(chuàng)建一個(gè)新的bitmap:binlog_write_set,專門用于控制寫binlog。


分享文章:回饋開源,我如何排查一個(gè)MySQLBug
網(wǎng)站URL:http://weahome.cn/article/psipoj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部