【问题标题】:Why doesn't LOCK TABLES [table] WRITE prevent table reads?为什么 LOCK TABLES [table] WRITE 不阻止表读取?
【发布时间】:2013-09-05 20:31:51
【问题描述】:

根据http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html,如果我锁定一个表以在 mysql 中写入,那么在它解锁之前没有其他人可以访问。我写了这个脚本,加载为 script.php 或 script.php?l=1 取决于你想做什么:

if ($_GET['l'])
{
    mysqli_query("LOCK TABLES mytable WRITE");
    sleep(10);
    mysqli_query("UNLOCK TABLES");
}
else
{
    $res=mysqli_query("SELECT * FROM mytable");
    // Print Result
}

如果我在一个浏览器窗口中加载 script.php?l=1 那么,当它处于睡眠状态时,我应该能够在另一个窗口中加载 script.php 并且它应该等到 script.php?l=1 完成,正确的?

问题是,script.php 会立即加载,即使 script.php?l=1 有一个写锁。如果我尝试在 script.php 中插入,它确实会等待,但为什么允许 SELECT?

注意:我不是在寻找关于是否使用 LOCK TABLES 的讨论。实际上我可能会进行交易,我现在正在调查,现在我只是想了解为什么上述方法不起作用。

【问题讨论】:

  • 您的 PHP 可以设置为使用共享 mysql 连接吗?
  • 我会检查,但如果是,为什么 INSERT 延迟而 SELECT 没有?
  • 我刚刚在mysql> 命令提示符下尝试过,锁定按您的预期工作。
  • 它看起来可能与查询缓存有关。我也在命令提示符下尝试过。第一次工作(SELECT 被延迟),第二次没有(SELECT 是即时的),但是一旦我在锁定会话中对表进行了更改,SELECT 又被延迟了。我猜这有点道理,但这不是它所说的应该做的。如果我写锁定一个表,它应该被锁定。当前的行为可能会破坏我的流程。
  • 事实上,将 SQL_NO_CACHE 添加到 SELECT 查询中就可以了!

标签: php mysql locking table-locking


【解决方案1】:

LOCK 的意义在于,当您在特定会话期间使用该表时,其他会话不会修改该表。

您能够执行SELECT 查询的原因是,即使您打开一个新窗口,它仍被视为同一MySQL 会话的一部分。

【讨论】:

  • 根据 MySQL 的 WRITE 锁阻止对表的所有访问。否则 READ 和 WRITE 锁有什么区别?至于同一个 MySQL 会话,我不相信这是真的,原因有两个。 1:我的 INSERT 被阻止,2:我可以在另一台计算机/IP 上执行而不是另一个浏览器窗口,但它仍然会发生
  • dev.mysql.com/doc/refman/5.0/en/lock-tables.html:“持有锁的会话可以读写表。”
  • 对于读锁:“持有锁的会话可以读表(但不能写)。”
  • 你为什么认为它们是同一个 MySQL 会话(如果是,那么 INSERT 怎么会延迟?)
【解决方案2】:

这是由于查询缓存而发生的。有一个不“影响”锁的可用缓存结果,因此返回结果。

这可以通过在选择中添加“SQL_NO_CACHE”关键字来避免:

SELECT SQL_NO_CACHE * FROM mytable

【讨论】:

  • 谢谢。你节省了我的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-23
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 2016-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多