事务的隔离级别:
1 READ UNCOMMITED(未提交读 ) 事务中的修改,在没有提交的时候,其他事务都是可以见的,
会产生脏读数据(未提交的数据,如果事务回滚,则当前修改的数据就是错误的)
2 READ COMMITED(提交读):事务从开始到提交之前,所做的修改对其他的事务都是不可见的,
会产生不可重复读(同一个事务中,由于修改导致两次查询结果可能不同)
3 REPEATABLE READ(可重复读):同一个事务中多次读取,查询结果是一样的,
会产生幻读数据(一个事务在读取数据时候,另一个事务插入新数据,导致查询结果不一样)
4 SERIALIZABLE(可串行化):强制事务串行执行,
一、理解事务的隔离级别(个人认为隔离级别就是数据的锁处理的):
为什么用事务:
在程序执行curd的时候,需要保证一个操作的完整性,我们通常在这个过程中添加事务,保证全部执行或全部不执行
事务隔离级别问题:
当多个事务并发执行的时候,需要处理好隔离级别,否则会产生脏读,幻读,不可重复读。
随着隔离级别的升高,数据库的并发能力会变低。
二、隔离级别种类:
定义的标准隔离级别有四种,从高到底依次为:可序列化(Serializable)、可重复读(Repeatable reads)、提交读(Read committed)、未提交读(Read uncommitted)。
一)未提交读(Read uncommitted):
表现:一个事务中更新数据未提交,在另一个事务中可以查询到这个未提交的数据,
问题:一旦回滚则会出现数据不一致的问题,这种就是(脏读即数据还是没有用的数据)。
锁情况:更新的数据时候会添加 排它锁,但查询数据并没有添加任何锁。
1) 更改数据隔离级别为未提交读,然后更新不提交,执行查询
SELECT @@tx_isolation;
SELECT @@session.tx_isolation;
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
START TRANSACTION;
update account_balance set balance=3 where account_id=1;
--更新数据不提交
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
2) 在另一个session中直接查询就可以查询未提交的数据
SELECT * FROM account_balance where account_id=1;
二)提交读(Read committed):
表现:一个事务中,两次查询中间如果有更新操作,则两次查询出来的数据不一样,但可以解决脏读问题。
问题:重复读(即重复读取一个数据结果不一样)
锁:每次查询数据后立刻释放行锁。
1)第一个session,执行查询条件,开启事务后,执行到第一个查询语句,然后执行更新 ,接着执行剩下的session,两次查询结果不一样。
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED ;
START TRANSACTION;
SELECT * FROM account_balance where account_id=1;
SELECT * FROM account_balance where account_id=1 LOCK IN SHARE MODE;
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
2)执行更新操作
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED ;
START TRANSACTION;
update account_balance set balance=5 where account_id=1;
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
三)可重复读(Repeatable reads):可以解决重复读问题即解决两次查询结果不一样问题
表现:一个事务中,两次查询结果一样
问题:幻读(两次查询过程中,查询结果集中间插入一条数据,则即使查询事务没结束也能查询出来,两次查询结果集的结果不一样,就像幻想一样)
锁:查询的结果集中,会对结果集添加行级共享锁,事务结束才会释放。
1)第一次查询不添加任何锁,然后执行2中的插入,提交后,在执行第二个查询,会多出来一条数据,这是幻读
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
START TRANSACTION;
SELECT * FROM account_balance where account_id>1;
SELECT * FROM account_balance where account_id>1 LOCK IN SHARE MODE;
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
2) 查询第一个后插入数据:
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
START TRANSACTION;
insert into account_balance values( 3,200)
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
四)可序列化(Serializable)
产生幻读的原因是事务一在进行范围查询的时候没有增加范围锁(range-locks:给SELECT 的查询中使用一个“WHERE”子句描述范围加锁),
所以导致幻读。
锁:事务在读取数据时,必须先对其加 表级共享锁 ,直到事务结束才释放;
事务在更新数据时,必须先对其加 表级排他锁 ,直到事务结束才释放。
五)锁机制:
锁类型:悲观锁、乐观锁
乐观锁:表中添加版本号实现
悲观锁:数据库自带包括表的锁和行级别的锁(共享所和排它锁)