MySQL的二进制日志可以说是MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的。
biglog日志linux系统中默认存放在/var/lib/mysql目录下,windows则存放data下,如果有手动指定那就看my.cnf(linux),my.ini(windows)文件里指定的路径
开启binlog日志:
在[mysqld] 区块
设置/添加 log-bin=mysql-bin 确认是打开状态(值 mysql-bin 是日志的基本名或前缀名);
查询log-bin日志的模式(在my.ini配置文件中指定,如 binlog_format="ROW")
mysql>show variables like "%binlog_format%";
1.Row
日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改,只记录要修改的数据,只有value,不会有sql多表关联的情况。
优点:在row模式下,bin-log中可以不记录执行的sql语句的上下文相关的信息,仅仅只需要记录那一条记录被修改了,修改成什么样了,所以row的日志内容会非常清楚的记录下每一行数据修改的细节,非常容易理解。而且不会出现某些特定情况下的存储过程和function,以及trigger的调用和出发无法被正确复制问题。
缺点:在row模式下,所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容。
2.statement
每一条会修改数据的sql都会记录到master的binlog中,slave在复制的时候sql进程会解析成和原来master端执行多相同的sql再执行。
优点:在statement模式下首先就是解决了row模式的缺点,不需要记录每一行数据的变化减少了binlog日志量,节省了I/O以及存储资源,提高性能。因为他只需要记录在master上所执行的语句的细节以及执行语句的上下文信息。
缺点:在statement模式下,由于他是记录的执行语句,所以,为了让这些语句在slave端也能正确执行,那么他还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信息,以保证所有语句在slave端被执行的时候能够得到和在master端执行时候相同的结果。另外就是,由于mysql现在发展比较快,很多的新功能不断的加入,使mysql的复制遇到了不小的挑战,自然复制的时候涉及到越复杂的内容,bug也就越容易出现。在statement中,目前已经发现不少情况会造成Mysql的复制出现问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现,比如:sleep()函数在有些版本中就不能被正确复制,在存储过程中使用了last_insert_id()函数,可能会使slave和master上得到不一致的id等等。由于row是基于每一行来记录的变化,所以不会出现,类似的问题。
3.Mixed
从官方文档中看到,之前的 MySQL 一直都只有基于 statement 的复制模式,直到 5.1.5 版本的 MySQL 才开始支持 row 复制。从 5.0 开始,MySQL 的复制已经解决了大量老版本中出现的无法正确复制的问题。但是由于存储过程的出现,给 MySQL Replication 又带来了更大的新挑战。另外,看到官方文档说,从 5.1.8 版本开始,MySQL 提供了除 Statement 和 Row 之外的第三种复制模式:Mixed,实际上就是前两种模式的结合。在 Mixed 模式下,MySQL 会根据执行的每一条具体的 SQL 语句来区分对待记录的日志形式,也就是在 statement 和 row 之间选择一种。新版本中的 statment 还是和以前一样,仅仅记录执行的语句。而新版本的 MySQL 中对 row 模式也被做了优化,并不是所有的修改都会以 row 模式来记录,比如遇到表结构变更的时候就会以 statement 模式来记录,如果 SQL 语句确实就是 update 或者 delete 等修改数据的语句,那么还是会记录所有行的变更。
刷新binlog日志(每当mysqld服务重启时,会自动执行此命令,刷新binlog日志;在mysqldump备份数据时加 -F 选项也会刷新binlog日志;)
mysql>flush logs;
查询mysql服务器有没开启binlog日志(ON为开启,OFF为未开启)
mysql>show variables like 'log_bin';
查询binlog日志存放位置
mysql>show variables like '%datadir%';
查看所有binlog日志列表
mysql> show master logs;
重置(清空)所有binlog日志
mysql> reset master;
获取binlog文件列表
mysql> show binary logs;
只查看第一个binlog文件的内容
mysql> show binlog events;
查看指定binlog文件的内容
mysql> show binlog events in 'mysql-bin.000002';
查看当前正在写入的binlog文件
mysql> show master status\G;
外部命令:mysqlbinlog
(binlog是二进制文件,普通文件查看器cat more vi等都无法打开,必须使用自带的 mysqlbinlog 命令查看 ,binlog日志与数据库文件在同目录中)
-d 选项,可以指定一个数据库名称,将只显示在该数据库上所发生的事件,
等同于 --database 命令
-D 选项,在使用二进制日志文件进行数据库恢复时,该过程中也会产生日志文件,就会进入一个循环状态,继续恢复该过程中的数据。因此,当使用mysqlbinlog命令时,要禁用二进制日志。
mysqlbinlog -D mysqld-bin.000001
等同于 --disable-log-bin 命令
-s 选项,只查看常规的SQL语句,而不需要其他内容
等同于 --short-form 命令
--start-datetime:从二进制日志中读取指定等于时间戳或者晚于本地计算机的时间
--stop-datetime:从二进制日志中读取指定小于时间戳或者等于本地计算机的时间 取值和上述一样
--start-position:从二进制日志中读取指定position 事件位置作为开始。
--stop-position:从二进制日志中读取指定position 事件位置作为事件截至
所谓恢复,就是让mysql将保存在binlog日志中指定段落区间的sql语句逐个重新执行一次而已。
基于开始/结束时间(binlog日志写绝对路径或cd到所在目录再执行该命令)
[root@tx ~]# mysqlbinlog --start-datetime="2019-06-024 00:00:00" --stop-datetime="2019-06-26 09:01:01" -d blockchain_trade mysql-bin.000001
将数据导出
mysqlbinlog --no-defaults --database=blockchain_trade --start-datetime="2019-06-26 07:21:09" --stop-datetime="2019-06-28 07:59:50" mysql-bin.000004 > G:\bak.sql
(也可以写入到一个TXT文本进行查看)
恢复数据库前先备份数据
#-l 是锁库的意思,-F 是备份成功后刷新binlog日志的意思,即生成一份新binlog日志文件
mysqldump -uroot -proot share -l -F > /tmp/test20190607.sql
导入数据
#-f 是出错继续的意思
mysql -uroot -proot -f test < /tmp/test20190607.sql
或者进入该库source一下sql文件进行恢复
#指定节点查看
mysqlbinlog --start-position=134 --stop-position=899 mysql-bin.000003
#查看指定库
mysqlbinlog --start-datetime="2019-06-07 00:00:00" --stop-datetime="2019-06-07 17:32:00" -d test mysql-bin.000003
linux的 | grep 命令也是可以使用的
mysqlbinlog --start-datetime="2016-12-07 00:00:00" --stop-datetime="2016-12-07 17:32:00" mysql-bin.000003 -d test | grep table1
只查询insert,update,delete的语句,可以这样写:
mysqlbinlog --no-defaults --database=raceEnroll mysql-bin.000008 |grep update |more
从远程服务器获取二进制日志
在本地机器上,还可以读取位于远程服务器上的mysql二进制日志文件。为此,需要指定远程服务器的ip地址、用户名和密码,如下所示。
此处使用-R选项。-R选项与-read-from-remote-server相同。
$ mysqlbinlog -R -h 192.168.101.2 -p mysqld-bin.000001
在上面命令中:
- -R 选项指示mysqlbinlog命令从远程服务器读取日志文件
- -h 指定远程服务器的ip地址
- -p 将提示输入密码。默认情况下,它将使用“root”作为用户名。也可以使用 -u 选项指定用户名。
- mysqld-bin.000001 这是在这里读到的远程服务器的二进制日志文件的名称。
下面命令与上面的命令完全相同:
$ mysqlbinlog --read-from-remote-server --host=192.168.101.2 -p mysqld-bin.000001
如果只指定 -h 选项,将会得到下面的错误消息。
$ mysqlbinlog -h 192.168.101.2 mysqld-bin.000001 mysqlbinlog: File 'mysqld-bin.000001' not found (Errcode: 2)
当你在远程数据库上没有足够的特权时,将得到以下“不允许连接”错误消息。在这种情况下,确保在远程数据库上为本地客户机授予适当的特权。
$ mysqlbinlog -R --host=192.168.101.2 mysqld-bin.000001 ERROR: Failed on connect: Host '216.172.166.27' is not allowed to connect to this MySQL server
如果没有使用 -p 选项指定正确的密码,那么将得到以下“访问拒绝”错误消息。
$ mysqlbinlog -R --host=192.168.101.2 mysqld-bin.000001 ERROR: Failed on connect: Access denied for user 'root'@'216.172.166.27' (using password: YES)