1.1、Mysql 学习——从数据库事务规范 到 Mysql 的 InnoDB 对事务特性的具体实现

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/bestcxx/article/details/100029817

前言

体能状态先于精神状态,习惯先于决心,聚焦先于喜好。

数据库事务

ACID的概念

暂略

ANSI SQL 隔离级别

暂略

Mysql 的服务器逻辑架构

Mysql 的服务器逻辑架构分为 服务器层和存储引擎层,服务器层调用存储引擎层。
每一个表可以指定存储引擎的类型。
图片来自互联网

在这里插入图片描述

Mysql 服务器层不负责事务

Mysql 的服务层不负责事务的实现,具体事务的实现由存储引擎负责。
需要强调的是不是所有的存储引擎都支持事务。比如 InnoDB 支持,MyISAM 不支持。

Mysql 服务器层和存储引擎 更细化的一个图片

图片来自互联网

在这里插入图片描述

存储引擎和事务

支持事务的存储引擎

Mysql 提供了两种 支持事务的存储引擎 InnoDB 和 NDB Cluster。

MyISAM 不支持事物

对于 支持压缩表的 MyISAM 存储引擎不支持事务——这意味着MyISAM表数据无法回滚。

存储引擎的混用

Mysql 允许不同存储引擎的混用但不建议这么做。
支持事务的和不支持事物的存储引擎可以搭配使用,并且不会报错,至多会有一些异常提示信息,但是涉及到数据回滚时,不支持事物的数据库表是不会回滚的,所以不建议在有事务需求的业务中混搭不支持事物的存储引擎。

Mysql 支持表锁和行锁

数据库表设计到表本身的修改以及表数据的修改,这不可避免的涉及到锁粒度的问题。
锁是需要开销的。

绝大多数商业数据库系统没有提供更多的选择,一把都是在表上施加行级锁(row level lock)。

Mysql 和表锁

Mysql 的表锁由 Mysql 服务器层 负责,比如修改表结构时就会加表锁。

Mysql和行锁

每种 Mysql 存储引擎都可以实现自己的锁策略和锁粒度。

InnoDB 中的事务和锁

InnoDB 支持事务

Mysql 默认的事务级别是 可重复读

Mysql 默认的事务级别是 可重复读

MVCC的概念

多版本并发控制。
每一条数据存在一个版本号,不同事务操作不同的版本号,这样可以在不加锁的情况下实现一定程度的非阻塞操作。

InnoDB 对MVCC的实现

InnoDB 存储引擎为每一行数据增加了默认的两列,第一列记录数据版本,第二列是数据删除版本,前者由INSERT的事务确定,后者由DELETE该数据的事务确定。
下面是四种场景

  • SELECT,搜索时需满足两个条件:
    一、数据版本早于本事务版本,确保读取到最新数据;
    二、删除版本号要么为空,要么大于本事务版本。即确保读到的数据在本事务开启前未被删除。
  • INSERT,每次将本事务版本作为新行的版本号。
  • DELETE,为删除的每一行添加删除版本号为本事务版本。
  • UPDATE,新插入一行,本事务版本作为新行的数据版本,同时将本事务版本保存到被修改行的删除版本。
MVCC 在什么时候生效?

MVCC 只在 读已提交和可重复读两个事务隔离级别时生效。

InnoDB 的行锁

InnoDB 只有在 序列化这个隔离级别才加行锁。其余隔离级别要么不加锁,要么使用MVCC机制,此外还有默认的间隙锁。下面介绍。

InnoDB 独有的间隙锁

搜索条件为一个范围,且该条件为索引时,索引之间的空间将被锁定,比如 表中目前的列为 id=1,id=5,id为索引列,搜索条件为 1<id AND id<5,那么在搜索期间无法向表插入 id=2,3,4的数据,索引 1-5之间被锁定了。这个间隙被锁定了。
这里需要注意,间隙所需要借助索引。

间隙所生效的隔离级别

只在 可重复读和序列化的隔离级别生效

可重复读状态下的间隙锁可以起到 避免幻读的作用

可重复读的隔离级别并没有要求避免幻读,但是由于InnoDB 间隙所的存在,当搜索条件为索引时,可以避免幻读的出现。

参考资料

[1]、https://blog.csdn.net/weixin_34344403/article/details/85996731
[2]、《高性能MySQL》
[3]、http://hedengcheng.com/?p=771

猜你喜欢

转载自blog.csdn.net/bestcxx/article/details/100029817