Skip to content

Commit a4d19f6

Browse files
authored
高性能MySQL笔记
高性能MySQL笔记
1 parent 8d89114 commit a4d19f6

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

docs/2019/高性能MySQL.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
2+
![SQL语句的执行流程](https://img-blog.csdnimg.cn/20190428211616178.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTAzOTEzNDI=,size_16,color_FFFFFF,t_70)
3+
>无论何时,只要有多个查询需要在同一个时刻修改数据时,就会有并发问题。MySql主要在`服务器层``存储引擎层`进行并发控制。
4+
5+
假设数据库中国一张邮箱表,每个邮件都是一条记录。如果某个客户正在读取邮箱,同时其他客户试图在删除邮箱表中的某一条数据。这个时候,读取的结构就是不确定的了。在MySql中会通过锁定防止其它用户读取同一数据。大多数时候,MySQL锁的内部管理都是透明的。
6+
7+
## MySQL锁的粒度
8+
* 每种MySql引擎都可以实现自己的锁策略和锁粒度,将锁粒度固定在某个级别,可以为某些特定的场景提供更好的性能。
9+
10+
**表锁(table lock)**
11+
* 表锁是mysql中最基本的锁略,并且是开销最小的策略。它会锁定整个表,一个用户在对表进行写操作(插入、删除、更新等)前,需要先获得写锁,这会阻塞其他用户对该表的所有读写操作。只有没有写锁时,其他读取的用户才能获得读锁,读锁之间是不相互阻塞的。
12+
* 在特定的场景中,表锁也可能有良好的性能。例如,`READ L0CAL` 表锁支持某些类型的并发写操作。另外,写锁也比读锁有更高的优先级,因此-一个写锁请求可能会被插入到读
13+
锁队列的前面(写锁可以插入到锁队列中读锁的前面,反之读锁则不能插入到写锁的前
14+
面)。
15+
* 尽管存储引擎可以管理自己的锁,MySQL本身还是会使用各种有效的表锁来实现不同
16+
的目的。例如,服务器会为诸如`ALTER TABLE` 之类的语句使用表锁,而忽略存储引擎的
17+
锁机制。
18+
19+
**行级锁(row lock)**
20+
* 行级锁可以最大程度地支持并发处理(同时也带来了最大的锁开销)。
21+
*`InnoDB``XtraDB`,以及其他一些存储引擎中实现了行级锁。
22+
* 行级锁只在存储引擎层实现,而MySQL服务器层没有实现。服务器层完全不了解存储引擎中的锁实现。
23+
24+
## MySQL的事务
25+
**事务特性**
26+
* A(原子性)事务的各步操作是不可分的,保证一系列的操作要么都完成,要么都不完成;
27+
* C(一致性)事务完成,数据必须处于一致的状态;
28+
* I(隔离性)对数据进行修改的所有并发事务彼此之间是相互隔离,这表明事务必须是独立的,不应以任何方式依赖或影响其他事务;
29+
* D(持久性)表示事务对数据处理结束后,对数据更改必须持久化,不管是事务成功还是回滚。事务日志都能够保持事务的永久性。
30+
31+
**事务的隔离级别**
32+
* SQL标准的事务隔离级别包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(serializable )
33+
* 读未提交是指,一个事务还没提交时,它做的变更就能被别的事务看到。
34+
* 读提交是指,一个事务提交之后,它做的变更才会被其他事务看到。
35+
* 可重复读是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。未提交的更改对其他事务是不可见的
36+
* 串行化:对应一个记录会加读写锁,出现冲突的时候,后访问的事务必须等前一个事务执行完成才能继续执行。最高的隔离级别
37+
38+
**MySQL中的事务**
39+
* MySQL提供了两种事务型的存储引擎: `InnoDB``NDB Cluster`。另外还有一些第三方
40+
存储引擎也支持事
41+
* MySQL默认采用自动提交(AUTOCOMIT) 模式。如果不是显式地开始-一个个事务,则每个查询都被当作一事务执行提交操作。在当前连接中,可以通过设置AUTOCOMMIT变量来启用或者禁用自动提交模式:
42+
* InnoDB采用的是两阶段锁定协议(two-phase locking protocol)。在事务执行过程中,随
43+
时都可以执行锁定,锁只有在执行`COMMIT`或者`ROLLBACK`的时候才会释放,并且所有的
44+
锁是在同一时刻被释放。
45+
* InnoDB也支持通过特定的语句进行显式锁定`SELECT ... LOCK IN SHARE MODE``SELECT FOR UPDATE` 些语句不属于SQL规范
46+
47+
## 多版本并发控制MVCC
48+
* `MVCC`是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。
49+
* MVCC的实现,是通过保存数据在某个时间点的快照来实现的。也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对同张表,同一时刻看到的数据可能是不一样的。
50+
* `InnoDB`的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或删除时间)。当然存储的并不是实际的时间值,而是系统版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。
51+
* MVCC只在可重复读和读提交的隔离级别生效。其它两个级别都不兼容
52+
53+
> 在可重复读(`REPEATABLE READ`) 隔离级别下,MVCC具体是如何操作的。
54+
55+
**SELECT查询操作时**
56+
57+
InnoDB会根据以下两个条件检查每行记录:
58+
* InnoDB只查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。
59+
* 行的删除版本要么未定义,要么大于当前事务版本号。这可以确保事务读取到的行,在事务开始之前未被删除。
60+
61+
**INSERT**
62+
* InnoDB为新播入的每-一行保存当前系统版本号作为行版本号。
63+
64+
**DELETE**
65+
* InnoDB为删除的每-*行保存当前系统版本号作为行删除标识。
66+
67+
**UPDATE**
68+
* InnoDB为插入-行新记录,保存当前系统版本号作为行版本号,同时保存当前系统
69+
版本号到原来的行作为行删除标识。

0 commit comments

Comments
 (0)