我有一个php
脚本,将被多次请求“同时”我也有一个表中的字段,我们称它为persons
作为激活/非激活标志。我希望脚本的第一个实例运行时将该字段设置为非活动状态,以便其他实例在检查该字段时会死掉。有人可以为此提供解决方案吗?我怎样才能确保这个脚本只运行一次?锁定表如何工作?
PHP, PDO, MySQL
非常感谢你提前。
我有一个php
脚本,将被多次请求“同时”我也有一个表中的字段,我们称它为persons
作为激活/非激活标志。我希望脚本的第一个实例运行时将该字段设置为非活动状态,以便其他实例在检查该字段时会死掉。有人可以为此提供解决方案吗?我怎样才能确保这个脚本只运行一次?锁定表如何工作?
PHP, PDO, MySQL
非常感谢你提前。
你的脚本应该获取使用锁定读事务中当前标志,如SELECT ... FOR UPDATE
:
$dbh = new PDO("mysql:dbname=$dbname", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
$dbh->beginTransaction();
// using SELECT ... FOR UPDATE, MySQL will hold all other connections
// at this point until the lock is released
$qry = $dbh->query('SELECT persons FROM my_table WHERE ... FOR UPDATE');
if ($qry->fetchColumn() == 'active') {
$dbh->query('UPDATE my_table SET persons = "inactive" WHERE ...');
$dbh->commit(); // releases lock so others can see they are inactive
// we are the only active connection
} else {
$dbh->rollBack();
// we are inactive
}
我正在为此做更多的工作,但比@Marc B的解决方案好吗? –
嗯,这不是关于可扩展性,这将保持原样,但更清洁更好,你给了示例代码,所以...我要这样做。非常感谢你。 –
您可以使用MySQL的自己“命名为”锁定功能,而不必锁定表:http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock
eg用0超时尝试get_lock('got here first', 0)
。如果你得到一个锁,你首先进入门,随后的任何请求都不会获得锁并立即中止。
但是,要小心这个东西。如果您没有自行清理并且获得锁定的客户端异常终止,则锁定将不会被释放,并且您的“需要锁定此系统”在水中死亡,直到您手动清除锁定为止。
这里的最后一位不正确。删除MySQL连接会自动删除其保存的所有锁。 – duskwuff
是真实的,但有些人确实使用持续连接。 –
您正在使用什么存储引擎? – eggyal
@eggyal:存储引擎是InnoDB –