三十二、MySQL基础系列笔记之事务实例演示(下)

作者: 温新

分类: 【MySql】

阅读: 2051

时间: 2020-11-22 10:51:19

上篇 MySQL基础系列笔记之事务基础概念详解 将事务的基本概念做了一个较为详细的基本概念记录,那么此篇将进行实例演示。对事务概念有所模糊,建议先阅读上篇文章。

准备工作-建表

CREATE TABLE `account`(
	`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '',
    `name` VARCHAR(30) NOT NULL COMMENT '姓名',
    `salary` DECIMAL(10,2) COMMENT '薪水'
)ENGINE=InnoDB DEFAULT CHARSET=UTF8;

INSERT INTO account VALUES (1,'张三',1000), (2,'李四',2000);

事务使用步骤

为了方便查看,此篇将温故下上篇文章的记录,事务的使用步骤。

# 第一步:关闭自动提交
set autocommit =0;
# 开启事务,[可选]
start transaction;
# 第二步:设置事务隔离级别
set session transaction isolation level Read Uncommitted;
# 第三步:sql语句
# 第四步:COMMIT或ROOLBACK

事务实例演示

准备工作:打开2个PowerShell黑窗口,分别连接上mysql。第一个黑窗口为A,第2个为B。

读未提交(Read Uncommitted)

步骤一:A、B窗口,关闭事务自动提交

set autocommit =0;

步骤二:A、B窗口设置事务隔离级别(两个一样)

# 读未提交
set session transaction isolation level Read Uncommitted;

步骤三:A窗口向表中插入一条数据

insert into account values (3,'lucy',3000);

注意:A窗口插入一条数据后,不要提交事务,不要提交事务,不要提交事务!A插入一条数据,立即到B窗口中查看数据。

步骤四:B窗口中查看数据

mysql>  select * from account;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 1000.00 |
|  2 | 李四   | 2000.00 |
|  3 | lucy   | 3000.00 |
+----+--------+---------+
3 rows in set (0.00 sec)

A窗口并未提交事务,此时B窗口中却查看到了A事务中插入的一条数据。

步骤五:A窗口ROLLBACK事务

ROLLBACK;

步骤六:B窗口查看数据

mysql>  select * from account;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 1000.00 |
|  2 | 李四   | 2000.00 |
+----+--------+---------+

当A窗口回滚事务之后,B窗口再次查看却发现那条数据神奇的消失了。

可重复读(Repeatable Read)

步骤一:A、B窗口,关闭事务自动提交

set autocommit =0;

步骤二:A、B窗口设置事务隔离级别(两个一样)

# 隔离级别为可以重复读
set session transaction isolation level Repeatable Read;

步骤三:A窗口向表中插入一条数据

insert into account values (3,'lucy',3000);
# 注意:不要提交事务

步骤四:B窗口中查询数据

mysql> select * from account;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 1000.00 |
|  2 | 李四   | 2000.00 |
+----+--------+---------+
2 rows in set (0.00 sec)

A窗口中插入了一条数据,此时B窗口查询数据并没有查看到A窗口插入的那一条数据。该隔离级别避免了脏读与不可重复读。

步骤五:A窗口提交事务

COMMIT;

步骤六:B窗口再次查看数据

mysql> select * from account;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 1000.00 |
|  2 | 李四   | 2000.00 |
+----+--------+---------+
2 rows in set (0.00 sec)

A窗口提交了事务,由于B窗口没有提交事务,因此看到的还是之前的数据。

步骤七:B窗口提交事务,然后再查看

# B窗口提交事务
COMMIT;
# B窗口查看数据
mysql> select * from account;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
...此处省略前面的数据
|  3 | lucy   | 3000.00 |
+----+--------+---------+
3 rows in set (0.00 sec)

读已提交(Read Committed)

步骤一:A、B窗口,关闭事务自动提交

set autocommit =0;

步骤二:A、B窗口设置事务隔离级别(两个一样)

# 读已提交
set session transaction isolation level read committed;

步骤三:A窗口中插入一条数据

insert into account values(4,'lily',4000);

步骤四:B窗口查看数据

mysql> select * from account;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
...
|  3 | lucy   | 3000.00 |
+----+--------+---------+
3 rows in set (0.00 sec)

还是之前的3条数据。避免了脏读。

步骤五:A窗口提交事务

COMMIT;

步骤六:B窗口查看数据并提交事务

mysql> select * from account;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
....
|  4 | lily   | 4000.00 |
+----+--------+---------+
4 rows in set (0.00 sec)
# 提交事务
COMMIT;
# 再次查看数据,发现仍旧是4条数据

可以清晰的看到,步骤四、六查询的结果不一致,这就是不可重复读。

串行(Serializable)

步骤一:A、B窗口,关闭事务自动提交

set autocommit =0;

步骤二:A、B窗口设置事务隔离级别(两个一样)

# 串行
set session transaction isolation level serializable;

步骤三:A窗口修改一条数据

update account set name='大明' where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
# 注意:此时可以看到修改成功,但实际上此时没有修改成功

可以看到A窗口事务处于阻塞状态,它在等待B窗口提交事务。

步骤四:B窗口插入一条数据

insert into account values (5,'小毛',100);
# 注意:此时B窗口事务处于阻塞状态

步骤五:A窗口提交事务并查看数据

COMMIT;
# 此时B窗口才插入成功

# A窗口查看,发现处于阻塞状态
select * from account;

步骤六:B窗口提交事务

COMMIT;
# B窗口提交事务之后,A窗口才看到了数据。

SERIALIZABLE会让并发的事务串行执行(多个事务之间读写、写读、写写会产生互斥,效果就是串行执行,多个事务之间的读读不会产生互斥)。

读写互斥:事务A中先读取操作,事务B发起写入操作,事务A中的读取会导致事务B中的写入处于等待状态,直到A事务完成为止。

表示我开启一个事务,为了保证事务中不会出现上面说的问题(脏读、不可重复读、读已提交、幻读),那么我读取的时候,其他事务有修改数据的操作需要排队等待,等待我读取完成之后,他们才可以继续。

写读、写写也是互斥的,读写互斥类似。

2020-11-22

请登录后再评论