4

我已经阅读了 mysql 文档,也许我只是不明白这一切。我正在寻找的是读取其他会话行锁定。当该行被锁定时,我希望其他会话等到锁定被释放。我不希望其他会话从快照中读取!他们必须等到发布!

我想得到的与以下示例完全相同,但对于单行而不是整个表锁:

START TRANSACTION
LOCK TABLES table1 WRITE
SELECT * FROM table1 WHERE id = 40912
UPDATE table1 SET column1 = 'value1' WHERE id = 40912
UNLOCK TABLES
COMMIT

先感谢您!

4

3 回答 3

3

Elena Sharovar 的回答是一种方法,但可能没有完全解释需要什么。每个要执行 SELECT 的进程都需要使用具有相同字符串的 GET_LOCK。如果他们这样做了,MySQL 将自动等待(最多指定的秒数)返回结果,直到另一个线程释放锁。

这是发生的事情,时间从上到下进行:

          THREAD 1                                 THREAD 2
DO GET_LOCK("table1.40912", 30)
SELECT * FROM table1 WHERE id=40912     DO GET_LOCK("table1.40912", 30)
[UPDATE query]                          [automatically waits]
[UPDATE query]                          [automatically waits]
DO RELEASE_LOCK("table1.40912")         [lock finally obtained, query terminates]
                                        SELECT * FROM table1 WHERE id=40912
于 2012-12-06T18:06:25.580 回答
1

我对这个有趣的问题(如何强制 MySQL 不读取快照,即使快照是一致的)的最佳想法是使用“FOR UPDATE”读取所有内容,如“SELECT FOR UPDATE #select-clause#” .

但是,这些选择使用非常窄的索引来查找记录非常重要,这意味着它们会锁定所读取的内容。通过全表扫描甚至 USING WHERE(在 EXPLAIN 语句中)运行 SELECT 会很糟糕,表大区域的长时间锁定可能会导致潜在的较长反应时间。

我建议您在数据库抽象层中对其进行测试。

您可以在隔离文档中阅读有关此机制的所有信息。

于 2012-10-24T08:24:01.207 回答
1

我还没有尝试这样做,但是可以使用 MySQL 函数 GET_LOCK(str,timeout) 和 RELEASE_LOCK(str)。这里的“str”是标识你的锁的任何字符串。

mysql_query('DO GET_LOCK("table1.40912", 60)')
mysql_query('SELECT * FROM table1 WHERE id = 40912')
mysql_query('UPDATE table1 SET column1 = 'value1' WHERE id = 40912')
mysql_query('DO RELEASE_LOCK("table1.40912")') 
于 2012-10-24T08:11:12.903 回答