天天看点

mysql 事务特性以及隔离级别

1、前述

相信我们开发中会遇到各种各样的异常,或者请求外部接口的异常,当客户端向我们的服务端发起一次请求的时候,通常在业务里会做一些数据库增删改查的操作,然后做一些业务逻辑处理来返回响应给客户端,但是代码里出现异常是不可避免的,这个时候就需要我们来做一些数据库回滚的操作,也就是事务回滚,否则就会出现很多的脏数据,影响系统后续的业务处理,本文是自己的一篇记录和理解

2、数据库事务回滚

说到数据库事务回滚,这里想提一点,Redis 是不支持事务回滚的,redis 是先对内存中的数据进行操作,再写入日志,这样可以防止 aof 文件写入许多错误的指令,而 Mysql 例如 innodb 是支持事务的,先写 redlog ,再对数据进行操作,

3、数据库事务特性 ACID

A:Atomicity,原子性说到底就是,一条绳子上的蚂蚱,谁都不能出事,一起成功一起失败
C:consistency,一致性也可以叫做数据完整性,事务在提交执行以后,必须有状态的改变
I:isolation,隔离性,并发的多个事务之间不能数据干扰,相互独立隔离
D:durability,持久性,当事务提交以后,对数据库进行的数据状态操作应该被记录下来,持久化保存
           

4、数据库隔离级别

4.1 隔离概念:

隔离级别是在多个事务同时进行更改和执行查询时,对性能和结果的可靠性、一致性和重现性之间的平衡进行微调的设置。

4.1 隔离级别:

InnoDB提供了SQL:1992标准描述的所有四个事务隔离级别:

READ UNCOMMITTED 读取未提交
READ COMMITTED 读取已提交
REPEATABLE READ 可重复读
SERIALIZABLE 串行化
           

InnoDB 的默认隔离级别是

REPEATABLE READ

4.1.1 READ UNCOMMITTED

mysql 事务特性以及隔离级别

如图,为一次示例读取未提交,

t1 开启事务 A
t2 开启事务 B
t3 事务 A 查询 username = ‘tanxi’
t4 事务 B 修改值 username = 'tanxi02'
t5 事务 A 查询 username = 'tanxi02'
           

很明显可以看出,事务 A 读取到了 事务 B 的未提交的数据,造成了脏读,这是最不安全的隔离级别,这种隔离级别解决不了任何问题

4.1.2 READ COMMITTED

mysql 事务特性以及隔离级别

如图,为一次示例读取已提交

t1 开启事务 A
    t2 开启事务 B
    t3 事务 A 查询 username = ‘tanxi’
    t4 事务 B 修改值 username = 'tanxi02'
    t5 事务 A 查询 username = 'tanxi'
    t6 事务 B 提交事务
    t7 事务 A 查询 username = 'tanxi02'
           

该隔离级别解决了 4.1.1 的脏读,但是不能解决不可重复读,这是不被允许的数据读取方式

4.1.3 REPEATABLE READ

mysql 事务特性以及隔离级别

如图,为一次示例可重复读

t1 开启事务 A
t2 开启事务 B
t3 事务 A 查询 username = ‘tanxi’
t4 事务 B 修改值 username = 'tanxi02'
t5 事务 A 查询 username = 'tanxi'
t6 事务 B 提交事务
t7 事务 A 查询 username = 'tanxi'     
           

该隔离级别解决了不可重复读的问题,事务 B 的事务提交没有影响到事务 A 的查询结果

4.1.4 SERIALIZABLE

mysql 事务特性以及隔离级别

如图,为一次示例串行化

t1 开启事务 A
t2 开启事务 B
t3 事务 A 查询 username = ‘tanxi’
t4 事务 B 修改值 username = 'tanxi02'
t5 事务 A 查询 ,阻塞等待
t6 事务 B 提交事务
t7 事务 A 查询 username = 'tanxi'
           

该隔离级别可以避免脏读以及不可重复读,但是会阻塞 sql,也就是写读不能并发。性能很差

5、总结说明

在 mysql 的 innodb 引擎中,InnoDB 引擎默认的行锁算法.,Next-Key locks 可以避免幻读,有兴趣的同学可以去官网了解。https://dev.mysql.com/doc/refman/5.7/en/

继续阅读