亚洲国产日韩人妖另类,久久只有这里有精品热久久,依依成人精品视频在线观看,免费国产午夜视频在线

      
      

        記一次排查線上MySQL死鎖過程,不能只會curd,還要知道加鎖原理

        記一次排查線上MySQL死鎖過程,不能只會curd,還要知道加鎖原理

        昨晚我正在床上睡得著著的,突然來了一條短信。

        啥,線上MySQL死鎖了,我趕緊登錄線上系統(tǒng),查看業(yè)務日志

        能清楚看到是這條insert語句發(fā)生了死鎖。

        MySQL如果檢測到兩個事務發(fā)生了死鎖,會回滾其中一個事務,讓另一個事務執(zhí)行成功。很明顯,我們這條insert語句被回滾了。

        insert into user (id, name, age) values (6, ‘張三’, 6);

        但是我們怎么排查這個問題呢?

        到底跟哪條SQL產(chǎn)生了死鎖?

        好在MySQL記錄了最近一次的死鎖日志,可以用命令行工具查看:

        show engine innodb status;

        在死鎖日志中,可以清楚地看到這兩條insert語句產(chǎn)生了死鎖,最終事務2被會回滾,事務1執(zhí)行成功。

        # 事務1insert into user (id,name,age) values (5,’張三’,5);# 事務2insert into user (id,name,age) values (6,’李四’,6);

        這兩條insert語句,怎么看也不像能產(chǎn)生死鎖,我們來還原一下事發(fā)過程

        先看一下對應的Java代碼:

        @Override@Transactional(rollbackFor = Exception.class)public void insertUser(User user) { User userResult = userMapper.selectByIdForUpdate(user.getId()); // 如果userId不存在,就插入數(shù)據(jù),否則更新 if (userResult == null) { userMapper.insert(user); } else { userMapper.update(user); }}

        業(yè)務邏輯代碼很簡單,如果userId不存在,就插入數(shù)據(jù),否則更新user對象。

        從死鎖日志中,我們看到有兩條insert語句,很明顯userId=5和userId=6的數(shù)據(jù)都不存在。

        所以對應的SQL執(zhí)行過程,可能就是這樣的:

        先用for update加上排他鎖,防止其他事務修改當前數(shù)據(jù),然后再insert數(shù)據(jù),最后發(fā)生了死鎖,事務2被回滾。

        兩個事務分別在兩個主鍵ID上面加鎖,為什么會產(chǎn)生死鎖呢?

        如果看過上篇文章,就會明白。

        當id=5存在這條數(shù)據(jù)時,MySQL就會加Record Locks(記錄鎖),意思就是只在id=5這一條記錄上加鎖。

        當id=5這條記錄不存在時,就會鎖定一個范圍。

        假設表中的記錄是這樣的:

        id

        name

        age

        1

        王二

        1

        10

        一燈

        10

        select * from user where id=5 for update;

        這條select語句鎖定范圍就是 (1, 10]。

        最后兩個事務的執(zhí)行過程就變成了:

        通過這個示例看到,兩個事務都可以先后鎖定 (1, 10]這個范圍,說明MySQL默認加的臨鍵鎖的范圍是可以交叉的。

        那怎么解決這個死鎖問題呢?

        我能想到的解決辦法就是,把這兩個語句select和insert,合并成一條語句:

        insert into user (id,name,age) values (5,’張三’,5) on duplicate key update name=’張三’,age=5;

        大家有什么好辦法嗎?

        這個死鎖情況,還是挺常見的,趕緊回去翻一下項目代碼有沒有這樣的問題。

        推薦閱讀:《我愛背八股系列》

        為什么要用MQ?MQ的作用有哪些? 高并發(fā)場景下,如何保證數(shù)據(jù)的一致性的? 如何進行分庫分表?分庫分表后有哪些問題以及對應的解決方案。 高并發(fā)下怎么生成訂單ID?以及每種方案的優(yōu)缺點。 如何實現(xiàn)分布式鎖?使用數(shù)據(jù)庫、分布式數(shù)據(jù)庫、分布式協(xié)調(diào)服務分別如何實現(xiàn)?

        MySQL索引底層數(shù)據(jù)結構為什么要用B+樹?以及紅黑樹、B樹的優(yōu)缺點。

        一篇文章講清楚MySQL的聚簇/聯(lián)合/覆蓋索引、回表、索引下推

        ThreadLocal線上故障復盤,差點丟了工作。詳解MySQL事務底層原理一文講清楚MySQL的所有鎖

        MySQL update語句加鎖過程和原理

        鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權歸原作者所有,如有侵權請聯(lián)系管理員(admin#wlmqw.com)刪除。
        上一篇 2022年6月13日 06:07
        下一篇 2022年6月13日 06:07

        相關推薦

        聯(lián)系我們

        聯(lián)系郵箱:admin#wlmqw.com
        工作時間:周一至周五,10:30-18:30,節(jié)假日休息