最近做了一个定时任务的项目, 因为多个定时任务在一个时间点同时进行, 从而产生了锁等待超时的问题;
产生问题原因:
A,B两个定时任务, 操作的同一张表; 并且两个任务同时触发;
业务逻辑都是先删除表中数据, 然后再新增数据, AB操作的不是同一条数据;
A业务处理速度快, 先拿到了该表的锁, B后面才拿到
但是由于我们数据库的表超时时间比较短, 导致A表操作没有结束, B表等待时间已经超时, 从而抛出了异常;
解决方案:
- 修改定时任务执行时间, 让两个任务有足够的错开时间
优点:
(1). 无代码逻辑修改, 解决问题方便
缺点:
(1). 定时任务的运行时间可能与业务强相关
(2). 该时间不太容易掌控, - 修改mysql锁等待时间
优点:
(1). 无需修改代码, 修改方便,
(2). 试用该数据库所有表
缺点:
(1). 有些公司对数据库管理严格, 审批繁琐, 可能不允许修改;
(2). 修改锁等待时间不容易掌控, 可能满足现状后续又要调; - 使用行级锁, 避免表锁(推荐)
优点:
(1). 适应能力强, 数据之间无干扰
缺点:
(1). 编码时需要注意sql对索引的使用
使用方法:
在编写sql时, 删除/修改走索引或者唯一主键(例如id), 注意使用时防止索引失效;
(InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁。)
一些关于表能用到的命令
# 查询全局等待事务锁超时时间
SHOW GLOBAL VARIABLES LIKE 'innodb_lock_wait_timeout';
#查看执行计划
show processlist;
#锁查询
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
网友评论