2013-01-21 54 views
1

我有一个php脚本,将被多次请求“同时”我也有一个表中的字段,我们称它为persons作为激活/非激活标志。我希望脚本的第一个实例运行时将该字段设置为非活动状态,以便其他实例在检查该字段时会死掉。有人可以为此提供解决方案吗?我怎样才能确保这个脚本只运行一次?锁定表如何工作?

PHP, PDO, MySQL

非常感谢你提前。

+0

您正在使用什么存储引擎? – eggyal

+0

@eggyal:存储引擎是InnoDB –

回答

3

你的脚本应该获取使用锁定读事务中当前标志,如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 
} 
+0

我正在为此做更多的工作,但比@Marc B的解决方案好吗? –

+0

嗯,这不是关于可扩展性,这将保持原样,但更清洁更好,你给了示例代码,所以...我要这样做。非常感谢你。 –

2

您可以使用MySQL的自己“命名为”锁定功能,而不必锁定表:http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock

eg用0超时尝试get_lock('got here first', 0)。如果你得到一个锁,你首先进入门,随后的任何请求都不会获得锁并立即中止。

但是,要小心这个东西。如果您没有自行清理并且获得锁定的客户端异常终止,则锁定将不会被释放,并且您的“需要锁定此系统”在水中死亡,直到您手动清除锁定为止。

+1

这里的最后一位不正确。删除MySQL连接会自动删除其保存的所有锁。 – duskwuff

+1

是真实的,但有些人确实使用持续连接。 –