Mysql事务隔离级别
- READ UNCOMMITTED(读未提交)
- 允许事务读取未被其他事务提交的变更。可能会导致脏读、不可重复读、幻读。
- READ COMMITTED(读已提交)
- 只允许事务读取已经被其他事务提交的变更。可以避免脏读,但可能会导致不可重复读、幻读。
- REPEATABLE READ(可重复读)
- 确保事务可以多次从一个字段读取相同的值,在这个事务持续期间,禁止其他事务更新这个字段。可以避免脏读和不可重复读,但可能导致幻读。
- SERIALIZABLE(串行化)
- 提供严格的事务隔离。事务串行化顺序执行,可以避免所有并发问题,但性能最差。
Mysql默认的隔离级别
mysql> show variables like '%isolation%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set, 1 warning (0.00 sec)
mysql>
READ UNCOMMITTED(读未提交)
存在脏读问题
SessionB读取到SessionA尚未提交的数据。
- 准备环境条件:
set autocommit = 0;
set session transaction isolation level read uncommitted;
- 执行流程
SessionA | SeesionB |
---|---|
begin; | |
begin; | |
update account set money = money - 100 where name = ‘kevin’; | |
select * from account where name = ‘kevin’; | |
rollback; | |
select * from account where name = ‘kevin’; | |
select * from account where name = ‘kevin’; |
在SessionB的第二条指令,查询到SessionA尚未提交的数据,这就是脏读。
READ COMMITTED(读已提交)
不存在脏读问题,但是存在不可重复读问题
- 准备环境条件:
set autocommit = 0;
set session transaction isolation level read committed;
- 执行流程
SessionA | SeesionB |
---|---|
begin; | |
begin; | |
update account set money = money - 100 where name = ‘kevin’; | |
select * from account where name = ‘kevin’; | |
commit; | |
select * from account where name = ‘kevin’; | |
select * from account where name = ‘kevin’; |
1、脏读问题:(不存在)
SessionA没有提交之前,SessionB是读取不到变化的,没有脏读问题
2、不可重复读问题:(存在)
SessionA虽然事务提交了,但是SessionB的事务还没有提交。但是却感知到了SessionA的变化之后的值。这导致SessionB在同一个事务中,先后读取的账户的值是不一样的。
REPEATABLE READ(可重复读)
没有出现脏读,不可重复读问题
- 准备环境条件:
set autocommit = 0;
set session transaction isolation level repeatable read;
- 执行流程
SessionA | SeesionB |
---|---|
begin; | |
begin; | |
update account set money = money - 100 where name = ‘kevin’; | |
select * from account where name = ‘kevin’; | |
commit; | |
select * from account where name = ‘kevin’; | |
select * from account where name = ‘kevin’; |
不管SessionA提交前后,SessionB一直保持这开启事务之后读取到的数值。没有出现脏读,不可重复读问题。
SERIALIZABLE(串行化)
没有出现脏读,不可重复读问题
- 准备环境条件:
set autocommit = 0;
set session transaction isolation level serializable;
- 执行流程
SessionA | SeesionB |
---|---|
begin; | |
begin; | |
update account set money = money - 100 where name = ‘kevin’; | |
select * from account where name = ‘kevin’; | |
commit; |
对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
学习交流,知识分享