2012-10-24 79 views
3

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

我想得到的是完全相同的,如以下示例但不是整个表锁单列

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

预先感谢您!

回答

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")') 
+0

嗨!谢谢你的回答,但它似乎不工作......另一个会话(select)仍然返回快照中的值! –

+0

谢谢埃琳娜,它的工作原理! –

1

我对这个有趣的问题最好的办法(如何强制MySQL不读快照,即使快照是一致的),将读取使用“FOR UPDATE”的一切,如“选择UPDATE#select-clause#“。

但是,这些选择使用非常狭窄的索引找到记录是非常重要的,这意味着它们会锁定他们阅读的内容。如果通过全表扫描或甚至USING WHERE(在EXPLAIN语句中)运行一个SELECT会很糟糕,那么表中大部分区域的锁定时间过长可能会导致可能很长的响应时间。

我建议你在数据库抽象层进行测试。

您可以在isolation documentation中阅读关于此机制的所有信息。

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