时间:2021-07-01 10:21:17 帮助过:11人阅读
书本解释 : 隔离级别都规定了一个事务中所做修改,哪些在事务内和事务间是可见的。
上面两段理解的区别在于是否存在事务内可见性的规定。我在各个级别似乎没有看到
下面开始说明MYSQL的四种隔离级别,先准备一张学生表:
mysql> CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL DEFAULT ‘‘,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
只有id(主键自增)与name字段
READ UNCOMMITTED(未提交读)
事务中修改没有提交对其他事务也是可见的,俗称脏读。非常不建议使用。
实例演示
客户端A和B设置隔离级别为未提交读
mysql> SET SESSION TX_ISOLATION=‘READ-UNCOMMITTED‘;
客户端A与B开启事务并查询student
mysql> BEGIN;
mysql> SELECT * FROM student;
Empty set (0.00 sec)
客户端A和B都是空数据
客服端B插入一条新的数据
mysql> INSERT INTO student(name) VALUES("polo");
Query OK, 1 row affected (0.00 sec)
此时事务未提交,客服端A查看student表
$ SELECT * FROM student;
mysql> SELECT * FROM student;
+----+------+
| id | name |
+----+------+
| 1 | polo |
+----+------+
1 row in set (0.00 sec)
客户端A看到B未提交的修改
客户端B执行回滚操作
mysql> ROLLBACK
成功之后,客户端A查看student表
mysql> SELECT * FROM student;
Empty set (0.00 sec)
客户端A查看数据为空
以上可以看出未提交读隔离级别的危险性,对于一个没有提交事务所做修改对另一个事务是可见状态,容易造成脏读。非特殊情况不得使用此级别
READ COMMITTED(提交读)
多数数据库系统默认为此级别(MYSQL不是)。已提交读级别即为一个事务只能已提交事务所做的修改,也就解决了未提交读的问题,即脏读的问题。
实例演示
客户端A和B设置隔离级别为已提交读
mysql> SET SESSION TX_ISOLATION=‘READ-COMMITTED‘;
客户端A与B开启事务并查询student
mysql> BEGIN;
mysql> SELECT * FROM student;
Empty set (0.00 sec)
客户端A和B都为空
客服端B插入一条新的数据,不提交
mysql> INSERT INTO student (name) VALUES(‘polo‘);
客户端A查看student
mysql> SELECT * FROM student;
Empty set (0.00 sec)
注意这里与上面不同了,在客户端B没有提交事务情况下无数据
下面客户端B提交事务
mysql> COMMIT;
客户端A再次查看student表。
mysql> SELECT * FROM student;
+----+------+
| id | name |
+----+------+
| 1 | polo |
+----+------+
1 row in set (0.00 sec)
成功读取到客户
从上面的示例可以看出,提交读没有了未提交读的问题,但我们可以看到在客户端A的一个事务中执行两次同样的SELECT语句得到不同结果,因此已提交读又被称为不可重复读。同样筛选条件可能得到不同的结果。
REPEATABLE READ(可重复读)
如其名也,解决已提交读不可重复读取的问题。
示例演示
客户端A和B设置隔离级别为可重复读
mysql> SET SESSION tx_isolation=‘REPEATABLE-READ‘
客户端A与B开启事务并查看
mysql> BEGIN;
mysql> SELECT * FROM student;
+----+------+
| id | name |
+----+------+
| 1 | polo |
+----+------+
1 rows in set (0.00 sec)
客服端B更新polo为jeff,并提交事务
mysql> UPDATE student SET name=‘jeff‘ WHERE id=1;
mysql> COMMIT
客户端A查看student表
mysql> SELECT * FROM student;
+----+------+
| id | name |
+----+------+
| 1 | jeff |
+----+------+
1 rows in set (0.00 sec)
注意客户端A查看数据未变,没有不可重复读问题
客户端A提交事务,并查看student表
mysql> COMMIT;
mysql> SELECT * FROM student;
+----+------+
| id | name |
+----+------+
| 1 | polo |
+----+------+
1 rows in set (0.00 sec)
上面实例可知,可重复读两次读取内容一样。数据库这级别并没有解决幻读的问题。但是MYSQL在可重复读基础上增加了MVCC机制解决了此问题,实例无法演示幻读效果。
那什么是幻读?首先,可重复读锁定范围为当前查询到的内容,如执行
mysql> SELECT * FROM student WHERE id>=1
锁定的即id>=1查到的行,为行级锁。如另一事务执行并默认提交以下语句
mysql> INSERT INTO student (name) VALUES (‘peter‘);
新增的这行并没有被锁定,此时读取student
mysql> SELECT * FROM student WHERE id>=1;
+----+---------+
| id | name |
+----+---------+
| 1 | polo |
| 2 | peter |
+----+---------+
2 rows in set (0.00 sec)
便出现了幻读
除了使用MYSQL的MVCC机制,还可以使用可串行化隔离级别解决此问题。
SEAIALIZABLE(可串行化)
可串行化是最高隔离级别,强制事务串行执行。执行串行了也就解决了一切的问题,这个级别只有在对数据一致性要求非常严格且没用并发的情况下使用
实例演示
客户端A和B设置隔离级别为可串行化
mysql> SET SESSION tx_isolation=‘SERIALIZABLE‘;
客户端A执行查询
mysql> SELECT * FROM student WHERE id<4;
+----+---------+
| id | name |
+----+---------+
| 1 | polo |
| 2 | peter |
+----+---------+
2 rows in set (0.00 sec)
客户端B执行新增
mysql> INSERT INTO student (name) VALUES(‘tiger‘);
好的!效果出现了,此时我们会发现INSERT语句被阻塞执行,原因就是A执行了查询表student同时满足id<4,已被锁定。如果查询表student条件为id<3,则新增语句可正常执行。
Mysql事务-隔离级别
标签:特性 max ges val ref select mysql session for