MySQL 事务与 MVCC

MySQL 中的事务

MySQL 提供了两种事务型的存储引擎:InnoDB 和 NDB Cluster 。另外还有一些第三方存储引擎也支持事务

自动提交(AUTOCOMMIT)

MySQL 默认采用自动提交模式。也就是说每个查询都被当作一个事务执行提交操作,可以设置`AUTOCOMMIT` 变量来启用或者禁止自动提交模式:

# 查询当前的模式

show variables like 'AUTOCOMMIT'

# 禁用自动提交

SET AUTOCOMMIT = 0;

当 AUTOCOMMIT=0 时,所有的查询都是在一个事务中,直到显示的执行 COMMIT` 或者 ROLLBACK

AUTOCOMMIT 对非事务存储引擎不会有任何影响

在事务中混用存储引擎

MySQL 在服务层不管理事务,事务由下层的存储引擎实现,所以在不同的存储引擎中处理同一个事务是不可靠的。

例如: table_a 使用 innodb 引擎, table_b 使用 MyISAM 引擎(不支持事务)

假设以下操作在一个事务中:

insert table_a ... # 1

insert table_b ... # 2

update table_a ... # 3

假设在 执行 # 3 时出现了异常,这时事务要回滚,因为 table_b 并不支持事务,这就导致 table_b 的修改无法回滚,导致违反事务的 一致性 和 原子性

多版本并发控制(MVCC)

MySQL 大部分事务型存储引擎并不是简单的行级锁。基于提升并发行的考虑,它们一般都同时实现了多版本并发控制 MVCC.

InnoDB 的MVCC

InnoDB 的 MVCC ,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列一把保存了行的创建时间,一个保存行的过期时间(或删除时间),当然存储的并不是真正的时间,而是系统版本号。每开始一个事务,系统版本号就会自动递增,事务开始时刻的版本号作为当前事务的版本号,用来和查询到的每行记录的版本号就行比较。

以下是 REPEATABLE READ 的隔离级别下具体操作:

SELECT

InnoDB 会根据以下两个条件检查每行记录:

a. InnoDB 只查询版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版号),这样可以确保事务读取的行,要么是在事务开始前的已经存在的,要么是事务自身插入或者修改过的。

b. 行的删除版本要么未定义,要么大于当前事务版本号。这可以确保事务读取到的行,在事务开始之前未被删除。

只有符合上述两个条件的记录,才能返回作为查询结果

INSERT

InnoDB 为新插入的每一行保存当前系统版本号作为行版本号

DELETE

InnoDB 为删除的每一行保存当前系统版本号作为行删除标识

UPDATE

InnoDB 为插入一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识

保存着两个额外的系统版本号,使大多数读操作都可以不用加锁。这样设计使得读数据操作很简单,性能很好,并且也能保证只会读取到符合标准的行

原文发布于微信公众号 - 全栈布道士(gh_773193545262)

原文发表时间:2017-09-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏WindCoder

Discuz!X3.1QQ互联Unknown column 'conuintoken' in 'field list'的解决办法

14110
来自专栏散尽浮华

mysql操作命令梳理(4)-grant授权和revoke回收权限

在mysql维护工作中,做好权限管理是一个很重要的环节。下面对mysql权限操作进行梳理: mysql的权限命令是grant,权限撤销的命令时revoke; g...

31450
来自专栏Java后端技术栈

MySQL日志文件之错误日志和慢查询日志详解

实验环境:MySQL Community Server (GPL) 5.7.17、Ubuntu 16.04

13710
来自专栏Linyb极客之路

Mysql慢查询日志的使用 和 Mysql的优化

1、临时开启慢查询日志(如果需要长时间开启,则需要更改mysql配置文件,第6点有介绍)

12820
来自专栏pangguoming

MyBatis两张表字段名相同产生的问题

MyBatis两张表字段名相同, 会导致bean属性都映射为第一个表的列, 解决方法: 通过设置别名的方式让其产生区别,如 <select id="queryB...

50970
来自专栏GopherCoder

sqlite 的分布式实现方案:rqlite

66740
来自专栏tiane12

DISCUS X3后台更新缓存失败提示:(1146) TABLE ‘COMMON_MEMBER_ARCHIVE’ DOESN’T EXIST的解决方案\

20240
来自专栏Java开发

CentOS6.5 离线安装MySQL5.6.26

98910
来自专栏数据和云

深入原理:分区剪裁特性剖析

小鱼(邓秋爽) 云和恩墨专家,有超过5年超大型数据库专业服务经验,擅长oracle 数据库优化,SQL优化和troubleshooting 编辑手记:深入学习...

37570
来自专栏我是攻城师

如何在Elasticsearch里面使用索引别名

60490

扫码关注云+社区

领取腾讯云代金券