MySQL隔离机制

1. 脏写、脏读、不可重复读、幻读等问题

1)脏写

2)脏读

无论是脏写还是脏读,都是一个事务去更新或查询了另一个事务未提交的数据,如果另一个事务回滚,

就出现了脏写、脏读的情况

3)不可重复读

不可重复读不是什么大问题,具体取决于是否允许不可重复读,如果业务要求事务期间每次读取的

数据都是一致的,这就是问题,需要解决

4)幻读

2. MySQL隔离机制

1)read uncommitted

不允许脏写(不允许两个未提交的事务同时更新一条数据),但是会出现脏读、不可重复读、幻读问题

2)read committed

不会出现脏写和脏读(查询不到别的事务未提交的数据),但是会出现不可重复读、幻读

3)repeatable read

不会出现脏写、脏读、不可重复读问题(事务一旦开启,别的事务提交后的值也不会读到),但是会出现幻读,

这里是mysql比较牛的地方,RR级别下可以解决幻读的问题,要借助于下面所讲的MVCC

4)serializable  

串行化执行,根本就不是并发,所以上述问题都不会出现

3. MVCC

讲MVCC之前,我们有必要聊下undo log版本链。

简单来说,我们每条数据都有两个隐藏的字段trx_id和roll_pointer,trx_id是最近一次更新数据的事务id, roll_pointer指向了你更新这个事务之前生成的undo log

再来看看基于undo log链的ReadView机制

简单说就是执行一个事务的时候,就会生成一个ReadView,里面有4个关键东西

1)m_ids --此时有哪些事务未提交

2)min_trx_id --m_ids里最小的值

3)max_trx_id --表示下一个事务生成时分配给它的id

4)creator_trx_id --当前事务id

 

4. 锁

1)独占锁(X锁)

脏写是绝对不允许的,是靠锁来实现的,让多个事务更新同一行数据串行化,避免同时更新

事务A要更新数据,一看该数据没有人锁定,立马创建一个锁,包含了自己的trx_id和等待状态,然后锁和数据

关联起来;此时事务B也想要更新数据,发现数据已经被加锁了,然后B也生成一个锁,但此时B是等待状态的

 

接着事务A更新完数据提交,会把锁释放掉。一旦锁释放,就会去找还有没有别的事务加锁了,找到B的锁把等

待状态改为false,然后唤醒事务B继续执行,此时事务B就获取到数据了

如果此时别的事务来读取这条数据会加锁嘛?不会,基于MVCC,避免了频繁加锁

2)共享锁(S锁)

select * from table lock in share mode会给当前数据加共享锁

 

此时明白了,独占锁和独占锁是互斥的,别的事务不可以更新操作;如果是查询,默认走MVCC不加锁,如果手

动加共享锁,也是互斥的;最后共享锁和共享锁是不互斥的

3)行锁(上述两种锁讲的就是行锁)

4)表锁(一般不会这样操作)

lock table *** read --表级共享锁

lock table *** write --表级独占锁

查询、更新行数据的时候会在表上加意向锁;分为意向共享锁和意向独占锁

         

posted @ 2021-09-14 06:55  星晕留谁  阅读(205)  评论(0编辑  收藏  举报