1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-16 18:10:13 +08:00

[docs update] 添加并发事务的控制方式、MySQL 日志,完善 MySQL 查询缓存

添加内容: 并发事务的控制方式、MySQL 日志
完善内容:MySQL 查询缓存
This commit is contained in:
Guide 2023-01-14 11:55:21 +08:00
parent a4cb5237d9
commit 653d7b59d6

View File

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