目的
锁机制的出现是为了解决资源共享而造成的并发问题。
并发问题包括 4 种:
- 脏读
- 幻读
- 不可重复读
- 丢失更新
从分类的角度来讲,可以将锁分为 2 类:
- 读锁,也叫共享锁,可读不可写
- 写锁,也叫互斥锁,不可读不可写
从操作范围的角度来讲,可以将锁分成 2 类:
- 表锁
- 行锁
表锁
是一次性对一张表整体加锁。
共有 6 个特点:
- 开销小
- 加锁快
- 无死锁
- 锁的范围大
- 容易发生锁冲突
- 并发度低
- 解锁命令解锁
使用举例:MyISAM 存储引擎使用
行锁
一次性对一条数据加锁。
共 6 个特点:
- 开销大
- 加锁慢
- 容易出现死锁
- 锁的范围较小
- 不容易发生锁冲突
- 并发度高
- 事务解锁
使用举例:InnoDB 存储引擎使用
存储引擎共 2 类:
- MyISAM
- InnoDB
MyISAM 在执行查询语句前会有 2 步,
- 会自动给涉及的所有表加读锁,
- 在执行更新操作前,会自动给涉及的表加写锁
因此,MyISAM 会导致 2 种结果:
- 对 MyISAM 的读操作,不会阻塞其他进程对同一表的读请求,但会阻塞同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。
- 对 MyISAM 的写操作,会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。
结论:
立刻获取的资源比较多的时候,使用 InnoDB ; 否则使用 MyISAM 。
分析锁定情况
表锁具体的方法有 2 种:
- 查看加锁情况 : show open tables
- 查看表锁定情况的严重程度 : show status like 'table%'
行锁分析的方法:
- 查看加行锁情况 :show status like '%innodb_row_lock%'
代码实例
实例 1
目的:表锁加读锁的展示
数据准备:
执行增加读锁:
执行后:
实例 2
目的:表锁加写锁的展示
执行后:
实例 3
目的:行锁操作相同的行数据
数据准备:
执行后:
总结:
如果会话 0 对数据 a 进行增删改操作时,则其它会话必须等待会话 0 结束事务 commit 或 rollback 之后,才能对数据 a 进行操作。
需要注意 2 项:
- 如果没有索引,行锁会自动转成表锁。
- 如果有 where , 则实际加锁的范围就是 where 后面的范围,不是实际的值。间隙锁会导致在范围内却不存在。
实例 4
目的:行锁操作不同的行数据
执行结果:
各自执行,互不影响。