mysql事务隔离级别 - wwq0912/mysql GitHub Wiki
Transaction isolation Sector
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 |
不可重复读(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
1、脏读:一个事务可以读取另一个尚未提交事务的修改数据。
2、不可重复读:在同一个事务中,不同时间查询到的数据不一样. 数据可能被update/delete
3、幻读:在同一事务中,同一查询多次进行时候,由于其他插入操作(insert)的事务提交,导致每次返回不同的结果集。(其他事务划重点
)
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增
读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)
- 快照读:普通的select语句 ---不加锁
- 当前读:
select * from table where ? lock in share mode; --共享锁
select * from table where ? for update;
insert into table values (…);
update table set ? where ?;
delete from table where ?;
对于当前读,只有第一条是加共享锁 其他都是排他锁。
四钟锁
下面是表级锁类型的兼容性!
四种锁 | 共享锁s | 排他锁x | 意向共享锁is | 意向排他锁ix |
---|---|---|---|---|
共享锁s | 兼容 | 冲突 | 兼容 | 冲突 |
排他锁x | 冲突 | 冲突 | 冲突 | 冲突 |
意向共享锁is | 兼容 | 冲突 | 兼容 | 兼容 |
意向排他锁ix | 冲突 | 冲突 | 兼容 | 兼容 |
shen
下面会用到锁的知识--,
https://blog.csdn.net/zhongyangjian/article/details/51968675?utm_source=blogxgwz9 (好的例子!!)
例子在1.2.1 锁与索引的关系
summary:
CREATE TABLE IF NOT EXISTS `msg` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`token` varchar(45) DEFAULT NULL,
`message` varchar(45) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `FK_TOKEN` (`token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
不可重复读(read-committed)
它可以防止不同事务版本的数据修改提交时造成数据冲突的情况,但当别的事务插入数据时可能会出现问题。
事务A:
select * from msg where token="asd"
result:
# ID, token, message
'4', 'asd', '订单号多少'
update msg set message='订单' where token='asd'; 1 row(s) affected
事务B
insert into msg values (null,'asd','hello'); commit;
事务A
select * from msg where token="asd"; return 2 rows;
所以这里就出现了幻读
可重复读(repeatable-read) 可以避免幻读, innodb引入了gap锁。
https://www.aneasystone.com/archives/2018/06/insert-locks-via-mysql-source-code.html
在事务A执行:update msg set message=‘订单’ where token=‘asd’;
innodb首先会和RC级别一样,给索引上的记录添加上X锁,此外,还在非唯一索引'asd'与相邻两个索引的区间加上锁。
这样,当事务B在执行insert into msg values (null,'asd','hello');
时,会首先检查这个区间是否被锁上,如果被锁上,则不能立即执行,需要等待该gap锁被释放。这样就能避免幻读问题。 (这个锁不是事务A的update执行完就可以释放的,需要是事务A结束掉)
Question: 什么叫相邻的两个索引区间??? 按什么排序的啊
======================== ok还是不懂怎么加的gap锁 好像要学B+树索引
gap的知识来了--。超棒的例子 ---http://hedengcheng.com/?p=771#_Toc374698322
相应的gap lock就是加在gap上的锁,还有一个next-key锁,是记录+记录前面的gap的组合的锁。
只有在read repeatable或者以上的隔离级别下的特定操作才会取得gap锁 (特定操作, select * for update/ locak in share mode/update/delete) 这些特殊操作除了对唯一索引的唯一搜索外(比如自增长的ID) 都会获取gap/next-key锁。 锁掉扫描范围