mysql batch insert 遇到错误跳过_这是MySQL的bug吗?
前語(yǔ):不要為了讀文章而讀文章,一定要帶著問(wèn)題來(lái)讀文章,勤思考。在此,建議大家為本公眾號(hào)加“星標(biāo)”。如文章寫(xiě)得好,望大家閱讀后在右下邊“在看”處點(diǎn)個(gè)贊,以示鼓勵(lì)!
作者:潘民蘭? 來(lái)源:http://t.cn/AiKrffGF
我們?cè)趯?shí)際業(yè)務(wù)場(chǎng)景中,經(jīng)常會(huì)有一個(gè)這樣的需求,插入某條記錄,如果已經(jīng)存在了則更新它如果更新日期或者某些列上的累加操作等,我們肯定會(huì)想到使用INSERT ... ON DUPLICATE KEY UPDATE語(yǔ)句,一條語(yǔ)句就搞定了查詢(xún)是否存在和插入或者更新這幾個(gè)步驟,但是使用這條語(yǔ)句在msyql的innodb5.0以上版本有很多的陷阱,即有可能導(dǎo)致death lock死鎖也有可能導(dǎo)致主從模式下的replication產(chǎn)生數(shù)據(jù)不一致。
正如前言說(shuō)的那樣,在實(shí)際業(yè)務(wù)中,曾經(jīng)有過(guò)一個(gè)需求就是插入一條業(yè)務(wù)數(shù)據(jù),如果不存在則新增,存在則累加更新某一個(gè)字段的值,于是乎就想到了使用insert... on duplicate key update這個(gè)語(yǔ)句,但是有一天去測(cè)試環(huán)境查看錯(cuò)誤日志時(shí),卻發(fā)現(xiàn)了在多個(gè)事務(wù)并發(fā)執(zhí)行同一條insert...on duplicate key update 語(yǔ)句時(shí),也就是insert的內(nèi)容相同時(shí),發(fā)生 了死鎖。
對(duì)于insert...on duplicate key update這個(gè)語(yǔ)句會(huì)引發(fā)dealth lock問(wèn)題,官方文檔也沒(méi)有相關(guān)描述,只是進(jìn)行如下描述:
An?INSERT ... ON DUPLICATE KEY UPDATE?statement against a table having more than one unique or primary key is also marked as unsafe. (Bug #11765650, Bug #58637)也就是如果一個(gè)表定義有多個(gè)唯一鍵或者主鍵時(shí),是不安全的,這又引發(fā)了以一個(gè)問(wèn)題,見(jiàn)https://bugs.mysql.com/bug.php?id=58637。
也就是當(dāng)mysql執(zhí)行INSERT ON DUPLICATE KEY的 INSERT時(shí),存儲(chǔ)引擎會(huì)檢查插入的行是否會(huì)產(chǎn)生重復(fù)鍵錯(cuò)誤。如果是的話(huà),它會(huì)將現(xiàn)有的行返回給mysql,mysql會(huì)更新它并將其發(fā)送回存儲(chǔ)引擎。當(dāng)表具有多個(gè)唯一或主鍵時(shí),此語(yǔ)句對(duì)存儲(chǔ)引擎檢查密鑰的順序非常敏感。根據(jù)這個(gè)順序,存儲(chǔ)引擎可以確定不同的行數(shù)據(jù)給到mysql,因此mysql可以更新不同的行。存儲(chǔ)引擎檢查key的順序不是確定性的。例如,InnoDB按照索引添加到表的順序檢查鍵。
insert ... on duplicate key 在執(zhí)行時(shí),innodb引擎會(huì)先判斷插入的行是否產(chǎn)生重復(fù)key錯(cuò)誤,如果存在,在對(duì)該現(xiàn)有的行加上S(共享鎖)鎖,如果返回該行數(shù)據(jù)給mysql,然后mysql執(zhí)行完duplicate后的update操作,然后對(duì)該記錄加上X(排他鎖),最后進(jìn)行update寫(xiě)入。
如果有兩個(gè)事務(wù)并發(fā)的執(zhí)行同樣的語(yǔ)句,那么就會(huì)產(chǎn)生death lock,如:
具體的bug描述見(jiàn):
https://bugs.mysql.com/bug.php?id=52020https://bugs.mysql.com/bug.php?id=58637https://bugs.mysql.com/bug.php?id=21356解決辦法:
1、盡量不對(duì)存在多個(gè)唯一鍵的table使用該語(yǔ)句。
2、在有可能有并發(fā)事務(wù)執(zhí)行的insert 的內(nèi)容一樣情況下不使用該語(yǔ)句。
---------------
看到這里還沒(méi)過(guò)癮,那么就來(lái)群里與更多的同學(xué)交流切磋技術(shù),戳這里:咱們來(lái)一起抱團(tuán)取暖,好嗎?
---END---
熱文推薦
技術(shù)團(tuán)隊(duì)一般是如何進(jìn)行代碼審查的?
面試官:給我說(shuō)說(shuō)你對(duì)Java GC機(jī)制的理解?
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的mysql batch insert 遇到错误跳过_这是MySQL的bug吗?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: gc的原因 频繁full_系统缓慢+CP
- 下一篇: mysql galera cluster