引入
1.什么是锁
- 锁是计算机协调多个进程或线程并发访问某一资源的机制,我们称之为锁机制
2.为何要使用锁机制
-
因为在数据库中,除了传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供需要用户共享的资源
-
当并发事务同时访问一个共享的资源时,有可能导致数据不一致、数据无效等问题
-
例如在上一篇介绍过的事务并发情况下出现的读现象: 脏读、不可重复读、幻读等
-
为了解决这些方法, 主流的数据库软件都提供了锁机制, 以及事务隔离级别的概念
-
而锁机制可以将并发的数据访问顺序化, 以保证数据库中数据的一致性和有效性
ps : 锁冲突也是影响数据库并发性能的一个重要因素, 对锁对数据库非常重要, 但也更加复杂
3.并发控制
- 在计算机科学,特别是程序设计、操作系统、多处理机和数据库等领域,并发控制(Concurrency control)是确保及时纠正由并发操作导致的错误的一种机制
- 为了更好的应对高并发, 封锁、时间戳、乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段
二.锁分类
-
按照按锁的粒度划分 : 可分为行级锁、表级锁、页级锁
-
按照级别划分 : 可分为共享锁、排他锁、意向锁、间隙锁(Next-Key)
-
按照使用方式分 : 可分为乐观锁、悲观锁
-
按照加锁方式分 : 可分为自动锁、显式锁
-
按照操作划分 : DDL锁、DML锁
-
其他 : 死锁、MVCC
三.DDL锁与DML锁
-
DML锁(data locks, 数据锁),用于保护数据的完整性, 其中包括行级锁(Row Locks (TX锁))、表级锁(table lock(TM锁))
-
DDL锁(dictionary locks,数据字典锁), 用于保护数据库对象的结构,如表、索引等的结构定义; 其中包排他DDL(Exclusive DDL lock)、共享DDL锁(Share DDL lock),可中断解析锁(Breakable parse locks)
四.MySQL中的行级锁、表级锁、页级锁 (按粒度分)
在DBMS中, 可以按照锁的粒度把数据库锁分为行级锁(Innodb引擎默认使用)、表级锁(Myisam引擎默认使用)和页级锁(BDB引擎默认使用)
1.行级锁
- 行级锁定义
行级锁是Mysql中锁定粒度最细的一种锁, 表示只针对当前操作的行进行加锁; 行级锁能大大减少数据库操作的冲突; 其加锁粒度最小, 但加锁的开销也最大; 行级锁分为共享锁和排它锁
- 特点
开销大, 加锁慢; 会出现死锁; 锁定粒度最小, 发生锁冲突的概率最低, 并发也最高
- 支持引擎
Innodb 引擎
- 语法
"共享锁(s)" : select * from [表名] where [条件] lock in share mode;
"排它锁(x)" : select * from [表名] where [条件] for update;
2.表级锁 (偏向于读)
- 表级锁定义
表级锁是MySQL中锁定粒度最大的一种锁, 表示对当前操作的整张表加锁, 它实现简单, 资源消耗较少, 被大部分MySQL引擎支持; 最常使用的Myisam与Innodb都支持表级锁定; 表级锁定分为表共享读锁(共享锁)和表独占写锁(排它锁)
- 特点
开销小, 加锁快; 不会出现死锁; 锁定粒度大, 发出锁冲突的概率最高, 并发度最低
- 支持引擎
Myisam引擎、Memory引擎、Innodb引擎
- 示例
"语法" : lock table [表名1] [resd|write],[表名2] [resd|write], ...; # 可以加读锁或者写作
lock table user read; # 将表 user 加上写锁
show open tables where in_user>=1; # 查看当前会话锁定一次以上的表
update user set name="song" where id=1; # 更新表数据(会提示表被锁定)
unlock tables; # 释放当前会话持有的任何锁
update user set name="song" where id=1; # 再次更新可以成功
3.页级锁
- 页级锁定义
页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁; 表级锁速度快, 但冲突多, 行级冲突少, 但速度慢; 所以取了折衷的页级, 一次锁定相邻的一组记录; BDB支持页级锁
- 特点
开销和加锁时间界于表锁和行锁之间; 会出现死锁; 锁定粒度界于表锁和行锁之间, 并发度一般
- 支持引擎
BDB引擎