Mysql(3)--事务四大特性、隔离级别、事务分类

Mysql中Innode引擎与Myisam引擎之间的不同就是,Innode支持事务,讲到事务,必然离不开事务的四大特性,今天就从事务的四大特性,以及事务的隔离级别,事务在Mysql中的实现方式来聊一聊Mysql中的事务

一、事务的四大特性

ACID,相信了解过事务的同学都知道这四大特性,我们具体说说:

  • 原子性:指事务的操作要么一起成功,要么一起失败,最简单的还是银行转账的例子,张三向李四转100元,张三的钱要减少,李四的钱要增加,这两个操作必须是一体的,不可被分割的
  • 一致性:指在执行事务前与执行事务后,数据库中的数据状态保存一致,可以简单的理解为转账前整个数据库的数据和转账后整个数据库的数据没有发生变化
  • 隔离性:指两个事务之间操作是被隔离的,互不干扰的,后面的四种隔离级别中会详细介绍隔离性
  • 持久性:指执行完事务后数据的状态是持久的,数据库不会发生丢失等等

Mysql中的原子性、一致性和持久性是通过事务日志实现,而隔离性是通过锁机制、MVCC进行实现

二、Mysql中的隔离级别

先来聊一聊在并发事务的情况下,有可能会出现什么问题?

  • 脏读:指读到了别的事务还没有提交的数据
  • 不可重复读:指在事务的执行过程中,对同一数据读取了两次,两次结果不一样
  • 幻读:指在事务的执行过程中,事务重复数据,在获得数据的时候多次读取的数据行数不一样

不可重复读重点是在修改,意思是在同一事务中,同样的条件下,两次读取的结果不一样,因为中间被事务修改,而幻读重点是在插入和删除,意思是在同一事务中,同样的条件下,两次读取出来的记录数不一样,因为中间被其他事务插入或者删除过数据

SQL标准中定义了四种隔离级别,下面分别来介绍:

  • 读未提交(RU):事务可以读取到其他事务没有提交的数据,在我的经验中,应该没有人会使用这种隔离级别,这会产生上面的所有问题,但是在特定环境下,例如在debug的时候可以暂时将隔离级别设置为读未提交,这样便于提交,不过debug完一定要设置回来
  • 读已提交(RC):这是大多数数据库默认的隔离级别,但是不是mysql的默认隔离级别,读已提交是指事务能看到其他事务已经提交过的数据,这个级别可以解决脏读,但是不能解决不可重复读,当有交叉事务的时候,如果其他事务commit了,那么该事务两次读取的数据就不一样
  • 可重复读(RR):这是Mysql默认的隔离级别,解决了RC的不可重复读的问题,指在同一个事务中,会看到相同的数据,但是没有解决幻读的问题
  • 可串行化(Serializable):这是最高的隔离级别,相当于Java中的Synchronized(没有优化前的),也就是说对数据库中的操作,同一时间内只能有一个事务,这样多个事务之间肯定不会有冲突,从而解决了幻读的问题,但是锁的效率很低,导致超时先现象等等

三、Mysql中的事务

从事务理论的角度来说,可以把事务分为:

  • 扁平事务
  • 带有保存点的事务
  • 链事务
  • 嵌套事务
  • 分布式事务

Mysql默认的存储引擎是Innode,对于Innode引擎来说原生支持的有扁平事务、带有保存点的事务、链事务、分布式事务,但是可以使用带有保存点的事务来模拟嵌套事务

扁平事务

扁平事务是最简单的一种类型,但是也是在一般情况下,使用最频繁的事务,在扁平事务中,所有事务都处于同一层次,由BEGIN 开始要么全部成功,要么全部失败

扁平事务的主要限制是不能回滚到指定的操作中,再此基础上,有带有保存点的扁平事务

带有保存点的扁平事务

带有保存点的扁平事务,除了支持扁平事务支持的所有操作外,还能允许设置一个保存点,当操作需要回滚时,可以回滚到自定义好的某一个保存点

BEGIN;
INSERT test VALUES(1,'张1');
SAVEPOINT A
INSERT test VALUES(2,'张2');
ROLLBACK TO A
COMMIT;

这就很适合于长事务,当数据处理失败后,不需要回滚所有的数据,而是选择回滚到已经成功的数据

链事务

带有保存点的事务,如果遇到系统崩溃的情况,所有的保存点都会消息,这就意味着当进行恢复的时候,就需要重新从执行处开始,而不能再最近的保存点开始。链事务相当于带有保存点的扁平事务的变种,在提交一个事务时,释放掉不需要的数据,然后将必要的上下文数据传给下一个事务

也就是说,提交事务操作和开始下一个数据的操作是一个原子操作,这主要是靠completion_type来实现的,具体可以看Commit Work 和Commit的区别

嵌套事务

嵌套事务就是说在一个事务中又包含了另外一个事务,事务之间存在父子级关系,子事务提交之后并不生效,而是等.

分布式事务

看名字就知其意,在当今的网络环境下都是说微服务,分布式的架构的。那么在分布式的环境下该如何保证事务?为什么需要事务?例如现在有两个微服务库存系统和订单系统,当用户购买商品之后,需要从库存系统里面扣减库存然后从订单系统里面增加订单,两个微服务可能有自己单独的数据库,那么如果没有分布式事务就会出问题了,有可能库存系统库存减少了,但是订单却没有创建,这和银行转账是一样的,只不过是在不同的机器上

解决上面分布式下的事务问题,一般使用XA分布式事务协议,分布式事务用于保证在分布式系统中保证不同节点之间的数据一致性问题。XA协议分为两阶段提交和三阶段提交,XA事务有一个事务管理器(用于管理所有事务),资源管理器(用于事务真正的执行),这里具体聊聊两阶段提交:

  • 所有参与全局事务的节点告诉事务管理器,都准备好了
  • 事务管理器告诉资源管理是回滚还是提交,如果任何一个节点不能提交,则所有的节点都需要被告知回滚

四、事务的实现原理

事务具有四大特性:原子性、一致性、隔离性、持久性。而原子性、一致性与持久性是通过事务日志来实现的,隔离性有两种方式:LBCC利用读写锁的方式,MVCC多版本并发控制,隔离性的实现方式由后续文章介绍。

undo log

undo log是一种逻辑日志,是事务中的原子性的实现原理。Innodb要实现回滚靠的是undo log,undo log里面存放的是一条sql语句,当事务执行insert语句时,会存入一条delete语句,相似的当事务执行update语句时会存入一条修改回去的update语句,当事务需要进行回滚的时候,使用undo log中保存的信息将数据回滚到之前的状态

redo log

redo log是一种物理日志,是事务中的持久性的实现原理。mysql中的数据最终是要存放在磁盘里的,但是如果每次只需一次操作就要进行磁盘的操作然后再更新,这样做效率会变低很多。这时候就需要redo log日志了,当有一条记录需要进行更新的时候,会先把记录写在redo log里面,并更新内存,同时Innode引擎会在合适的时间内将redo log中的操作记录更新到磁盘里面

binlog

msql中还存在另外一个很重要的日志binlog二进制日志,也用于记录操作并用于数据的恢复,与redo log不同的是binlog是存在于Server层的日志,而redo log是引擎层的日志,Mysql采用两阶段提交的方式保证两个状态保持逻辑上得一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值