doc: 阅读redis sentinel文档

This commit is contained in:
2025-12-22 16:44:19 +08:00
parent 61578e0ed2
commit f5d24865b5
9 changed files with 2140 additions and 2057 deletions

View File

@@ -1,363 +1,363 @@
- [文件](#文件)
- [参数](#参数)
- [参数查看](#参数查看)
- [参数类型](#参数类型)
- [动态参数修改](#动态参数修改)
- [静态参数修改](#静态参数修改)
- [日志文件](#日志文件)
- [错误日志](#错误日志)
- [慢查询日志](#慢查询日志)
- [log\_queries\_not\_using\_indexes](#log_queries_not_using_indexes)
- [查询日志](#查询日志)
- [二进制日志](#二进制日志)
- [max\_binlog\_size](#max_binlog_size)
- [binlog\_cache\_size](#binlog_cache_size)
- [binlog\_cache\_use](#binlog_cache_use)
- [binlog\_cache\_disk\_use](#binlog_cache_disk_use)
- [sync\_binlog](#sync_binlog)
- [innodb\_flush\_log\_at\_trx\_commit](#innodb_flush_log_at_trx_commit)
- [binlog\_format](#binlog_format)
- [使用statement可能会存在的问题](#使用statement可能会存在的问题)
- [mysqlbinlog](#mysqlbinlog)
- [pid文件](#pid文件)
- [表结构定义文件](#表结构定义文件)
- [表空间文件](#表空间文件)
- [innodb\_data\_file\_path](#innodb_data_file_path)
- [innodb\_file\_per\_table](#innodb_file_per_table)
- [redo log文件](#redo-log文件)
- [循环写入](#循环写入)
- [redo log capacity](#redo-log-capacity)
- [redo log和binlog的区别](#redo-log和binlog的区别)
- [记录内容](#记录内容)
- [写入时机](#写入时机)
- [redo log写入时机](#redo-log写入时机)
# 文件
## 参数
### 参数查看
mysql参数为键值对可以通过`show variables`命令查看所有的数据库参数,并可以通过`like`来过滤参数名称。
除了`show variables`命令之外,还能够在`performance_schema`下的`global_variables`视图来查找数据库参数,示例如下:
```sql
-- 查看innodb_buffer_pool_size参数
show variables like 'innodb_buffer_pool_size'
```
上述`show variables`命令的执行结果为
| Variable\_name | Value |
| :--- | :--- |
| innodb\_buffer\_pool\_size | 4294967296 |
```sql
select * from performance_schema.global_variables where variable_name like 'innodb_buffer_pool%';
```
上述sql的执行结果如下
| VARIABLE\_NAME | VARIABLE\_VALUE |
| :--- | :--- |
| innodb\_buffer\_pool\_chunk\_size | 134217728 |
| innodb\_buffer\_pool\_dump\_at\_shutdown | ON |
| innodb\_buffer\_pool\_dump\_now | OFF |
| innodb\_buffer\_pool\_dump\_pct | 25 |
| innodb\_buffer\_pool\_filename | ib\_buffer\_pool |
| innodb\_buffer\_pool\_in\_core\_file | ON |
| innodb\_buffer\_pool\_instances | 4 |
| innodb\_buffer\_pool\_load\_abort | OFF |
| innodb\_buffer\_pool\_load\_at\_startup | ON |
| innodb\_buffer\_pool\_load\_now | OFF |
| innodb\_buffer\_pool\_size | 4294967296 |
### 参数类型
mysql中的参数可以分为`动态``静态`两种类型,
- 动态动态参数代表可以在mysql运行过程中进行修改
- 静态:代表在整个实例的声明周期内都不得进行修改
#### 动态参数修改
对于动态参数,可以在运行时通过`SET`命令来进行修改,`SET`命令语法如下:
```sql
set
| [global | session] system_var_name=expr
| [@@global. | @@session. | @@] system_var_name = expr
```
在上述语法中,`global``session`关键字代表该动态参数的修改是针对`当前会话`还是针对`整个实例的生命周期`
- 有些动态参数只能在会话范围内进行修改,例如`autocommit`
- 有些参数修改后,实例整个生命周期内都会生效,例如`binglog_cache_size`
- 有些参数既可以在会话范围内进行修改,又可以在实例声明周期范围内进行修改,例如`read_buffer_size`
使用示例如下:
查询read_buffer_size的global和session值
```sql
-- 查询read_buffer_size的global和session值
select @@session.read_buffer_size,@@global.read_buffer_size;
```
返回结果为
| @@session.read\_buffer\_size | @@global.read\_buffer\_size |
| :--- | :--- |
| 131072 | 131072 |
设置@@session.read_buffer_size为524288
```sql
set @@session.read_buffer_size = 1024 * 512;
```
设置后再次查询read_buffer_size的global和session值结果为
| @@session.read\_buffer\_size | @@global.read\_buffer\_size |
| :--- | :--- |
| 524288 | 131072 |
在调用set命令修改session read_buffer_size参数后session参数发生变化但是global参数仍然为旧的值。
> `set session xxx`命令并不会对global参数的值造成影响新会话的参数值仍然为修改前的值。
之后再对global read_buffer_size值进行修改执行如下命令
```sql
set @@global.read_buffer_size = 496 * 1024;
```
执行该命令后sesion和global参数值为
| @@session.read\_buffer\_size | @@global.read\_buffer\_size |
| :--- | :--- |
| 524288 | 507904 |
> `set global xxx`命令只会修改global参数值对session参数值不会造成影响新的session其`session参数值, global参数值`和修改后的global参数值保持一致
> 即使针对参数的global值进行了修改其影响范围是当前实例的整个生命周期`但是其并不会对参数文件中的参数值进行修改故而下次启动mysql实例时仍然会从参数文件中取值新实例的值仍然是修改前的值`。
>
> 如果想要修改下次启动实例的参数值,需要修改参数文件中该参数的值。(参数文件路径通常为`/etc/my.cnf`
#### 静态参数修改
在运行时,如果尝试对静态参数进行修改,那么会发生错误,示例如下:
```sql
> set global datadir='/db/mysql'
[2025-01-30 15:05:17] [HY000][1238] Variable 'datadir' is a read only variable
```
## 日志文件
mysql中常见日志文件如下
- 错误日志(error log)
- 二进制日志binlog
- 慢查询日志slow query log
- 查询日志log
### 错误日志
错误日志针对mysql的启动、运行、关闭过程进行了记录用户可以通过`show variables like 'log_error';`来获取错误日志的路径:
```sql
show variables like 'log_error';
```
其输出值如下:
| Variable\_name | Value |
| :--- | :--- |
| log\_error | /var/log/mysql/mysqld.log |
当mysql数据库无法正常启动时应当首先查看错误日志。
### 慢查询日志
慢查询日志存在一个阈值,通过`long_query_time`参数来进行控制,该参数默认值为`10`代表慢查询的限制为10s。
通过`slow_query_log`参数,可以控制是否日志输出慢查询日志,默认为`OFF`,如果需要开启慢查询日志,需要将该值设置为`ON`
关于慢查询日志的输出地点,可以通过`log_output`参数来进行控制。该参数默认为`FILE`,支持`FILE, TABLE, NONE``log_output`支持制定多个值,多个值之间可以通过`,`分隔,当值中包含`NONE`时,以`NONE`优先。
#### log_queries_not_using_indexes
`log_queryies_not_using_indexes`开启时如果运行的sql语句没有使用索引那么这条sql同样会被输出到慢查询日志。该参数默认关闭。
`log_throttle_queries_not_using_idnexes`用于记录`每分钟允许记录到慢查询日志并且没有使用索引`的sql语句次数该参数值默认为0代表每分钟输出到慢查询日志中的数量没有限制。
该参数主要用于防止大量没有使用索引的sql添加到慢查询日志中造成慢查询日志大小快速增加。
当慢查询日志中的内容越来越多时可以通过mysql提供的工具`mysqldumpslow`命令,示例如下:
```sql
mysqldumpslow -s at -n 10 ${slow_query_log_path}
```
### 查询日志
查询日志记录了对mysql数据库所有的请求信息无论请求是否正确执行。
查询日志通过`general_log`参数来进行控制,默认该参数值为`OFF`.
### 二进制日志
二进制日志binary log记录了针对mysql数据库执行的所有更改操作不包含select以及show这类读操作
对于update操作等即使没有对数据库进行修改affected rows为0也会被写入到binary log中。
二进制日志的主要用途如下:
- 恢复recovery某些数据恢复需要二进制日志例如在数据库全备份文件恢复后用户可以通过二进制日志进行point-in-time的恢复
- 复制replication通过将一台主机master的binlog同步到另一台主机slave并且在另一台主机上执行该binlog可以令slave与master进行实时同步
- 审计audit用户可以对binlog中的信息进行审计判断是否存在对数据库进行的注入攻击
通过参数`log_bin`可以控制是否启用二进制日志。
binlog通常存放在`datadir`参数所指定的目录路径下。在该路径下,还存在`binlog.index`文件该文件为binlog的索引文件文件内容包含所有binlog的文件名称。
#### max_binlog_size
`max_binlog_size`参数控制单个binlog文件的最大大小如果单个文件超过该值会产生新的二进制文件新binlog的后缀会+1并且新文件的文件名会被记录到`.index`文件中。
`max_binlog_size`的默认值大小为`1G`
#### binlog_cache_size
当使用innodb存储引擎时所有未提交事务的binlog会被记录到缓存中等到事务提交后会将缓存中的binlog写入到文件中。缓存大小通过`binlog_cache_size`决定,该值默认为`32768`,即`32KB`
`binlog_cache_size`是基于会话的,`在每个线程开启一个事务时mysql会自动分配一个大小为binlog_cache_size大小的缓存因而该值不能设置过大`
当一个事务的记录大于设定的`binlog_cache_size`mysql会将缓冲中的日志写入到一个临时文件中故而该值无法设置过小。
通过`show global status like 'binlog_cache%`命令可以查看`binlog_cache_use``binlog_cache_disk_use`的状态可以通过上述两个状态判断binlog cache大小是否合适。
##### binlog_cache_use
`binlog_cache_use`记录了使用缓冲写binlog的次数
##### binlog_cache_disk_use
`binlog_cache_disk_use`记录了使用临时文件写二进制日志的次数
#### sync_binlog
`sync_binlog`参数控制mysql server同步binlog到磁盘的频率该值默认为`1`
- 0: 如果参数值为0代表mysql server禁用binary log同步到磁盘。mysql会依赖操作系统将binary log刷新到磁盘中该设置性能最佳但是遇到操作系统崩溃时可能会出现mysql事务提交但是还没有同步到binary log的场景
- 1: 如果参数值设置为1代表在事务提交之前将binary log同步到磁盘中该设置最安全但是会增加disk write次数对性能会带来负面影响。在操作系统崩溃的场景下binlog中缺失的事务还只处于prepared状态从而确保binlog中没有事务丢失
- N当参数值被设置为非`01`的值时每当n个binlog commit groups被收集到后同步binlog到磁盘。在这种情况下可能会发生事务提交但是还没有被刷新到binlog中`当n值越大时性能会越好但是也会增加数据丢失的风险`
为了在使用innodb事务和replciation时获得最好的一致性和持久性请使用如下设置
```cnf
sync_binlog=1
innodb_flush_log_at_trx_commit=1
```
#### innodb_flush_log_at_trx_commit
innodb_flush_log_at_trx_commit用于控制redo log的刷新。
该参数用于平衡`commit操作ACID的合规性`以及`更高性能`。通过修改该参数值,可以实现更佳的性能,但是在崩溃时可能会丢失事务:
- 1: 1为该参数默认值代表完全的ACID合规性日志在每次事务提交后被写入并刷新到磁盘中
- 0: 日志每秒被写入和刷新到磁盘中,如果事务没有被刷新,那么日志将会在崩溃中被丢失
- 2: 每当事务提交后,日志将会被写入,并且每秒钟都会被刷新到磁盘中。如果事务没有被刷新,崩溃同样会造成日志的丢失
如果当前数据库为slave角色那么其不会把`从master同步的binlog`写入到自己的binlog中如果要实现`master=>slave=>slave`的同步架构,必须设置`log_slave_updates`参数。
#### binlog_format
binlog_format用于控制二进制文件的格式可能有如下取值
- statement: 二进制文件记录的是日志的逻辑sql语句
- row记录表的行更改情况默认值为`row`
- mixed: 如果参数被配置为mixedmysql默认会采用`statement`格式进行记录,但是在特定场景能够下会使用`row`格式:
- 使用了uuid, user, current_user,found_rows, row_count等不确定函数
- 使用了insert delay语句
- 使用了用户自定义函数
- 使用了临时表
##### 使用statement可能会存在的问题
在使用statement格式时可能会存在如下问题
- master运行randuuid等不确定函数时或使用触发器操作时会导致主从服务器上的数据不一致
- innodb的默认事务隔离级别为`repetable_read`,如果使用`read_commited`级别时statement格式可能会导致丢失更新的情况从而令master和slave的数据不一致
binlog为动态参数可以在数据库运行时进行修改并且可以针对session和global进行修改。
#### mysqlbinlog
在查看二进制日志时,可以使用`mysqlbinlog`命令,示例如下
```bash
mysqlbinlog --start-position=203 ${binlog_path}
```
## pid文件
mysql实例启动时会将进程id写入到一个文件中该文件被称为pid文件。
pid文件路径通过`pid_file`参数来进行控制fedora中默认路径为`/run/mysqld/mysqld.pid`
## 表结构定义文件
mysql中数据的存储是根据表进行的每个表都有与之对应的文件。无论表采用何种存储引擎都会存在一个以`frm`为后缀的文件,该文件中保存了该表的表结构定义。
> mysql 8中schema对应目录下不再包含frm文件。
## 表空间文件
innodb采用将存储的数据按照表空间tablespace进行存放的设计。在默认配置下将会有一个初始大小为10MB名称为ibdata1的文件该文件为默认的表空间文件。
### innodb_data_file_path
可以通过`innodb_data_file_path`参数对默认表空间文件进行设置,示例如下:
```sql
innodb_data_file_path=datafile_spec1[;datafile_spec2]...
```
用户可以通过多个文件组成一个表空间,示例如下:
```sql
innodb_data_file_path=/db/ibdata1:2000M;/dr2/db/ibdata2:2000M;autoextend
```
在上述配置中,表空间由`/db/ibdata1``/dr2/db/ibdata2`两个文件组成,如果两个文件位于不同的磁盘上,那么磁盘的负载将会被平均,数据库的整体性能将会被提高。
同时,在上述示例中,为两个文件都指定了后续属性,含义如下:
- ibdata1文件大小为2000M
- ibdata2:文件大小为2000M并且当文件大小被用完后文件会自动增长
`innodb_data_file_path`被设置后所有基于innodb存储引擎的表其数据都会记录到该共享表空间中。
### innodb_file_per_table
如果`innodb_file_per_table`被启用后默认启用则每个基于innodb存储引擎的表都可以有一个独立的表空间独立表空间的命名规则为`表名+.ibd`
通过innodb_file_per_table,用户不需要将所有的数据都放置在默认的表空间中。
> `innodb_file_per_table`所产生的独立表空间文件其仅存储该表的数据、索引和插入缓冲BITMAP信息其余信息仍然存放在默认的表空间中。
## redo log文件
redo log是一个基于磁盘的数据结构用于在crash recovery过程中纠正由`未完成事务写入的错误数据`
> 在一般操作中redo log对那些`会造成表数据发生改变的请求`进行encode操作请求通常由sql statement或地级别api发起。
redo log通常代表磁盘上的redo log file。写入重做日志文件的数据通常基于受影响的记录进行编码。在数据被写入到redo log file中时LSN值也会不断增加。
### 循环写入
innodb会按顺序写入redo log文件例如redo log file group中存在两个文件innodb会先写文件1文件1写满后会切换文件2在文件2写满后重新切换到文件1。
### redo log capacity
从mysql 8.0.30开始,`innodb_redo_log_capacity`参数用于控制redo log file占用磁盘空间的大小。该参数可以在实例启动时进行设置也可以通过`set global`来进行设置。
`innodb_redo_log_capacity`默认值为`104857600`,即`100M`
redo log文件默认位于`datadir`路径下的`#innodb_redo`目录下。innodb会尝试维护32个redo log file每个redo log file文件大小都相同`1/32 * innodb_redo_log_capacity`
redo log file将会使用`#ib_redoN`的命名方式,`N`是redo log file number。
innodb redo log file分为如下两种:
- ordinary正在被使用的redo log file
- spare等待被使用的redo log file
> 相比于ordinary redo log filespare redo log file的名称中还包含了`_tmp`后缀
每个oridnary redo log file都关联了一个制定的LSN范围可以通过查询`performance_schema.innodb_redo_log_files`表里获取LSN范围。
示例如下:
```sql
select file_name, start_lsn, end_lsn from performance_schema.innodb_redo_log_files;
```
查询结果示例如下:
| file\_name | start\_lsn | end\_lsn |
| :--- | :--- | :--- |
| ./#innodb\_redo/#ib\_redo6 | 19656704 | 22931456 |
当执行checkpoint时innodb会将checkpoint LSN存储在文件的header中在recovery过程中所有的redo log文件都将被检查并且基于最大的LSN来执行恢复操作。
常用的redo log状态如下
```bash
# resize operation status
Innodb_redo_log_resize_status
# 当前redo log capacity
Innodb_redo_log_capacity_resized
Innodb_redo_log_checkpoint_lsn
Innodb_redo_log_current_lsn
Innodb_redo_log_flushed_to_disk_lsn
Innodb_redo_log_logical_size
Innodb_redo_log_physical_size
Innodb_redo_log_read_only
Innodb_redo_log_uuid
```
> 重做日志大小设置时,如果设置大小过大,那么在执行恢复操作时,可能需要花费很长时间;如果重做日志文件大小设置过小,可能会导致事务的日志需要多次切换重做日志文件。
>
> 此外重做日志太小会频繁发生async checkpoint导致性能抖动。重做日志存在一个capacity代表了最后的checkpoint不能够超过这个阈值如果超过必须将缓冲区中的部分脏页刷新到磁盘中此时可能会造成用户线程的阻塞。
### redo log和binlog的区别
#### 记录内容
binlog记录的是一个事务的具体操作内容该日志为逻辑日志。
而innodb redo log记录的是关于某个页的修改为物理日志。
#### 写入时机
binlog仅当事务提交前才进行提交即只会写磁盘一次。
redo log则是在事务运行过程中不断有重做日志被写入到redo log file中。
### redo log写入时机
- master thread会每秒将redo log从buffer中刷新到redo log ile中不露内事务是否已经提交
- [文件](#文件)
- [参数](#参数)
- [参数查看](#参数查看)
- [参数类型](#参数类型)
- [动态参数修改](#动态参数修改)
- [静态参数修改](#静态参数修改)
- [日志文件](#日志文件)
- [错误日志](#错误日志)
- [慢查询日志](#慢查询日志)
- [log\_queries\_not\_using\_indexes](#log_queries_not_using_indexes)
- [查询日志](#查询日志)
- [二进制日志](#二进制日志)
- [max\_binlog\_size](#max_binlog_size)
- [binlog\_cache\_size](#binlog_cache_size)
- [binlog\_cache\_use](#binlog_cache_use)
- [binlog\_cache\_disk\_use](#binlog_cache_disk_use)
- [sync\_binlog](#sync_binlog)
- [innodb\_flush\_log\_at\_trx\_commit](#innodb_flush_log_at_trx_commit)
- [binlog\_format](#binlog_format)
- [使用statement可能会存在的问题](#使用statement可能会存在的问题)
- [mysqlbinlog](#mysqlbinlog)
- [pid文件](#pid文件)
- [表结构定义文件](#表结构定义文件)
- [表空间文件](#表空间文件)
- [innodb\_data\_file\_path](#innodb_data_file_path)
- [innodb\_file\_per\_table](#innodb_file_per_table)
- [redo log文件](#redo-log文件)
- [循环写入](#循环写入)
- [redo log capacity](#redo-log-capacity)
- [redo log和binlog的区别](#redo-log和binlog的区别)
- [记录内容](#记录内容)
- [写入时机](#写入时机)
- [redo log写入时机](#redo-log写入时机)
# 文件
## 参数
### 参数查看
mysql参数为键值对可以通过`show variables`命令查看所有的数据库参数,并可以通过`like`来过滤参数名称。
除了`show variables`命令之外,还能够在`performance_schema`下的`global_variables`视图来查找数据库参数,示例如下:
```sql
-- 查看innodb_buffer_pool_size参数
show variables like 'innodb_buffer_pool_size'
```
上述`show variables`命令的执行结果为
| Variable\_name | Value |
| :--- | :--- |
| innodb\_buffer\_pool\_size | 4294967296 |
```sql
select * from performance_schema.global_variables where variable_name like 'innodb_buffer_pool%';
```
上述sql的执行结果如下
| VARIABLE\_NAME | VARIABLE\_VALUE |
| :--- | :--- |
| innodb\_buffer\_pool\_chunk\_size | 134217728 |
| innodb\_buffer\_pool\_dump\_at\_shutdown | ON |
| innodb\_buffer\_pool\_dump\_now | OFF |
| innodb\_buffer\_pool\_dump\_pct | 25 |
| innodb\_buffer\_pool\_filename | ib\_buffer\_pool |
| innodb\_buffer\_pool\_in\_core\_file | ON |
| innodb\_buffer\_pool\_instances | 4 |
| innodb\_buffer\_pool\_load\_abort | OFF |
| innodb\_buffer\_pool\_load\_at\_startup | ON |
| innodb\_buffer\_pool\_load\_now | OFF |
| innodb\_buffer\_pool\_size | 4294967296 |
### 参数类型
mysql中的参数可以分为`动态``静态`两种类型,
- 动态动态参数代表可以在mysql运行过程中进行修改
- 静态:代表在整个实例的声明周期内都不得进行修改
#### 动态参数修改
对于动态参数,可以在运行时通过`SET`命令来进行修改,`SET`命令语法如下:
```sql
set
| [global | session] system_var_name=expr
| [@@global. | @@session. | @@] system_var_name = expr
```
在上述语法中,`global``session`关键字代表该动态参数的修改是针对`当前会话`还是针对`整个实例的生命周期`
- 有些动态参数只能在会话范围内进行修改,例如`autocommit`
- 有些参数修改后,实例整个生命周期内都会生效,例如`binglog_cache_size`
- 有些参数既可以在会话范围内进行修改,又可以在实例声明周期范围内进行修改,例如`read_buffer_size`
使用示例如下:
查询read_buffer_size的global和session值
```sql
-- 查询read_buffer_size的global和session值
select @@session.read_buffer_size,@@global.read_buffer_size;
```
返回结果为
| @@session.read\_buffer\_size | @@global.read\_buffer\_size |
| :--- | :--- |
| 131072 | 131072 |
设置@@session.read_buffer_size为524288
```sql
set @@session.read_buffer_size = 1024 * 512;
```
设置后再次查询read_buffer_size的global和session值结果为
| @@session.read\_buffer\_size | @@global.read\_buffer\_size |
| :--- | :--- |
| 524288 | 131072 |
在调用set命令修改session read_buffer_size参数后session参数发生变化但是global参数仍然为旧的值。
> `set session xxx`命令并不会对global参数的值造成影响新会话的参数值仍然为修改前的值。
之后再对global read_buffer_size值进行修改执行如下命令
```sql
set @@global.read_buffer_size = 496 * 1024;
```
执行该命令后sesion和global参数值为
| @@session.read\_buffer\_size | @@global.read\_buffer\_size |
| :--- | :--- |
| 524288 | 507904 |
> `set global xxx`命令只会修改global参数值对session参数值不会造成影响新的session其`session参数值, global参数值`和修改后的global参数值保持一致
> 即使针对参数的global值进行了修改其影响范围是当前实例的整个生命周期`但是其并不会对参数文件中的参数值进行修改故而下次启动mysql实例时仍然会从参数文件中取值新实例的值仍然是修改前的值`。
>
> 如果想要修改下次启动实例的参数值,需要修改参数文件中该参数的值。(参数文件路径通常为`/etc/my.cnf`
#### 静态参数修改
在运行时,如果尝试对静态参数进行修改,那么会发生错误,示例如下:
```sql
> set global datadir='/db/mysql'
[2025-01-30 15:05:17] [HY000][1238] Variable 'datadir' is a read only variable
```
## 日志文件
mysql中常见日志文件如下
- 错误日志(error log)
- 二进制日志binlog
- 慢查询日志slow query log
- 查询日志log
### 错误日志
错误日志针对mysql的启动、运行、关闭过程进行了记录用户可以通过`show variables like 'log_error';`来获取错误日志的路径:
```sql
show variables like 'log_error';
```
其输出值如下:
| Variable\_name | Value |
| :--- | :--- |
| log\_error | /var/log/mysql/mysqld.log |
当mysql数据库无法正常启动时应当首先查看错误日志。
### 慢查询日志
慢查询日志存在一个阈值,通过`long_query_time`参数来进行控制,该参数默认值为`10`代表慢查询的限制为10s。
通过`slow_query_log`参数,可以控制是否日志输出慢查询日志,默认为`OFF`,如果需要开启慢查询日志,需要将该值设置为`ON`
关于慢查询日志的输出地点,可以通过`log_output`参数来进行控制。该参数默认为`FILE`,支持`FILE, TABLE, NONE``log_output`支持制定多个值,多个值之间可以通过`,`分隔,当值中包含`NONE`时,以`NONE`优先。
#### log_queries_not_using_indexes
`log_queryies_not_using_indexes`开启时如果运行的sql语句没有使用索引那么这条sql同样会被输出到慢查询日志。该参数默认关闭。
`log_throttle_queries_not_using_idnexes`用于记录`每分钟允许记录到慢查询日志并且没有使用索引`的sql语句次数该参数值默认为0代表每分钟输出到慢查询日志中的数量没有限制。
该参数主要用于防止大量没有使用索引的sql添加到慢查询日志中造成慢查询日志大小快速增加。
当慢查询日志中的内容越来越多时可以通过mysql提供的工具`mysqldumpslow`命令,示例如下:
```sql
mysqldumpslow -s at -n 10 ${slow_query_log_path}
```
### 查询日志
查询日志记录了对mysql数据库所有的请求信息无论请求是否正确执行。
查询日志通过`general_log`参数来进行控制,默认该参数值为`OFF`.
### 二进制日志
二进制日志binary log记录了针对mysql数据库执行的所有更改操作不包含select以及show这类读操作
对于update操作等即使没有对数据库进行修改affected rows为0也会被写入到binary log中。
二进制日志的主要用途如下:
- 恢复recovery某些数据恢复需要二进制日志例如在数据库全备份文件恢复后用户可以通过二进制日志进行point-in-time的恢复
- 复制replication通过将一台主机master的binlog同步到另一台主机slave并且在另一台主机上执行该binlog可以令slave与master进行实时同步
- 审计audit用户可以对binlog中的信息进行审计判断是否存在对数据库进行的注入攻击
通过参数`log_bin`可以控制是否启用二进制日志。
binlog通常存放在`datadir`参数所指定的目录路径下。在该路径下,还存在`binlog.index`文件该文件为binlog的索引文件文件内容包含所有binlog的文件名称。
#### max_binlog_size
`max_binlog_size`参数控制单个binlog文件的最大大小如果单个文件超过该值会产生新的二进制文件新binlog的后缀会+1并且新文件的文件名会被记录到`.index`文件中。
`max_binlog_size`的默认值大小为`1G`
#### binlog_cache_size
当使用innodb存储引擎时所有未提交事务的binlog会被记录到缓存中等到事务提交后会将缓存中的binlog写入到文件中。缓存大小通过`binlog_cache_size`决定,该值默认为`32768`,即`32KB`
`binlog_cache_size`是基于会话的,`在每个线程开启一个事务时mysql会自动分配一个大小为binlog_cache_size大小的缓存因而该值不能设置过大`
当一个事务的记录大于设定的`binlog_cache_size`mysql会将缓冲中的日志写入到一个临时文件中故而该值无法设置过小。
通过`show global status like 'binlog_cache%`命令可以查看`binlog_cache_use``binlog_cache_disk_use`的状态可以通过上述两个状态判断binlog cache大小是否合适。
##### binlog_cache_use
`binlog_cache_use`记录了使用缓冲写binlog的次数
##### binlog_cache_disk_use
`binlog_cache_disk_use`记录了使用临时文件写二进制日志的次数
#### sync_binlog
`sync_binlog`参数控制mysql server同步binlog到磁盘的频率该值默认为`1`
- 0: 如果参数值为0代表mysql server禁用binary log同步到磁盘。mysql会依赖操作系统将binary log刷新到磁盘中该设置性能最佳但是遇到操作系统崩溃时可能会出现mysql事务提交但是还没有同步到binary log的场景
- 1: 如果参数值设置为1代表在事务提交之前将binary log同步到磁盘中该设置最安全但是会增加disk write次数对性能会带来负面影响。在操作系统崩溃的场景下binlog中缺失的事务还只处于prepared状态从而确保binlog中没有事务丢失
- N当参数值被设置为非`01`的值时每当n个binlog commit groups被收集到后同步binlog到磁盘。在这种情况下可能会发生事务提交但是还没有被刷新到binlog中`当n值越大时性能会越好但是也会增加数据丢失的风险`
为了在使用innodb事务和replciation时获得最好的一致性和持久性请使用如下设置
```cnf
sync_binlog=1
innodb_flush_log_at_trx_commit=1
```
#### innodb_flush_log_at_trx_commit
innodb_flush_log_at_trx_commit用于控制redo log的刷新。
该参数用于平衡`commit操作ACID的合规性`以及`更高性能`。通过修改该参数值,可以实现更佳的性能,但是在崩溃时可能会丢失事务:
- 1: 1为该参数默认值代表完全的ACID合规性日志在每次事务提交后被写入并刷新到磁盘中
- 0: 日志每秒被写入和刷新到磁盘中,如果事务没有被刷新,那么日志将会在崩溃中被丢失
- 2: 每当事务提交后,日志将会被写入,并且每秒钟都会被刷新到磁盘中。如果事务没有被刷新,崩溃同样会造成日志的丢失
如果当前数据库为slave角色那么其不会把`从master同步的binlog`写入到自己的binlog中如果要实现`master=>slave=>slave`的同步架构,必须设置`log_slave_updates`参数。
#### binlog_format
binlog_format用于控制二进制文件的格式可能有如下取值
- statement: 二进制文件记录的是日志的逻辑sql语句
- row记录表的行更改情况默认值为`row`
- mixed: 如果参数被配置为mixedmysql默认会采用`statement`格式进行记录,但是在特定场景能够下会使用`row`格式:
- 使用了uuid, user, current_user,found_rows, row_count等不确定函数
- 使用了insert delay语句
- 使用了用户自定义函数
- 使用了临时表
##### 使用statement可能会存在的问题
在使用statement格式时可能会存在如下问题
- master运行randuuid等不确定函数时或使用触发器操作时会导致主从服务器上的数据不一致
- innodb的默认事务隔离级别为`repetable_read`,如果使用`read_commited`级别时statement格式可能会导致丢失更新的情况从而令master和slave的数据不一致
binlog为动态参数可以在数据库运行时进行修改并且可以针对session和global进行修改。
#### mysqlbinlog
在查看二进制日志时,可以使用`mysqlbinlog`命令,示例如下
```bash
mysqlbinlog --start-position=203 ${binlog_path}
```
## pid文件
mysql实例启动时会将进程id写入到一个文件中该文件被称为pid文件。
pid文件路径通过`pid_file`参数来进行控制fedora中默认路径为`/run/mysqld/mysqld.pid`
## 表结构定义文件
mysql中数据的存储是根据表进行的每个表都有与之对应的文件。无论表采用何种存储引擎都会存在一个以`frm`为后缀的文件,该文件中保存了该表的表结构定义。
> mysql 8中schema对应目录下不再包含frm文件。
## 表空间文件
innodb采用将存储的数据按照表空间tablespace进行存放的设计。在默认配置下将会有一个初始大小为10MB名称为ibdata1的文件该文件为默认的表空间文件。
### innodb_data_file_path
可以通过`innodb_data_file_path`参数对默认表空间文件进行设置,示例如下:
```sql
innodb_data_file_path=datafile_spec1[;datafile_spec2]...
```
用户可以通过多个文件组成一个表空间,示例如下:
```sql
innodb_data_file_path=/db/ibdata1:2000M;/dr2/db/ibdata2:2000M;autoextend
```
在上述配置中,表空间由`/db/ibdata1``/dr2/db/ibdata2`两个文件组成,如果两个文件位于不同的磁盘上,那么磁盘的负载将会被平均,数据库的整体性能将会被提高。
同时,在上述示例中,为两个文件都指定了后续属性,含义如下:
- ibdata1文件大小为2000M
- ibdata2:文件大小为2000M并且当文件大小被用完后文件会自动增长
`innodb_data_file_path`被设置后所有基于innodb存储引擎的表其数据都会记录到该共享表空间中。
### innodb_file_per_table
如果`innodb_file_per_table`被启用后默认启用则每个基于innodb存储引擎的表都可以有一个独立的表空间独立表空间的命名规则为`表名+.ibd`
通过innodb_file_per_table,用户不需要将所有的数据都放置在默认的表空间中。
> `innodb_file_per_table`所产生的独立表空间文件其仅存储该表的数据、索引和插入缓冲BITMAP信息其余信息仍然存放在默认的表空间中。
## redo log文件
redo log是一个基于磁盘的数据结构用于在crash recovery过程中纠正由`未完成事务写入的错误数据`
> 在一般操作中redo log对那些`会造成表数据发生改变的请求`进行encode操作请求通常由sql statement或地级别api发起。
redo log通常代表磁盘上的redo log file。写入重做日志文件的数据通常基于受影响的记录进行编码。在数据被写入到redo log file中时LSN值也会不断增加。
### 循环写入
innodb会按顺序写入redo log文件例如redo log file group中存在两个文件innodb会先写文件1文件1写满后会切换文件2在文件2写满后重新切换到文件1。
### redo log capacity
从mysql 8.0.30开始,`innodb_redo_log_capacity`参数用于控制redo log file占用磁盘空间的大小。该参数可以在实例启动时进行设置也可以通过`set global`来进行设置。
`innodb_redo_log_capacity`默认值为`104857600`,即`100M`
redo log文件默认位于`datadir`路径下的`#innodb_redo`目录下。innodb会尝试维护32个redo log file每个redo log file文件大小都相同`1/32 * innodb_redo_log_capacity`
redo log file将会使用`#ib_redoN`的命名方式,`N`是redo log file number。
innodb redo log file分为如下两种:
- ordinary正在被使用的redo log file
- spare等待被使用的redo log file
> 相比于ordinary redo log filespare redo log file的名称中还包含了`_tmp`后缀
每个oridnary redo log file都关联了一个制定的LSN范围可以通过查询`performance_schema.innodb_redo_log_files`表里获取LSN范围。
示例如下:
```sql
select file_name, start_lsn, end_lsn from performance_schema.innodb_redo_log_files;
```
查询结果示例如下:
| file\_name | start\_lsn | end\_lsn |
| :--- | :--- | :--- |
| ./#innodb\_redo/#ib\_redo6 | 19656704 | 22931456 |
当执行checkpoint时innodb会将checkpoint LSN存储在文件的header中在recovery过程中所有的redo log文件都将被检查并且基于最大的LSN来执行恢复操作。
常用的redo log状态如下
```bash
# resize operation status
Innodb_redo_log_resize_status
# 当前redo log capacity
Innodb_redo_log_capacity_resized
Innodb_redo_log_checkpoint_lsn
Innodb_redo_log_current_lsn
Innodb_redo_log_flushed_to_disk_lsn
Innodb_redo_log_logical_size
Innodb_redo_log_physical_size
Innodb_redo_log_read_only
Innodb_redo_log_uuid
```
> 重做日志大小设置时,如果设置大小过大,那么在执行恢复操作时,可能需要花费很长时间;如果重做日志文件大小设置过小,可能会导致事务的日志需要多次切换重做日志文件。
>
> 此外重做日志太小会频繁发生async checkpoint导致性能抖动。重做日志存在一个capacity代表了最后的checkpoint不能够超过这个阈值如果超过必须将缓冲区中的部分脏页刷新到磁盘中此时可能会造成用户线程的阻塞。
### redo log和binlog的区别
#### 记录内容
binlog记录的是一个事务的具体操作内容该日志为逻辑日志。
而innodb redo log记录的是关于某个页的修改为物理日志。
#### 写入时机
binlog仅当事务提交前才进行提交即只会写磁盘一次。
redo log则是在事务运行过程中不断有重做日志被写入到redo log file中。
### redo log写入时机
- master thread会每秒将redo log从buffer中刷新到redo log ile中不露内事务是否已经提交
- innodb_flush_log_at_trx_commit控制redo log的刷新时机默认情况下在事务提交前会将数据从redo log buffer刷新到redo log file中