Mysql死锁排查

问题

有一天客户告知,用户的功能使用有问题,然后去线上正式环境排查发现日志记录了异常:
DeadlockLoserDataAccessException
死锁日志查询
show engine innodb status \G;
具体异常错误信息为:

Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.
MySQLTransactionRollbackException:
Deadlock found when trying to get lock; try restarting transaction
简单而言就是死锁了,死锁造成的原因

排它锁(X锁)和共享锁(S锁).
所谓X锁,是事务T对数据A加上X锁时,只允许事务T读取和修改数据A
所谓S锁,是事务T对数据A加上S锁时,其他事务只能再对数据A加S锁,而不能加X锁,直到T释放A上的S锁
若事务T对数据对象A加了S锁,则T就可以对A进行读取,但不能进行更新(S锁因此又称为读锁),在T释放A上的S锁以前,其他事务可以再对A加S锁,但不能加X锁,从而可以读取A,但不能更新A.

其实,我的理解很简单,就是在有一定并发的情况下,多个线程对同一条数据进行查询与修改同时进行造成资源不足。或者是表没有索引,频繁的查询以及修改,修改没有索引的字段会造成全局锁,导致死锁。

重现问题

打开两个窗口依次执行执行
START TRANSACTION; update t_sysorderhead set ohid='1' WHERE gfsh ='123' ;
在没有索引的情况,会造成第二次更新操作等待超时

标准处理方式
  1. 分析sql语句 使所有sql子查询语句都走唯一索引、索引等 不要全表扫描导致产生表级别的锁
    执行explain sql语句 ,把ALL类型的全表扫描的执行sql都优化成走索引执行
  2. 降低事务等级为 ISOLATION_READ_COMMITTED ,缩小事务 及时commit
    READ_COMMITTED 不会锁表,是Oracle的默认事务等级,MySql默认使用的REPEATABLE READ ,READ UNCOMMITTED更快 更不易锁表。
  3. 分解service impl中的方法中作为整体事务的容易出错的代码,单独进行异常的捕获,防止其出现IP错误等导致数据库回滚
  4. 其他业务语句涉及到同一张表的 要使用索引 避免全表扫描的update 。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值