数据库两大神器索引和锁( 四 )

看完上面的有没有发现,在一开始所说的:X锁,S锁,读锁 , 写锁,共享锁,排它锁其实总共就两个锁 , 只不过它们有多个名字罢了~~~

Intention locks do not block anything except full table requests (for example, LOCK TABLES ... WRITE). The main purpose of intention locks is to show that someone is locking a row, or going to lock a row in the table.
另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁:
  • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁 。意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁 。意向锁也是数据库隐式帮我们做了,不需要程序员操心!
参考资料:
  • ***/question/51513268***/doc/refman/8.0/en/innodb-locking.html
2.2.1MVCC和事务的隔离级别
数据库事务有不同的隔离级别,不同的隔离级别对锁的使用是不同的,锁的应用最终导致不同事务的隔离级别
MVCC(Multi-Version Concurrency Control)多版本并发控制,可以简单地认为:MVCC就是行级锁的一个变种(升级版) 。
  • 事务的隔离级别就是通过锁的机制来实现 , 只不过隐藏了加锁细节
在表锁中我们读写是阻塞的,基于提升并发性能的考虑 , MVCC一般读写是不阻塞的(所以说MVCC很多情况下避免了加锁的操作)
  • MVCC实现的读写不阻塞正如其名:多版本并发控制--->通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取 。从用户的角度来看,好像是数据库可以提供同一数据的多个版本 。
快照有两个级别:
  • 语句级针对于Read committed隔离级别事务级别针对于Repeatable read隔离级别
我们在初学的时候已经知道,事务的隔离级别有4种:
  • Read uncommitted会出现脏读,不可重复读,幻读Read committed会出现不可重复读,幻读Repeatable read会出现幻读(但在Mysql实现的Repeatable read配合gap锁不会出现幻读!)
Serializable
  • 串行,避免以上的情况!
Read uncommitted会出现的现象--->脏读:一个事务读取到另外一个事务未提交的数据
例子:A向B转账,A执行了转账语句,但A还没有提交事务,B读取数据,发现自己账户钱变多了!B跟A说,我已经收到钱了 。A回滚事务【rollback】,等B再查看账户的钱时,发现钱并没有多 。出现脏读的本质就是因为操作(修改)完该数据就立马释放掉锁 , 导致读的数据就变成了无用的或者是错误的数据 。
Read committed避免脏读的做法其实很简单:
  • 就是把释放锁的位置调整到事务提交之后 , 此时在事务提交前,其他进程是无法对该行数据进行读取的,包括任何操作
但Read committed出现的现象--->不可重复读:一个事务读取到另外一个事务已经提交的数据,也就是说一个事务可以看到其他事务所做的修改
注:A查询数据库得到数据,B去修改数据库的数据 , 导致A多次查询数据库的结果都不一样【危害:A每次查询的结果都是受B的影响的,那么A查询出来的信息就没有意思了】
上面也说了 , Read committed是语句级别的快照!每次读取的都是当前最新的版本!
Repeatable read避免不可重复读是事务级别的快照!每次读取的都是当前事务的版本,即使被修改了 , 也只会读取当前事务版本的数据 。
呃...如果还是不太清楚,我们来看看InnoDB的MVCC是怎么样的吧(摘抄《高性能MySQL》)
数据库两大神器索引和锁

文章插图
数据库两大神器索引和锁

文章插图
至于虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致 。
  • 注:和不可重复读类似,但虚读(幻读)会读到其他事务的插入的数据,导致前后读取不一致MySQL的Repeatable read隔离级别加上GAP间隙锁已经处理了幻读了 。
参考资料:
  • ***/p/cb97f76a92fd***/question/263820564
扩展阅读:
  • ***/question/67739617
2.3乐观锁和悲观锁
无论是Read committed还是Repeatable read隔离级别,都是为了解决读写冲突的问题 。
单纯在Repeatable read隔离级别下我们来考虑一个问题:


推荐阅读