编程知识 cdmana.com

Mysql数据库的事务特性、隔离级别及MVCC多版本并发控制简介

事务的特性

数据库如果支持事务,就要满足下面四个特性(ACID)。

原子性(A:Atomicity)

在一个事务中,多个sql操作,要么一起成功(所有数据操作都成功),要么一起回滚(其中一个没有成功,其他数据操作一起恢复到开始状态)。

一致性(C:Consistency)

数据修改前是准确的,修改后也要说准确的。指的是数据从一个一致性状态,转换到另一种一致性的状态。(例如:A和B总共有10个苹果,A转让了几个苹果给B,事务结束后,A和B总共还是10个苹果)。

隔离性(I:Isolation)

当数据库有多个事务一起执行时,各个事务之间互相不影响,每个事务感知不到有其他的事务在执行。

持久性(D:Durability)

数据库事务结束提交后,数据修改永久有效,即使数据库重启,遇到其他问题关掉,再打开后,之前提交过的数据的修改还是生效的(例如:程序执行数据的操作,事务提交后,突然数据库服务器断电等原因导致数据库停掉不可用,恢复后,数据还是修改后的状态)。

事务隔离级别

读未提交

两个事务同时操作数据库,其中一个事物修改数据库后,没有提交,另一个事物可以读取到修改过的数据。

读已提交

有两个事务,第一个事务查询一条数据,第二个事务修改这条数据提交后,第一个事务又查询该数据,第一个事务前后两次查询的结果不一致。

可重复读(mysql默认隔离级别,通过MVCC<Mutil-Version Concurrency Control>机制实现)

有两个事务,第一个事务查询一条数据,第二个事务修改这条数据提交后(出于性能考虑,使用了以乐观锁为理论基础的MVCC<多版本并发控制>来实现),第一个事务又查询该数据,第一个事务前后两次查询的结果不致。

串行化(解决 幻读 的问题)

可重复读可以限制两个事务并发修改删除数据导致前后查询不一致的情况,但是无法限制insert(行锁只能锁住行,新增数据无法限制)。

幻读的案例场景:有两个事务,第一个数据查询列表数据条数,第二个事务新增数据到表中并提交事务,第一个事务又重新查询数据条数,第一个事务前后两次查询的数据不一致。

串行化:有两个事务,第一个事务查询数据,第二个事务新增数据到表中,会报错(表级锁),不能插入数据,第一个事务再查询数据,前后两次结果一致。串行化并发低。

MVCC原理简介:

通过事务id控制不同版本数据(因为通过事务id控制数据,所以下面数据中id也是会重复的),sql查询的时候,后两列隐藏列不会显示。下列表格对应的事务开始顺序与数字大小顺序一致,最终所有事务一起结束。(通过并发情况简单说明MVCC原理)

事务id=1插入数据;事务id=3插入数据;事务id=4删除数据;事务id=5修改数据;表最终数据如下:

id 数据 更新事务ID(隐藏列) 删除事务ID(隐藏列)
1 张三 1 4
2 小明 1
3 李四 1
4 王五 3
2 小明111 5

事务id=2,查询全表数据,查询数据如下:

start transactionselect * from a; //(1) 

select * from a; //(2) 

commit

假设:

事务id=2中(1)查询发生在事务id=1之后 ;

事务id=2中(2)查询发生在事务id=3插入数据之后;

事务id=2两次查询结果都一样(通过事务id做了限制,只会查询小于等于当前事务id的数据)

id 数据 更新事务ID(隐藏列) 删除事务ID(隐藏列)
1 张三 1
2 小明 1
3 李四 1

假设:

事务id=2中(1)查询发生在事务id=1之后 ;

事务id=2中(2)查询发生在事务id=4删除数据之后;

事务id=2两次查询结果都一样(通过事务id做了限制,只会查询小于等于当前事务id的数据)

id 数据 更新事务ID(隐藏列) 删除事务ID(隐藏列)
1 张三 1 4
2 小明 1
3 李四 1

假设:

事务id=2中(1)查询发生在事务id=1之后 ;

事务id=2中(2)查询发生在事务id=5修改数据之后(修改也相当于插入一条数据,数据的事务id是不同的);

事务id=2两次查询结果都一样(通过事务id做了限制,只会查询小于等于当前事务id的数据)

id 数据 更新事务ID(隐藏列) 删除事务ID(隐藏列)
1 张三 1
2 小明 1
3 李四 1

版权声明
本文为[成钰]所创,转载请带上原文链接,感谢
https://my.oschina.net/tongchengyu/blog/4714950

Scroll to Top