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:
parent
a4cb5237d9
commit
653d7b59d6
@ -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) 的 **「技术面试题篇」** 中找到。
|
||||
|
||||

|
||||
|
||||
## MySQL 事务
|
||||
|
||||
### 何谓事务?
|
||||
@ -360,6 +379,26 @@ COMMIT;
|
||||
|
||||
举个例子:执行 `delete` 和 `update` 操作的时候,可以直接对记录加锁,保证事务安全。而执行 `insert` 操作的时候,由于记录锁(Record Lock)只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁(Gap Lock)。也就是说执行 `insert` 操作的时候需要依赖 Next-Key Lock(Record Lock+Gap Lock) 进行加锁来保证不出现幻读。
|
||||
|
||||
### 并发事务的控制方式有哪些?
|
||||
|
||||
MySQL 中并发事务的控制方式无非就两种:**锁** 和 **MVCC**。锁可以看作是悲观控制的模式,多版本并发控制(MVCC,Multiversion concurrency control)可以看作是乐观控制的模式。
|
||||
|
||||
**锁** 控制方式下会通过锁来显示控制共享资源而不是通过调度手段,MySQL 中主要是通过 **读写锁** 来实现并发控制。
|
||||
|
||||
- **共享锁(S 锁)** :又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时获取(锁兼容)。
|
||||
- **排他锁(X 锁)** :又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被加了排他锁,那其他事务不能再对这条事务加任何类型的锁(锁不兼容)。
|
||||
|
||||
读写锁可以做到读读并行,但是无法做到写读、写写并行。另外,根据根据锁粒度的不同,又被分为 **表级锁(table-level locking)** 和 **行级锁(row-level locking)** 。InnoDB 不光支持表级锁,还支持行级锁,默认为行级锁。行级锁的粒度更小,仅对相关的记录上锁即可(对一行或者多行记录加锁),所以对于并发写入操作来说, InnoDB 的性能更高。不论是表级锁还是行级锁,都存在共享锁(Share Lock,S 锁)和排他锁(Exclusive Lock,X 锁)这两类。
|
||||
|
||||
**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 标准定义了四个隔离级别:
|
||||
|
Loading…
x
Reference in New Issue
Block a user