厦门大学数据库实验室 dblab.xmu

Post on 15-Jan-2016

645 views 0 download

description

厦门大学数据库实验室 http://dblab.xmu.edu.cn. MySQL 加锁处理分析. 赖明星 2014 年 5 月 17 日. 目录. 学习目标. 背景知识. 简单 SQL 语句加锁分析. 复杂 SQL 语句加锁分析. 总结. 学习目标. 1. 理解锁的概念与锁的类型 理解加锁操作涉及到的考虑因素 理解 lock 与 latch 的区别 能够分析简单的 SQL 语句的加锁情况. 目录. 学习目标. 背景知识. 简单 SQL 语句加锁分析. 复杂 SQL 语句加锁分析. 总结. 背景知识. 2. 事务的 ACID 特性 - PowerPoint PPT Presentation

Transcript of 厦门大学数据库实验室 dblab.xmu

厦门大学数据库实验室http://dblab.xmu.edu.cn

赖明星2014 年 5 月 17 日

MySQL 加锁处理分析

目录

学习目标 学习目标

背景知识 背景知识

简单 SQL 语句加锁分析 简单 SQL 语句加锁分析

复杂 SQL 语句加锁分析 复杂 SQL 语句加锁分析

总结 总结

学习目标 1• 理解锁的概念与锁的类型• 理解加锁操作涉及到的考虑因素• 理解 lock与 latch的区别• 能够分析简单的 SQL语句的加锁情况

目录

学习目标 学习目标

背景知识 背景知识

简单 SQL 语句加锁分析 简单 SQL 语句加锁分析

复杂 SQL 语句加锁分析 复杂 SQL 语句加锁分析

总结 总结

背景知识 21. 事务的 ACID特性2. 事务的隔离级别3. 2PL

4. MVCC

5. 聚簇索引6. 锁类型与锁算法

背景知识 2.1

背景知识 2.1

事务的隔离级别 2.2•READ UNCOMMITTED(未提交读)事务在这个级别下,事务所做的修改,即使没有提交,对其他事务也是可见的。

•READ COMMITTED(提交读) READ COMMITTED 下,只能“看见”已提交事务所做的修改,但是 RC 会出现一个问题,即同一事务两次读可能得到不一样的结果,因此, READ COMMITTED 又称为不可重复读。

•REPEATABLE READ(可重复读) REPEATABLE READ 级别保证在同一个事务中多次读取同样的记录结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读的问题。

•SERIALIZABLE(可串行化)最高的隔离级别,强制事务串行执行。

提交读

解决不可重复读未提交读

解决脏读可重复读

解决幻读可串行化

2PL协议 2.3

MVCC 2.41. MySQL InnoDB 存储引擎,实现的是基于多版本的并发控制协议——

MVCC , MVCC 最大的好处是“读不加锁,读写不冲突”。

2. 在 MVCC 并发控制中,读操作可以分成两类:快照读 (snapshot read) 与当前读 (current read) 。快照读,读取的是记录的可见版本 ,不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。

下面的 SQL语句哪些是快照读,哪些是当前读?

1. select * from table where ?;2. select * from table where ? lock in share mode;3. select * from table where ? for update;4. insert into table values (…);5. update table set ? where ?;6. delete from table where ?;

MVCC 2.4以 MySQL InnoDB 为例:• 快照读:简单的 select 操作,属于快照读,不加锁。

– select * from table where ?;

• 当前读:特殊的读操作,插入 / 更新 / 删除操作,属于当前读,需要加锁– select * from table where ? lock in share mode;– select * from table where ? for update;– insert into table values (…);– update table set ? where ?;– delete from table where ?;

所有以上的语句,都属于当前读,读取记录的最新版本。并且,读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中,除了第一条语句,对读取记录加 S 锁 (共享锁 ) 外,其他的操作,都加的是 X 锁 ( 排它锁 ) 。

聚簇索引 2.5• 在聚集索引中,叶结点也即数据结点,所有数据行的存储顺序与索引的

存储顺序一致, innodb 就是聚集索引(注意:一个表只能有一个聚集索引)

• 非聚集索引即为从属索引,索引在物理上与它描述的表文件分离

锁的类型 2.6从资源竞争的角度理解锁的类型

X S

X 不兼容 不兼容S 不兼容 兼容

锁的类型 2.6从保护资源的角度理解锁的类型

lock latch

对象 事务 线程保护 数据库内容 内存数据结构持续时间 整个事务过程 临界资源模式 行锁、表锁、意向锁 读写锁、互斥量死锁 通过 waits-for

graph 、 time out 等机制进行死锁检测

无死锁检测机制,如果出现死锁,则说明数据库存在 bug

存在于 Lock Manager 的哈希表中 每个数据结构的对象中

锁的类型 2.6从数据库设计者的角度理解锁的类型• 表锁• 行锁• 意向共享锁( IS)和意向排他锁( IX)

目录

学习目标 学习目标

背景知识 背景知识

简单 SQL 语句加锁分析 简单 SQL 语句加锁分析

复杂 SQL 语句加锁分析 复杂 SQL 语句加锁分析

总结 总结

简单 SQL语句加锁分析 3下面的 SQL语句加什么锁? SQL1 : select * from t1 where id = 10;

SQL2 : delete from t1 where id = 10;

加锁涉及到的因素: 前提一: id列是不是主键? 前提二:当前系统的隔离级别是什么? 前提三: id列如果不是主键,那么 id列上有索引吗? 前提四: id列上如果有二级索引,那么这个索引是唯一索引吗? 前提五:两个 SQL 的执行计划是什么?索引扫描?全表扫描?

简单 SQL语句加锁分析 3不同前提与不同的隔离级别的组合:

组合一: id列是主键, RC 隔离级别 组合二: id列是二级唯一索引, RC 隔离级别 组合三: id列是二级非唯一索引, RC 隔离级别 组合四: id列上没有索引, RC 隔离级别 组合五: id列是主键, RR 隔离级别 组合六: id列是二级唯一索引, RR 隔离级别 组合七: id列是二级非唯一索引, RR 隔离级别 组合八: id列上没有索引, RR 隔离级别 组合九: Serializable 隔离级别

简单 SQL语句加锁分析 3SQL1 : select * from t1 where id = 10;

组合一: id列是主键, RC 隔离级别 组合二: id列是二级唯一索引, RC 隔离级别 组合三: id列是二级非唯一索引, RC 隔离级别 组合四: id列上没有索引, RC 隔离级别 组合五: id列是主键, RR 隔离级别 组合六: id列是二级唯一索引, RR 隔离级别 组合七: id列是二级非唯一索引, RR 隔离级别 组合八: id列上没有索引, RR 隔离级别 组合九: Serializable 隔离级别

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10;

组合一: id列是主键, RC 隔离级别 组合二: id列是二级唯一索引, RC 隔离级别 组合三: id列是二级非唯一索引, RC 隔离级别 组合四: id列上没有索引, RC 隔离级别 组合五: id列是主键, RR 隔离级别 组合六: id列是二级唯一索引, RR 隔离级别 组合七: id列是二级非唯一索引, RR 隔离级别 组合八: id列上没有索引, RR 隔离级别 组合九: Serializable 隔离级别

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10; 组合一: id列是主键, RC 隔离级别

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10; 组合二: id列是二级唯一索引, RC 隔离级别

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10; 组合三: id列是二级非唯一索引, RC 隔离级别

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10; 组合四: id列上没有索引, RC 隔离级别

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10; 组合五: id列是主键, RR 隔离级别

与组合一类似

组合六: id列是二级唯一索引, RR 隔离级别 与组合二类似

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10; 组合七: id列是二级非唯一索引, RR 隔离级别RC 隔离级别允许幻读,而 RR 隔离级别,不允许存在幻读。但是在组合五、组合六中,加锁行为又是与 RC 下的加锁行为完全一致。那么 RR 隔离级别下,如何防止幻读呢

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10; 组合五: id列是主键, RR 隔离级别 组合六: id列是二级唯一索引, RR 隔离级别

为什么组合五、组合六,也是 RR 隔离级别,却不需要加GAP 锁呢?

对于组合五, id 是主键;对于组合六, id 是 unique键,都能够保证唯一性。一个等值查询,最多只能返回一条记录,而且新的相同取值的记录,一定不会在新插入进来,因此也就避免了 GAP 锁的使用。

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10; 组合八: id列上没有索引, RR 隔离级别

简单 SQL语句加锁分析 3SQL2 : delete from t1 where id = 10; 组合九: Serializable 隔离级别

• 对于 SQL2 : delete from t1 where id = 10; 来说, Serializable 隔离级别与Repeatable Read 隔离级别完全一致。

• 对于 SQL1 : select * from t1 where id = 10; 这条 SQL ,在 RC , RR 隔离级别下,都是快照读,不加锁。但是在 Serializable 隔离级别, SQL1 会加读锁,也就是说快照读不复存在, MVCC 并发控制降级为 Lock-Based CC 。

• 结论:在 MySQL/InnoDB 中,所谓的读不加锁,并不适用于所有的情况,而是隔离级别相关的。 Serializable 隔离级别,读不加锁就不再成立,所有的读操作,都是当前读。

目录

学习目标 学习目标

背景知识 背景知识

简单 SQL 语句加锁分析 简单 SQL 语句加锁分析

复杂 SQL 语句加锁分析 复杂 SQL 语句加锁分析

总结 总结

复杂 SQL语句加锁分析 4加什么锁?

SQL语句的三个阶段:1. Index key : pubtime > 1 and puptime < 202. Index Filter : userid = ‘hdc’3. Table Filter : comment is not NULL

复杂 SQL语句加锁分析 4Index Condition Pushdown 是 MySQL 5.6 开始支持的一种根据索引进行查询的优化方式。之前的 MySQL 数据库版本不支持 Index Condition Pushdown ,当进行索引查询时,首先根据索引记录来查找记录,然后再根据 WHEREguol4记录,在支持 Index Condition Pushdown 后, MySQL 数据库会在取出索引的同时,判断是否可以进行 WHERE 条件的过滤,也就是将WHERE 的部分过滤操作放到了存储引擎层。在某些查询下,可以大大减少上层 SQL层对记录的索取( fetch ),从而提高数据库的整体性能。

Index Condition Pushdown 是 MySQL 5.6 开始支持的一种根据索引进行查询的优化方式。之前的 MySQL 数据库版本不支持 Index Condition Pushdown ,当进行索引查询时,首先根据索引记录来查找记录,然后再根据 WHEREguol4记录,在支持 Index Condition Pushdown 后, MySQL 数据库会在取出索引的同时,判断是否可以进行 WHERE 条件的过滤,也就是将WHERE 的部分过滤操作放到了存储引擎层。在某些查询下,可以大大减少上层 SQL层对记录的索取( fetch ),从而提高数据库的整体性能。

目录

学习目标 学习目标

背景知识 背景知识

简单 SQL 语句加锁分析 简单 SQL 语句加锁分析

复杂 SQL 语句加锁分析 复杂 SQL 语句加锁分析

总结 总结

死锁分析与总结 5

死锁分析与总结 5

死锁分析与总结 5

结论:死锁的发生与否,并不在于事务中有多少条 SQL 语句,死锁的关键在于:两个 (或以上 )

的 Session加锁的顺序不一致。

死锁分析与总结 5

总结:1.MVCC

2.事务隔离级别3.加锁操作的考虑因素4.加锁的详细过程5.死锁分析

THANKS