【发布时间】:2021-10-15 13:20:11
【问题描述】:
我使用Postgres advisory locks 和MySQL GET_LOCK() 向Sqitch 添加了咨询锁定。此功能可防止一次将多个 Sqitch 实例部署到数据库。这很好用,但我也想添加锁定超时,这样就不会发现 CI/CD 进程因为出现问题而挂起数小时或数天。
MySQL 的GET_LOCK() 支持超时参数,但 Postgres 咨询锁不支持。因为我认为其他数据库引擎也可能没有超时,所以我认为最好在 Perl 中实现超时。按照DBI手册,我用Sys::SigAction来设置和处理the timeout:
# Try waiting for the lock.
require App::Sqitch::SigAction;
return $self->_locked(1) unless App::Sqitch::SigAction::timeout_call($wait, sub {
$self->wait_lock
});
我还添加了tests 以确认它适用于 MySQL 和 Postgres。到目前为止一切顺利。
唉,Sys::SigAction does not work on Windows。我采取了刺和testing it on Windows,但由于Windows Perl 不是用d_sigaction 编译的,Sys::SigAction also requires,我没有走多远。我尝试实现Perl-standard alarm/$SIG{ALRM} pattern,但在等待 Postgres 锁时无法发送信号。
这导致我来到这里并提出我的问题:在 Perl 中超时某些执行的最佳跨平台模式是什么?理想情况下,它有一个直接的界面,可以在 *nix 和 Windows 上运行,并且可以有效地处理数据库查询的中断。
【问题讨论】:
-
Widnows 没有信号。 (Ctrl-C 和 Ctrl-Break 确实有类似的东西,但仅此而已。)所以所问的问题没有答案。没有通用的跨平台通用超时机制。有针对特定领域的解决方案。例如,如果你想做 IO,你可以使用异步 IO 库之一。如果要杀死整个进程,可以在 unix 中使用信号,在 Windows 中使用休眠线程。等等 MySQL 库可能是根据 unix 系统调用(
open、write等并希望您使用信号)而不是考虑 Windows 编写的。 -
(这不是一个“unix 比 Windows 更好的东西,这是关于 C 库(以及 Perl 代码)几乎总是被编写为 unix 程序而不是 Windows 程序,即使是那些打算在其上运行的程序Windows。操作系统有根本不同的处理方法,C 标准库非常以 unix 为中心。)
-
异步 io 库是什么样的?它唯一需要超时的是调用like
$dbh->do('SELECT pg_advisory_lock(75474063)');。但是,由于它获取了数据库会话锁,因此它不能是单独的进程或线程。 -
这里没用,因为你不做 IO。虽然可能有异步数据库库?
-
在 postgres 中有
pg_try_advisory_lock ( key )返回 false 而不是阻塞。
标签: postgresql perl timeout signals alarm