[xuxueli/xxl-job]分布式锁等待问题

2023-12-15 888 views
3

目前使用的是v2.3.0的xxl-job,发现一个问题,具体如下:

  1. xxl-job是通过数据库实现的分布式锁,即:select * from xxl_job_lock where lock_name = 'schedule_lock' for update

  2. 如果在此语句执行后,还未提交事务前,xxl-job由于某种原因(宕机或网络),导致还没来得及提交事务,那么就会导致此表的锁一直不释放,从而所有任务被阻塞。

  3. 就算xxl-job重启后恢复,由于之前的数据库锁一直存在,任务仍然一直被阻塞,除非人工介入操作数据库将此锁释放才行

不知道这是否算是系统的缺陷,或者有什么解决办法吗

目前能想到只能是使用redis分布式锁做改造

PS:经测试,当客户端关闭时,能够释放连接。但如果出现网络故障,则不会释放连接(即使网络后续恢复)它将导致锁一直等待。

回答

7

这个问题可以,我也想像

0

客户端宕机mysql不会自动释放锁吗

7

我也是遇到了这个问题,慢查询全是这个语句

4

不会,mysql感知不到客户端宕机,只有明确收到提交或回滚命令时,才会释放锁

5

我主要测的是网络故障会导致这个问题。

  1. 用客户端发送for update查询,但不提交事务
  2. 断开客户端与数据库的网络
  3. 恢复客户端与数据库的网络
  4. 再次发送for update查询,发现查询被锁

测试工具:DBeaver 22.2.4 mysql-connector-java版本:8.0.29

3

感觉是不是redis这种,有默认释放锁的过期时间比较好一点

0

@312292061 @szx1 测试结果:关闭客户端链接后,会释放锁. 使用Navicat、MYSQL8,在可视化界面中,建立两个链接测试。 第一步:建立第一个链接,执行语句: set autocommit=0; START TRANSACTION; SELECT * FROM xxl_job_lock WHERE lock_name = 'schedule_lock' FOR UPDATE; //注意:不要执行提交语句 第二步:建立第二个链接,执行语句 START TRANSACTION; UPDATE xxl_job_lock SET lock_name = '1' WHERE lock_name = 'schedule_lock' ; COMMIT; //此时,阻塞在update语句 第三步:关闭第一个链接,采用方式是直接点击页面的X。 第四步:查看第二个链接执行情况:获得锁,执行成功。 控制台日志如下,自动获得锁并操作完成:
UPDATE xxl_job_lock SET lock_name = '1' WHERE lock_name = 'schedule_lock'

Affected rows: 1 查询时间: 43.252s COMMIT OK 查询时间: 0.017s

1

改成乐观锁是否可行?