1. 实验环境准备
create table hero(number int,name varchar(100),country varchar(100),primary key(number),key id_name(name)) engine=innodb charset=utf8;
Query OK, 0 rows affected (0.09 sec)
mysql> insert into hero values(1,'l刘备','蜀'),(3,'z诸葛亮','蜀'),(8,'c曹操','魏'),(15,'x荀彧','魏'),(20,'s孙权','吴');
mysql> select * from hero;
+--------+------------+---------+
| number | name | country |
+--------+------------+---------+
| 1 | l刘备 | 蜀 |
| 3 | z诸葛亮 | 蜀 |
| 8 | c曹操 | 魏 |
| 15 | x荀彧 | 魏 |
| 20 | s孙权 | 吴 |
+--------+------------+---------+
5 rows in set (0.00 sec)
2. 读
1. 普通读(MVCC)不加锁
- 读未提交:不加锁,直接读,脏读 重复度 幻读
- 读已提交不加锁 每次查询生成 ReadView,避免脏读
- 可重复读 不加锁 第一次查询生成 RV,避免 脏读 重复度 幻读(很大程度)
实验: 读已提交部分避免幻读
- 在可重复读隔离级别下,T1:
mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
mysql> begin;
mysql> select * from hero where number = 30;
Empty set (0.00 sec) - 此时T2插入一条数据(T2隔离级别任意)
INSERT INTO hero VALUES(30,‘g关羽’,‘魏’);(已提交) - T1 继续读
mysql> select * from hero where number = 30;
Empty set (0.00 sec) - T1尝试修改,并查询
mysql> update hero set country=‘shu’ where number=30;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from hero where number = 30;
±-------±--------±--------+
| number | name | country |
±-------±--------±--------+
| 30 | g关羽 | shu |
±-------±--------±--------+
1 row in set (0.00 sec)
5. 竟然查到了,同一事物,两次查询数据条目数不一样,幻读
6. 原因
2.锁定读语句
能触发锁定读的语句
- select … lock in share mode;
- select … for update;
- update (更新操作需要先读取记录(定位记录))
- delete (删除操作tongli)
select语句锁定读的步骤
假设锁定读语句读取表中若干区间
- 在B+树叶子结点中定位到第一条记录,把该记录作为当前记录
精确匹配【x,x】
- <=读已提交
x记录加锁,下一条不匹配,直接报“查询完毕”,不会再加锁了
2。 >=可重复度
会在扫描区间的下一条记录加gap锁,当扫描区间在页面中没有一条记录,也会在该区间下一条记录加锁。
【x,y),且第一条扫描到的记录为x,隔离级别>=可重复读
只为第一条记录加正经锁(因为在前面插入,并不会幻读,故无gap)