您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

分享一个MySQL死锁问题解决的方法

2024/2/24 20:08:01发布14次查看
分享一个mysql死锁问题解决的方法一、环境centos, mysql 5.6.21-70, jpa
问题场景:系统有定时批量更新数据状态操作,每次更新上千条记录,表中总记录数约为500w左右。
二、错误日志2017-2-25 17:38:41 org.hibernate.util.jdbcexceptionreporter logexceptions 严重: lock wait timeout exceeded; try restarting transaction 2017-2-25 17:39:05 org.hibernate.util.jdbcexceptionreporter logexceptions 警告: sql error: 1213, sqlstate: 40001 2017-2-25 17:39:05 org.hibernate.util.jdbcexceptionreporter logexceptions 严重: deadlock found when trying to get lock; try restarting transaction
三、排查check innodb status for locks mysql> show engine innodb status; check mysql open tables mysql> show open tables where in_use > 0; check pending innodb transactions mysql> select * from `information_schema`.`innodb_trx` order by `trx_started`; check lock dependency - what blocks what mysql> select * from `information_schema`.`innodb_locks`;
排查后发现都是执行类似这样的语句出现问题的:
update t_task_tel set state='iok', update_date='2017-02-27 11:03:02' where tel_id=66042 and task_id=350199;
四、分析搜索相关资料后发现,原来mysql innodb并不一定都是行级锁。
相关参考资料片段如下:
锁选择
1)、如果更新条件没有走索引,例如执行”update from t1 set v2=0 where v2=5;” ,此时会进行全表扫描,扫表的时候,要阻止其他任何的更新操作,所以上升为表锁。
2)、如果更新条件为索引字段,但是并非唯一索引(包括主键索引),例如执行“update from t1 set v2=0 where v1=9;” 
那么此时更新会使用next-key lock。使用next-key lock的原因:
a)、首先要保证在符合条件的记录上加上排他锁,会锁定当前非唯一索引和对应的主键索引的值;
b)、还要保证锁定的区间不能插入新的数据。
3)、如果更新条件为唯一索引,则使用record lock(记录锁)。
innodb根据唯一索引,找到相应记录,将主键索引值和唯一索引值加上记录锁。但不使用gap lock(间隙锁)。
由于innodb预设是row-level lock,所以只有「明确」的指定主键,mysql才会执行row lock (只锁住被选取的资料例) ,否则mysql将会执行table lock (将整个资料表单给锁住)。
根据分析结论,猜测是在更新_task_tel表时where条件中tel_id和task_id没有建立unique(唯一索引)原因;
五、解决据此分析,尝试通过tel_id和task_id两个字段建立unique(唯一索引)来解决。 (也可以先查询出来,然后根据主键id来更新,这样不会因表中数据量较大影响线上业务)。
通过此种方式解决后,问题没有再重现。
如果你的问题和我遇到的类似,可以尝试据此解决。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product