并行事务会引发什么问题?

并行事务会引发什么问题?

MySQL 服务端是允许多个客户端连接的,这意味着 MySQL 会出现同时处理多个事务的情况。

那么在同时处理多个事务的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)的问题

接下来,通过举例子给大家说明,这些问题是如何发生的。

脏读

如果一个事务「读到」了另一个「未提交事务修改过的数据」,就意味着发生了「脏读」现象。

不可重复读

在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象。

幻读

在一个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不一样的情况,就意味着发生了「幻读」现象。

事务A:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into user values(1522158666475192324,'testtt','test','1','test','test',0);
Query OK, 1 row affected (0.00 sec)

mysql> select * from user;
+---------------------+--------------+-------------+------+-----------+--------+--------+
| id                  | name         | phone       | sex  | id_number | avatar | status |
+---------------------+--------------+-------------+------+-----------+--------+--------+
| 1522158666475192321 | 我是谁??? | 13571761373 | NULL | NULL      | NULL   |      1 |
| 1522158666475192323 | test         | test        | 1    | test      | test   |      0 |
| 1522158666475192324 | testtt       | test        | 1    | test      | test   |      0 |
+---------------------+--------------+-------------+------+-----------+--------+--------+

mysql> commit;

事务B:

mysql> start transaction;
mysql> select * from user;
+---------------------+--------------+-------------+------+-----------+--------+--------+
| id                  | name         | phone       | sex  | id_number | avatar | status |
+---------------------+--------------+-------------+------+-----------+--------+--------+
| 1522158666475192321 | 我是谁??? | 13571761373 | NULL | NULL      | NULL   |      1 |
| 1522158666475192323 | test         | test        | 1    | test      | test   |      0 |
+---------------------+--------------+-------------+------+-----------+--------+--------+
2 rows in set (0.11 sec)

mysql> select * from user for update;
+---------------------+--------------+-------------+------+-----------+--------+--------+
| id                  | name         | phone       | sex  | id_number | avatar | status |
+---------------------+--------------+-------------+------+-----------+--------+--------+
| 1522158666475192321 | 我是谁??? | 13571761373 | NULL | NULL      | NULL   |      1 |
| 1522158666475192323 | test         | test        | 1    | test      | test   |      0 |
| 1522158666475192324 | testtt       | test        | 1    | test      | test   |      0 |
+---------------------+--------------+-------------+------+-----------+--------+--------+
3 rows in set (33.73 sec)

-- 或者
mysql> update user set name = 'up' where id = 1522158666475192324;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> select * from user;
+---------------------+--------------+-------------+------+-----------+--------+--------+
| id                  | name         | phone       | sex  | id_number | avatar | status |
+---------------------+--------------+-------------+------+-----------+--------+--------+
| 1522158666475192321 | 我是谁??? | 13571761373 | NULL | NULL      | NULL   |      1 |
| 1522158666475192323 | test         | test        | 1    | test      | test   |      0 |
| 1522158666475192324 | up           | test        | 1    | test      | test   |      0 |
+---------------------+--------------+-------------+------+-----------+--------+--------+
3 rows in set (0.09 sec)

执行顺序:

B:select * from user; -- 结果两条记录
A:insert into user values();  -- 未提交
B:select * from user for update; -- 结果三条记录,查当前(for update)
-- 或
B:update user set name = 'up' where id = 1522158666475192324;
B:select * from user; -- 结果三条记录,因为上条更新语句会先查全表数据

-- 对于事务B来说出现了幻觉,这种现象即为幻读。在同一事务中,相同查询条件记录数不同。
posted @ 2022-10-16 19:53  lam要努力  阅读(80)  评论(0编辑  收藏  举报