Mysql频繁操作出现锁表问题

一、报错现象

org.springframework.dao.CannotAcquireLockException:

### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

这个错误是由于有线程或者是有其他操作在频繁的操作mysql数据库导致表被锁了。

二、原因

1、Spring事务嵌套,当前的业务方法中在一个事务中执行,但是这个方法里还存在调用其他方法,可能也加了事务,底层报错时,事务回滚造成死锁

A,B两个方法开启事务 ,

A的传播级别为默认REQUIRED(当前有事务则加入,没有则创建),

B的传播级别为NOT_SUPPORTED (当前有事务则挂起,以非事务方式执行)

A新增/更新数据 ,B更新同条数据,然后会发生事务死锁

原因分析 : A开启事务,新增/更新数据时会锁住数据,之后执行B方法,B不支持事务会暂停A的事务,A事务还未提交就被暂停,数据加锁,B又去更新数据(此时无法更新一直等待锁的释放,陷入死锁)

2、查询性能太慢,数据库压力太大,对象被锁定,导致事务出现问题。 

三、解决方式

1、排查对应方法使用的事务传播性为以及使用了事务的方法之间的调用是否合理。

2、如果是查询性能太慢,那就需要优化查询sql了,通过explain分析查询语句,查看是否命中索引。sql的type是否达到ref级别以上,如果是range级别,说明未能命中所有索引。

3、本次出现这个问题是由于,测试环境中有测试同学进行性能压测,然后关联到了这张表,导致对这种表出现频繁操作,以至于数据库压力增大而锁表。

在数据库中执行下面语句。

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

会出现

2、然后找到  trx_mysql_thread_id 列  

使用kill id;删除掉对应线程id即可解决。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要避免MySQL锁表问题,我们可以采取以下几种方法: 1. 尽量缩小事务范围:尽量将事务的范围缩小到最小,这样可以减少锁表的时间,并降低其他会话的等待时间。 2. 合理设计索引:通过合理设计索引,可以提高查询的效率,减少锁表的概率。将频繁用于查询的列设置为索引,可以加快读取数据的速度,减少锁表的时间。 3. 避免长事务和大事务:较长的事务或者涉及大量数据的事务,容易引发锁表问题。尽量将事务的执行时间缩短,或者将一些操作拆分成多个小的事务,以减少锁表的概率。 4. 使用读写分离:将读操作和写操作分离,将查询操作分发到只读从库上,以减轻主库的压力,提高系统的并发能力,减少锁表问题的发生。 5. 合理使用锁:在必要的时候,可以使用合适的锁机制,如共享锁、排他锁等,来规避冲突和死锁问题。尽量避免在高并发环境下使用悲观锁,可以考虑使用乐观锁等机制来提高并发处理能力。 6. 避免全表更新和删除操作:全表更新和删除操作会对整个表加锁,影响其他会话的正常访问。可以通过限定更新或删除的条件,以及设置合适的索引,来避免全表操作带来的锁表问题。 7. 合理设置事务隔离级别:选择合适的事务隔离级别也可以减少锁表问题。根据业务需求和性能要求,选择合适的隔离级别。 总之,通过以上几种方法,可以有效避免MySQL锁表问题,提高数据库性能和并发处理能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值