剑客
关注科技互联网

spring-transaction-isolation

事务隔离级别的语义:当前事务执行过程中,通过select,update,delete 操作,对其他事务的影响,反过来也是如此,通俗的说就是 当前事务是否可以看到其他事务的操作结果。

1、如何查询当前数据库的隔离级别(我们只讨论mysql的事务隔离级别)

select @@tx_isolation;
SELECT @@session.tx_isolation; 
SELECT @@global.tx_isolation; 
//设置
set tx_isolation='read-committed';

2、不同隔离级别的影响

ANSI/ISO SQL标准定义了4中事务隔离级别:未提交读(read uncommitted),提交读(read committed),重复读(repeatable read),串行读(serializable)。

对于不同的事务,采用不同的隔离级别分别有不同的结果。不同的隔离级别有不同的现象。主要有下面3种现在:

1、脏读(dirty read):一个事务可以读取另一个尚未提交事务的修改数据。

2、不可重复读(nonrepeatable read):在同一个事务中,同一个查询在T1时间读取某一行,在T2时间重新读取这一行时候,这一行的数据已经发生修改,可能被更新了(update),也可能被删除了(delete)。

3、幻像读(phantom read):在同一事务中,同一查询多次进行时候,由于其他插入操作(insert)的事务提交,导致每次返回不同的结果集。

不同的隔离级别有不同的现象,并有不同的锁定/并发机制,隔离级别越高,数据库的并发性就越差,4种事务隔离级别分别表现的现象如下表:


隔离级别

脏读

非重复读

幻像读
read uncommitted 允许 允许 允许
read committed 允许 允许
repeatable read 允许
serializable

mysql 默认的隔离级别是:REPEATABLE-READ 

注意:

1、repeatable read 允许幻读,这是ANSI/ISO SQL标准的定义要求,运行幻读依然有非常大的隐患,mysql 在repeatable read  即可满足没有幻读的要求。


2、不可重复读和幻读的区别:不可重复读的重点是修改,幻读的重点是插入或者删除了新数据。两都会造成系统错误,但是避免的方法则区别比较大,

对于前者, 只需要锁住满足条件的记录,对于后者, 要锁住满足条件及其相近的记录。

举例验证:

1、建表

CREATE TABLE `t_pai` (
   `id` bigint(20) NOT NULL AUTO_INCREMENT,
   `name` varchar(10) NOT NULL,
   `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   PRIMARY KEY (`id`),
   KEY `idx_update_time` (`update_time`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8

2、验证不存在幻读

client1 :SET autocommit= 0;

client2:SET autocommit= 0;

client1:START TRANSACTION;

client2:

START TRANSACTION;

INSERT INTO t_pai (`name`) VALUE ("2");

COMMIT;

client1:SELECT * FROM t_pai;

结果:查询不到数据:

client1:

COMMIT;

SELECT * FROM t_pai;

结果:有数据。

spring支持的隔离级别:

隔离级别
含义

ISOLATION_DEFAULT 使用后端数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
ISOLATION_READ_COMMITTED 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
ISOLATION_REPEATABLE_READ 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
ISOLATION_SERIALIZABLE 最高的隔离级别,完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读,也是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的

spring 在使用事务的时候,一般不会设置隔离级别,而采用默认的隔离级别,即底层数据库的隔离级别。

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址