【Innodb阅读笔记】之 二进制文件

   一、什么是二进制文件     

        二进制文件记录了对mySQL数据库执行修改的所有操作,不包括select和show这类操作,因为这类操作对数据库本身没有修改。但是,当执行修改操作,数据库没有发生变化,这类操作也会写入二进制文件中。通过配置参数 log-bin 开启 二进制日志。如:

# 配置文件写入 开启二进制 指定文件名称为:mysql-bin
# log-bin # 不指定名称 默认使用主机名
log-bin = mysql-bin

# 当前存在一个二进制文件 
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+


# 二进制文件最新写入到 154 位置

mysql> show binlog events in 'mysql-bin.000001' ;
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                  |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| mysql-bin.000001 |   4 | Format_desc    |         1 |         123 | Server ver: 5.7.39-log, Binlog ver: 4 |
| mysql-bin.000001 | 123 | Previous_gtids |         1 |         154 |                                       |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+

# 查询数据 username 为 111 de password 值只有 222
mysql> SELECT DISTINCT PASSWORD FROM ums_member WHERE username = '111';
+----------+
| PASSWORD |
+----------+
| 222      |
+----------+

# 执行修改语句, 没有数据发生变化 
mysql> update ums_member  set password = '222' where username = '111';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 32  Changed: 0  Warnings: 0


# 查询二进制记录格式
mysql> show variables like 'binlog_format';
+---------------+-----------+
| Variable_name | Value     |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+


# 查看二进制文件 我们发现当前sql已经记录到二进制文件当中
mysql> show binlog events in 'mysql-bin.000001' ;
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                                                                   |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| mysql-bin.000001 |   4 | Format_desc    |         1 |         123 | Server ver: 5.7.39-log, Binlog ver: 4                                                  |
| mysql-bin.000001 | 123 | Previous_gtids |         1 |         154 |                                                                                        |
| mysql-bin.000001 | 154 | Anonymous_Gtid |         1 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                   |
| mysql-bin.000001 | 219 | Query          |         1 |         322 | BEGIN                                                                                  |
| mysql-bin.000001 | 322 | Query          |         1 |         482 | use `msb_dongbao_test`; update ums_member  set password = '222' where username = '111' |
| mysql-bin.000001 | 482 | Xid            |         1 |         513 | COMMIT /* xid=419 */                                                                   |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+


# 修改二进制记录格式  改为: row
mysql> set session binlog_format = row;
Query OK, 0 rows affected (0.00 sec)

# 重新执行修改语句 
mysql> update ums_member  set password = '222' where username = '111';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 32  Changed: 0  Warnings: 0

# 查询二进制文件 
mysql> show binlog events in 'mysql-bin.000001' ;
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                                                                   |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| mysql-bin.000001 |   4 | Format_desc    |         1 |         123 | Server ver: 5.7.39-log, Binlog ver: 4                                                  |
| mysql-bin.000001 | 123 | Previous_gtids |         1 |         154 |                                                                                        |
| mysql-bin.000001 | 154 | Anonymous_Gtid |         1 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                   |
| mysql-bin.000001 | 219 | Query          |         1 |         322 | BEGIN                                                                                  |
| mysql-bin.000001 | 322 | Query          |         1 |         482 | use `msb_dongbao_test`; update ums_member  set password = '222' where username = '111' |
| mysql-bin.000001 | 482 | Xid            |         1 |         513 | COMMIT /* xid=419 */                                                                   |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+

# 总结 当 binlog_format = row 的时候,如果没有发生实际修改,是不会记录到二进制文件当中的,当 
# binlog_format = STATEMENT,有没有发生实际修改,都会把sql记录到二进制文件

二、二进制文件有哪些作用

        1. 恢复:某些数据的恢复需要二进制文件,例如,在一个数据库全备份文件恢复后,用户可以通过二进制日志进行point-in-time的恢复

        2. 复制: 其原理与恢复类似,通过复制和执行二进制文件使一台远程数据库与主数据库进行同步

        3. 审计: 用户可以通过二进制文件的信息进行审计,判断是否有对数据库进行注入的攻击

三、二进制的性能影响

        开启二进制文件默认情况下没有启动,需要手动配置指定参数启动,开启这个选项会影响数据库性能,但是损失比较有限,根据官方测试申明,开启后会使性能下降1%,但是考虑到可以使用 恢复 和 复制 保障数据安全,这些性能的损失绝对是可以且应该被接受的。

四、关于二进制文件的其他配置参数

1. max_binlog_size:

单个二进制文件最大值,如果超越该值,则产生新的二进制文件,后缀名 + 1,并记录到 .index文件当中。同时 该值最小为 4096,默认为 1G,  如:

# 修改二进制文件最大为 1024 
mysql> set global max_binlog_size = 1024;
Query OK, 0 rows affected, 1 warning (0.00 sec)

# 重新查询 max_binlog_size , 发现二进制文件设置为 4096,
# 所以,max_binlog_size 最小值为4kb
mysql> select @@max_binlog_size ;
+-------------------+
| @@max_binlog_size |
+-------------------+
|              4096 |
+-------------------+
1 row in set (0.00 sec)

# 执行多次修改语句 
update ums_member  set password = '222' where username = '111';

# 查询二进制文件, 我们发现序号已经增加到 3
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |     1590 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

2. binlog_cache_size:

        当使用事务表存储引擎时,所以未提交的二进制日志,都先存储到缓存当中,等事务提交将缓存日志刷新到二进制文件当中,缓存大小由 binlog_cache_size 决定,默认值为 32K,同时,每个线程开启事务的时候,单独分配一个 binlog_cache_size 大小的缓存,当缓存超过 binlog_cache_size 大小,会写入到临时文件当中,如:

# 查询缓存大小 
mysql> show variables like 'binlog_cache_size';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| binlog_cache_size | 32768 |
+-------------------+-------+
1 row in set, 1 warning (0.00 sec)

# 修改二进制缓存大小
mysql> set global binlog_cache_size = 1024;
Query OK, 0 rows affected, 1 warning (0.00 sec)

# 重新查询缓存大小为 4kb ,说明,缓存设置最小为4kb
mysql> show variables like 'binlog_cache_size';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| binlog_cache_size | 4096  |
+-------------------+-------+
1 row in set, 1 warning (0.00 sec)

# 通过监控 Binlog_cache_disk_use 和 Binlog_cache_use 来判断当前缓存池设置是否合适
mysql> SHOW GLOBAL STATUS LIKE 'binlog_cache%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Binlog_cache_disk_use | 0     |
| Binlog_cache_use      | 28    |
+-----------------------+-------+
2 rows in set (0.00 sec)
# Binlog_cache_use  表示使用缓存28次
# Binlog_cache_disk_use 表示 写入临时文件的次数,当前为 0 说明二进制缓存不需要修改

3. sync_binlog

        参数 sync_binlog = [N] 表示每写入多少次就刷新到磁盘,如果将 N 设置为 1,表示每次写入都刷新到磁盘,以同步的形式写入到二进制文件,

        但是,即使将 sync_binlog 设为 1,  还是会有一种可能发生,在一个事务发生 commit 之前,由于sync_binlog 为 1, 因此,会将二进制日志同步到磁盘,此时事务还没有提交,并且此时发生了宕机,再下次启动的时候,这个事务就会回滚,但是二进制文件写入的事务信息不能被回滚,会造成数据差异,这个问题可以将 innodb_support_xa 设为 1 来解决。

# 查询 sync_binlog 参数 默认为 1,代表同步写入二进制文件
mysql> show variables like 'sync_binlog';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog   | 1     |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)

# 执行一次修改 
UPDATE ums_member SET PASSWORD = '555' WHERE username = '111'

# 我们发现文件大小变为 12kb

# 修改为 3 次刷新一次 
mysql> set global sync_binlog = 3;
Query OK, 0 rows affected (0.00 sec)

# 执行3 次修改 我们发现 前两次文件大小没有变动 ,第三次执行后文件大小变为47kb
mysql-bin.000001 47KB

4. binlog_format 

        binlog_format 用于表明二进制文件的记录格式,默认为 ROW, 可设置的值为 row 、statement 和 mixed     

  • binlog_format= statement :日志记录的是主机数据库的写指令,性能高,但是 now() 之类的函数以及获取系统参数的操作会出现主从数据不同步的问题。
  • binlog_format = row(默认):日志记录的是主机数据库的写后的数据,批量操作时性能较差,解决now()或者 user()或者 @@hostname 等操作在主从机器上不一致的问题。
  • binlog_format = mixed :是以上两种level的混合使用,有函数用ROW,没函数用STATEMENT,但是无法识别系统变量。
# 先查询 binlog_format, 默认为 ROW 
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)

# 此时 我们执行修改语句 
UPDATE ums_member SET PASSWORD = '555' WHERE username = '111'

# 查询二进制文件内容 我们发现只展示一下基础信息,没有但是文件变的很大 
mysql> show binlog events in 'mysql-bin.000001' ;
+------------------+-------+----------------+-----------+-------------+---------------------------------------------+
| Log_name         | Pos   | Event_type     | Server_id | End_log_pos | Info                                        |
+------------------+-------+----------------+-----------+-------------+---------------------------------------------+
                        |
| mysql-bin.000001 | 35947 | Anonymous_Gtid |         1 |       36012 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'        |
| mysql-bin.000001 | 36012 | Query          |         1 |       36096 | BEGIN                                       |
| mysql-bin.000001 | 36096 | Table_map      |         1 |       36187 | table_id: 109 (msb_dongbao_test.ums_member) |
| mysql-bin.000001 | 36187 | Update_rows    |         1 |       44377 | table_id: 109                               |
| mysql-bin.000001 | 44377 | Update_rows    |         1 |       47847 | table_id: 109 flags: STMT_END_F             |
| mysql-bin.000001 | 47847 | Xid            |         1 |       47878 | COMMIT /* xid=27 */                         |
+------------------+-------+----------------+-----------+-------------+---------------------------------------------+
26 rows in set (0.00 sec)

# 将 binlog_format 设置为 statement
mysql> set global binlog_format = statement;
Query OK, 0 rows affected (0.00 sec)

# 修改当前回话
mysql> set session binlog_format=statement;
Query OK, 0 rows affected (0.00 sec)

# 验证一下是否修改成功 
mysql> show variables like 'binlog_format';
+---------------+-----------+
| Variable_name | Value     |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set, 1 warning (0.00 sec)

# 执行修改表语句
mysql> update ums_member set password = '555' where username = '111' ;
Query OK, 0 rows affected (0.01 sec)
Rows matched: 256  Changed: 0  Warnings: 0


# 查询二进制文件内容 我们发现最新一条记录了具体的修改sql
mysql> show binlog events in 'mysql-bin.000001' ;
+------------------+-------+----------------+-----------+-------------+---------------------------------------------------------------------------------------+
| Log_name         | Pos   | Event_type     | Server_id | End_log_pos | Info                                                                                  |
+------------------+-------+----------------+-----------+-------------+---------------------------------------------------------------------------------------+

| mysql-bin.000001 | 47878 | Anonymous_Gtid |         1 |       47943 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                  |
| mysql-bin.000001 | 47943 | Query          |         1 |       48046 | BEGIN                                                                                 |
| mysql-bin.000001 | 48046 | Query          |         1 |       48205 | use `msb_dongbao_test`; update ums_member set password = '555' where username = '111' |
| mysql-bin.000001 | 48205 | Xid            |         1 |       48236 | COMMIT /* xid=47 */                                                                   |
+------------------+-------+----------------+-----------+-------------+---------------------------------------------------------------------------------------+ 


# 修改  binlog_format = mixed
mysql> set session binlog_format=mixed ;
Query OK, 0 rows affected (0.00 sec)

# 验证是否修改成功
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | MIXED |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)

# 执行修改语句 
# 没有使用函数 
mysql> update ums_member set password = '666' where username = '111' ;
Query OK, 256 rows affected (0.00 sec)
Rows matched: 256  Changed: 256  Warnings: 0

# 使用函数 
mysql> update ums_member set password = uuid() where username = '111' ;
Query OK, 256 rows affected (0.01 sec)
Rows matched: 256  Changed: 256  Warnings: 0


# 查询二进制 没有使用函数的记录具体的sql 使用函数记录的具体修改的内容
mysql> show binlog events in 'mysql-bin.000001' ;
+------------------+-------+----------------+-----------+-------------+---------------------------------------------------------------------------------------+
| Log_name         | Pos   | Event_type     | Server_id | End_log_pos | Info                                                                                  |
+------------------+-------+----------------+-----------+-------------+---------------------------------------------------------------------------------------+
| mysql-bin.000001 | 48236 | Anonymous_Gtid |         1 |       48301 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                  |
| mysql-bin.000001 | 48301 | Query          |         1 |       48404 | BEGIN                                                                                 |
| mysql-bin.000001 | 48404 | Query          |         1 |       48563 | use `msb_dongbao_test`; update ums_member set password = '666' where username = '111' |
| mysql-bin.000001 | 48563 | Xid            |         1 |       48594 | COMMIT /* xid=51 */                                                                   |
| mysql-bin.000001 | 48594 | Anonymous_Gtid |         1 |       48659 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                  |
| mysql-bin.000001 | 48659 | Query          |         1 |       48743 | BEGIN                                                                                 |
| mysql-bin.000001 | 48743 | Table_map      |         1 |       48834 | table_id: 109 (msb_dongbao_test.ums_member)                                           |
| mysql-bin.000001 | 48834 | Update_rows    |         1 |       57046 | table_id: 109                                                                         |
| mysql-bin.000001 | 57046 | Update_rows    |         1 |       65246 | table_id: 109                                                                         |
| mysql-bin.000001 | 65246 | Update_rows    |         1 |       68980 | table_id: 109 flags: STMT_END_F                                                       |
| mysql-bin.000001 | 68980 | Xid            |         1 |       69011 | COMMIT /* xid=52 */                                                                   |
+------------------+-------+----------------+-----------+-------------+---------------------------------------------------------------------------------------+
41 rows in set (0.00 sec)

5. binlog-do-db 和 binlog-ignore-db

        表示需要写入或忽略写入哪些库的日志,默认为空,代表同步所有库的日志到二进制日志文件。

五、总结

        1. 开启二进制日志会损失1%的性能

        2. 通过参数 log-bin 开启二进制

        3. 通过 max_binlog_size、binlog_format 、sync_binlog、binlog_cache_size等一些参数来控制和影响二进制

        4.二进制文件可以用来 恢复 、复制 数据,可以用来做主从复制、读写分离等一些操作

你可能感兴趣的:(笔记)