我有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");
?>
这可以吗?
答案 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?