【MySQL】事务隔离级别

2018-02-28  本文已影响0人  拾荒者charley

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

小明在在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)
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)

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

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)
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,它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

上一篇 下一篇

猜你喜欢

热点阅读