美文网首页
【MySQL】事务隔离级别

【MySQL】事务隔离级别

作者: 拾荒者charley | 来源:发表于2018-02-28 14:38 被阅读0次

今天利用空闲时间给大家分享一下个人对事务隔离级别的理解,我们生活中应该都有存钱取钱的经历吧,那么我就用存钱取钱这个例子来讲解。
现在银行有一张money表,大概记录了交易id,客户名称,客户余额。

  • READ-UNCOMMITTED
    (1)所有事务都可以看到其他未提交事务的执行结果
    (2)本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少
    (3)该级别引发的问题是——脏读(Dirty Read):读取到了未提交的数据

小明在在ATM机往自己账户存入100元,此时未点确定,但是小明老婆小红却看到小明账户已经有100元了。
小明:

06:48:10 root@mysql3306.sock [xucl]>start transaction;
Query OK, 0 rows affected (0.00 sec)

06:48:24 root@mysql3306.sock [xucl]>insert into money values(1,'小明',100);
Query OK, 1 row affected (0.00 sec)

小红:

06:48:38 root@mysql3306.sock [xucl]>select * from money;
+------+--------+--------+
| tid  | cname  | cmoney |
+------+--------+--------+
|    1 | 小明   |    100 |
+------+--------+--------+
1 row in set (0.00 sec)
  • READ-COMMITED
    (1)这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)
    (2)它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变
    (3)这种隔离级别出现的问题是——不可重复读(Nonrepeatable Read):不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。
    |——>导致这种情况的原因可能有:
    (1)有一个交叉的事务有新的commit,导致了数据的改变;
    (2)一个数据库被多个实例操作时,同一事务的其他实例在该实例处理其间可能会有新的commit
    我们还是用例子来理解这件事情,小红打算去取小明卡里的钱的时候,看到了小明卡里有100元,这个时候小明往自己卡里又偷偷存了100元进去,小红取消了取钱,上面显示小明卡里有200块了。
    小红:
06:55:56 root@mysql3306.sock [xucl]>start transaction;
Query OK, 0 rows affected (0.00 sec)

06:56:02 root@mysql3306.sock [xucl]>select * from money;
+------+--------+--------+
| tid  | cname  | cmoney |
+------+--------+--------+
|    1 | 小明   |    100 |
+------+--------+--------+
1 row in set (0.00 sec)

此时小明偷偷存入100元并提交:

06:56:30 root@mysql3306.sock [xucl]>update money set cmoney=200 where tid = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

06:58:24 root@mysql3306.sock [xucl]>commit;
Query OK, 0 rows affected (0.00 sec)

此时小红取消交易,再次查看余额显示200元

06:56:04 root@mysql3306.sock [xucl]>select * from money;
+------+--------+--------+
| tid  | cname  | cmoney |
+------+--------+--------+
|    1 | 小明   |    200 |
+------+--------+--------+
1 row in set (0.00 sec)

如果把小红取钱看成一次交易的话,在交易的过程中看到的两次余额不一样,这就是不可重复读。

  • REPEATABLE READ
    (1)这是MySQL的默认事务隔离级别
    (2)它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行
    (3)此级别可能出现的问题——幻读(Phantom Read):当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行
    (4)InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题
    下面我们来看例子:
    小红:
07:12:40 root@mysql3306.sock [xucl]>start transaction;
Query OK, 0 rows affected (0.00 sec)

07:12:51 root@mysql3306.sock [xucl]>select * from money;
+------+--------+--------+
| tid  | cname  | cmoney |
+------+--------+--------+
|    1 | 小明   |    200 |
+------+--------+--------+
1 row in set (0.00 sec)

小明:

07:12:31 root@mysql3306.sock [xucl]>start transaction;
Query OK, 0 rows affected (0.00 sec)

07:13:08 root@mysql3306.sock [xucl]>update money set cmoney=300 where tid=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

07:13:26 root@mysql3306.sock [xucl]>select * from money;
+------+--------+--------+
| tid  | cname  | cmoney |
+------+--------+--------+
|    1 | 小明   |    300 |
+------+--------+--------+
1 row in set (0.00 sec)

07:13:34 root@mysql3306.sock [xucl]>commit;
Query OK, 0 rows affected (0.00 sec)

小红再次查看:

07:12:57 root@mysql3306.sock [xucl]>select * from money;
+------+--------+--------+
| tid  | cname  | cmoney |
+------+--------+--------+
|    1 | 小明   |    200 |
+------+--------+--------+
1 row in set (0.00 sec)

显示还是只有200元,小红取出卡后再次查看就变成300元了。

07:16:57 root@mysql3306.sock [xucl]>start transaction;
Query OK, 0 rows affected (0.00 sec)

07:17:00 root@mysql3306.sock [xucl]>select * from money;
+------+--------+--------+
| tid  | cname  | cmoney |
+------+--------+--------+
|    1 | 小明   |    300 |
+------+--------+--------+
1 row in set (0.00 sec)
  • SERIALIZABLE
    (1)这是最高的隔离级别
    (2)它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。
    (3)在这个级别,可能导致大量的超时现象和锁竞争
    简单来说就是小红一旦查看小明的账户,这个时候小明想要偷偷存钱进去就没办法了。
    小红:
07:24:52 root@mysql3306.sock [xucl]>start transaction;
Query OK, 0 rows affected (0.00 sec)

07:25:33 root@mysql3306.sock [xucl]>select * from money;
+------+--------+--------+
| tid  | cname  | cmoney |
+------+--------+--------+
|    1 | 小明   |    300 |
+------+--------+--------+
1 row in set (10.04 sec)

小明:

07:26:15 root@mysql3306.sock [xucl]>update money set cmoney=400 where tid=1;
事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

小明发现自己的钱存不进去了。
简单总结
一、

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

二、事务隔离等级高->低:
serializable -> repeatable-read -> read-committed -> read-uncommitted

三、隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

相关文章

  • 聊聊MySQL的隔离级别

    原文:聊聊MySQL的隔离级别 | MySQL隔离级别原理参考:oracle - mysql - 数据库事务隔离级...

  • mysql事务隔离级别的实现原理

    mysql事务隔离级别的实现原理 mysql innodb中的四种事务隔离级别[https://www.jians...

  • MySQL 事务隔离级别解析和实战

    MySQL 事务隔离级别解析和实战 1、MySQL 隔离界别查看 查看回话隔离级别 查看系统隔离级别 2、MySQ...

  • Mysql事务

    1) mysql事务的ACID特性 2)MySQL事务隔离级别

  • mysql隔离级别

    一、MySQL事务隔离级别 mysql默认的事务隔离级别为repeatable-read(可重复读) 1.未提交可...

  • Mac系统mysql设置事务隔离级别

    Mac系统mysql设置事务隔离级别 MySQL数据库事务隔离级别主要有四种: Serializable 串行化,...

  • 数据库事务相关

    事务隔离级别(tx_isolation)mysql 有四级事务隔离级别 每个级别都有字符或数字编号 级别symbo...

  • MYSQL事务

    常用语句 MYSQL事务,锁表 事务控制语句 事务的隔离级别 隔离级别描述产生风险READUNCOMMITTED ...

  • 面试官:说一下MySQL事务隔离级别?

    MySQL 事务隔离级别是为了解决并发事务互相干扰的问题的,MySQL 事务隔离级别总共有以下 4 种: READ...

  • mysql笔记

    mysql笔记 查看事务隔离级别 show variables like '%iso%'; 设置事务级别 mysq...

网友评论

      本文标题:【MySQL】事务隔离级别

      本文链接:https://www.haomeiwen.com/subject/todbxftx.html