关系型数据库都具有一套事务级别,以前的开发和学习过程我很少关注过这个概念,今天搜集了一些资料,在
结合spring声明式事务学习的同时,总结一下数据库的事务级别与操作。
READ-UNCOMMITTED: 未提交读 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )
READ-COMMITTED: 提交读 会出现不可重复读、幻读问题(锁定正在读取的行)
REPEATABLE-READ: 可重复读 会出幻读(锁定所读取的所有行)
SERIALIZABLE: 序列化 保证所有的情况不会发生(锁表)
详细说明:
未提交读——这通常称为 'dirty read':non-locking SELECT 的执行使我们不会看到一个记录的可能更早的版本;
因而在这个隔离级别下是非 'consistent' reads;这级隔离级别的运作如同 READ COMMITTED。处于这个隔离级的
事务可以读到其他事务还没有提交的数据。如果这个事务使用其他事务未提交的变化作为计算的基础,然后那些未
提交的变化被他们的父事务撤销,则会导致误差。
提交读——在一个事务中已经COMMIT的数据可以在其他事务中看到。如果这个事务频繁提交的话,其他的大的查询
事务中可能会得到多个不同的结果。
可重复读——这是 InnoDB 默认的事务隔离级。在一个事务中所有读都是连续的。
序列化——提供最大程度的隔离,如果每个事务都以这种隔离级运行就会影响Mysql的性能,因为需要大量的资源来
使大量事务在任一时刻不被看到。如果一个事务在执行一个SELECT操作,另外的事务不允许执行UPDATE操作,这个
隔离级别下的SELECT操作被阴式地转换为 SELECT ... LOCK IN SHARE MODE。
不可重复读的重点是修改 :
同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了
幻读的重点在于新增或者删除
同样的条件 , 第 1 次和第 2 次读出来的记录数不一样
MySQL InnoDB存储引擎的事务隔离级别
查看InnoDB系统级别的事务隔离级别:
以下为引用的内容:
mysql> SELECT @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.00 sec)
查看InnoDB会话级别的事务隔离级别:
以下为引用的内容:
mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
修改事务隔离级别:
以下为引用的内容:
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
InnoDB的可重复读隔离级别和其他数据库的可重复读是有区别的,不会造成幻象读(phantom read),所谓幻象读,
就是同一个事务内,多次select,可以读取到其他session insert并已经commit的数据。下面是一个小的测试,证明
InnoDB的可重复读隔离级别不会造成幻象读。测试涉及两个session,分别为session 1和session 2,隔离级别都是
repeateable read,关闭autocommit
以下为引用的内容:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> set autocommit=off;
Query OK, 0 rows affected (0.00 sec)
session 1 创建表并插入测试数据
mysql> create table test(i int) engine=innodb;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values(1);
Query OK, 1 row affected (0.00 sec)
session 2 查询,没有数据,正常,session1没有提交,不允许脏读
mysql> select * from test;
Empty set (0.00 sec)
session 1 提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
session 2 查询,还是没有数据,没有产生幻象读
mysql> select * from test;
Empty set (0.00 sec)
以上试验版本:
mysql> select version();
+-------------------------+c
| version() |
+-------------------------+
| 5.0.37-community-nt-log |
+-------------------------+
1 row in set (0.00 sec)
spring的声明式事务的隔离级别与数据库的如出一辙,共5种级别:
1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
另外四个与JDBC的隔离级别相对应
2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
这种隔离级别会产生脏读,不可重复读和幻像读。
3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
除了防止脏读,不可重复读外,还避免了幻像读。
来源:https://www.cnblogs.com/shiyangxt/archive/2009/02/11/1388519.html