Mysql 百问系列:认识锁

因为锁的内容涉及比较多,会分多篇文章讲解。本文主要从锁的种类讲解下,先搞清楚到底有哪些锁而后咱们后面再根据不一样锁不一样问题来详细说明。因此如今先把精力放在搞清楚到底有哪些锁 mysql

问题:

  1. 锁分哪几种?
  2. 不一样锁各自用处?

根据加锁的范围能够分为:

  • 全局锁
  • 表级锁
  • 行级锁
针对这个三类锁,须要明白一下几个问题:
  1. 全局锁怎么加? 何时加全局锁?
Flush tables with read lock;
复制代码

加上全局所后,整个数据库就是只读的了。 其余客户端链接后没法修改数据。须要注意的是,若是加锁的客户端断开链接,那么锁就会解除。
若是须要备份整个数据库,那么可使用全局锁,使在备份过程当中只容许读,保障备份数据的一致性。
虽然全局锁能够保障备份数据时候的一致性,可是因为变成只读,那么可定会影响业务的进行。咱们也没见过由于备份数据库致使线上服务没法正常工做啊。因此通常状况下,生成中的确不多用到这个功能,取而代之的是mysqldump 工具,使用–single-transaction 参数,因为Innodb 的MVCC能力,因此能够保障备份事数据一致性的同时又不上锁。(这也是InnoDb 基本取代MyISAM 引擎的缘由之一)sql

  1. 表级锁何时加? 什么场景须要用到表级别锁?

咱们都知道MyISAM 与 InnoDB 的一个区别是,MyISAM支持的是表级锁,而InnoDB能够支持行级锁,因此InnoDB 的并发性更好一点。 可是这不意味着这InnoDB中没有表级锁。InnoDB 一样存在表级别锁数据库

先来看这样一个场景,我有一张student 表,其中字段有 id,name ,age 三个字段。表中有100万条数据。假设如今有个长事务正在进行,正在给student表其中5万人审核年龄并修改为正确年龄。若是这个事务要持续1小时。期间,咱们同时须要更新表结构,给student表添加一个address字段。
咱们会发现表结构更新语句会被阻塞,须要等到长事务结束才更新表结构。
那么更新表结构是被什么阻塞呢? 显而易见的时事务更新对应数据的年龄,那么其中有5万条数据加上了行级锁。是被这个行级锁阻塞的的吗?其实不是。 这里Mysql 引入了MDL(metadata lock) 元数据锁。简单来讲他是用来锁表的,是个表级别锁。MDL也分为读锁和写锁。
例子中修改数据时,开始前会先给表student 加 MDL 的读锁来锁住整个表,防止表中数据在查询,修改的时候表的结构被改变。因为咱们须要给student表添加字段的时候会给表添加MDL的写锁。这是MDL写锁只能等待MDL读锁被释放才能加上去而被阻塞。
概况下MDL 的加锁规律就是: 表作查询,修改,新增,删除时会对表先加MDL的读锁,而后再加对应的行锁。 而对表结构作修改时,会对表加MDL的写锁并发

  1. 行级锁有哪些?
  • Record Locks (记录锁) 能够分为读(S)记录锁,和写(X)记录锁。用来锁住记录
  • Gap Locks (间隙锁),用来防止幻影
  • Next-Key Locks (Next-Key 锁),记录锁和间隙锁的合体
  • Insert Intention Locks (插入意向锁)

要讲解行数的加锁机制比较麻烦,后续另外一篇文章详细聊。这里咱们只要知道InnoDB支持行锁,而MyISAM 是不支持的。工具

根据锁的兼容性来分

  • 共享锁 Shared Locks(S 锁)
  • 独占锁 Exclusive Locks(X 锁)

共享锁能够同时获取,而独占锁至于在对象上没有存在任何锁的状况下能够获取
事务A, 查询 表student 中id 为1,2,3的数据,那么事务A就分别给数据1,2,3添加了共享行锁。
事务B,  查询 表student 中id 为1,3,5的数据,那么事务B就分别给数据1,3,5添加了共享行锁。
若是事务A,B都未提交,这时候数据1,3分别挂了2把共享锁。
事务C,  想要修改表student id 为 1 的数据,那么他须要给数据1挂上独占锁,因为1已经有共享锁存在,他被挂起等待。
因为共享锁和独占锁的特性,就会产生一个死锁问题,这个问题我也会另开一篇详细说明。spa

总结:

根据锁的加锁范围咱们能够有 全局锁,表锁(MDL为表锁的一种),行锁。而行锁又细分红了几种不一样的锁。 同时无论是表锁,仍是行锁可能根据兼容性来分,又会有共享表锁,独占表锁,共享行锁,独占行锁等code

相关文章
相关标签/搜索