Skip to content

Commit 653d7b5

Browse files
committed
[docs update] 添加并发事务的控制方式、MySQL 日志,完善 MySQL 查询缓存
添加内容: 并发事务的控制方式、MySQL 日志 完善内容:MySQL 查询缓存
1 parent a4cb523 commit 653d7b5

File tree

1 file changed

+42
-3
lines changed

1 file changed

+42
-3
lines changed

docs/database/mysql/mysql-questions-01.md

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,16 +234,35 @@ set global query_cache_type=1;
234234
set global query_cache_size=600000;
235235
```
236236
237-
如上,**开启查询缓存后在同样的查询条件以及数据情况下,会直接在缓存中返回结果**。这里的查询条件包括查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息。**查询缓存不命中的情况:(1)**)因此任何两个查询在任何字符上的不同都会导致缓存不命中。此外,(**查询缓存不命中的情况:(2)**)如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL 库中的系统表,其查询结果也不会被缓存。
237+
如上,**开启查询缓存后在同样的查询条件以及数据情况下,会直接在缓存中返回结果**。这里的查询条件包括查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息。
238238
239-
**查询缓存不命中的情况:(3)****缓存建立之后**,MySQL 的查询缓存系统会跟踪查询中涉及的每张表,如果这些表(数据或结构)发生变化,那么和这张表相关的所有缓存数据都将失效。
239+
**查询缓存不命中的情况:**
240240
241-
**缓存虽然能够提升数据库的查询性能,但是缓存同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。** 因此,开启查询缓存要谨慎,尤其对于写密集的应用来说更是如此。如果开启,要注意合理控制缓存空间大小,一般来说其大小设置为几十 MB 比较合适。此外,**还可以通过 sql_cache 和 sql_no_cache 来控制某个查询语句是否需要缓存:**
241+
1. 任何两个查询在任何字符上的不同都会导致缓存不命中。
242+
2. 如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL 库中的系统表,其查询结果也不会被缓存。
243+
3. 缓存建立之后,MySQL 的查询缓存系统会跟踪查询中涉及的每张表,如果这些表(数据或结构)发生变化,那么和这张表相关的所有缓存数据都将失效。
244+
245+
**缓存虽然能够提升数据库的查询性能,但是缓存同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。** 因此,开启查询缓存要谨慎,尤其对于写密集的应用来说更是如此。如果开启,要注意合理控制缓存空间大小,一般来说其大小设置为几十 MB 比较合适。此外,**还可以通过 `sql_cache``sql_no_cache` 来控制某个查询语句是否需要缓存:**
242246
243247
```sql
244248
select sql_no_cache count(*) from usr;
245249
```
246250
251+
## MySQL 日志
252+
253+
- MySQL 中常见的日志有哪些?
254+
- 慢查询日志有什么用?
255+
- binlog 主要记录了什么?
256+
- redo log 如何保证事务的持久性?
257+
- 页修改之后为什么不直接刷盘呢?
258+
- binlog 和 redolog 有什么区别?
259+
- undo log 如何保证事务的原子性?
260+
- ......
261+
262+
上诉问题的答案可以在[《Java 面试指北》(付费)](https://javaguide.cn/zhuanlan/java-mian-shi-zhi-bei.html) 的 **「技术面试题篇」** 中找到。
263+
264+
![《Java 面试指北》技术面试题篇](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javamianshizhibei/technical-interview-questions.png)
265+
247266
## MySQL 事务
248267
249268
### 何谓事务?
@@ -360,6 +379,26 @@ COMMIT;
360379
361380
举个例子:执行 `delete``update` 操作的时候,可以直接对记录加锁,保证事务安全。而执行 `insert` 操作的时候,由于记录锁(Record Lock)只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁(Gap Lock)。也就是说执行 `insert` 操作的时候需要依赖 Next-Key Lock(Record Lock+Gap Lock) 进行加锁来保证不出现幻读。
362381
382+
### 并发事务的控制方式有哪些?
383+
384+
MySQL 中并发事务的控制方式无非就两种:******MVCC**。锁可以看作是悲观控制的模式,多版本并发控制(MVCC,Multiversion concurrency control)可以看作是乐观控制的模式。
385+
386+
**** 控制方式下会通过锁来显示控制共享资源而不是通过调度手段,MySQL 中主要是通过 **读写锁** 来实现并发控制。
387+
388+
- **共享锁(S 锁)** :又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时获取(锁兼容)。
389+
- **排他锁(X 锁)** :又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被加了排他锁,那其他事务不能再对这条事务加任何类型的锁(锁不兼容)。
390+
391+
读写锁可以做到读读并行,但是无法做到写读、写写并行。另外,根据根据锁粒度的不同,又被分为 **表级锁(table-level locking)****行级锁(row-level locking)** 。InnoDB 不光支持表级锁,还支持行级锁,默认为行级锁。行级锁的粒度更小,仅对相关的记录上锁即可(对一行或者多行记录加锁),所以对于并发写入操作来说, InnoDB 的性能更高。不论是表级锁还是行级锁,都存在共享锁(Share Lock,S 锁)和排他锁(Exclusive Lock,X 锁)这两类。
392+
393+
**MVCC** 是多版本并发控制方法,即对一份数据会存储多个版本,通过事务的可见性来保证事务能看到自己应该看到的版本。通常会有一个全局的版本分配器来为每一行数据设置版本号,版本号是唯一的。
394+
395+
MVCC 在 MySQL 中实现所依赖的手段主要是: **隐藏字段、read view、undo log**
396+
397+
- undo log : undo log 用于记录某行数据的多个版本的数据。
398+
- read view 和 隐藏字段 : 用来判断当前版本数据的可见性。
399+
400+
关于 InnoDB 对 MVCC 的具体实现可以看这篇文章:[InnoDB 存储引擎对 MVCC 的实现](https://javaguide.cn/database/mysql/innodb-implementation-of-mvcc.html) 。
401+
363402
### SQL 标准定义了哪些事务隔离级别?
364403
365404
SQL 标准定义了四个隔离级别:

0 commit comments

Comments
 (0)