Read uncommitted(读取未提交内容)
在该隔离级别,所有的事务都可以看到其他未提交的事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他的级别好多少。读取未提交的数据,也被称为脏读。
模拟实例: 需要两个终端
#注意,切换隔离级别建议退出mysql终端重新登录,否则有可能修改失败
A终端:
#设置可以隔离模式
mysql> set global tx_isolation="READ-UNCOMMITTED";
Query OK, 0 rows affected (0.00 sec)
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)
mysql> use wangdk;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> desc user;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | char(20) | NO | | | |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> select * from user;
Empty set (0.00 sec)
#开启事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
#注意这里并未提交 commit
mysql> insert into user(name) values("test");
Query OK, 1 row affected (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
B终端:
mysql> set global tx_isolation="READ-UNCOMMITTED";
Query OK, 0 rows affected (0.00 sec)
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)
mysql> use wangdk;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
#注意:A终端并未 commit 提交事务。这里已经可以查到这个事务的数据,但是数据随时可以回滚的。
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 12 | test |
+----+------+
1 row in set (0.00 sec)
#A终端 rollback 后数据消失
mysql> select * from user;
Empty set (0.00 sec)
READ-COMMITTED (读取提交内容)
这是大多数数据库系统的默认系统隔离级别(但不是mysql默认的)。它满足了隔离的简单定义:事务的数据只有被提交才能被查询到。这种隔离级别也成为不可重复读,
以为同一事务的其他实例处理期间可能会有新的commit,所以同一个select会有不同的结果。
A终端:
mysql> set global tx_isolation="READ-COMMITTED";
Query OK, 0 rows affected (0.00 sec)
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)
mysql> use wangdk;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 13 | 1 |
| 14 | 2 |
| 15 | 4 |
+----+------+
3 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
#删除一条数据,未提交事务
mysql> delete from user where id = 15;
Query OK, 1 row affected (0.00 sec)
#删除后A终端已经发生变化
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 13 | 1 |
| 14 | 2 |
+----+------+
2 rows in set (0.00 sec)
B终端:
mysql> set global tx_isolation="READ-COMMITTED";
Query OK, 0 rows affected (0.00 sec)
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)
mysql> use wangdk;
Database changed
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 13 | 1 |
| 14 | 2 |
| 15 | 4 |
+----+------+
3 rows in set (0.00 sec)
#事务未提交B终端未发生变化
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 13 | 1 |
| 14 | 2 |
| 15 | 4 |
+----+------+
3 rows in set (0.00 sec)
Repeatable READ (可以重复读)
这是Mysql默认的事务隔离级别,它确保同一事务的多个实例在并发读数据时候,会看到同样的数据行。不过理论上,这会导致另一个问题(幻读)
(Phantom Read)简单的说,幻读是指永固读取某一个范围的数据行时,另一个事务又在该范围内插入了新行,当用户在读取该范围的
数据行是,会发现有新的幻影行,Innodb和falcon存储引擎通过多版本并发控制解决该问题 (MVCC,Multiversion Concurrency Control)机制
理解:A begin 读取的数据 和 B begin 读取的数据相同,如果B插入了数据,并commit ,A等待自己的事务完毕后才能重新读取B事务提交的数据。
模拟:
A终端:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
B终端
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from user;
+----+--------+
| id | name |
+----+--------+
| 21 | wangdk |
+----+--------+
1 row in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into user(name) values("hello");
Query OK, 1 row affected (0.01 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
+----+--------+
| id | name |
+----+--------+
| 21 | wangdk |
| 22 | hello |
+----+--------+
2 rows in set (0.00 sec)
A终端:
#并未查找到B事务的数据
mysql> select * from user;
+----+--------+
| id | name |
+----+--------+
| 21 | wangdk |
+----+--------+
1 row in set (0.00 sec)
mysql> commit;
#必须等待A事务完成,才能读取到B事务已经提交上来的数据
mysql> select * from user;
+----+--------+
| id | name |
+----+--------+
| 21 | wangdk |
| 22 | hello |
+----+--------+
3 rows in set (0.00 sec)
Serializable(可串行化)
这种最高的隔离级别,它通过强制事务排序,使之不能相互冲突。从而解决幻读的问题。简而言之,它是在每个读的数据行上加上共享锁
在这个级别,可能导致大量的超时和锁竞争
实例:
A终端:
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE |
+----------------+
1 row in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from wangdk.user;
+----+--------+
| id | name |
+----+--------+
| 21 | wangdk |
| 22 | hello |
| 23 | hello |
+----+--------+
3 rows in set (0.00 sec)
#先不要提交,要先操作B终端,最后一句在执行commit
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
B 终端:
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE |
+----------------+
1 row in set (0.01 sec)
mysql> select * from wangdk.user;
+----+--------+
| id | name |
+----+--------+
| 21 | wangdk |
| 22 | hello |
| 23 | hello |
+----+--------+
3 rows in set (0.00 sec)
#看到了么,更新秒数,等待A终端commit以后,这一句才会执行
mysql> update wangdk.user set name="wangdk1" where id = 21;
Query OK, 1 row affected (17.09 sec)
Rows matched: 1 Changed: 1 Warnings: 0