MySQL关于事务acid特性的简单介绍

1.基础概念

事务是操作数据库的程序执行单元,一个事务可能包含一个或多个sql语句。

1.1逻辑架构

在这里插入图片描述

如图所示,mysql服务器逻辑架构分为三层:

  • 第一层:处理客户端连接、授权认证
  • 第二层:服务器层,负责sql的解析、优化以及内置函数实现、存储过程等
  • 第三层:存储引擎层,负责数据的存取

mysql中服务器层不管理事务,事务是由存储引擎实现的。mysql支持事务的存储引擎有innodb、ndb cluster等,其中innodb使用最广泛

1.2acid特性

acid是事务的4个特性:

  • 原子性(atomicity)
  • 一致性(consistency)
  • 隔离性(isolation)
  • 持久性(durability)
2.原子性
2.1定义

原子性是指一个事务是不可分割的最小单位,其中的操作要么都成功,要么都失败;如果事务中的一个sql执行失败,则已执行成功的sql必须回滚,数据库退回到事务执行前的状态

2.2原理

实现原子性的关键在于,当事务回滚时能撤销所有已执行成功的sql语句。innodb实现回滚,靠的是undo log:当事务对数据进行修改时,会记录修改前的数据信息到undolog中,如果事务执行失败,就可以利用这些数据恢复到原来的状态

3.持久性
3.1定义

持久性是指事务一旦提交,它对数据库的改变就应该是永久的。接下来的操作或故障不会导致数据丢失或其他异常。

3.2原理

innodb引擎数据是存储在磁盘上的,如果每次读写都需要磁盘io,那么效率是很低的。mysql通过引入一块buffer pool缓冲区来加速读写,但也带来了问题,如果数据还在缓冲区中,没刷到磁盘上,这时数据库宕机就会导致数据丢失。

redolog记录了事务修改后的数据信息,当事务提交时,会先将redolog刷盘,再更新缓冲区。如果数据库宕机,可以借助redolog进行恢复

3.3问题
  1. redolog也要刷盘,那为何不直接将修改的数据刷盘,反而要多此一举?
    • 直接将数据写入磁盘是随机io,效率低;写redolog是顺序io,效率高
    • 将数据刷盘是以页为单位,默认16K,一个小修改都要整页写入,无效io多
  2. binlog同样记录了所有操作,为什么不用binlog进行恢复呢?
    • binlog是追加写入的,达到阈值就切换到下一个binlog文件,所以会记录所有的操作,不管操作是否已经刷盘。那么宕机恢复时,仅凭binlog是无法定位从哪个事务开始进行恢复的。
    • redolog是循环写入的(就像一个圆圈),只要刷入磁盘的数据都会被标记为清除,所以他记录的是未刷盘的数据,崩溃恢复时把redolog中的数据都恢复即可
    • binlog是属于MySQL服务层面的,而redolog是由innodb引擎实现的,且通常情况下,binlog适用于主从复制场景
4.隔离性
4.1定义

隔离性是指事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。严格的隔离性,对应了事务隔离级别中的Serializable,但实际应用中出于性能考虑基本不会使用该级别

隔离性可从两方面探究:

  • 写对写的影响:锁
  • 写对读的影响:多版本并发控制(mvcc)
4.2锁

锁机制:事务修改数据前,需要先获取相应的锁才能进行修改操作。这时如果其他事务也要修改相同的数据,则需要等待锁被释放并获取锁

行锁与表锁:按照粒度,锁可以分为表锁、行锁以及二者之间的锁。表锁会锁整张表,行锁只锁操作的数据。

4.3并发问题

并发事务下,读操作可能遇到的三种问题:

  1. 脏读:事务读到其他事务未提交的数据
  2. 不可重复读:事务中的两次相同的读操作获取到了不同的数据,原因是两次读之间有其他事务修改了数据
  3. 幻读:事务中两次相同的读操作读到了行数不一样的数据,原因是其他事务添加或删除了行

不可重复读与幻读的区别🐯:两者都是针对同一个事务内的两次读取结果不同产生的,幻读是结果行数不同,不可重复读是结果内容不同

4.4隔离级别
  1. read uncommitted

    概念:事务能读取到其他事务未提交的修改

    存在的问题:事务A还未提交的修改,在事务B中能够获取到,这会导致脏读问题

  2. read committed

    概念:事务只能读取到其他事务提交后的修改

    存在的问题:同一个事务内的多次读取可能导致不同的结果。

    例子:事务A中包含两次查询,第一次查询到数据后,其他事物修改了数据并提交了,则第二次查询到的数据会与第一次不一样,这就是不可重复读问题

  3. repeatable read

    概念:通过事务快照、间隙锁等实现一个事务内的读一致

    存在的问题:事务内的当前读操作可能会导致幻读问题

  4. serializable

    概念:读加读锁,写加写锁,读读不影响,读写、写写需要等待锁

    存在的问题:没有并发问题,单纯的性能低

4.5mvcc

多版本并发控制,借助undolog、隐藏字段和ReadView实现了读写的并发执行而互不影响(实际就是读取数据的快照)。

5.一致性
5.1定义

一致性是指事务结束后,数据库的完整性没有被破坏,包括实体完整性(如主键唯一)、列完整性(字段类型、长度、大小符合要求)及用户自定义完整性(转账前后,两个账户余额和不变)等

5.2实现一致性

一致性是事务的最终目标,原子性、持久性和隔离性都是为了保证一致性。

实现一致性的一些措施:

  • 保证原子性、持久性和隔离性
  • 数据库本身提供约束及保障
  • 应用层进行约束及保障
6.mysql中事务使用
6.1基本使用

开启一个事务

  • begin
  • start transaction

beginstart transaction都代表开启一个事务,不同的是start transaction后可以跟几个修饰符

  • read only:开启一个只读事务,事务内的操作只能读不能更新
  • read write:开启一个读写事务
  • with consistent snapshot:开启一个一致性读事务,详情参考mvvc

可以同时使用多个修饰符,以逗号分隔

start transaction read only, with consistent snapshot;

关闭自动提交

默认情况下,mysql是自动提交事务的;每条sql都会被当作一个事务执行。

set autocommit = 0;#关闭自动提交

结束事务

使用commit提交事务或者rollback回滚事务,他们都代表着事务的结束

强制中止事务

使用show processlist查看mysql当前的线程情况

找到需要结束的那个线程,使用kill指令将其中止

保存点

在一个事务中,可以设置保存点,让事务回滚到指定位置,而不是回滚整个事务

savepoint sp1;#创建保存点
release savepoint sp1;#删除保存点
rollback work to savepoint sp1;#回滚到指定保存点
6.2注意事项

事务的隐式提交

  • 当一个事务中执行ddl(修改库表)语句时,系统会自动提交一次,这会导致ddl前面执行的操作不能回滚,需要注意!
  • 如果在一个事务还没结束前又开启另一个事务,那么前面的事务会被自动提交
  • 28
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值