【问题标题】:How can a row be read when the table is read/write locked?当表被读/写锁定时如何读取一行?
【发布时间】:2013-11-24 10:07:30
【问题描述】:

我在 MySQL 5.6.13 上运行这些查询。 我使用可重复的读取隔离级别。该表如下所示:

在会话 A 终端中我发布了以下声明

UPDATE manufacurer
SET lead_time = 2
WHERE mname = 'Hayleys';

在 Session B 终端中,我尝试将 ACL Cables 的值 lead_time 更新为 2。但由于 Session A 的前一个 UPDATE 命令尚未提交(并且 Session A 在制造商表上具有排他锁),所以此更新等待。这个我能理解。

但是当我尝试在会话 B 上执行如下的 SELECT 语句时,

SELECT * FROM manufacturer
WHERE mcode = 'ACL';

它正确地查询制造商表并给出行。这怎么可能发生?因为会话 A 仍然持有制造商表上的排他锁,并且据我所知,当一个表上持有排他锁时,在提交前一个事务之前,没有其他事务可以读取或写入它。 p>

【问题讨论】:

  • 在您的问题标题中,您区分了读取和写入锁,而在问题中您谈到了防止读取写入的锁。请更新您的问题/标题以保持一致性。
  • 由于您没有修改 Session B 中的行。返回数据。
  • @KayNelson Umm..如果我理解正确,即使我没有修改行,我仍在尝试从中读取,并且独占锁不允许其他会话读取或写入 直到前一个事务被提交。
  • 你使用innodb作为引擎吗?
  • @Thili InnoDB 提供行级锁定。您的UPDATE 仅触及WHERE mname = 'Hayleys' 行。您的 SELECT 用于不同行中的数据 WHERE mcode = 'ACL'。因此,该行可以安全读取 - 尽管这也取决于您的表上有哪些索引 - 比更新的行更多的行可能会被锁定。

标签: mysql innodb isolation-level readwritelock


【解决方案1】:

mysql中的锁有几种:行级锁和表级锁。

你需要的是行级锁,它允许读取更新之外的行。

并且要实现行级锁,您必须将表的引擎类型定义为“InnoDB”:

alter table TABLE_NAME engine=innodb;

【讨论】:

  • 我认为它称为 ROW 级锁定。
【解决方案2】:

在此页面上找到以下信息

http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_repeatable-read

交易范围特征

您可以全局设置交易特征,对于当前 会话,或用于下一个事务:

使用 GLOBAL 关键字,该语句全局适用于所有 随后的会议。现有会话不受影响。

使用 SESSION 关键字,该语句适用于所有后续 当前会话中执行的事务。

没有任何 SESSION 或 GLOBAL 关键字,该语句适用于 在当前会话中执行的下一个(未开始的)事务。

是否考虑到这一点?

可重复阅读

这是 InnoDB 的默认隔离级别。对于一致的读取, 与 READ COMMITTED 隔离有一个重要区别 level:同一个事务中的所有一致性读 由第一次读取建立的快照。这个约定意味着如果 您在同一个文件中发出几个普通(非锁定)SELECT 语句 事务,这些 SELECT 语句也是一致的 彼此。

在这篇文章中它描述得很好。

http://www.mysqlperformanceblog.com/2012/08/28/differences-between-read-committed-and-repeatable-read-transaction-isolation-levels/

重要的是要记住 InnoDB 实际上会锁定索引条目, 不是行。在执行语句期间,InnoDB 必须锁定每个 它遍历的索引中的条目以查找它正在修改的行。 它必须这样做以防止死锁并保持隔离级别。

这些表的索引是否正确?您可以运行SHOW ENGINE innodb STATUS 来确认锁已被持有吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    相关资源
    最近更新 更多