锁表分析及解决方案

锁表

​ 表处于被锁定状态,无法进行后续对表的操作

业务中产生原因

业务逻辑中对表进行insert/update/delete 后未进行commite或者回滚或者退出数据库用户,后续进行insert/update/delete 时发生资源正忙异常(发生锁表),也就是insert/update/delete 操作间隔commit或者回滚或者退出数据库用户时间过长导致

锁表常发生于并发而不是并行(并行时,一个线程操作数据库时,另一个线程是不能操作数据库的,cpu 和i/o 分配原则)

程序级别原因

sql原因:insert/update/delete操作sql执行时间过长。可能是where条件没有走索引导致的。

业务代码原因:可能insert/update/delete操作后续执行了较为耗时的业务代码逻辑,再进行commit操作

解决方案

  1. 优化sql,适当增加索引,让其走索引(减少锁表概率)(常用方案)

  2. 优化代码,使其sql的insert/update/delete操作到commit操作的中间代码运行时间短(减少锁表概率),具体点批量执行改为单个执行、优化sql自身的非执行速度, 如果异常对事物进行回滚。(一般是业务需求无法优化)

  3. 直接杀掉锁表进程(已经发生死锁,打开死锁)(临时方案,常用)

    事务:

    # 查询事务是否发生死锁
    select * from information_schema.innodb_trx
    # 杀死进程
    kill thread_id;
    

    非事务:

    #查看进程id,然后用kill id杀掉进程
    show processlist;
    SELECT * FROM information_schema.PROCESSLIST;
    #查询正在执行的进程
    SELECT * FROM information_schema.PROCESSLIST where length(info) >0 ;
    #查询是否锁表
    show OPEN TABLES where In_use > 0;
    #查看被锁住的
    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
    #等待锁定
    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
    #杀掉锁表进程
    kill 5601
    

企业开发中造成的死锁

由于企业中常常是微服务架构,常常使用SpringBoot的@Transactional注解进行声明式事务管理,大量使用该注解出现死锁的情况。

  1. 被事务托管的方法出现异常,而Transactional注解却未指定rollbackFor异常回滚属性,发生死锁

    @Transactional(rollbackFor = Exception.class)
    
  2. 业务中,服务A中的某个方法操作了调用了服务B的另一个方法,且服务A的方法被事务管理,而两个方法均操作同一张表,服务A操作表在前,服务B操作表在后,导致死锁。

    分析:因为服务A操作表且被事务管理,未提交前会将该表锁住,此事调用服务B继续操作该表,产生死锁

  3. 业务中存在并发操作或者多个方法操作同一张表,发生锁表,等待未响应,某个方法执行时间过于较长时,当超过100秒未结束的事务,会被做超时处理,抛出异常。解决方案,杀死死锁进程

解决方案

  1. 运行以下命令,查找提交事务的数据,杀掉线程即可解决
 select * from information_schema.innodb_trx
 kill thread_id;
  1. 增加锁等待时间,即增大下面配置项参数值,单位为秒(s)
  innodb_lock_wait_timeout=500
  1. 优化存储过程,事务避免过长时间的等待。

可以用下面三张表来查原因-information_schema:

  innodb_trx ## 当前运行的所有事务
  innodb_locks ## 当前出现的锁
  innodb_lock_waits ## 锁等待的对应关系

其他:

1、开始事务(使用@transtion)必须指定超时时间

@Transactional( rollbackFor = Exception.class , isolation = Isolation.REPEATABLE_READ, timeout = 30)

2、事务中存在批量修改、删除的语句的时候,where 条件尽量加索引

3、事务中存在批量修改、删除数据时,尽可能减少事务的执行时间。将代码解耦,不要将很多的更新操作在一个长事务中使用

4、在没必要的情况下,去除@Transactional注解

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值