【问题标题】:How is MySQL allowing acquiring a shared lock when another transaction has an exclusive lock?当另一个事务具有排他锁时,MySQL 如何允许获取共享锁?
【发布时间】:2020-08-11 17:14:52
【问题描述】:

我正在尝试了解事务是如何工作的,但我遇到了一个对我来说没有多大意义的场景。我希望有人能帮助我理解它。

我有两笔交易

事务 1

 BEGIN; update data set val = val + 1 where id = 1

事务 2

BEGIN; select * from data

我有两个终端打开,我开始第一个事务并运行更新查询。据说这会为 id 为 1 的元组上的事务 1 提供排他锁。

之后,我在提交第一个事务之前在另一个终端中运行第二个查询。我原以为它会停止,因为第一个事务具有排他锁,这将阻止该事务获取 id 为 1 的元组上的读锁。

然而,mysql 运行选择查询并返回“未脏”数据。

谁能给我解释一下mysql这种行为背后的原因?

【问题讨论】:

    标签: mysql concurrency transactions rdbms


    【解决方案1】:

    默认情况下,SELECT 不需要共享行锁。通过使用multi-version concurrency control (MVCC) architecture,它可以在不锁定的情况下读取该行的最新提交版本。

    你可以写一个SELECT query that explicitly requests a lock,但是没有这些锁定子句,SELECT 不需要行锁。

    【讨论】:

    【解决方案2】:

    为了全面了解事务的工作原理,我认为了解共享锁的获取方式不同,具体取决于隔离级别。

    无论隔离级别如何,事务结束时都会释放独占锁。

    隔离级别之间的差异是指获取/释放共享(读取)锁的方式。

    在未提交的读取隔离级别下,不会获取共享锁。在此隔离级别下,可能会发生称为“脏读”的并发问题。

    在 Read Committed 隔离级别下,为相关记录获取共享锁。当前指令结束时释放共享锁。此隔离级别可防止“脏读”,但由于其他并发事务可以更新记录,因此可能会发生“不可重复读”或“幻读”。

    在可重复读取隔离级别下,在事务期间获取共享锁。 “脏读”和“不可重复读”被阻止,但“幻读”仍然可能发生。

    在可序列化隔离级别下,在事务期间获取范围共享锁。上述并发问题均未发生,但性能大幅下降,并且存在发生死锁的风险。

    【讨论】:

      猜你喜欢
      • 2018-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多