2

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

在此处输入图像描述

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

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

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

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

SELECT * FROM manufacturer
WHERE mcode = 'ACL';

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

4

2 回答 2

2

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

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

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

alter table TABLE_NAME engine=innodb;
于 2013-11-12T10:22:07.243 回答
2

在此页面上找到以下信息

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

交易特征范围

您可以为当前会话或下一个事务全局设置事务特征:

使用 GLOBAL 关键字,该语句将全局应用于所有后续会话。现有会话不受影响。

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

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

有没有考虑到这一点?

可重复阅读

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

在这篇文章中,它的描述非常好。

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

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

这些表是否被很好地索引?你能运行 aSHOW ENGINE innodb STATUS来确认锁被持有吗?

于 2013-11-12T10:48:11.443 回答