社区编辑申请
注册/登录
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-04-01 10:08:21

SQL 优化MySQL数据库

2022-05-07 10:20:17

truncatedeleteMySQL

2022-04-19 11:23:26

release3.1子系统鸿蒙

2022-05-16 10:49:28

网络协议数据

2022-05-18 08:02:27

2022-05-09 11:57:39

云原生实践安全

2022-04-25 14:06:28

数据分析人工智能机器学习

2022-05-24 08:21:16

数据安全API

2022-04-26 08:10:33

MySQL存储InnoDB

2022-05-05 13:57:43

2022-05-10 14:11:05

网络安全网络犯罪

2022-04-02 10:23:12

MySQL数据库

2022-03-16 14:45:18

MySQL慢查询数据库

2022-04-17 23:02:08

数据分析数字化转型人工智能

2022-03-25 10:38:40

索引MySQL数据库

2022-04-28 08:05:05

2022-05-20 16:50:33

区块链Web3加密资产

2022-04-19 06:20:14

CentOSLinux红帽

2022-04-14 13:48:33

MySQL数据库并发量

2022-04-29 13:15:13

数据中台管控

同话题下的热门内容

分库分表会带来读扩散问题?怎么解决?浅析MySQL日志体系面试官问我 InnoDB 的物理存储结构!InnoDB B-TREE 索引怎么定位一条记录?聊聊索引失效的经典场景关于MySQL数据库性能优化方法,看这一篇文章就够了

编辑推荐

MySQL集群搭建详解如果对MySQL还停留在这个印象,就out了防止服务器宕机时MySQL数据丢失的几种方案MySQL innodb引擎备份工具XtraBackup之二(数据库全备)MySQL优化: Slave延迟很大的优化方法总结
我收藏的内容
点赞
收藏

51CTO技术栈公众号