我已经用MyISAM引擎解决了MySQL表锁的奇怪问题。
假设我有这种类型的代码:
LOCK TABLES t1 WRITE;
SELECT SQL_NO_CACHE val1 FROM t1 WHERE something; // val1 = old
// some conditions on val1 and logic
UPDATE t1 SET val1 = new WHERE something;
UNLOCK TABLES;
据我所知,这应该防止任何并发更新。但事实并非如此。有时它只是忽略锁,而在另一个线程将其更改为“新”之后,在val1中读取“旧”。我什至使用SQL_NO_CACHE来防止错误地检索旧数据。
那是为什么?我该如何确定防止更新竞赛?
谢谢。
MySQL 5.5.28,MyISAM,PHP 5.2,mysql_扩展(已过时,但在旧项目上)
编辑:
好的,它不应该在纯SQL中发生,因此有PHP代码:
<?php
$conn = mysql_connect(...);
...
mysql_query("LOCK TABLES t1, t2 WRITE"); //t2 also used
$result = mysql_fetch_array(mysql_query("SELECT last_user, ... FROM t1 WHERE id = XXX"));
if($result["last_user"] != $session_user) { //is last activity from another than current user?
DoStuffWithUser(...); //custom function which uses t2 table
mysql_query("UPDATE t1 SET last_user = ".$session_user." WHERE id = XXX");
}
mysql_query("UNLOCK TABLES");
...
?>
结果是,当前用户多次调用DoStuffWithUser()。
没有特殊的应用程序,驱动程序和框架。只是内置的PHP函数。
看来,这个问题主要是(我不能确定是否排他地)一个用户多次执行操作时-双击,网络故障等。
答案 0 :(得分:1)
好的,这是我今天的歌https://www.youtube.com/watch?v=48rz8udZBmQ
@Solarflare非常想把我推向正确的方向。
好的,某处有错误,让我们找到它。第一行,简单的锁查询,无需检查,非常明显... 哦,等等...
LOCK TABLES t1 **WRITE**, t2 WRITE
每个表都必须设置锁类型:)