二进制日志可以说是MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的。一般来说开启二进制日志大概会有1%的性能损耗(参见MySQL官方中文手册 5.1.24版)。二进制有两个最重要的使用场景:
其一:MySQL Replication在Master端开启binlog,Mster把它的二进制日志传递给slaves来达到master-slave数据一致的目的。
其二:自然就是数据恢复了,通过使用mysqlbinlog工具来使恢复数据。
二进制日志包括两类文件:二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件,二进制日志文件(文件名后缀为.00000*)记录数据库所有的DDL和DML(除了数据查询语句)语句事件。
mysql> show variables like '%log_bin%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin | OFF |
| log_bin_trust_function_creators | OFF |
| sql_log_bin | ON |
+---------------------------------+-------+
3 rows in set (0.00 sec)
step1:my.ini中添加log-bin配置
mysql5.7见mysql需要修改的my.ini见此
[mysqld] #mysqld节点添加
log-bin=D:\MySqlUse\MySql-binlog #表示binlog的存储路径
在指定路径时要注意以下两点:
1 在目录的文件夹命名中不能有空格,比如“aa bb”文件夹 是不允许的,这样,在访问日志时候会报错;
2 指定目录时候一定要以*.log结尾,即不能仅仅指定到文件夹的级别,如上面我写的logbin.log,这时候,日志文件的名称是logbin.000001 logbin.000002。。。不然不会有日志文件产生。
step2:重启mysql:services.exe调起服务,然后关闭mysql,再重启。
step3:查看log_bin开关状态
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.00 sec)
step4:查看binlog信息
mysql> show binary logs;
+---------------------+-----------+
| Log_name | File_size |
+---------------------+-----------+
| MySql-binlog.000001 | 285 |
+---------------------+-----------+
1 row in set (0.00 sec)
step5:mysqlbinlog 查看binlog内容
为了方便查看日志内容 可以导出到.sql文件
mysqlbinlog ..\log-bin\MySql-binlog.000001 ->a.sql
C:\Users\Administrator>mysqlbinlog MySql-binlog.000001;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
mysqlbinlog: File 'MySql-binlog.000001;' not found (Errcode: 2)
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
C:\Users\Administrator>
mysql> show binlog events; #只查看第一个binlog文件的内容
mysql> show binlog events in 'mysql-bin.000002';#查看指定binlog文件的内容
mysql> show binary logs; #获取binlog文件列表
mysql> show master status; #查看当前正在写入的binlog文件
实际操练:
mysql> show binlog events in 'MySql-binlog.000008';
+---------------------+------+-------------+-----------+-------------+----------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info
|
+---------------------+------+-------------+-----------+-------------+----------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------+
| MySql-binlog.000008 | 4 | Format_desc | 1 | 107 | Server ver: 5.5.40-log, Binlog ver: 4
|
| MySql-binlog.000008 | 107 | Query | 1 | 176 | BEGIN
|
| MySql-binlog.000008 | 176 | Table_map | 1 | 220 | table_id: 33 (learn.t1)
|
| MySql-binlog.000008 | 220 | Update_rows | 1 | 276 | table_id: 33 flags: STMT_END_F
|
| MySql-binlog.000008 | 276 | Xid | 1 | 303 | COMMIT /* xid=26 */
|
| MySql-binlog.000008 | 303 | Query | 1 | 372 | BEGIN
|
| MySql-binlog.000008 | 372 | Table_map | 1 | 416 | table_id: 33 (learn.t1)
|
| MySql-binlog.000008 | 416 | Update_rows | 1 | 472 | table_id: 33 flags: STMT_END_F
|
| MySql-binlog.000008 | 472 | Xid | 1 | 499 | COMMIT /* xid=31 */
|
| MySql-binlog.000008 | 499 | Query | 1 | 770 | use `learn`; CREATE TABLE `t` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `t_modified` timestamp NOT NULL DEFAULT CURRENT_
TIMESTAMP, PRIMARY KEY (`id`), KEY `a` (`a`), KEY `t_modified`(`t_modified`)) ENGINE=InnoDB |
| MySql-binlog.000008 | 770 | Query | 1 | 847 | BEGIN
|
| MySql-binlog.000008 | 847 | Query | 1 | 957 | use `learn`; insert into t values(1,1,'2018-11-13')
|
| MySql-binlog.000008 | 957 | Xid | 1 | 984 | COMMIT /* xid=47 */
|
| MySql-binlog.000008 | 984 | Query | 1 | 1061 | BEGIN
|
| MySql-binlog.000008 | 1061 | Query | 1 | 1171 | use `learn`; insert into t values(2,2,'2018-11-12')
|
| MySql-binlog.000008 | 1171 | Xid | 1 | 1198 | COMMIT /* xid=48 */
|
| MySql-binlog.000008 | 1198 | Query | 1 | 1275 | BEGIN
|
| MySql-binlog.000008 | 1275 | Query | 1 | 1385 | use `learn`; insert into t values(3,3,'2018-11-11')
|
| MySql-binlog.000008 | 1385 | Xid | 1 | 1412 | COMMIT /* xid=49 */
|
| MySql-binlog.000008 | 1412 | Query | 1 | 1489 | BEGIN
|
| MySql-binlog.000008 | 1489 | Query | 1 | 1599 | use `learn`; insert into t values(4,4,'2018-11-10')
|
| MySql-binlog.000008 | 1599 | Xid | 1 | 1626 | COMMIT /* xid=50 */
|
| MySql-binlog.000008 | 1626 | Query | 1 | 1703 | BEGIN
|
| MySql-binlog.000008 | 1703 | Query | 1 | 1813 | use `learn`; insert into t values(5,5,'2018-11-09')
|
| MySql-binlog.000008 | 1813 | Xid | 1 | 1840 | COMMIT /* xid=51 */
|
| MySql-binlog.000008 | 1840 | Query | 1 | 1917 | BEGIN
|
| MySql-binlog.000008 | 1917 | Query | 1 | 2052 | use `learn`; delete from t where a>=4 and t_modified<='2018-11-10' limit 1
|
| MySql-binlog.000008 | 2052 | Xid | 1 | 2079 | COMMIT /* xid=54 */
|
| MySql-binlog.000008 | 2079 | Query | 1 | 2156 | BEGIN
|
| MySql-binlog.000008 | 2156 | Query | 1 | 2291 | use `learn`; delete from t where a>=4 and t_modified<='2018-11-10' limit 1
|
| MySql-binlog.000008 | 2291 | Xid | 1 | 2318 | COMMIT /* xid=56 */
|
+---------------------+------+-------------+-----------+-------------+----------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------+
31 rows in set (0.02 sec)
1 )当停止或重启服务器时,服务器会把日志文件记入下一个日志文件,Mysql会在重启时生成一个新的日志文件,文件序号递增;
2) 如果日志文件超过max_binlog_size(默认值1G)系统变量配置的上限时,也会生成新的日志文件(在这里需要注意的是,如果你正使用大的事务,二进制日志还会超过max_binlog_size,不会生成新的日志文件,事务全写入一个二进制日志中,这种情况主要是为了保证事务的完整性)
3 )日志被刷新时,新生成一个日志文件。
flush实验:
mysql> show binary logs;
+---------------------+-----------+
| Log_name | File_size |
+---------------------+-----------+
| MySql-binlog.000001 | 304 |
| MySql-binlog.000002 | 107 |
+---------------------+-----------+
2 rows in set (0.00 sec)
mysql> flush logs;
Query OK, 0 rows affected (0.31 sec)
mysql> show binary logs;
+---------------------+-----------+
| Log_name | File_size |
+---------------------+-----------+
| MySql-binlog.000001 | 304 |
| MySql-binlog.000002 | 153 |
| MySql-binlog.000003 | 107 |
+---------------------+-----------+
3 rows in set (0.00 sec)
1.1 Row Level 行模式
日志中会记录每一行数 据被修改的形式,然后在slave端再对相同的数据进行修改
优点:在row level模式下,bin-log中可以不记录执行的sql语句的上下文相关的信息,仅仅只需要记录那一条被修改。
所以rowlevel的日志内容会非常清楚的记录下每一行数据修改的细节。
不会出现某些特定的情况下的存储过程或function,以及trigger的调用和触发无法被正确复制的问题
缺点:row level,所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,会产生大量的日志内容。
1.2 Statement Level(默认)
每一条会修改数据的sql都会记录到master的bin-log中。slave在复制的时候sql进程会解析成和原来master端
执行过的相同的sql来再次执行。
**优点:**statement level下的优点首先就是解决了row level下的缺点,不需要记录每一行数据的变化,减
少bin-log日志量,节约IO,提高性能,因为它只需要在Master上锁执行的语句的细节,以及执行语句的上下文的
信息。
缺点:由于只记录语句,所以,在statement level下 已经发现了有不少情况会造成MySQL的复制出现问题,主
要是修改数据的时候使用了某些定的函数或者功能的时候会出现。
1.3 Mixed 自动模式
在Mixed模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志格式,也就是在Statement和
Row之间选择一种。如果sql语句确实就是update或者delete等修改数据的语句,那么还是会记录所有行的变更。
1.4 企业场景如何选择binlog模式
1、互联网公司,使用MySQL的功能相对少(存储过程、触发器、函数)
选择默认的语句模式,Statement Level(默认)
2、公司如果用到使用MySQL的特殊功能(存储过程、触发器、函数)
则选择Mixed模式
3、公司如果用到使用MySQL的特殊功能(存储过程、触发器、函数)又希望数据最大化一直,此时最好选择Row level模式
1.5 如何配置binlog
mysql> show global variables like '%binlog_format%';
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)
mysql> SET GLOBAL binlog_format = 'ROW';
Query OK, 0 rows affected (0.08 sec)
mysql> show global variables like '%binlog_format%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)
但是要注意如果set global variables,那么show variables 还是老的binlog格式,需要从配置文件修改。然后重启mysql
mysql> show variables like '%binlog_format%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)
mysql> show global variables like '%binlog_format%';
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)
[myslqd]
log-bin=mysql-bin
#binlog_format="STATEMENT"
#binlog_format="ROW"
#binlog_format="MIXED"
mysql>SET GLOBAL binlog_format = 'ROW';
mysql>show global variables like '%binlog_format%';
其他模式命令为:
SET GLOBAL binlog_format = 'MIXED';
SET GLOBAL binlog_format = 'STATEMENT';
说明:
GLOBAL=全局会话
SESSION=当前会话
检验ROW模式下binlog日志记录效果
#记得binlog后不要加分号
D:\MySqlUse>mysqlbinlog --base64-output="decode-rows" --verbose MySql-binlog.000008
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200326 0:47:37 server id 1 end_log_pos 107 Start: binlog v 4, server v 5.5.40-log created 200326 0:47:37
# Warning: this binlog is either in use or was not closed properly.
# at 107
#200326 0:47:40 server id 1 end_log_pos 176 Query thread_id=1 exec_time=0 error_code=0
SET TIMESTAMP=1585154860/*!*/;
SET @@session.pseudo_thread_id=1/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1344274432/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 176
# at 220
#200326 0:47:40 server id 1 end_log_pos 220 Table_map: `learn`.`t1` mapped to number 33
#200326 0:47:40 server id 1 end_log_pos 276 Update_rows: table id 33 flags: STMT_END_F
### UPDATE `learn`.`t1`
### WHERE
### @1=1
### @2=1
### @3=19
### SET
### @1=1
### @2=1
### @3=20
# at 276
#200326 0:47:40 server id 1 end_log_pos 303 Xid = 26
COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
D:\MySqlUse>
二进制日志可以使用mysqlbinlog命令查看
mysqlbinlog [option] log-file1 log-file2...
以下是常用的几个选项:
-d,--database=name:只查看指定数据库的日志操作
-o,--offset=#:忽略掉日志中的前n个操作命令
-r,--result-file=name:将输出的日志信息输出到指定的文件中,使用重定向也一样可以。
-s,--short-form:显示简单格式的日志,只记录一些普通的语句,会省略掉一些额外的信息如位置信息和时间信
息以及基于行的日志。可以用来调试,生产环境千万不可使用
--set-charset=char_name:在输出日志信息到文件中时,在文件第一行加上set names char_name
--start-datetime,--stop-datetime:指定输出开始时间和结束时间内的所有日志信息
--start-position=#,--stop-position=#:指定输出开始位置和结束位置内的所有日志信息
-v,-vv:显示更详细信息,基于row的日志默认不会显示出来,此时使用-v或-vv可以查看
MySql日志分析:
日志分析