Mysql系列三——数据库事务(事务隔离性)

什么是数据库事务?

数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。(百度百科)
简单举个例子:
假如A要向B转账100元,那么主要包含两个数据库操作。
(1)A账户扣100元
(2)B账户加100元
那么假如在将A账户扣了100元成功之后,B账户加钱操作没有执行成功,那么就是一次意外事故了。所以,就有了事务的概念。
事务就是将一系列数据库操作封装为一个原子操作,成为一个操作单位,假如事务任一步骤没有执行完成,就会执行回滚,返回执行事务前的状态。
那么,将转账操作设为事务之后:假如A账户扣钱成功,B账户加钱未成功,那么事务就会回滚,即再加回A的100元,恢复执行事务前的状态。
所以,事务就是事务中的数据库操作,要么不做,要么全做。

谁控制完成事务?

数据库事务是由存储引擎来完成的。那么,我们知道,Mysql有多种数据库引擎:InnoDB、MyISAM等。InnoDB支持事务,而MyISAM不支持事务,所以这也是MyISAM逐渐被淘汰的重要原因。

多事务执行时产生的问题以及事务的隔离级别

事务有四大特性,ACID,即原子性、一致性、隔离性、持久性。那么现在着重探讨隔离性。

数据库的运行过程中往往是会存在多个事务同时存在的情况,如果事务之间不涉及对同一数据的操作时,那么事务并发执行是不会有问题的。但是当事务操作了同一数据时,就会产生一些问题:
对于多个事务同时操作相同数据项的问题。

数据库对写事务之间是会互相阻止的,就是会加锁,即A事务更改数据X,B事务只能等事务A提交之后执行。但是写事务对于读事务,设置了不同的隔离级别
对于多个事务操作同一数据项的问题,数据库为事务设置了四种等级的隔离级别,**每一种级别的隔离度逐渐增大,数据也更加安全,但是执行效率也就更低。**所以,我们操作数据库事务时,就需要寻找这两者的平衡点。

(1)读未提交:
事务的最低隔离级别为读未提交,读未提交的意思就是一个事务还没提交时,它做的变更就能被别的事务看到。就是说:
当事务A正在更改数据X,并且还未提交,事务B查询数据X时获得的就是被更改后的X的值,即使事务A尚未提交
读未提交的隔离级别最低,因为A事务中间过程对数据的更改对其他事务时完全透明的。读未提交可能存在的问题就是“脏读”。
脏读就是当A事务对数据X进行操作,并且尚未提交时,B事务对数据X进行了读取,之后A事务提交。那么B事务读取的数据其实就是“数据,即B事务读到的数据是事务A提交之前的数据
在这里插入图片描述

以此为例,B事务使用了A事务更改中未提交的数据,那么B事务很有可能使用了错误的数据:
(1)A事务回滚了,那么X数据就回归了原始数据了,而B却读取X的值为2。
(2)A事务之后可能又对数据X做了修改,例如修改X为3,那么B又是读取了错误的数据。
所以,B读取的数据就是脏数据
为了解决脏读,数据库设置了“读提交”隔离级别,解决了脏读。

(2)读提交:(可能出现的问题:)
读提交是比读未提交更高一级别的隔离级别,读提交是ORACLE数据库的默认隔离级别。读提交是指一个事务提交之后,它做的变更才会被其他事务看到

A事务对数据X做了修改且尚未提交,此时B事务读取X的数据值,为X的原始数据。
读提交解决了脏读的问题。
在这里插入图片描述
继续以此图为例,B事务读取的数据为1,不会出现脏数据。
但是读提交隔离级别仍然有未解决的问题:不可重复读。
不可重复读就是A事务更改数据X,B事务多次读取事务,重复读取到的X的数据不一致:
在这里插入图片描述
B事务一共读取了两次数据X,分别读取值为1、2,两次数据不一致。

数据库对于不可重复读问题的解决方案为设置隔离级别:可重复读

(3)可重复读
可重复读的意思是一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。Mysql的默认隔离级别为可重复读。
即A事务更改数据X,B事务在A事务提交之前和之后都读取了X,读取的结果是一样的。
以上图为例,B事务最终读取到的X的值为1。

可能这里有些难以理解,下面讲到隔离级别的实现便会理解可重复读的概念了。

但是,可重复读仍然有未解决的问题:幻读

在这里插入图片描述
可重复读隔离级别实现了事务对同一数据的查询始终一致。但是这种隔离级别只能限制已经查到的数据,保证一致。

假如B事务是查询所有满足查询提交的所有数据项,未提交事务时,C事务insert了一条新的数据X,并且X同样满足B事务的查询条件,那么B事务的两次相同的查询却出现了不同的数据结果集,就是幻读。

解决幻读的隔离级别便是:串行化

(4)串行化
串行化是指**对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成。**即读操作也会阻止写操作。
串行化相当于除了查询事务之间,读写事务之间也会完全加锁,顺序执行,完全保证数据一致。
即上图的C事务需要等待事务B提交之后才能执行。

事务隔离的实现方式

事务的隔离级别是靠视图实现的。数据库会创建视图,访问的时候以视图的逻辑结果为准
视图就相当于是当前持久化数据的一个副本。
四种隔离级别分别对应不同的视图。
(1)读未提交级别:
没有视图概念。因为任何一个写事务在未提交时,数据都可以被其他事物所看到,其他事物是直接读取数据的。
(2)读提交级别:
在每个SQL语句执行时创建视图。即假如A事务读取数据X,在每个SQL语句执行都会新建视图,即每次SQL语句都会更新视图。
(3)可重复读级别:
在事务启动时创建视图,所以整个事务对数据的访问都会以事务启动时查到的数据为准。
(4)串行化级别:
也没有视图概念。但因为串行化直接对事务加锁避免并行访问,所以不需要视图。

以读提交为例,当执行一条SQL语句时,数据库就会创建一个视图(副本),然后在此事务的下一次查询之前,数据都以此视图(副本)为准。当此事务的下一次SQL语句执行时,就会更新视图。因为视图都是当前数据库持久化的数据,所以事务执行过程当中不会读取到其他事物的更改。

以可重复读为例,当事务启动时,数据库会创建一个视图(副本),然后此事务中所有对该数据的访问都会以此视图(副本)为准。所以,在此事务的所有查询操作的结果都是相同的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值