2017大年初一晚上,线上报死锁了..
大家挂着×××排查问题,也是有点意思.
不过当时并没有排查出原因

上班之后,发现是客户端的一个bug.本来应该发送一个请求,但是却发送了大量的请求,应用层面又没有做幂等设计,所以所有的请求都落到了数据库层面。
数据库是一个过程

环境
MySQL 5.6.14
事务隔离级别 读提交

引起问题的逻辑大致如下:

  1.     if not exists (select UserID from award_free_firecracker_watch_common where UserID=pUserID and AwardDate=pToday and GiftID=pGift) then

  2.       insert into award_free_firecracker_watch_common (UserID, AwardDate,GiftID) values (pUserID, pToday,pGift);

  3.     end if;

  4.     

  5.     select AwardTotal into pOld from award_free_firecracker_common where UserID=pUserID and GiftID=pGift for update;

  6.     update award_free_firecracker_common set AwardTotal=AwardTotal+1,AwardLeft=AwardLeft+where UserID=pUserID and GiftID=pGift;

  7.     

  8.     SELECT ROW_COUNT() into pUpdateCount;

  9.     if pUpdateCount>then

  10.       update award_free_firecracker_watch_common set WatchCount=WatchCount+where UserID=pUserID and AwardDate=pToday and GiftID=pGift ; 

  11.     end if;



因为这个过程也不是我写的,大致的意思是先查询award_free_firecracker_watch_common表,如果没有这个用户的记录,则插入.
然后修改award_free_firecracker_common的记录,最后在修改award_free_firecracker_watch_common的记录.

MySQL的加锁过程
https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html

CREATE TABLE t1 (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;

Session 1:

Session 2:

Session 3: