隔离级别:
READ UNCOMMITTED 读未提交
READ COMMITTED 读以提交
REPEATABLE READ 可重复读
SERIALIZABLE 串行化
隔离级别造成3个问题:
脏读:一个事务处理过程里读取了另一个未提交的事务中的数据。
不可重复读:一个事务内读取表中的某一行数据,多次读取结果不同。
幻读:指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致
解决3个问题:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交 | √ | √ | √ |
读已提交 | × | √ | √ |
可重复读 | × | × | √ |
串行化 | × | × | × |
查询隔离级别的
SELECT @@global.tx_isolation;
设置隔离级别
set global transaction isolation level read committed;
案例演示:
读未提交(Read Uncommitted)
产生的问题:
在读未提交 隔离级别下,一个事务会读到其他事务未提交的数据的,即存在脏读问题。第二个事务都还没commit到数据库呢,第一个事务就读到了。
读已提交(Read committed)
解决脏读:
将隔离级别从读未提交设置为读已提交级别
图一:为事务A
图二:为事务B
当事务B没有commit的时候,事务A前两次查都是正确的金额1000,当事务B进行了commit后,事务A查询的金额就是事务B修改后的金额,解决了脏读的问题。
读已提交产生新的问题:
事务A在读取金额为1000,当事务B修改了金额并且提交了事务修改,那么数据库现在金额变为1200,而事务A在次读取时金额为1200,那么事务A第一次读和第二次读的金额数据不一致,这个问题就是不可重复读的问题。
可重复读( Repeatable Read)
解决不可重复读
将隔离级别从读已提交设置为可重复读。
图一:事务A
图二:事务B
在事务B提交了修改sql后,事务A在自己的事务中没有提交,两次读取都是相同的结果,解决了不可重复读的问题。
可重复读产生新的问题幻读:
当我事务A没有提交事务。事务B修改了而且也提交了,事务A没有提交事务的情况下,读取的数据都是1000,解决了不可重复读的问题。
但是现在事务B插入一条数据,并且提交了事务。现在事务A提交事务了,然后事务A在查询所有的数据时,发现多了一条数据,这就产生了幻读问题
串行化(SERIALIZABLE )
解决幻读问题
将隔离界别从可重复读设置为串行化
图一和图三:事务A
图二和图四:事务B
事务A开启事务,执行查询所有数据的sql,但是不提交事务。事务B开始事务,新增一条数据,但是这个时候新增不进去,被阻塞了。
当事务A提交事务后,事务B就可以新增成功。
因为隔离级别是串行化,当一个事务未执行完,其他事务必须等待第一个事务提交后才能进行事务操作,解决了幻读,不可重复读,脏读问题。