【问题标题】:Mysql Events Execution cycleMysql事件执行周期
【发布时间】: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 手册,但找不到任何内容。

【问题讨论】:

标签: mysql events


【解决方案1】:

这是 cron、EVENT 等的经典问题。

我喜欢推荐这个解决方案:

与其反复启动一个可能很慢的进程,不如让一个进程循环。它会完成任务,然后重复。

点缀

  • 在迭代之间添加“睡眠”。
  • 添加计算好的睡眠以暂停“剩余 5 分钟”。
  • 做点什么观察系统忙,休眠时间长。
  • 添加一个 cron/EVENT 作为“keepalive”。如果它死了,这将重新启动循环任务。这也可能是在任何类型的崩溃或正常中断后最初启动的方式。

我还会查看查询——5 分钟对于 SQL 任务来说太长了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多