MySQL 忽略锁定表

MySQL lock tables ignored

我遇到了 MySQL table MyISAM 引擎锁的奇怪问题。

假设我有这种类型的代码:

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;

据我所知,这应该会阻止任何并发更新。但事实并非如此。有时它只是忽略锁,并且 "old" 在另一个线程将其更改为 "new" 后在 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 函数。

看起来,这个问题主要是(我不能确定是否完全)当一个用户多次执行操作时 - 双击,一些网络故障,等等。

好的,这是我今天的歌https://www.youtube.com/watch?v=48rz8udZBmQ

非常感谢@Solarflare 将我推向正确的方向。

OK,哪里有错误,我们找找看。第一行,简单的锁查询,没有什么可检查的,很明显...哦,等等...

LOCK TABLES t1 **WRITE**, t2 WRITE

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