文档章节

mysql并发控制——数据多版本

DamienChen
 DamienChen
发布于 2018/08/21 17:27
字数 1425
阅读 126
收藏 1

内容提取自 58沈剑公众号:架构师之路

1、共享锁和排他锁

因为普通锁不能并发,所以出现了共享和排它锁

共享锁(Share Locks,记为S锁),读取数据时加S锁

排他锁(exclusive Locks)修改数据时加X锁

兼容互斥表

        S            X

S    兼容        互斥

X    互斥        互斥

这种情况下,如果写数据的任务没有完成,数据不能被任务读取的。这回阻塞读取任务。

画外音:对应到数据库,可以理解为,写事务没有提交,读取相关数据的select会被阻塞

2、数据多版本

核心原理:

1)写任务发生时,将数据克隆一份,以版本号区分

2)写任务操作新克隆的数据,直至提交;(提交时覆盖原来版本?提交方式有待思考)

3)并发读任务可以继续读取旧版本的数据,不至于阻塞

 

3、redo,undo,回滚段

在进一步介绍InnoDB如何使用“读取旧版本数据”极大提高任务的并发度之前,有必要先介绍下redo日志,undo日志,回滚段(rollback segment)。

 

为什么要有redo日志?

数据库事务提交后,必须将更新后的数据刷到磁盘上,以保证ACID特性。磁盘随机写性能较低,如果每次都刷盘,会极大影响数据库的吞吐量。

 

优化方式是,将修改行为先写到redo日志里(此时变成了顺序写),再定期将数据刷到磁盘上,这样能极大提高性能。

画外音:这里的架构设计方法是,随机写优化为顺序写,思路更重要。

 

假如某一时刻,数据库崩溃,还没来得及刷盘的数据,在数据库重启后,会重做redo日志里的内容,以保证已提交事务对数据产生的影响都刷到磁盘上。

 

一句话,redo日志用于保障,已提交事务的ACID特性。

 

为什么要有undo日志?

数据库事务未提交时,会将事务修改数据的镜像(即修改前的旧版本)存放到undo日志里,当事务回滚时,或者数据库奔溃时,可以利用undo日志,即旧版本数据,撤销未提交事务对数据库产生的影响。

画外音:更细节的,

对于insert操作,undo日志记录新数据的PK(ROW_ID),回滚时直接删除;

对于delete/update操作,undo日志记录旧数据row,回滚时直接恢复;

他们分别存放在不同的buffer里。

 

一句话,undo日志用于保障,未提交事务不会对数据库的ACID特性产生影响。

 

什么是回滚段?

存储undo日志的地方,是回滚段。

如果事务未提交,修改数据的记录就可以在回滚段中的undo日志中找回原来的记录,如果rollback则可以保证数据正确,数据提交之后回滚段的日志可以删除

核心问题:

旧版本的数据存储在哪里-----------------回滚段里面

存储旧版本数据,对MySQL 和InnoDB原有的架构是否有巨大冲击?----冲击不大

 

InnoDB的内核,会对所有row数据增加三个内部属性:

(1)DB_TRX_ID,6字节,记录每一行最近一次修改它的事务ID;

(2)DB_ROLL_PTR,7字节,记录指向回滚段undo日志的指针;

(3)DB_ROW_ID,6字节,单调递增的行ID;

 

InnoDB为何能够做到这么高的并发?

回滚段里的数据,其实是历史数据的快照(snapshot),这些数据是不会被修改,select可以肆无忌惮的并发读取他们。

 

快照读(Snapshot Read),这种一致性不加锁的读(Consistent Nonlocking Read),就是InnoDB并发如此之高的核心原因之一。

 

这里的一致性是指,事务读取到的数据,要么是事务开始前就已经存在的数据(当然,是其他已提交事务产生的),要么是事务自身插入或者修改的数据。

 

什么样的select是快照读?

除非显示加锁,普通的select语句都是快照读,例如:

select * from t where id>2;

 

这里的显示加锁,非快照读是指:

select * from t where id>2 lock in share mode;

select * from t where id>2 for update;

 

问题来了,这些显示加锁的读,是什么读?会加什么锁?和事务的隔离级别又有什么关系?

 

本节的内容已经够多了,且听下回分解。

 

总结

(1)常见并发控制保证数据一致性的方法有数据多版本

(2)普通锁串行,读写锁读读并行,数据多版本读写并行;

(3)redo日志保证已提交事务的ACID特性,设计思路是,通过顺序写替代随机写,提高并发;

(4)undo日志用来回滚未提交的事务,它存储在回滚段里;

(5)InnoDB是基于MVCC的存储引擎,它利用了存储在回滚段里的undo日志,即数据的旧版本,提高并发;

(6)InnoDB之所以并发高,快照读不加锁;

(7)InnoDB所有普通select都是快照读;

画外音:本文的知识点均基于MySQL5.6。

 

 

 

本文转载自:https://mp.weixin.qq.com/s/R3yuitWpHHGWxsUcE0qIRQ

DamienChen
粉丝 0
博文 17
码字总数 3688
作品 0
广州
程序员
私信 提问
加载中

评论(0)

InnoDB多版本并发控制——MVCC

Multi-Version Concurrency Control -多版本并发控制 MySQL的大多数事务存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制(MVCC)。MVCC没有...

秋风醉了
2014/03/17
1.2K
0
[Mysql]——事务的4种隔离级别

[Mysql]——事务的4种隔离级别 SQL标准定义了4种隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。 低级别的隔离级一般支持更高的并发处理,并拥有更低的...

望崖
03/31
0
0
事务隔离级别

在SQL标准中定义了四种隔离级别,每种隔离级别都规定了一个事务中所做的修改,哪些事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。 *每...

青春掌柜
2016/05/26
0
0
MySQL MVCC && 事务隔离级别 && 锁

MySQL MVCC && 事务隔离级别 && 锁 InnoDB多版本并发控制——MVCC http://my.oschina.net/xinxingegeya/blog/208821 MySQLS锁X锁read lockwrite lock http://my.oschina.net/xinxingegeya/bl......

秋风醉了
2014/07/30
649
0
SQL--事物隔离级别

数据库事务的隔离级别有4个,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。 事务隔离.png ...

HaleyLiu
2017/12/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Apache Tomcat 8 ARM 移植

tomcat 下载地址 https://tomcat.apache.org/download-80.cgi

osc_y08db3kb
1分钟前
10
0
splunk搜索语法笔记

全文搜索 搜索框直接输入”搜索词“   ERROR 查找匹配词”ERROR“ 字段搜索 字段名=”搜索词“ LogLevel=ERROR 查找数据来源为"LogLevel=ERROR" 通配符搜索 Version=5.* 查找数据来源为Ver...

KaWaE
1分钟前
5
0
开发APP、小程序怎么选择云主机的配置

在云服务器的运用上,不仅可以节省高昂的硬件采购成本以及人力成本,后期需要更高配置的云主机时,也可以进行升级,以此减少过高的运维成本,那么开发APP、小程序怎么选择云主机的配置? 内存...

Cloudam云端
2分钟前
7
0
手把手教你开发docker一样的命令行

目录 前言 一、安装 二、初始化应用 初始化项目 创建入口文件cmd/root.go 创建主程序main.go 三、如何自定义命令 创建hello子命令 创建version子命令 四、如何设置flag选项 全局选项 本地选项...

osc_b9r67jnt
3分钟前
7
0
[PHP] 解决mysql下1366 Incorrect string value错误

这个错误是字符编码的问题 , 因为内容里有可能有表情等特殊字符 , 需要使用utf8mb4编码 重点还有一个是 , 在php代码中连接上mysql后一定要执行一下 set name utf8mb4 否则也是不行的 比如下面...

osc_kvlhvh2u
4分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部