事务的隔离级别
数据库事务的隔离级别有4个,由低到高依次为Read uncommitted(读未提交)、Read committed(读已提交)、
Repeatable read(可重复读取)、Serializable(序列化),后三个级别可以逐个解决脏读、不可重复读、幻象读这几类问题。
1、Read uncommitted(读未提交):
如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。这样就避免了更新丢失,却可能出现脏读。也就是说事务B读取到了事务A未提交的数据。
2、Read committed(读已提交):
读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。该隔离级别避免了脏读,但是却可能出现不可重复读。事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
3、Repeatable read(可重复读取):
可重复读是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,即使第二个事务对数据进行修改,第一个事务两次读到的的数据是一样的。这样就发生了在一个事务内两次读到的数据是一样的,因此称为是可重复读。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。这样避免了不可重复读取和脏读,但是有时可能出现幻象读。(读取数据的事务)这可以通过“共享读锁”和“排他写锁”实现。(这是数据库的默认隔离级别)
4、Serializable(序列化):
提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大
脏读:读取事务还未提交的数据
流程 | session1 | session2 |
事务1先开启事务 | 开启事务 | |
事务2开启事务 | 开启事务 | |
两个事务同时查询一条数据 | 查询id=1的数据 | 查询id=1的数据 |
事务1进行修改数据 | 修改id=1的数据 | |
因为隔离级别为Read uncommitted(读未提交),使用排他写锁实现,事务2还可以继续查看id=1的数据 | 查看未提交的id=1的数据 |
解决方案:解决脏读使用Read uncommitted(读未提交)以上隔离级别
不可重复度:两次读取数据结果不一致
流程 | session1 | session2 |
事务1先查询了id=1的数据 | select id=1 的数据 | |
事务2在事务1查询数据后更新数据 | update id=1的数据 | |
事务1再次查询数据 | select id=1 的数据 | |
结果 | 查询结果不一样 |
解决:使用Repeatable read(可重复读取)以上隔离级别
幻读:当前事务读取到其他事务提交的数据,但找不到这条数据
流程 | session1 | session2 |
事务1查询id=1的数据,不存在添加 | select id=1的数据 | |
事务2也查询id=1的数据 | 没有发现id=1的数据,准备新增 | select id=1的数据 |
也没有发现id=1的数据,准备新增 | ||
因为其他事情耽误了,事务2先进行了提交 | 这里去做其他事情了 | insert 一条id=1的数据,commit |
事务1再去新增 | 出现主键冲突或者数据已存在 | |
出现幻读 | 查询id=1的数据,查不到,也添加不了 |
解决:使用最高级别的序列化级别,但是会产生一定的性能
隔离级别:非序列化
程序在运行过程中,通常会有多个事务同事执行,往往是并发运行的
级联回滚:一定时间内有两个及以上的事务在运行,由于最先开始的事务出现了“异常”,导致其他事务报错而进行回滚
session1 | session2 | session3 |
select * from table id=1; | ||
update table set count = 1 where id=1 | select * from table id=1; | |
update table set count = 2 where id=1 | ||
等待事务1提交 | 等待事务1提交 | |
执行到错误的sql语句,报错 | 因为事务1报错异常回滚 | 因为事务1报错异常回滚 |
这里出现的问题主要是因为事务2,事务3依赖事务1完成的某些业务,为了保证数据的一致性,全部回滚