今天想要了解MySQL隔离级别的具体意思,在MySQL做了几个实验,因为在命令行展示不清楚,就在sqlyog中做了这个实验,首先创建领两张表

#学生表
CREATE TABLE t_student (
s_id int(11) NOT NULL AUTO_INCREMENT COMMENT ‘学号’,
s_name varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT ‘学生姓名’,
s_cid int(11) DEFAULT NULL COMMENT ‘学生所属班级’,
PRIMARY KEY (s_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

#班级表
CREATE TABLE t_class (
c_id int(11) NOT NULL AUTO_INCREMENT COMMENT ‘班号’,
c_name varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT ‘班级名称’,
c_num int(11) DEFAULT NULL COMMENT ‘班级人数’,
PRIMARY KEY (c_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
并且插入如下数据

MySQL事务隔离
MySQL事务隔离
1.首先尝试数据库的最低隔离级别(ru,读未提交),将t_student表中的id为3的学生转入2班。
MySQL事务隔离
(1)首先在客户端1号,开启事务,将为3的学生转入2班,并且未执行班级人数的相应改变,也未提交事务。

MySQL事务隔离
(2)在客户端2号查询t_student表
MySQL事务隔离
(3)在客户端查询班级表
MySQL事务隔离
发现学生表已经发生了改变,班级表没有任何改变。
在客户端1未提交事务的时候,客户端2已经能查出客户端1所操作的数据,假如客户端1的事务发生回滚,那么客户端2号读到的数据也会相应的回滚,但在回滚之前读到的数据就叫脏读。Ru的隔离级别其实违背了事务的隔离性。经典的银行转账,a用户转钱给b用户,虽然执行的是a账户减钱,b账户加钱,但不能只看到一个操作,另一个未操作的画面,在概念上必须将两个操作和为一个操作,并且其他事务读取a与b账户的状态要么一起成功,要么一起失败。
2.将事务设置为read committed(读已提交)

MySQL事务隔离
(1)在客户端1,修改学号为一的学生,暂不提交事务
MySQL事务隔离
(2)在客户端2号开启事务,查询学生表,先不提交事务。

(3MySQL事务隔离)在客户端1提交事务。后在客户端2再次查询学生表。之后提交事务。
MySQL事务隔离
总结:很显然,在客户端2同一事务中,查询到了两次不同的结果。也就是在客户端1中改变数据影响了客户端2的查询,read committed虽然解决了脏读的现象,但却出现了不可重复读的现象。一个事务中所查询的东西不应该改变。
3.将事务设置为repeatable read(可重复读)
(1)将数据库隔离级别设置为repeatable read
MySQL事务隔离
(2)再次在客户端2开启事务,并且查询学生表的数据,暂不提交事务。
MySQL事务隔离
(3)在客户端1修改学号为2的学生姓名,并且查询,提交事务,发现在客户端1的事务数据已经发生了变化。MySQL事务隔离
MySQL事务隔离

(4)再次在客户端2中查询学生表,发现与第一次查询(2)没有任何变化。
MySQL事务隔离
总结:在repeatable read隔离级别中,同一事务中的每次查询结果都不会发生变化,这就是可重复读的现象,也就是在客户端1中改变数据并未影响到客户端2中的查询,为什么会出现这种现象,因为MySQL的可重复读实现了MVCC的控制方式 ,即Mutil-Version Concurrency Control,多版本并发控制,类似于乐观锁的一种实现方式,其原理是,每个数据都会有一个版本号,当有A事务操作数据时,读取的是当前版本号,如果B事务再次操作该数据时,版本号会加1,,A事务会一直读取所属于A的版本号,而不会读到B事务所改变的数据。

相关文章: