sqlican 2019-06-26
(提交读)
了解了之前 READ UNCOMMITTED
隔离级别是如何加锁的, 并且在文章中, 已经知道 READ COMMITTED
隔离级别可以解决脏读的问题, 那接下来, 对于 READ COMMITTED
隔离级别, 试想一下如果让你用锁来设计, 你会怎么做?
READ COMMITTED
隔离级别可以解决脏读
的问题, 也就是他可以让事务只能读其他事务已提交的的记录。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
的修改语句会锁等待~