数据库
首页 > 数据库> > Mysql锁

Mysql锁

作者:互联网

Mysql锁

锁是计算机协调多个进程或线程并发访问某一资源的机制

我们认知中的行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁,这些锁统称为悲观锁

概述

MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。

从锁的角度来说:

MyISAM锁

MySQL的表级锁有两种模式:表共享读锁(Table Read Lock)表独占写锁(Table Write Lock)

InnoDB锁

InnoDB与MyISAM的不同:

  • 是否支持行级锁 : MyISAM 只有表级锁(table-level locking),而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。
  • 是否支持事务和崩溃后的安全恢复: MyISAM 强调的是性能,每次查询具有原子性,其执行速度比InnoDB类型更快,但是不提供事务支持。但是InnoDB 提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。
  • 是否支持外键: MyISAM不支持,而InnoDB支持
  • 是否支持MVCC :仅 InnoDB 支持。应对高并发事务, MVCC比单纯的加锁更高效;MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作;MVCC可以使用 乐观(optimistic)锁 和 悲观(pessimistic)锁来实现;各数据库中MVCC实现并不统一

InnoDB实现了两种类型的行锁。

InnoDB行锁是通过给索引上的索引项加锁来实现的。

InnoDB这种行锁实现特点:

  • 只有通过索引条件检索数据,InnoDB才使用行级锁,否则锁表
  • 不论条件是普通索引还是主键索引,都会锁当前记录
  • 建议操作普通字段,条件索引字段

可以这么理解:
共享锁就是我读的时候,你可以读,但是不能写。排他锁就是我写的时候,你不能读也不能写。其实就是MyISAM的读锁和写锁,但是针对的对象不同了而已。

这两种方式在事务(Transaction) 进行当中SELECT 到同一个数据表时,都必须等待其它事务数据被提交(Commit)后才会执行。而主要的不同在于LOCK IN SHARE MODE 在有一方事务要Update 同一个表单时很容易造成死锁 (所以实际项目中基本不使用共享锁IS)。
简单的说,如果SELECT 后面若要UPDATE 同一个表单,最好使用SELECT … for UPDATE (上面的悲观锁就是用for update来实现的)。

除此之外InnoDB还有两个表锁:

间隙锁

间隙锁作用在索引记录之间的间隔,又或者作用在第一个索引之前,最后一个索引之后的间隙。不包括索引本身。

这是出现在RR隔离级别下的一种锁,目的是防止幻读,MySQL会锁住相应数据的临近范围而避免其他事务再去插入新的数据,我们把它叫做间隙锁。

很显然,在使用范围条件检索并锁定记录时,InnoDB这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。因此,在实际应用开发中,尤其是并发插入比较多的应用,我们要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件。

所以在很多情况下,我们会直接为了避免出现间隙锁,直接放弃RR这个MySql默认隔离级别而采用RC。

邻键锁

Next-key锁实际上是Record锁和gap锁的组合。Next-key锁是在下一个索引记录本身和索引之前的gap加上S锁或是X锁(如果是读就加上S锁,如果是写就加X锁)。
默认情况下,InnoDB的事务隔离级别为RR,系统参数innodb_locks_unsafe_for_binlog的值为false。InnoDB使用next-key锁对索引进行扫描和搜索,这样就读取不到幻象行,避免了幻读的发生。

意向锁

需要强调一下,意向锁是一种不与行级锁冲突表级锁,这一点非常重要。意向锁分为两种:

即:意向锁是有数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享 / 排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁。MySql InnoDB 中意向锁的作用

锁分类

加锁情况

针对当前读select ... for update

索引使用条件\索引类型 聚簇索引 二级唯一索引 二级非唯一索引
精确匹配(RC级别) 命中索引项记录锁 命中索引项、对应聚簇索引项记录锁 命中索引项、对应聚簇索引项记录锁
精确匹配(RR级别) 命中索引项记录锁 命中索引项、对应聚簇索引项记录锁 命中索引项临键锁,后一索引项间隙锁,对应聚簇索引项记录锁
范围匹配(RC级别) 所有命中索引项记录锁 所有命中索引项、对应聚簇索引项记录锁 所有命中索引项、对应聚簇索引项记录锁
范围匹配(RR级别) 所有命中索引项、后一索引项临键锁 所有命中索引项、后一索引项临键锁,对应聚簇索引项记录锁 所有命中索引项、后一索引项临键锁,对应聚簇索引项记录锁
索引未命中(RC级别) 不加锁 不加锁 不加锁
索引未命中(RR级别) 未命中索引与前后索引的间隔加gap锁 未命中索引与前后索引的间隔加gap锁 未命中索引与前后索引的间隔加gap锁
不使用索引(RC级别) 全表扫描,读到的每行加记录锁(释放不符合条件的锁)
不使用索引(RR级别) 全表扫描,读到的每一行加临键锁,直到事务结束释放

参考链接

标签:事务,加锁,索引,InnoDB,Mysql,命中,共享
来源: https://www.cnblogs.com/faetbwac/p/16380740.html