4. MySQL事务隔离级别

一、事务 Transaction

  • 针对写操作

1、启动事务

> start transaction;

2、提交事务

> commit;

3、回滚事务

> rollback;

二、MySQL事务隔离级别

1、事务并发产生的问题

  • 脏读、可重复读、幻读

2、四种隔离级别

  • read uncommited 读未提交
  • read commited 读已提交
  • repeatable read 可重复读
  • serializable 串行化

三、read uncommited 读未提交

1、说明

事务A会读取到事务B未提交的数据,产生脏读

2、调整事务隔离级别

MariaDB [test]> set global transaction isolation level READ UNCOMMITTED;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

3、测试

3.1 启动事务A,查看表info中的数据
MariaDB [test]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> select * from info;
+----+--------+
| id | name   |
+----+--------+
|  1 | martin |
|  2 | demon  |
+----+--------+
2 rows in set (0.00 sec)
3.2 在另一个终端,启动事务B,对info表中的数据进行修改,但不提交
MariaDB [(none)]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> update info set name="AA" where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MariaDB [test]> 
3.3 在事务A中查看数据
MariaDB [test]> select * from info;
+----+-------+
| id | name  |
+----+-------+
|  1 | AA    |
|  2 | demon |
+----+-------+
2 rows in set (0.00 sec)

发现读取到的是事务B未提交的数据,即为脏读
3.4 事务B回滚,在事务A中再次查看数据
MariaDB [test]> rollback;
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> select * from info;
+----+--------+
| id | name   |
+----+--------+
|  1 | martin |
|  2 | demon  |
+----+--------+
2 rows in set (0.00 sec)

四、read commited 读已提交

1、说明

事务A不会读取到事务B未提交的数据,只有事务B提交后事务A才会查看到修改后的数据

2、调整事务隔离级别

MariaDB [test]> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

3、测试

3.1 启动事务A,查看表info中的数据
MariaDB [test]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> select * from info;
+----+--------+
| id | name   |
+----+--------+
|  1 | martin |
|  2 | demon  |
+----+--------+
2 rows in set (0.00 sec)
3.2 在另一个终端,启动事务B,对info表中的数据进行修改,但不提交
MariaDB [test]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> update info set name="BB" where id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
3.3 在事务A中查看数据
MariaDB [test]> select * from info;
+----+--------+
| id | name   |
+----+--------+
|  1 | martin |
|  2 | demon  |
+----+--------+
2 rows in set (0.00 sec)

发现查看到的是事务B修改前的数据
3.4 在事务B中进行提交,再次在事务A中查看数据
MariaDB [test]> commit;
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> select * from info;
+----+--------+
| id | name   |
+----+--------+
|  1 | martin |
|  2 | BB     |
+----+--------+
2 rows in set (0.00 sec)
可以查看到事务B提交的数据,但是,事务A两次读取到的数据不一致,存在不可重复读的问题

五、repeatable read 可重复读 [默认]

1、说明

事务A启动后,在未提交前,查看数据时不会受到其他事务修改的影响

2、调整事务隔离级别

MariaDB [test]> set global transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

3、测试

3.1 启动事务A,查看表info中的数据
MariaDB [(none)]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> use test;

MariaDB [test]> select * from info;
+----+--------+
| id | name   |
+----+--------+
|  1 | martin |
|  2 | BB     |
+----+--------+
2 rows in set (0.00 sec)
3.2 启动事务B,修改info表中的数据,但不提交
MariaDB [test]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> update info set name="AA" where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MariaDB [test]> select * from info;
+----+------+
| id | name |
+----+------+
|  1 | AA   |
|  2 | BB   |
+----+------+
2 rows in set (0.00 sec)
3.3 在事务A中查看数据
MariaDB [test]> select * from info;
+----+--------+
| id | name   |
+----+--------+
|  1 | martin |
|  2 | BB     |
+----+--------+
2 rows in set (0.00 sec)
3.4 事务B提交,再在事务A中查看数据
MariaDB [test]> commit;
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> select * from info;
+----+--------+
| id | name   |
+----+--------+
|  1 | martin |
|  2 | BB     |
+----+--------+
2 rows in set (0.00 sec)

即使事务B已经提交,但在事务A中查看到的还是之前未修改的数据,称为可重复读; 起始事务A中每次读的数据是一致的,不会受其他事务的影响
3.5 启动事务C,向表info中插入一条数据
MariaDB [test]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> insert into info(name) values("leah");
Query OK, 1 row affected (0.00 sec)

MariaDB [test]> commit;
Query OK, 0 rows affected (0.00 sec)
3.6 再次在事务A中查看数据
MariaDB [test]> select * from info;
+----+--------+
| id | name   |
+----+--------+
|  1 | martin |
|  2 | BB     |
+----+--------+
2 rows in set (0.00 sec)
 
 发现一样查看不到事务C新写入的数据,称为幻读,即查看不到最新的数据 
3.7 事务A提交,再次查看数据
MariaDB [test]> select * from info;
+----+------+
| id | name |
+----+------+
|  1 | AA   |
|  2 | BB   |
|  3 | leah |
+----+------+
3 rows in set (0.00 sec)

查看到最新的数据 !!!! 

六、serializable 串行化

1、说明

事务A启动后,会锁定整个表,后续其他事务B必须等待事务A结束后,才可正常执行

2、调整事务隔离级别

MariaDB [test]> set global transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE   |
+----------------+
1 row in set (0.00 sec)

3、测试

3.1 启动事务A,查看表info中的数据
MariaDB [test]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> select * from info;
+----+------+
| id | name |
+----+------+
|  1 | AA   |
|  2 | BB   |
|  3 | leah |
+----+------+
3 rows in set (0.00 sec)
3.2 启动事务B,对表info中的数据进行修改
MariaDB [test]> start transaction;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> update info set name="martin" where id=1;

发现事务B中的操作会进入等待状态,因为事务A锁了整个表
3.3 事务A提交
MariaDB [test]> commit;
Query OK, 0 rows affected (0.00 sec)

事务A提交后,事务B中的操作才会开始执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值