二进制文件记录了对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,并记录到 .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 | | | |
+------------------+----------+--------------+------------------+-------------------+
当使用事务表存储引擎时,所以未提交的二进制日志,都先存储到缓存当中,等事务提交将缓存日志刷新到二进制文件当中,缓存大小由 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 说明二进制缓存不需要修改
参数 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
binlog_format 用于表明二进制文件的记录格式,默认为 ROW, 可设置的值为 row 、statement 和 mixed
# 先查询 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)
表示需要写入或忽略写入哪些库的日志,默认为空,代表同步所有库的日志到二进制日志文件。
1. 开启二进制日志会损失1%的性能
2. 通过参数 log-bin 开启二进制
3. 通过 max_binlog_size、binlog_format 、sync_binlog、binlog_cache_size等一些参数来控制和影响二进制
4.二进制文件可以用来 恢复 、复制 数据,可以用来做主从复制、读写分离等一些操作