pull/1/head
595208882@qq.com 3 years ago
parent 4604e050ba
commit 72563484e4

@ -2401,54 +2401,18 @@ select * from t where k1=1 and k3=3;
# MySQL日志
**生产优化**
- 在生产上,建议 innodb_flush_log_at_trx_commit 设置成 1可以让每次事务的 redo log 都持久化到磁盘上。保证异常重启后redo log 不丢失
- 建议 sync_binlog 设置成 1可以让每次事务的 binlog 都持久化到磁盘上。保证异常重启后binlog 不丢失
**IO性能优化**
- `binlog_group_commit_sync_delay`:表示延迟多少微秒后,再执行 `fsync`
- `binlog_group_commit_sync_no_delay_count`:表示累计多少次后,在调用 `fsync`
`MySQL` 出现了 `IO` 的性能问题,可以考虑下面的优化策略:
- 设置 `binlog_group_commit_sync_delay``binlog_group_commit_sync_no_delay_count`。可以使用故意等待来减少,`binlog` 的写盘次数,没有数据丢失的风险,但是会有客户端响应变慢的风险
- 设置 `sync_binlog` 设置为 `100~1000` 之间的某个值。这样做存在的风险是可能造成 `binlog` 丢失
- 设置 `innodb_flush_log_at_trx_commit = 2`,可能会丢数据
**重做日志redo log、二进制日志bin log、回滚日志undo log、错误日志error log、慢查询日志slow query log、一般查询日志general log、中继日志relay log**。
**重做日志redo log、二进制日志bin log、回滚日志undo log、错误日志error log、慢查询日志slow query log、一般查询日志general log、中继日志relay log。**
## 二进制日志(bin log)
`binlog` 用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。`binlog` 是 `mysql`的逻辑日志,并且由 `Server` 层进行记录,使用任何存储引擎的 `mysql` 数据库都会记录 `binlog` 日志。
- **逻辑日志**可以简单理解为记录的就是sql语句 。
- **物理日志**`mysql` 数据最终是保存在数据页中的,物理日志记录的就是数据页变更 。
`binlog` 用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。`binlog` 是 `mysql`的逻辑日志(即SQL语句),并且由 `Server` 层进行记录,使用任何存储引擎的 `mysql` 数据库都会记录 `binlog` 日志。`binlog` 是通过追加的方式进行写入的,可以通过`max_binlog_size` 参数设置每个 `binlog`文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。
`binlog` 是通过追加的方式进行写入的,可以通过`max_binlog_size` 参数设置每个 `binlog`文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。
### 作用
- 用于复制在主从复制中从库利用主库上的binlog进行重播实现主从同步
- 用于数据库的基于时间点的还原
**作用**
### 使用场景
在实际应用中, `binlog` 的主要使用场景有两个,分别是 **主从复制** 和 **数据恢复** 。
- **主从复制** :在 `Master` 端开启 `binlog` ,然后将 `binlog`发送到各个 `Slave` 端, `Slave` 端重放 `binlog` 从而达到主从数据一致
- **数据恢复** :通过使用 `mysqlbinlog` 工具来恢复数据
- **主从复制**在主从复制中从库利用主库上的binlog进行重播实现主从同步
- **数据恢复**通过使用mysqlbinlog`工具来实现数据库基于时间点的还原
@ -2456,9 +2420,9 @@ select * from t where k1=1 and k3=3;
对于 `InnoDB` 存储引擎而言,只有在事务提交时才会记录`biglog` ,此时记录还在内存中,那么 `biglog`是什么时候刷到磁盘中的呢?`mysql` 通过 `sync_binlog` 参数控制 `biglog` 的刷盘时机,取值范围是 `0-N`
- `sync_binlog=0`:不去强制要求,由系统自行判断何时写入磁盘
- `sync_binlog=1`:每次 `commit` 的时候都要将 `binlog` 写入磁盘
- `sync_binlog=N(N>1)`每N个事务才会将 `binlog` 写入磁盘
- `sync_binlog=0`:不去强制要求,由系统自行判断何时写入磁盘
- `sync_binlog=1`:每次 `commit` 的时候都要将 `binlog` 写入磁盘
- `sync_binlog=N(N>1)`每N个事务才会将 `binlog` 写入磁盘
从上面可以看出, `sync_binlog` 最安全的是设置是 `1` ,这也是`MySQL 5.7.7`之后版本的默认值。但是设置一个大一些的值可以提升数据库性能,因此实际情况下也可以将值适当调大,牺牲一定的一致性来获取更好的性能。
@ -2466,39 +2430,47 @@ select * from t where k1=1 and k3=3;
### 日志格式
`binlog` 日志有三种格式,分别为 `STATMENT``ROW``MIXED`。
`binlog` 日志有三种格式,日志格式通过 `binlog-format` 指定。在 `MySQL 5.7.7` 之前,默认的格式是 `STATEMENT` `MySQL 5.7.7` 之后,默认值是 `ROW`。
`MySQL 5.7.7` 之前,默认的格式是 `STATEMENT` `MySQL 5.7.7` 之后,默认值是 `ROW`。日志格式通过 `binlog-format` 指定。
- `STATMENT`:基于`SQL`语句的复制( `statement-based replication, SBR` )每一条会修改数据的sql语句会记录到`binlog` 中
- - 优点:不需要记录每一行的变化,减少了 binlog 日志量,节约了 IO , 从而提高了性能;
- 缺点在某些情况下会导致主从数据不一致比如执行sysdate() 、 slepp() 等 。
- `ROW`:基于行的复制(`row-based replication, RBR` )不记录每条sql语句的上下文信息仅需记录哪条数据被修改了 。
- 优点不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题
- 缺点:会产生大量的日志,尤其是` alter table ` 的时候会让日志暴涨
- `STATMENT`:基于`SQL`语句复制(`statement-based replication, SBR`)每一条会修改数据的sql语句会记录到`binlog`中
- **优点**不需要记录每一行的变化减少了binlog日志量节约了IO从而提高了性能
- **缺点**在某些情况下会导致主从数据不一致比如执行sysdate()、slepp() 等
- `ROW`:基于行复制(`row-based replication, RBR` )不记录每条sql语句的上下文信息仅需记录哪条数据被修改了。
- **优点**不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题
- **缺点**:会产生大量的日志,尤其是` alter table ` 的时候会让日志暴涨
- `MIXED`:基于`STATMENT` 和 `ROW` 两种模式的混合复制(`mixed-based replication, MBR` ),一般的复制使用`STATEMENT` 模式保存 `binlog` ,对于 `STATEMENT` 模式无法复制的操作使用 `ROW` 模式保存 `binlog`
## 重做日志(redo log)
重做日志redo log是InnoDB引擎层的日志用来记录事务操作引起数据的变化记录的是数据页的物理修改。
**重做日志是InnoDB引擎层日志用来记录事务操作引起数据变化记录的是数据页的物理修改。**包括两部分:
- **内存中的日志缓冲(redo log buffer)**
- **磁盘上的日志文件(redo logfile)**
MySQL 每执行一条 DML 语句,先将记录写入 redo log buffer后续某个时间点再一次性将多个操作记录写到 redo log file种先写日志再写磁盘的技术就是 WAL(Write-Ahead Logging) 技术。之后MySQL会在合适的时候将操作记录 flush 到磁盘上面flush 的条件可能是系统比较空闲,或 redo log 空间不足时。redo log 文件的大小是固定的如可以是由4个1GB文件组成的集合。
在MySQL里如果我们要执行一条更新语句。执行完成之后数据不会立马写入磁盘因为这样对磁盘IO的开销比较大。MySQL里面有一种叫做WALWrite-Ahead Logging就是先写日志再写磁盘。就是当有一条记录需要更新的时候InnoDB 会先写redo log 里面并更新内存这个时候更新的操作就算完成了。之后MySQL会在合适的时候将操作记录 flush 到磁盘上面。当然 flush 的条件可能是系统比较空闲,或者是 redo log 空间不足时。redo log 文件的大小是固定的比如可以是由4个1GB文件组成的集合。
### 作用
**WAL(Write-Ahead Logging)**
确保事务的持久性。防止在发生故障的时间点尚有脏页未写入磁盘在重启mysql服务的时候根据redo log进行重做从而达到事务的持久性这一特性。
**作用**
- **确保事务的持久性**
- **防止发生故障时,尚有脏页未写入磁盘**。在重启mysql服务时根据redo log进行重做从而达到事务的持久性特性
### 写入流程
为了控制 redo log 的写入策略innodb_flush_log_at_trx_commit 会有下面 3 中取值:
为了控制 `redo log` 的写入策略,`innodb_flush_log_at_trx_commit` 会有下面 3 中取值:
- **0每次提交事务只写在 redo log buffer 中**
- **1每次提交事务持久化到磁盘**
- **2每次提交事务写到 文件系统的 page cache 中**
- `0`**每次提交事务只写在 `redo log buffer` 中**
- `1`**每次提交事务持久化到磁盘**
- `2`**每次提交事务写到 文件系统的 `page cache` 中**
@ -2516,11 +2488,20 @@ redo log 实际的触发 fsync 操作写盘包含以下几个场景:
## 回滚日志(undo log)
### 作用
undo log记录的是数据修改之前的数据。主要用于**回滚,**MySQL数据库事务的**原子性**就是通过 undo log实现的。
undo log主要存储的是数据的逻辑变化日志比如我们要 insert 一条数据,那么 undo log 就会生成一条对应的 delete 日志。所以当需要回滚时只需要利用undo log 就可以恢复都修改前的数据。
undo log另一个作用是用来实现**多版本并发控制 MVCC。**
undo记录中包含了记录更改前的镜像如果更改数据的事务未提交对于隔离级别大于等于 read commit的事务而言不应该返回更改后的数据而应该返回更改前的数据。
保证数据的原子性保存了事务发生之前的数据的一个版本可以用于回滚同时可以提供多版本并发控制下的读MVCC也即非锁定读。
**作用**
- 保证数据的原子性。保存了事务发生之前的数据的一个版本,可以用于回滚
- 可以提供多版本并发控制下的读MVCC也即非锁定读

Loading…
Cancel
Save