MySQL锁表被忽略

MySQL锁表被忽略,mysql,myisam,Mysql,Myisam,我在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; 据我所知,这应该可以防止任何并发更新。但事实并非如此。有时

我在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;
据我所知,这应该可以防止任何并发更新。但事实并非如此。有时它只是忽略锁,在另一个线程将其更改为“new”后,在val1中读取“old”。我甚至使用SQL\u NO\u缓存来防止错误地检索旧数据

为什么呢?我如何才能确保防止更新竞赛

谢谢

MySQL 5.5.28、MyISAM、PHP5.2、MySQL_uuu扩展(过时,但在遗留项目上)

编辑:

好的,它不应该发生在纯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函数


看来,这个问题主要是(我不能确定是否是排他性的)当一个用户多次执行操作时——双击、一些网络故障等等。

好的,这是我今天的歌

许多泰克人对@Solarflare推卸我的责任表示不满

好的,哪里有错误,让我们找到它。第一行,简单的锁查询,无需检查,很明显。。。哦,等等

LOCK TABLES t1 **WRITE**, t2 WRITE

每个表都必须设置锁类型:)

并且在另一个线程将其更改为“new”后,val1中读取“old”
进行这些更新的应用程序是什么?预缓存驱动程序是缓存的目的吗?这应该是不可能的,虽然可能会发生错误,但这是一个非常古老的、经常使用和测试的功能,因此更可能是您的代码中出现了错误,或者是外部影响(例如,自动重新连接?连接池?)。为了检查发生了什么,我会尝试在锁之后、val1之后以及释放锁之前和之后登录到一个日志表(使用autoincrement),并检查是否有一些意外的顺序。为了清楚起见,我还添加了php代码…@Solarflare log table done and tested(由我编写,multiclick)。在日志表中,我可以看到,在第一次锁定之后,我又建立了两个连接,它们能够读取和更新锁定的表-所以日志顺序类似于lock1、lock2、select1、select2、update1、update2、dostuff1、lock3、dostuff2、unlock1、select3、unlock2、unlock3。所以第三个连接没有执行操作,但仍然与其他锁干涉…
Lock1,lock2
应该已经不可能了,会话2应该在那里等待,然后才能获得锁。您是否可以在日志中包含
连接\u id()
(以及val1的值),以排除您正在重新连接或重新使用相同的连接来进行不同的会话。另外,您可以检查您的表是否不是临时表吗?(从上下文来看,这似乎没有什么意义,只是为了确定一下)。我还假设您没有使用群集/负载平衡(复制)设置或类似的设置。