MySQL 锁机制存在的价值是什么?

数据库 MySQL
锁的存在就是为了解决并发访问下数据的不一致问题。而数据库之所以要提供并发访问,是为了提高数据库的运行效率。

我们都知道 MySQL 中有各种各样的锁,例如:表锁、间隙锁、意向锁、行锁等等。但你是否想过:为啥 MySQL 要有锁机制的存在,它的存在是为了解决什么问题?今天我们就来聊聊这个问题。

没有锁的串行世界

我们先假设这样一个场景:王五现在账户里没有钱,于是向张三、李四各借 100 元,张三、李四很爽快地答应了。如果数据库这时候是串行的,没有并发执行的线程,那么其转账示意图如下所示。

王五借款串行执行 - 示意图

从上图可以看到:

  • 时间点 1 - 2 的时候,数据库处理了张三的转账请求,读取到王五的账户余额为 0,并将其余额加 100,此时王五账户余额为 100。
  • 时间点 3 - 4 的时候,数据库处理了李四的转账请求,读取到王五的账户余额为 100,并将其余额加 100,此时王五账户余额为 200。
  • 最后,在时间点 5 的时候,王五账户余额为 200 元。

可以看到最终王五的账户余额是 200 元,转账是没问题的。这种数据库访问方式虽然能保证数据一致性,但是每次只能执行一个请求,并发访问性能太差。

没有锁的并行世界

为了提高数据库的并发访问性能,MySQL 其实是支持多线程并发执行的。我们上面的例子,如果使用多线程并发处理,其可能存在的一种情况如下图所示。

这种情况的处理流程可能是这样的:

  • 在时间点 1 的时候,线程 A 读取到王五的账户余额为 0。
  • 在时间点 2 的时候,线程 B 读取到王五的账户余额为 0。
  • 在时间点 3 的时候,线程 A 将王五账户余额加 100,此时王五账户余额为 100。
  • 在时间点 4 的时候,线程 B 将王五账户余额加 100,此时王五账户余额为 100。
  • 在时间点 5/6 的时候,线程 A、B 都将王五的余额回写回去,王五账户余额为 100。

正常来说,王五最终的账户余额应该是 200 元,但实际上王五账户余额却只有 100 元。通过分析上面的转账示意图,我们会发现问题的关键点在于时间 4。

在这个时间点时,王五的账户余额应该是 100 元了,但是数据库线程 B 还是以为王五的账户余额是 0 元,所以导致了最后的数据不一致。那么如何解决数据不一致的问题呢?答案就是:锁机制。

有锁的并行世界

实际上,对于上述的转账例子,在 InnoDB 中的处理流程如下图所示。

  • 在时间点 2 的时候,线程 A 读取到王五的账户余额为 0。
  • 在时间点 3 的时候,线程 B 读取到王五的账户余额为 0。
  • 在时间点 4 的时候,线程 A 将王五账户余额加 100,并获取到锁,此时王五账户余额为 100。
  • 在时间点 5 的时候,线程 B 准备将王五账户余额加 100,但此时发现王五账户被锁了,于是阻塞等待。
  • 在时间点 6 的时候,线程 A 提交事务。
  • 在时间点 7 的时候,线程 B 重新读取王五最新的余额为 100 元,并加 100 元,最终在时间点 8 提交事务。

在时间点 4 的时候,数据库线程 A 对王五账号余额加锁,告诉其他线程:我正在更新这条数据,你们其他人不要动。 在时间点 5 的时候,当数据库线程 B 准备将对王五账号余额做加 100 操作时,其发现已经有数据库线程 A 在操作了,所以其将线程阻塞了。

等到数据库线程 A 提交事务,释放锁之后,数据库线程 B 获取到对应的锁。这时候数据库线程 B 发现王五账号的余额是 100 了,所以就在 100 余额的基础上做更新,之后提交事务,最终王五账号的余额就是 200 元。

提示:该例子只是为了粗略说明 InnoDB 是如何通过锁解决数据一致性问题的,在一些细节上大家不必对于纠结。例如这个例子在事务隔离级别为 READ COMMIT 的时候适用,但是在 REPEATABLE READ 隔离级别时存在问题。

看到这里,相信大家已经明白:锁的存在就是为了解决并发访问下数据的不一致问题。而数据库之所以要提供并发访问,是为了提高数据库的运行效率。

责任编辑:武晓燕 来源: 陈树义
相关推荐

2022-01-17 16:02:32

区块链私有链数据库

2024-05-13 12:44:00

InnodbMySQL行级锁

2020-04-24 15:44:50

MySQL数据库锁机制

2021-10-11 08:58:34

Goroutine操作系统

2019-08-29 15:56:05

商业价值物联网IT

2022-08-02 11:29:17

数据分析场景RFM

2010-11-22 14:18:32

MySQL锁机制

2020-11-04 13:01:38

FastThreadLocalJDK

2022-08-08 11:07:57

5G边缘移动

2022-09-09 16:18:57

物联网工业物联网云平台

2023-11-09 09:26:22

MySQL存储引擎

2024-03-04 10:00:35

数据库处理机制

2023-10-13 13:30:00

MySQL锁机制

2010-06-07 13:30:15

2020-08-03 14:53:18

区块链标准化信任互联网

2020-11-12 08:32:11

物联网价值链IOT

2024-06-27 08:55:41

2010-09-08 09:40:19

SIP协议是什么

2021-02-10 16:53:56

区块链加密货币数字货币

2021-07-17 21:49:15

区块链加密货币账本
点赞
收藏

51CTO技术栈公众号