使用PHP锁定MYSQL表

时间:2012-02-08 06:56:00

标签: php mysql locking

我有mysql表fg_stock。大多数情况下,此表中发生了并发访问。我使用了这段代码,但它不起作用:

<?php
    mysql_query("LOCK TABLES fg_stock READ");

    $select=mysql_query("SELECT stock FROM fg_stock WHERE Item='$item'");

    while($res=mysql_fetch_array($select))
    {
        $stock=$res['stock'];
        $close_stock=$stock+$qty_in;
        $update=mysql_query("UPDATE  fg_stock SET stock='$close_stock' WHERE Item='$item' LIMIT 1");
    }

    mysql_query("UNLOCK TABLES");    
?>

这可以吗?

3 个答案:

答案 0 :(得分:4)

“大多数时候并发访问都发生在这个表中”

那么,当你明确尝试访问表中的特定行(WHERE Item ='$ item')时,为什么还要锁定ENTIRE表?您可能正在为相关表运行MyISAM存储引擎,您应该考虑使用InnoDB引擎,因为其中一个优点是它支持行级锁定,因此您无需锁定整个表格。

答案 1 :(得分:4)

为什么你还需要锁定你的桌子?????

   mysql_query("UPDATE fg_stock SET stock=stock+$qty_in WHERE Item='$item'");

就是这样!无需锁定表,也不需要使用一组查询进行不必要的循环。例如,尝试通过在$ qty_in上使用intval php函数来避免SQL注入(如果它是一个整数)。

而且,可能time concurrent access只是由于数据库的非优化工作而发生的,查询次数过多。

ps:而且,你的例子没有任何意义,因为mysql可以在循环中一直更新相同的记录。您没有告诉MySQL您要更新哪个记录。只告诉用Item ='$ item'更新一条记录。在下一次迭代中,SAME记录可以再次更新,因为MySQL不知道已更新的记录与尚未触及的记录之间的差异。

答案 2 :(得分:1)

http://dev.mysql.com/doc/refman/5.0/en/internal-locking.html

mysql> LOCK TABLES real_table WRITE, temp_table WRITE;
mysql> INSERT INTO real_table SELECT * FROM temp_table;
mysql> DELETE FROM temp_table;
mysql> UNLOCK TABLES;

所以你的语法是正确的。

另外还有一个问题:

  

故障排除:您可以通过尝试工作来测试表锁定是否成功   与另一个未锁定的表。如果你获得了锁,   试图写入一个未包含在lock语句中的表   应该生成错误。

     

您可能需要考虑替代解决方案。而不是锁定,   执行包含已更改元素的更新作为其中一部分   where子句。如果您要更改的数据自您更改后发生了变化   读取它,更新将“失败”并返回零行修改。这个   消除了表锁,以及可能出现的所有混乱恐怖   有了它,包括死锁。   PHP, mysqli, and table locks?