事务特性:
ACID
特性 | 说明 | |
---|---|---|
A 原子性(针对执行单元) | Atomic,一个事务并不一定是一条sql,可能是将多条sql捆绑在一块,而原子性保证这一整块的sql要都成功,要么都失败,然后回滚 | |
C一致性(针对整体状态转变)) | Consistency,事务保证让数据库从一个一致性状态变换到另一个一致性状态 | 比如a,b账户一共500,无论a,b间怎么转,事务结束后钱加起来都是500 |
I隔离性(针对并发事务) | Isolation,多个线程并发操作同一张表时,数据库给每个线程开启一个事务,不能被其他事务干扰,多个事务之间相互隔离 | 比如是两个事务,A事务认为B事务在A开始前结束,或者是A结束后才开始 |
D持久性(针对数据保存) | Durablility,指的是一旦事务被提交,那么对数据哭的影响必须是永久性的,即便在数据库系统遇到故障的情况下也是这样 | 比如系统宕机,事务一开始,就会将数据写入到redolo文件中,提交后,redolog中的sql在内存中执行,数据写入到缓冲中,然后定时将缓冲中数据刷入磁盘;然后删除redolog 中相应记录(此时持久化已经成功)如果断电,缓冲中的数据会消失,但是redolog 中还有记录,重启自动执行relog内容 |
事务隔离性会出现的问题
以转钱为例
张三(老板)与李四(职员)
术语 | 描述 | 简化 |
---|---|---|
脏读 | 张三开启事务,给李四转500块,但是还未提交事务,然后通知张三去查询余额,发现钱到账了,后面张三操作有误,事务回滚,转账失败 | 读到未提交的数据 |
不可重复读 | 单个事物多次查询同一条记录,但是返回的记录在查询间隔内被其他事务修改了,导致获取到不同的值 | 注意与脏读的区别:不可重复读,是读取到了前一个事务提交的数据,脏读是读取到其他事物未提交的数据 |
幻读 | 张三给所有员工交社保,有一个字段标记为是否缴纳社保,设置为1,这时候人事部新来了一位员工,将其记录插入表中,而他的社保字段默认是0,如果张三再检查一下是刚刚操作的缴纳数据,发现还有一个没缴纳,而这个数据是来自其他事物的,就像是幻觉,这就是幻读 | 与不可重复读都是读取到其他事物提交后的数据,但是幻读针对的是一批数据(比如数据个数),不可重复读是针对的同一个记录 |
隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read-uncommitted 读未提交 | 出现 | 出现 | 出现 |
read-committed 读已提交 | 不会出现 | 出现 | 出现 |
repeatable-read 可重复读 | 不会出现 | 不会出现 | 出现 |
serializable 串行化 | 不会出现 | 不会出现 | 不会出现 |
测试隔离级别
设置隔离级别以及查看当前session隔离级别
set session transaction level read committed;
-- level 后的参数可选值 为 read committed/read uncommitted/ repeateable read/serializable
select @@tx_isolation;
1. 测试隔离级别:read-uncommitted(都是此隔离级别)
测试逻辑:
初始余额899
A事务中加钱,B查询余额(变成了999)
A事务回滚,B查询余额(变成了899)
测试效果:
2 .测试隔离级别:read-committed
开启session cmd 窗口,事物隔离级别都设置为
read-committed:
set session transaction isolation level read committed;
测试逻辑:
初始余额999
A事务加钱+100, B事务查询余额 999
A事务提交,B事务查询余额 1099
测试效果:
3. 测试隔离级别repeatable read
测试逻辑:
初始余额为899
事务A使用 read committed 隔离级别
事务B使用repeatable read 隔离级别
事务A加钱,事务B查询余额,依然是旧数据
事务A提交,事务B查询余额,依然是旧数据
事务B提交,查询余额,显示新数据
测试效果:
4. 测试隔离级别serializable(串行化)
这完全将事务的并发性给消除掉,全部进行串行化开启-提交
测试逻辑:
重点测试能否避免幻读(同一事务对一批数据进行两次查询,查询间隔内,这批数据被某个事务修改并提交)
A事务开启,B事务开启, 插入zhangsi记录
A事务中查询全部人员信息,发现会阻塞,没有输出,然后会输出报错
B事务提交
重新开启A事务,查询数据
发现zhangsi 数据被存入
串行化一般不会被使用,这完全是消除了数据库的并发性能.
总结:
- 事务隔离级别说白了是描述的事务之间能否窥探到其他事物的过程中的某些状态
- read-uncommitted:要求最低,可以读取其他事物未提交的状态
- read-committed:只能读取到其他事物提交之后的状态,或者是其他事物开始之前的状态
- repeatable-read:当前事务内部只能读取到开启事务时刻的数据状态,即使在此期间其他事物提交了相关数据修改的事物,也会是视而不见
- serializable:串行化,或者是序列化,所有的事务都在一个队列中,只能按顺序提交如果有事物在修改数据,其他事物也只能等待修改数据的事物提交后,才能查询(可以理解为给表加锁)
参考博客:
隔离级别测试