2012-04-16 37 views
1

函数有一个结构:MySQL的MyISAM的竞争条件

$q = 'LOCK TABLES table1 WRITE;'; 
mysql_query($q);  
$q = 'select id from table1 where is_delete = 0 limit 1;'; 
$res = mysql_fetch_assoc(mysql_query($q)); 
if($res) { 
$q = 'UPDATE table1 SET is_delete = 1 WHERE id = '".$res['id']."''; 
mysql_query($q); 
} 
$q = 'UNLOCK TABLES;'; 
mysql_query($q); 

我锁定所有的表,但查询的并行运行。 这个怎么解决?

+1

哪里锁定表的代码? – 2012-04-16 18:56:59

+0

对不起,问题更新 – Merlin 2012-04-16 19:02:53

+0

您的用户是否拥有LOCK TABLES特权? – angrychimp 2012-04-16 19:30:55

回答

0

检查您是否在LOCK TABLES查询得到任何MySQL的错误:

$q = 'LOCK TABLES table1 WRITE'; 
$r = mysql_query($q) or die(mysql_error());  

但是,如果这是所有你在干什么,你也可以简单地写:

UPDATE `table1 SET `is_delete` = 1 WHERE `is_delete` = 0 LIMIT 1 

,它根本不需要任何锁。当然,只有当第一个查询中的数据没有以任何方式处理时,才会起作用,并且只要其中的is_delete设置为0即可。也就是你发布的代码也是这样的,但是对于我而言并不是很明显你想要使用这个代码:)

更一般地说,如果你使用MySQL表的默认InnoDB存储引擎,可能要考虑SELECT ... FOR UPDATE: http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

你可以写:

$q = 'select id from table1 where is_delete = 0 limit 1 for update'; 
$res = mysql_fetch_assoc(mysql_query($q)); 

if($res) { 
    $q = 'UPDATE table1 SET is_delete = 1 WHERE id = '".$res['id']."''; 
    mysql_query($q); 
} 

另请参阅:http://www.mysqlperformanceblog.com/2006/08/06/select-lock-in-share-mode-and-for-update/

+0

这里要复杂得多 – Merlin 2012-04-16 19:37:32

+0

在这种情况下,当然,您将不得不向我们展示特定的代码。 – Daan 2012-04-16 19:38:31

+0

我的存储引擎是myisam,锁表应该适用于这种情况。但没有帮助( – Merlin 2012-04-16 19:40:19