【发布时间】:2022-11-19 08:18:45
【问题描述】:
我在 mysql 中创建了一个事件来从不同的表中收集一些数据,这些数据将每 5 分钟重复一次。假设在某些情况下事件可能需要 5 分钟以上才能完成(可能数据库运行缓慢或需要重新启动)。许多其他事件同时被触发,所以为了处理这个我读到的锁可以按照 mysql 手册使用。
如果重复事件没有在其调度间隔内终止,则结果可能是该事件的多个实例同时执行。如果这是不可取的,您应该建立一种机制来防止同时发生实例。例如,您可以使用 GET_LOCK() 函数,或者行或表锁定。
但是简单地放置一个锁并不能解决我的问题,因为事件仍在队列中执行并且无法预测的数据被转储,我想要的只是如果锁在那里不做任何事情并等待。
在我读到的锁中,如果一个命名锁被分配给一个会话,则可以使用另一个同名锁,直到更早的锁被释放。
if GET_LOCK('ev_test',-1) is not TRUE then
SIGNAL SQLSTATE '45000' set MESSAGE_TEXT = 'failed to obtain lock; not continuing; ';
end if;
some_event_body
RELEASE_LOCK('ev_test');
所以我在 mysql 事件主体中使用了这个语句。然后在事件完成后手动释放此锁
我的问题是当事件 some_event_body 触发一些其他异常时会发生什么,例如是否有选择查询并且事件主体使用的某些列被删除?
锁会自动释放吗?锁会一直存在吗?
mysql 手册说锁会一直保留到会话终止。但我不知道事件是否存在于会话中或每个事件都创建一个新会话?
在外部没有上面的代码只是使用GET_LOCK 我遇到了这种情况。
+------+-----------------+-----------+-------------+---------+------+-----------------------------+-----------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+------+-----------------+-----------+-------------+---------+------+-----------------------------+-----------------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 30 | Waiting for next activation | NULL |
| 8 | root | localhost | logi_test_2 | Query | 0 | init | show processlist |
| 1330 | root | localhost | logi_test_2 | Connect | 2 | User sleep | SELECT SLEEP(30) |
| 1331 | root | localhost | logi_test_2 | Connect | 4974 | User lock | SELECT GET_LOCK('test', -1) |
| 1332 | root | localhost | logi_test_2 | Connect | 4969 | User lock | SELECT GET_LOCK('test', -1) |
| 1333 | root | localhost | logi_test_2 | Connect | 4964 | User lock | SELECT GET_LOCK('test', -1) |
| 1334 | root | localhost | logi_test_2 | Connect | 4959 | User lock | SELECT GET_LOCK('test', -1) |
| 1335 | root | localhost | logi_test_2 | Connect | 4953 | User lock | SELECT GET_LOCK('test', -1) |
| 1338 | root | localhost | logi_test_2 | Connect | 4949 | User lock | SELECT GET_LOCK('test', -1) |
| 1339 | root | localhost | logi_test_2 | Connect | 4944 | User lock | SELECT GET_LOCK('test', -1) |
| 1340 | root | localhost | logi_test_2 | Connect | 4939 | User lock | SELECT GET_LOCK('test', -1) |
| 1341 | root | localhost | logi_test_2 | Connect | 4934 | User lock | SELECT GET_LOCK('test', -1) |
| 1342 | root | localhost | logi_test_2 | Connect | 4929 | User lock | SELECT GET_LOCK('test', -1) |
| 1343 | root | localhost | logi_test_2 | Connect | 4924 | User lock | SELECT GET_LOCK('test', -1) |
| 1344 | root | localhost | logi_test_2 | Connect | 4919 | User lock | SELECT GET_LOCK('test', -1) |
| 1345 | root | localhost | logi_test_2 | Connect | 4914 | User lock | SELECT GET_LOCK('test', -1) |
| 1346 | root | localhost | logi_test_2 | Connect | 4909 | User lock | SELECT GET_LOCK('test', -1) |
| 1347 | root | localhost | logi_test_2 | Connect | 4904 | User lock | SELECT GET_LOCK('test', -1) |
| 1348 | root | localhost | logi_test_2 | Connect | 4899 | User lock | SELECT GET_LOCK('test', -1) |
| 1349 | root | localhost | logi_test_2 | Connect | 4894 | User lock | SELECT GET_LOCK('test', -1) |
| 1352 | root | localhost | logi_test_2 | Connect | 4889 | User lock | SELECT GET_LOCK('test', -1) |
| 1353 | root | localhost | logi_test_2 | Connect | 4884 | User lock | SELECT GET_LOCK('test', -1) |
为什么无论会话如何,只允许一个命名锁时,锁会在这里重复?
我尝试在 stackoverflow 上查找结果并阅读 mysql 手册,但找不到任何内容。
【问题讨论】:
-
用户锁状态是指线程将要请求或正在等待通过get_lock()授予锁,而不是已经被授予锁! dev.mysql.com/doc/refman/8.0/en/general-thread-states.html