前言
在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。数据库事务的隔离级别有4个,下面话不多说了,来一起看看详细的介绍吧。
数据库事务有四种隔离级别:
未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据。 提交读(Read Committed):只能读取到已经提交的数据,Oracle等多数数据库默认都是该级别。 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻读。 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。上面这样的教科书式定义第一次接触事务隔离概念的朋友看了可能会一脸懵逼,下面我们就通过具体的实例来解释四个隔离级别。
首先我们创建一个user表:
CREATE TABLE user ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE `uniq_name` USING BTREE (name)) ENGINE=`InnoDB` AUTO_INCREMENT=10 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; |
读未提交隔离级别
我们先将事务的隔离级别设置为read committed:
mysql> set session transaction isolation level read uncommitted;Query OK, 0 rows affected (0.00 sec)mysql> select @@session.tx_isolation;+------------------------+| @@session.tx_isolation |+------------------------+| READ-UNCOMMITTED |+------------------------+1 row in set (0.00 sec) |
在下面我们开了两个终端分别用来模拟事务一和事务二,p.s: 操作一和操作二的意思是按照时间顺序来执行的。
事务1
mysql> start transaction; # 操作1Query OK, 0 rows affected (0.00 sec)mysql> insert into user(name) values('ziwenxie'); # 操作3Query OK, 1 row affected (0.05 sec) |
事务2
mysql> start transaction; # 操作2Query OK, 0 rows affected (0.00 sec)mysql> select * from user; # 操作4+----+----------+| id | name |+----+----------+| 10 | ziwenxie |+----+----------+1 row in set (0.00 sec) |
从上面的执行结果可以很清晰的看出来,在read uncommited级别下面我们在事务一中可能会读取到事务二中没有commit的数据,这就是脏读。
读提交隔离级别
通过设置隔离级别为committed可以解决上面的脏读问题。
mysql> set session transaction isolation level read committed; |
事务一
mysql> start transaction; # 操作一Query OK, 0 rows affected (0.00 sec)mysql> select * from user; # 操作三+----+----------+| id | name |+----+----------+| 10 | ziwenxie |+----+----------+1 row in set (0.00 sec)mysql> select * from user; # 操作五,操作四的修改并没有影响到事务一+----+----------+| id | name |+----+----------+| 10 | ziwenxie |+----+----------+1 row in set (0.00 sec)mysql> select * from user; # 操作七+----+------+| id | name |+----+------+| 10 | lisi |+----+------+1 row in set (0.00 sec)mysql> commit; # 操作八Query OK, 0 rows affected (0.00 sec) |