MySQL四种隔离级别与并发存在的问题。

1、事务的四个特性

事务是一个或多个SQL语句组成的一个不可分割的单元。事务中的一组SQL语句,要么全部成功,要么全部失败。四个特性 ACID

原子性 atomic

一致性 consistency

隔离性 isolation    针对数据库中的并发来说,隔离性越好,并发性越低。根据的是innodb的锁机制

持久性 durability   redo日志,保证数据的持久性,极端情况 commit后,服务器宕机,数据还没有持久化到磁盘,就需要依靠redo日志了。

ACD依靠的是redo、undo日志。I 依靠的是锁机制。

2、并发存在的问题

以 user 表为例,进行描述。

select * from user;
+----+----------+-----+-----+
| id | name     | age | sex |
+----+----------+-----+-----+
|  1 | zhangsan |  22 | M   |
|  2 | lisi     |  22 | W   |
+----+----------+-----+-----+
2 rows in set (0.00 sec)

1、脏读

//设置隔离级别为读未提交 read-uncommitted
mysql> set tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected, 1 warning (0.00 sec)



事务A
A1、mysql> begin;
Query OK

A2、mysql> update user set age=30 where name='zhangsan';
Query OK

A3、mysql> rollback;
Query OK


事务B

B1、mysql> begin;
Query OK

B2、mysql> select * from user where name='zhangsan';
+----+----------+-----+-----+
| id | name     | age | sex |
+----+----------+-----+-----+
|  1 | zhangsan |  22 | M   |
+----+----------+-----+-----+

B3、mysql> select * from user where name='zhangsan';
+----+----------+-----+-----+
| id | name     | age | sex |
+----+----------+-----+-----+
|  1 | zhangsan |  30 | M   |
+----+----------+-----+-----+



当事务A,事务B均开启事务,
首先事务B查询,执行了B2,得到了结果如上。
事务A开始进行update,执行A2,
事务B再次进行查询,执行B3,得到结果,此时的结果要用到相应的业务。
事务A进行回滚,未进行commit。而事务B对A未提交的业务已经进行使用。

2、不可重复读

//设置隔离级别为读已提交 read-commited;
set tx_isolation='READ-COMMITTED';
Query OK, 0 rows affected, 1 warning (0.00 sec)


事务A
A1、mysql> begin;
Query OK, 0 rows affected (0.00 sec)

A2、mysql> update user set age=30 where name='zhangsan';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

A3、mysql> commit;
Query OK, 0 rows affected (0.00 sec)

 
事务B
begin;
Query OK, 0 rows affected (0.00 sec)

B1 、mysql> select * from user where name='zhangsan';
+----+----------+-----+-----+
| id | name     | age | sex |
+----+----------+-----+-----+
|  1 | zhangsan |  22 | M   |
+----+----------+-----+-----+
1 row in set (0.00 sec)

B2、mysql> select * from user where name='zhangsan';
+----+----------+-----+-----+
| id | name     | age | sex |
+----+----------+-----+-----+
|  1 | zhangsan |  22 | M   |
+----+----------+-----+-----+
1 row in set (0.00 sec)

B3、mysql> select * from user where name='zhangsan';
+----+----------+-----+-----+
| id | name     | age | sex |
+----+----------+-----+-----+
|  1 | zhangsan |  30 | M   |
+----+----------+-----+-----+
1 row in set (0.00 sec)

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



和上面一样,在事务A,执行A2,进行updata后
事务B再次进行查询,执行B2,查询结果和未修改前一样。
当事务A commit后,事务B再次查询,执行B3,得到更新后的结果。

3、幻读

在很多博客中,会这样说,幻读是事务A对表进行增加或者删除,然后在事务B中,select的时候,会直接发现改变,经过我的多次实验,感觉这么说多少有点不太准确。可以看下面的描述。

设置隔离级别为 可重复读。这也是innoDB默认的隔离级别。
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)


首先,可重复读可以解决 脏读和不可重复读的问题,
对于解决不可重复读的问题。
事务B在未commit事务前,不管事务A是如何 update,
事务B都会和事务A begin 之前的结果一样。


看一下幻读:
事务A:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

A1  mysql> insert into user(name, age, sex) values('aaa', 19, 'M');
Query OK, 1 row affected (0.00 sec)

A2  mysql> select * from user where age=19;
+----+------+-----+-----+
| id | name | age | sex |
+----+------+-----+-----+
| 15 | aaa  |  19 | M   |
+----+------+-----+-----+
1 row in set (0.00 sec)

A3  mysql> commit;
Query OK, 0 rows affected (0.00 sec)

事务B:
B1  mysql> begin;
Query OK, 0 rows affected (0.00 sec)

  事务A insert 前,未commit

B2  mysql> select * from user where age=19;
Empty set (0.00 sec)

  事务A insert 后,未commit

B3  mysql> select * from user where age=19;
Empty set (0.01 sec)

  事务A commit后,查询结果还是空。

B4  mysql> select * from user where age=19;
Empty set (0.00 sec)

  但此时已经有幻读了,但是还是看不到,需要update。

B5  mysql> update user set name='aaa' where age=19;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0
  
  这个就是幻读,上下结果不一样,

B6  mysql> select * from user where age=19;
+----+------+-----+-----+
| id | name | age | sex |
+----+------+-----+-----+
| 15 | aaa  |  19 | M   |
+----+------+-----+-----+
1 row in set (0.00 sec)

B7  mysql> commit;
Query OK, 0 rows affected (0.00 sec)

3、隔离级别

  MySQL支持的四种隔离级别是:

  • 1、TRANSACTION_READ_UNCOMMITTED。

  读未提交。说明在提交前一个事务可以看到另一个事务 的变化。这样读脏数据,不可重复读和虚读都是被允许的。

  • 2、TRANSACTION_READ_COMMITTED。

  读已提交。说明读取未提交的数据是不允许的。这个级别仍 然允许不可重复读和虚读产生。

  • 3、TRANSACTION_REPEATABLE_READ。

可重复读。说明事务保证能够再次读取相同的数据而不会失 败,但虚读仍然会出现。

  • 4、TRANSACTION_SERIALIZABLE。

串行化。是最高的事务级别,它防止读脏数据,不可重复读和虚 读。

串行化是隔离级别最高的,开启 事务A 和 事务B 后,便不能再插入删除了。

可重复读 中的幻读现象,insert或者delete,没有update的话,也不会产生幻读现象。

4、 常用语句

查询隔离级别:

select @@tx_isolation;

设置隔离级别:

set tx_isolation='隔离级别';
    
隔离级别四种可选择的:
read-uncommitted    read-committed    repeatable-read    serializable

set tx_isolation='read-uncommitted';

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值