2011-06-12 66 views

回答

3

MVCC非阻塞读,在某种程度上,锁定的没有。 MVCC使得一个或多个读取器可以获得对数据的可重复读取访问,即使在作者正在更新相同行时也是如此。在这种情况下不需要锁定。

例如,如果我更改某行,InnoDB立即创建该行旧版本的副本。读取该数据的并发事务可以继续读取副本。只要您的交易持续,该旧版本就会保留在数据库中。

如果您启动一个新事务,您将看到该行的最近提交版本,并且旧版本最终可能被垃圾收集,从而回收一些空间。

锁定是当多个作家正试图更新相同的行。只有一个编写者可以一次更新一行,并且第一个更新行将其锁定,直到他们提交更改。其他作家必须等到第一个作者提交。但至少在行级锁定时,如果它们正在更新相同的行,则它们只会有争用。

一个很好的资源,学习更多关于InnoDB的并发和锁定为@AlexYakunin High Performance MySQL, 3rd ed.


回复评论:

任意数量的并发线程可以获取在同一行上的共享锁。但是排他锁需要不存在任何类型的锁 - 一次只有一个线程可以获得排他锁。

UPDATE总是要求独占锁,这是更常见的情况。共享锁用于InnoDB中一些更具有异国情调的案例:

  • 我更新了一个具有外键到父表的子行。我在子行上获得一个X锁,并在父行上获得一个S锁。基本上,没有人可以更新父行,而我正在更新取决于该父母的行。

  • 我明确地使用SELECT ... LOCK IN SHARE MODE来阻止某些行在我阅读时的更新。这通常不是必需的。

  • 我执行任何SELECT,而我的事务隔离级别为SERIALIZABLE(这不常见)。

  • 我发出一个导致重复键错误的INSERT,我的线程请求该行上的共享锁。

有关更多详细信息和示例,请参阅http://dev.mysql.com/doc/refman/5.6/en/innodb-locks-set.html

+0

那么InnoDB共享锁的目的是什么?这是文档的一个正确部分: “如果事务T1在行r上持有排它(X)锁定,则不能立即授予来自某个不同事务T2的r上任一类型锁定的请求,而是事务T2必须等待事务T1释放其对行r的锁定。“ - 这意味着作家阻止读者。 – 2013-07-11 19:47:36

+0

我提到的页面:http://dev.mysql.com/doc/refman/5.0/en/innodb-lock-modes.html – 2013-07-11 19:49:51

+0

感谢您的澄清 - 我现在看到了这一点。共享锁实际上是显式应用的,或者是在SERIALIZABLE上的,或者它们有必要为DML语句正确提供隔离来更新具有FK的行。所以作家几乎从不阻碍读者。 – 2013-07-11 20:10:34