MySQL与Oracle等数据库不同,Redo log不会作为归档,仅做Failover等作用;MySQL引用了binlog来实现归档日志,提供复制、恢复、审计功能。
在MySQL中,Redo log和binlog有以下三点不同:
binlog是记录所有数据库结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。binlog不会记录SELECT和SHOW这类操作,因为这类操作对数据本身并没有修改,但可以通过查询日志general_log来查看MySQL执行过的所有语句。
三个重要用途:
复制
复制源服务器上的二进制日志提供要发送到副本的数据更改的记录。源将其二进制日志中包含的信息通过dump线程发送到其副本,副本通过IO线程接受这些事务,然后通过SQL线程以进行与源上相同的数据更改。
恢复
某些数据恢复操作需要使用二进制日志。恢复备份后,将重新执行备份后在二进制日志中记录的事件。这些事件使数据库从备份时起是最新的。
审计
用户可以通过二进制日志中的信息来进行审计,判断是否有对数据库进行注入攻击。
binlog是一组文件,由一组二进制日志文件和一个索引文件组成。
binlog文件
binlog cache:实际上就是参数binlog_cache_size指定的大小,它指定的是一段内存空间用于存储生成的binlog event。
binlog cache 临时文件:实际上就是参数max_binlog_cache_size指定的大小,它指定是一个临时磁盘文件存储由于binlog cache不足溢出的binlog event,其名字由"ML"打头。
binlog file:代表就是我们平时说的binglog 文件,由max_binlog_size指定大小。
binlog event:代表是各种各样的binlog中的记录比如MAP_EVENT/QUERY EVENT/XID EVENT/WRITE EVENT等。
binlog event
binlog源码文件在binlog_event.h
enum Log_event_type {
if a event type before is deprecated and removed directly from
- Fix Format_description_event::Format_description_event().
UNKNOWN_EVENT = 0,
START_EVENT_V3 = 1,
QUERY_EVENT = 2,
STOP_EVENT = 3,
ROTATE_EVENT = 4,
INTVAR_EVENT = 5,
SLAVE_EVENT = 7,
APPEND_BLOCK_EVENT = 9,
DELETE_FILE_EVENT = 11,
RAND_EVENT = 13,
USER_VAR_EVENT = 14,
FORMAT_DESCRIPTION_EVENT = 15,
XID_EVENT = 16,
BEGIN_LOAD_QUERY_EVENT = 17,
EXECUTE_LOAD_QUERY_EVENT = 18,
TABLE_MAP_EVENT = 19,
The V1 event numbers are used from 5.1.16 until mysql-5.6.
WRITE_ROWS_EVENT_V1 = 23,
UPDATE_ROWS_EVENT_V1 = 24,
DELETE_ROWS_EVENT_V1 = 25,
INCIDENT_EVENT = 26,
Heartbeat event to be send by master at its idle time
HEARTBEAT_LOG_EVENT = 27,
IGNORABLE_LOG_EVENT = 28,
ROWS_QUERY_LOG_EVENT = 29,
/** Version 2 of the Row events */
WRITE_ROWS_EVENT = 30,
UPDATE_ROWS_EVENT = 31,
DELETE_ROWS_EVENT = 32,
GTID_LOG_EVENT = 33,
ANONYMOUS_GTID_LOG_EVENT = 34,
PREVIOUS_GTIDS_LOG_EVENT = 35,
TRANSACTION_CONTEXT_EVENT = 36,
VIEW_CHANGE_EVENT = 37,
/* Prepared XA transaction terminal event similar to Xid */
XA_PREPARE_LOG_EVENT = 38,
Extension of UPDATE_ROWS_EVENT, allowing partial values according
PARTIAL_UPDATE_ROWS_EVENT = 39,
TRANSACTION_PAYLOAD_EVENT = 40,
Add new events here - right above this comment!
Existing events (except ENUM_END_EVENT) should never change their numbers
ENUM_END_EVENT /* end marker */
Struct to pass basic information about a event: type, query, is it ignorable
1、开启事务
2、执行dml语句,在dml语句第一次执行的时候会分配内存空间binlog cache
,执行dml语句期间生成的event不断写入到binlog cache。
3、如果binlog cache的空间已经满了,则将binlog cache的数据写入到binlog临时文件,同时清空binlog cache。如果binlog临时文件的大小大于max_binlog_cache_size的设置则抛错MySQL error code 1197 (ER_TRANS_CACHE_FULL): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
。
4、事物提交,整个binlog cache和binlog临时文件数据全部写入到binlog file中进行固化,释放binlog cache和binlog临时文件。但是注意此时binlog cache的内存空间留用供下次事物使用,但是binlog临时文件被截断为0,保留文件描述符。
5、断开连接,这个过程会释放IO_CACHE同时释放其持有的binlog cache内存空间以及持有的binlog 临时文件。
format | 定义 | 优点 | 缺点 |
---|---|---|---|
statement | 记录的是修改SQL语句 | 日志文件小,节约IO,提高性能 | 准确性差,对一些系统函数不能准确复制或不能复制,如now()、uuid()等 |
row | 记录的是每行实际数据的变更 | 准确性强,能准确复制数据的变更 | 日志文件大,较大的网络IO和磁盘IO |
mixed | statement和row模式的混合 | 准确性强,文件大小适中 | 有可能发生主从不一致问题 |
无特殊情况,推荐使用row模式
mysql> show variables like '%binlog%';
+------------------------------------------------+----------------------+
| Variable_name | Value |
+------------------------------------------------+----------------------+
| binlog_cache_size | 4194304 |
| binlog_checksum | CRC32 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_encryption | OFF |
| binlog_error_action | ABORT_SERVER |
| binlog_expire_logs_seconds | 604800 |
| binlog_format | ROW |
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| binlog_gtid_simple_recovery | ON |
| binlog_max_flush_queue_time | 0 |
| binlog_order_commits | ON |
| binlog_rotate_encryption_master_key_at_startup | OFF |
| binlog_row_event_max_size | 8192 |
| binlog_row_image | FULL |
| binlog_row_metadata | MINIMAL |
| binlog_row_value_options | |
| binlog_rows_query_log_events | OFF |
| binlog_stmt_cache_size | 32768 |
| binlog_transaction_compression | OFF |
| binlog_transaction_compression_level_zstd | 3 |
| binlog_transaction_dependency_history_size | 25000 |
| binlog_transaction_dependency_tracking | COMMIT_ORDER |
| innodb_api_enable_binlog | OFF |
| log_statements_unsafe_for_binlog | ON |
| max_binlog_cache_size | 2147483648 |
| max_binlog_size | 1073741824 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| sync_binlog | 1 |
+------------------------------------------------+----------------------+
29 rows in set (0.00 sec)
mysql> show variables like '%log_bin%';
+---------------------------------+----------------------------------+
| Variable_name | Value |
+---------------------------------+----------------------------------+
| log_bin | ON |
| log_bin_basename | /data/mysql8/binlog/binlog |
| log_bin_index | /data/mysql8/binlog/binlog.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+----------------------------------+
6 rows in set (0.01 sec)
参数名 | 含义 |
---|---|
log_bin | 指定实例是否启动二进制日志 |
log_bin_basename | 指定binlog文件名称:路径+名称 |
log_bin_index | 指定binlog索引文件名称:路径+名称 |
log_bin_trust_function_creators | 用于控制MySQL对存储函数和触发器创建的限制 |
sql_log_bin | 控制是否开启对二进制日志的日志记录功能 |
binlog_cache_size | 设置binlog_cache_size大小 |
max_binlog_cache_size | 指定二进制日志缓存最大大小 |
binlog_checksum | 为二进制日志中的每个事件写入校验和 |
binlog_encryption | binlog加密 |
expire_logs_days | 设置binlog过期天数 |
binlog_expire_logs_seconds | 设置binlog过期秒数 |
binlog_format | binlog格式 |
binlog_group_commit_sync_delay | 控制在将二进制日志文件同步到磁盘之前等待多少微秒以把事务合并到一个 |
binlog_group_commit_sync_no_delay_count | 在binloggroupcommitsyncdelay指定的延迟时间之内,一次组提交允许等待的 大事务数量,超过这个数量则不会进行组提交,不会再进行等待 |
binlog_order_commits | 用于控制主库中binlog的提交顺序是否需要和redo log的提交顺序保持一致 |
binlog_row_image | 控制binlog记录的前后镜像内容 |
sync_binlog | 指定binlog刷盘机制 |
binlog_rows_query_log_events | 控制是否记录用户原生SQL的参数到binlog file |
max_binlog_size | 单个文件最大大小 |
查看binlog信息
mysql> show master status\G
*************************** 1. row ***************************
File: binlog.000013
Position: 196
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: 6ac2c3ad-c5b7-11ea-8d1a-00163e0c8a51:1-403
1 row in set (0.00 sec)
mysql> show master logs;
+---------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000004 | 2466 | No |
| binlog.000005 | 1997 | No |
| binlog.000006 | 196 | No |
| binlog.000007 | 2736 | No |
| binlog.000008 | 419 | No |
| binlog.000009 | 1713 | No |
| binlog.000010 | 908 | No |
| binlog.000011 | 20821 | No |
+---------------+-----------+-----------+
8 rows in set (0.15 sec)
mysql> show binlog events in 'binlog.000011';
+---------------+-------+----------------+-----------+-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+---------------+-------+----------------+-----------+-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| binlog.000011 | 4 | Format_desc | 33071 | 125 | Server ver: 8.0.21, Binlog ver: 4 |
| binlog.000011 | 125 | Previous_gtids | 33071 | 196 | 6ac2c3ad-c5b7-11ea-8d1a-00163e0c8a51:1-338 |
| binlog.000011 | 196 | Gtid | 33071 | 273 | SET @@SESSION.GTID_NEXT= '6ac2c3ad-c5b7-11ea-8d1a-00163e0c8a51:339' |
| binlog.000011 | 273 | Query | 33071 | 382 | use `test`; create table test_t1 like t1 /* xid=4111 */ |
| binlog.000011 | 382 | Gtid | 33071 | 461 | SET @@SESSION.GTID_NEXT= '6ac2c3ad-c5b7-11ea-8d1a-00163e0c8a51:340' |
| binlog.000011 | 461 | Query | 33071 | 544 | BEGIN |
| binlog.000011 | 544 | Table_map | 33071 | 622 | table_id: 120 (test.test_t1) |
| binlog.000011 | 622 | Write_rows | 33071 | 1778 | table_id: 120 flags: STMT_END_F |
| binlog.000011 | 1778 | Xid | 33071 | 1809 | COMMIT /* xid=4112 */
命令行查看mysqlbinlog
mysqlbinlog --no-defaults -vvv mysql-bin.000458 --start-datetime="2020-04-18 16:15:00"
备份binlog
以前备份binlog时,都是先在本地进行备份压缩,然后发送到远程服务器中。但是这其中还是有一定风险的,因为日志的备份都是周期性的,如果在某个周期中,服务器宕机了,硬盘损坏了,就可能导致这段时间的binlog就丢失了。
而且,以前用脚本对远程服务器进行备份的方式,有个缺点:无法对MySQL服务器当前正在写的二进制日志文件进行备份。所以,只能等到MySQL服务器全部写完才能进行备份。而写完一个binlog的时间并不固定,这就导致备份周期的不确定。
从MySQL5.6开始,mysqlbinlog支持将远程服务器上的binlog实时复制到本地服务器上。
mysqlbinlog的实时二进制复制功能并非简单的将远程服务器的日志复制过来,它是通过MySQL 5.6公布的Replication API实时获取二进制事件。本质上,就相当于MySQL的从服务器。与普通服务器类似,主服务器发生事件后,一般都会在0.5~1秒内进行备份。
mysqlbinlog --read-from-remote-server --raw --host=192.168.244.145 --port=3306 --user=repl --password=repl --stop-never mysql-bin.000001
清理binlog
PURGE { BINARY | MASTER } LOGS {
TO 'log_name'
| BEFORE datetime_expr