在共享模式锁定和更新锁定之间的mysql中间地带?

时间:2011-11-01 15:53:49

标签: mysql locking

我试图找到锁定共享模式和锁定更新之间的中间地带。

只要尚未更新正在修改的行,就可以通过两个不同的事务获取共享模式中的锁。这在以下情况中很糟糕:

  • t1开始
  • t1读取X上的锁定
  • t2开始
  • t2读取X上的锁定
  • t2检查X.foo == 0
  • t1更新X.foo = 1
  • t1 end
  • t2自X.foo!= 0
  • 以来继续使用错误的逻辑

我可以使用的替代方法是锁定更新,但这对我的应用程序来说限制太多,因为我不关心我的用户是否读取了10秒的值。所以我永远不想使用锁来进行更新。

问题:我可以使用哪个锁:

  1. 是独家的
  2. 允许读取行而不获取锁定
  3. 示例:

    • t1 my_lock row X
    • t2 my_lock row X =>不允许
    • t3选择行X =>允许,返回最新提交的数据,如锁定共享模式

    编辑: 我使用NDB集群作为我的存储引擎。 服务器版本:5.1.56-ndb-7.1.15a-cluster-gpl-log MySQL Cluster Server(GPL)

2 个答案:

答案 0 :(得分:1)

如果不了解您正在做的事情,很难确切地知道推荐。但是这里有几个指针可能会帮助您找到答案。

首先,正常的SELECT ... FROM ...不会对任何行进行任何锁定,并提供一致的读取 - - 也就是说,它根据SELECT语句开始时数据库中的内容提供结果集。

这一点很重要,因为锁定唯一的问题是:

  • 多个语句同时尝试更新相同的数据,或
  • 由于某种原因,您希望在长SELECT语句中间完成更新,以反映在结果中。 (我不确定为什么这会有效。)

其次,为其他类型的语句(例如SELECT ... FROM ... LOCK IN SHARE MODE)锁定的行将取决于用于选择要更新的行的INDEXES。基本上,扫描所有行以查找行的行将被锁定。

这很重要,因为您可以通过制作索引来显着减少锁定的行数,这些索引允许您的UPDATE语句选择要直接更新的行。例如,如果您可以在表上创建UNIQUE索引,然后在运行更新时让UPDATE语句命中INDEX,则只会阻止该行。

所以我遇到锁定问题的最好的运气是获取这两条信息 - 1)普通的SELECTS没有做任何锁定,2)我可以定义好的索引来最小化那些行实际上确实被锁定 - 然后设计导致没有锁定冲突的sql。

这是一个指向页面的链接,该页面始终帮助我解决锁定时遇到的任何问题。它具体描述了生成锁的每种语句以及它们是什么类型的锁:Locks Set by Different SQL Statements in InnoDB

答案 1 :(得分:0)

您使用的是MyISAM还是InnoDB?我建议使用InnoDB并使用MVCC的事务隔离级别来实现所需的并发级别。

由于MVCC,InnoDB中的正常选择不会锁定。所以你永远不会阻止读者。