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 都必须设置锁类型:)
我遇到了 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 都必须设置锁类型:)