事务隔离机制-Mysql版本控制MVCC
事务隔离机制-Mysql版本控制MVCC
一、序言:
我们学习一项功能,可以利用2W1H的思路,2W(what 是什么,why该功能为什么会出现,可以解决什么样的业务场景),1H(我们知道了前面两个因素后,我们如果感兴趣,会暗自发问:How 如何学)
接下来我会按照这样的思路,给大家系统性的介绍一下事务以及事务的隔离机制是啥?诞生的背景?以及如何学习?
二、事务以及事务的隔离级别:
1、事务的定义:
事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
解决了What,我们再尝试灵魂拷问一下,事务诞生的背景是啥?它解决了啥实际问题?
举个实际生活的场景银行转账(同行转账简单点),单机情况下的并发控制:A给B转账100元,C给B同时也转账100元,假设B账户当前有1000元,A,C同时操作给B账户累加100元。累加完B账户完美的情况下是1200元,但是也有极端的情况,可能是1100元。
再举个多机情况下,在线支付场景,支付完成,需要完成库存扣减服务,以及订单创建;如果库存扣减失败,需要触发事务回滚,触发退款操作。这里相信大家或多或少的了解分布式事务的解决数据一致性的方案:两阶段提交(2PC, Two-phase Commit)。
在单机场景下,有些同学也许会说,我们把业务处理改成串行处理,这样是不是解决了B账户1100的问题,但是这种明显降低了并发性。显然事务的诞生背景是为了解决高并发场景下,提供高可靠的服务,数据一致性问题一直是绕不开的话题。
事务的特征有四种(ACID): 原子性、一致性、隔离性、持久性;
原子性,一个事务中的操作序列,例如转账服务:A账户扣减,B账户增加金额,必须在一个事务中完成,要么全部成功,要么全部失败,这是一个原子原子操作,不可拆分的业务单元。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
隔离性,A事务和B事务,互不影响,在SQL92标准中,定义了四种事务的隔离级别,供各个数据库厂商来实现, 隔离性的问题(脏读、不可重复读、幻读)。
持久性,在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
一致性,在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏;事务的原子性,隔离性,持久性为一致性提供了保障。
2、事务的隔离级别:
咱们看一下SQL92标准中关于事务隔离级别的定义: http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
__Table_9-SQL-transaction_isolation_levels_and_the_three_phenomena_
_Level__________________P1______P2_______P3________________________
| READ UNCOMMITTED | Possib|e Possib|e Possible |
| | | | |
| READ COMMITTED | Not | Possibl| Possible |
Possible
| REPEATABLE READ | Not | Not | Possible |
| | Possib|e Possib|e |
| | | | |
| SERIALIZABLE | Not | Not | Not Possible |
|______________________|_Possib|e_Possib|e_________________________|
| | | | |
|Note: The exclusion of|these p|enomena |or SQL-transactions ex- |
ecuting at isolation level SERIALIZABLE is a consequence of the
requirement that such transactions be serializable.
关于p1,p2,p3的问题描述:
The isolation level specifies the kind of phenomena that can occur
during the execution of concurrent SQL-transactions. The following
phenomena are possible:
1) P1 ("Dirty read"): SQL-transaction T1 modifies a row. SQL-
transaction T2 then reads that row before T1 performs a COMMIT.
If T1 then performs a ROLLBACK, T2 will have read a row that was
never committed and that may thus be considered to have never
existed.
2) P2 ("Non-repeatable read"): SQL-transaction T1 reads a row. SQL-
transaction T2 then modifies or deletes that row and performs
a COMMIT. If T1 then attempts to reread the row, it may receive
the modified value or discover that the row has been deleted.
3) P3 ("Phantom"): SQL-transaction T1 reads the set of rows N
that satisfy some <search condition>. SQL-transaction T2 then
executes SQL-statements that generate one or more rows that
satisfy the <search condition> used by SQL-transaction T1. If
SQL-transaction T1 then repeats the initial read with the same
<search condition>, it obtains a different collection of rows.
我转换成以下表格,大家应该比较熟悉了:
隔离级别 脏读(Dirty read) 不可重复读(Non-repeatable read) 幻读(Phantom)
读提未交(READ UNCOMMITTED) X X X
读已提交(READ COMMITTED) √ X X
可重复读(REPEATABLE READ) √ √ X
序列化 (SERIALIZABLE) √ √ √
从以上表格,我们可以看出 读未提交,啥问题都没有解决;读已提交阶段,存在不可重复读,幻读问题;可重复读阶段,存在幻读问题,序列化解决了所有问题,但是牺牲了并发,显然不可取。
我们分别看一下mysql ,oracle对以上四种隔离级别的实现:
在mysql 中,5.5以后的版本默认采用Innodb存储引擎,在众多的存储引擎中,只有两款支持事务,其中一款就是Innodb,Innodb的MVCC+行锁(间隙锁、临键锁)解决了幻想问题。
隔离级别 脏读(Dirty read) 不可重复读(Non-repeatable read) 幻读(Phantom)
未提交读(READ UNCOMMITTED) X X X
读已提交(READ COMMITTED) √ X X
可重复读(REPEATABLE READ) √ √ InnoDB
序列化 (SERIALIZABLE) √ √ √
Oracle仅支持两种隔离级别:Read Committed(默认隔离级别)与Serializable。尽管官方这样描述,Oracle的Serializable实际是基于MVCC+Lock based的SI(Snapshot Isolation)隔离级别。
本篇我们重点介绍mysql 的几种隔离级别:
1、读未提交:
2、读已提交:
3、可重复读:
3、高深问题收集:
InnoDB如何利用间隙锁、临界锁解决幻读问题????
InnoDB如何解决更新丢失问题???
以上问题,单独写个帖子来补充以上疑问,本篇重点介绍事务,以及事务的隔离级别,mysql对92标准中的隔离级别的实现
————————————————
版权声明:本文为CSDN博主「石头城程序猿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jason_jiahongfei/article/details/116041337