`

隔离级别理解

 
阅读更多

 

事务的隔离级别:

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”子句描述范围加锁),

  所以导致幻读。

  锁:事务在读取数据时,必须先对其加 表级共享锁 ,直到事务结束才释放;

      事务在更新数据时,必须先对其加 表级排他锁 ,直到事务结束才释放。

 

五)锁机制:

锁类型:悲观锁、乐观锁

乐观锁:表中添加版本号实现

悲观锁:数据库自带包括表的锁和行级别的锁(共享所和排它锁)

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics