mysql(InnoDB)事务隔离级别(READ COMMITTED) 与 锁,MVCC
READ COMMITTED
(提交读)
了解了之前
READ UNCOMMITTED
隔离级别是如何加锁的, 并且在文章中, 已经知道READ COMMITTED
隔离级别可以解决脏读的问题, 那接下来, 对于READ COMMITTED
隔离级别, 试想一下如果让你用锁来设计, 你会怎么做?- 既然
READ COMMITTED
隔离级别可以解决脏读
的问题, 也就是他可以让事务只能读其他事务已提交的的记录。 - 如果用锁机制来实现该隔离级别:
试想一下, 当在事务A中读取数据D的时候, 假设D之前已经在事务B中了, 并且事务B中对数据D做了修改, 但是事务B还没有完成(commit/rollback), 那如何让事务A无法读取数据D呢?
当事务B在对数据D操作的时候, 假设给数据D加上了行级的排他锁(X lock), 那事务A自然只能阻塞等事务A完成后才能读取数据D了! - 数据库这样做的话确实实现了
READ COMMITTED
隔离级别的效果, 也就避免了脏读
, 但问题是这是一种很低效的做法, 因为对于大部分应用来说, 读操作是多于写操作的, 当写操作加锁时, 那么读操作全部被阻塞, 这样在大用户量高并发的情况下, 会直接降低数据库的读效率。
- 既然
- 那么, 既然用锁机制实现该隔离级别是低效的做法, 数据库是如何做的?
之前在相关MVCC的文章中可以得到答案: 数据库是使用了 排他锁+MVCC 的机制来实现该隔离级别的, 而不是单纯的使用锁或者单纯的使用MVCC
READ COMMITTED与锁 测试
数据表结构如下:
mysql> select * from test_transaction; +----+---------------+-----+--------+--------------------+ | id | user_name | age | gender | desctiption | +----+---------------+-----+--------+--------------------+ | 1 | 金刚狼 | 127 | 2 | 我有一双铁爪 | | 2 | 钢铁侠-rym | 120 | 1 | 我有一身铁甲 | | 3 | 绿巨人 | 0 | 2 | 我有一身肉 | +----+---------------+-----+--------+--------------------+ 3 rows in set (0.00 sec) mysql>
重新设置
客户端1
事务隔离级别为read committed:SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
mysql> SELECT @@SESSION.tx_isolation; +------------------------+ | @@SESSION.tx_isolation | +------------------------+ | REPEATABLE-READ | +------------------------+ 1 row in set (0.00 sec) mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; Query OK, 0 rows affected (0.00 sec) mysql> SELECT @@SESSION.tx_isolation; +------------------------+ | @@SESSION.tx_isolation | +------------------------+ | READ-COMMITTED | +------------------------+ 1 row in set (0.00 sec) mysql>
- 再重新打开一个
客户端2
并设置事务隔离级别为read committed; - 在
客户端1
中打开事务, 然后更改数据, 先不提交; 然后在客户端2
中打开事务, 读取客户端1
中尚未提交的那条被修改数据 - 结果发现在
客户端2
中可以正常读取到那条数据, 只不过, 那条数据并不是被客户端1
事务中修改后的数据, 而是最初的稳定数据
, 这就避免了脏读
!! 对于该隔离级别修改数据时使用的锁类型, 其分析方法, 和之前一篇MySQL(INNODB引擎)事务READ UNCOMMITTED隔离级别和锁的关系 是一样的:
- 可以在
客户端1
的事务在修改数据并且未提交时, 在客户端2
中对同一数据进行修改, 然后在客户端2
阻塞阶段通过查看表的加锁情况: select * from information_schema.INNODB_LOCKS;
,事务状态: select * from information_schema.INNODB_TRX;
,
进行分析, 结果就不展示了, 可以自行测试一下, 该隔离级别修改数据时使用的也是排他锁, 并且客户端2
的修改语句会锁等待~
(和之前分析READ UNCOMMITTED隔离级别一样, 既然使用了排他锁, 竟然别的事务还能读取, 这特么不就又违反了排他锁的特性么? 还是那句话, 另一个事务在读取的时候并不会加锁, 而是用的MVCC机制读取的镜像)
- 可以在
- 小结:
InnoDB在该隔离级别(READ COMMITTED)写数据是使用排他锁, 读取数据不加锁而是使用了MVCC机制, 这样就可以大大提高并发读写效率, 写不影响读, 因为读并未加锁, 读的是记录的镜像版本!!
相关推荐
DriveCar 2020-09-07
quniMdejiangyou 2020-08-15
silencehgt 2020-07-04
zhanbuquan 2020-07-04
liaomingwu 2020-06-25
zhanbuquan 2020-06-21
vincen 2020-06-10
zjx0 2020-05-20
愿天下再无BUG 2020-05-16
MissFuTT 2020-05-11
好记忆也需烂 2020-05-10
wenjieyatou 2020-05-06
bluet00 2020-05-05
jiong 2020-04-19
逍遥斩舞 2020-04-17
achiverhai 2020-04-16
zhengsj 2020-03-28
qingjiuquan 2020-07-18
lpfvip00 2020-06-25
daillo 2020-06-17
sunysh00 2020-06-11
langyue 2020-06-09
DriveCar 2020-06-09
airfling 2020-06-08
sofast 2020-06-03
weikaixxxxxx 2020-05-30