Mysql总结

MVVC的实现原理

MVVC有什么用

间隙锁

还是最开始更新用户年龄的例子,如果 id = 49 这条记录不存在,这个 SQL 语句还会加锁吗?答案是可能有,这取决于数据库的隔离级别。这种情况下,在 RC 隔离级别不会加任何锁,在 RR 隔离级别会在 id = 49 前后两个索引之间加上间隙锁。

间隙锁是一种加在两个索引之间的锁,或者加在第一个索引之前,或最后一个索引之后的间隙。这个间隙可以跨一个索引记录,多个索引记录,甚至是空的。使用间隙锁可以防止其他事务在这个范围内插入或修改记录,保证两次读取这个范围内的记录不会变,从而不会出现幻读现象。

值得注意的是,间隙锁和间隙锁之间是互不冲突的,间隙锁唯一的作用就是为了防止其他事务的插入,所以加间隙 S 锁和加间隙 X 锁没有任何区别。

Next-Key 锁

Next-key锁是记录锁和间隙锁的组合,它指的是加在某条记录以及这条记录前面间隙上的锁。假设一个索引包含 15、18、20 ,30,49,50 这几个值,可能的 Next-key 锁如下:

(-∞, 15],(15, 18],(18, 20],(20, 30],(30, 49],(49, 50],(50, +∞)

通常我们都用这种左开右闭区间来表示 Next-key 锁,其中,圆括号表示不包含该记录,方括号表示包含该记录。前面四个都是 Next-key 锁,最后一个为间隙锁。和间隙锁一样,在 RC 隔离级别下没有 Next-key 锁,只有 RR 隔离级别才有。还是之前的例子,如果 id 不是主键,而是二级索引,且不是唯一索引,那么这个 SQL 在 RR 隔离级别下就会加如下的 Next-key 锁 (30, 49](49, 50)

此时如果插入一条 id = 31 的记录将会阻塞住。之所以要把 id = 49 前后的间隙都锁住,仍然是为了解决幻读问题,因为 id 是非唯一索引,所以 id = 49 可能会有多条记录,为了防止再插入一条 id = 49 的记录。

幻读

1:幻读是什么?幻读有什么问题?如何避免?
幻读我的理解是,读出的数据出现了不一致的现象,在事务的读未提交和读已提交这两种事务的隔离级别下会出现幻读的现象,问题嘛?就是数据不一致了,对于数据严格要求一致的场景是不能够允许的。如何避免?在可重复读和串行化的事务隔离级别下应该不会出现
课后思考
1:学完此节后发现自己的认知,基本是错的
1-1:什么是幻读?
幻读是指在同一个事务中,存在前后两次查询同一个范围的数据,但是第二次查询却看到了第一次查询没看到的行。
注意,幻读出现的场景
第一:事务的隔离级别为可重复读,且是当前读
第二:幻读仅专指新插入的行
1-2:幻读带来的问题?
一是,对行锁语义的破坏
二是,破坏了数据一致性
1-3:怎么避免幻读?
存储引擎采用加间隙锁的方式来避免出现幻读
1-4:为啥会出现幻读?
行锁只能锁定存在的行,针对新插入的操作没有限定
1-5:间隙锁是啥?它怎么避免出现幻读的?它引入了什么新的问题?
间隙锁,是专门用于解决幻读这种问题的锁,它锁的了行与行之间的间隙,能够阻塞新插入的操作
间隙锁的引入也带来了一些新的问题,比如:降低并发度,可能导致死锁。
注意,读读不互斥,读写/写读/写写是互斥的,但是间隙锁之间是不冲突的,间隙锁会阻塞插入操作
另外,间隙锁在可重复读级别下才是有效的

MVCC真的解决了幻读?

从最开始我们的测试示例和上面的理论支持来看貌似在MySQL中通过MVCC就解决了幻读的问题,那既然这样串行化读貌似就没啥意义了,带着疑问继续测试。

测试前数据:

测试前数据

事物 1 事物 2
begin begin
select * from dept
- insert into dept(name) values("研发部")
- commit
update dept set name="财务部"(工作中如果不想被辞退一定要写where条件)
commit

根据上面的结果我们期望的结果是这样的:

id  name
1   财务部
2   研发部 

但是实际上我们的经过是:

测试后数据

本来我们希望得到的结果只是第一条数据的部门改为财务,但是结果确实两条数据都被修改了。这种结果告诉我们其实在MySQL可重复读的隔离级别中并不是完全解决了幻读的问题,而是解决了读数据情况下的幻读问题。而对于修改的操作依旧存在幻读问题,就是说MVCC对于幻读的解决时不彻底的。

执行update时以非索引字段作为查询条件会有什么问题?

对于非索引字段进行update或select .. for update操作,代价极高。所有记录上锁,以及所有间隔的锁。
对于索引字段进行上述操作,代价一般。只有索引字段本身和附近的间隔会被加锁。

所以update、delete语句用不上索引是很恐怖的

你可能感兴趣的:(java)