認識MySQL的binlog日誌

coldplay.xixi
發布: 2020-10-12 17:43:14
轉載
2723 人瀏覽過

mysql教學欄位今天介紹MySQL的binlog日誌。

認識MySQL的binlog日誌

binlog 基本認知

MySQL的二進位日誌可以說是MySQL最重要的日誌了,它記錄了所有的DDL和DML(除了資料查詢語句)語句,以事件形式記錄,也包含語句所執行的消耗的時間,MySQL的二進位日誌是事務安全型的。

一般來說開啟二進位日誌大概會有1%的效能損耗(參見MySQL官方中文手冊 5.1.24版)。二進位有兩個最重要的使用場景:

其一:MySQL Replication在Master端開啟binlog,Mster把它的二進位日誌傳遞給slaves來達到master-slave資料一致的目的。

其二:自然就是資料恢復了,透過使用mysqlbinlog工具來使恢復資料。

二進位日誌包含兩個類別檔案:二進位日誌索引檔案(檔案名稱後綴為.index)用於記錄所有的二進位文件,二進位日誌檔案(檔案名稱後綴為.00000* )記錄資料庫所有的DDL和DML(除了資料查詢語句)語句事件。

一、開啟binlog日誌:

vi編輯開啟mysql設定檔

# vi /usr/local/mysql/etc/my.cnf

在[mysqld] 區塊

設定/新增log-bin=mysql-bin 確認是開啟狀態(值mysql-bin 是日誌的基本名稱或前綴名稱);

重新啟動mysqld服務讓設定生效

# pkill mysqld

# pkill mysqld

# /usr/local/mysql/bin/mysqld_safe --user=mysql &sql &sql

二、也可登入mysql伺服器,透過mysql的變數設定表,查看二進位日誌是否開啟單字:variable[ˈvɛriəbəl] 變數

# 登入伺服器

# /usr/local/mysql/bin/mysql -uroot -p123456 mysql> show variables like 'log_%'; +----------------------------------------+---------------------------------------+ | Variable_name | Value | +----------------------------------------+---------------------------------------+ | log_bin | ON | ------> ON表示已经开启binlog日志 | log_bin_basename | /usr/local/mysql/data/mysql-bin | | log_bin_index | /usr/local/mysql/data/mysql-bin.index | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | | log_error | /usr/local/mysql/data/martin.err | | log_output | FILE | | log_queries_not_using_indexes | OFF | | log_slave_updates | OFF | | log_slow_admin_statements | OFF | | log_slow_slave_statements | OFF | | log_throttle_queries_not_using_indexes | 0 | | log_warnings | 1 | +----------------------------------------+---------------------------------------+
登入後複製

三、常用binlog日誌作業指令

1.查看所有binlog日誌清單

mysql> show master logs;

2.檢視master狀態,即最後(最新查看)一個binlog日誌的編號名稱,及其最後一個操作事件pos結束點(Position)值

mysql> show master status;

3.刷新log日誌,自此刻開始產生一個新編號的binlog日誌檔

mysql> flush logs;

附註:每當mysqld服務重新啟動時,會自動執行此指令,刷新binlog日誌;在mysqldump備份資料時加上-F選項也會刷新binlog日誌;

4.重置(清除)所有binlog日誌

mysql> reset master;

四、查看某個binlog日誌內容,並常用有兩種方法:

1.使用mysqlbinlog自帶檢視指令法:

注意: binlog是二進位文件,普通文件檢視器cat more vi等都無法打開,必須使用自帶的mysqlbinlog 指令檢視

binlog日誌與資料庫檔案在同目錄中(我的環境設定安裝是選擇在/usr/local/mysql/data中)

以下版本使用mysqlbinlog指令時若報錯,就加上「--no-defaults」選項

# /usr/local/mysql/bin/mysqlbinlog /usr/local/mysql/data/ mysql-bin.000013

下面截取一個片段分析:

............................................................................... # at 552 #131128 17:50:46 server id 1 end_log_pos 665 Query thread_id=11 exec_time=0 error_code=0 ---->执行时间:17:50:46;pos点:665 SET TIMESTAMP=1385632246/*!*/; update zyyshop.stu set name='李四' where id=4 ---->执行的SQL /*!*/; # at 665 #131128 17:50:46 server id 1 end_log_pos 692 Xid = 1454 ---->执行时间:17:50:46;pos点:692 ...............................................................................
登入後複製

注: server id 1 數據庫主機的服務號;

end_log_pos 665 pos點

thread_id=11 線程號

2.上面這種辦法讀取binlog日誌的全文內容較多,不容易分辨查看pos點信息,這裡介紹一種更為方便的查詢命令:

###########################################################################################################################n## #### mysql> show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];###### 指定要查詢的binlog檔名(不指定就是第一個binlog檔)###### FROM pos 指定從哪個pos起始點開始查起(不指定就是從整個檔案首個點開始算# LIMIT [offset,] 偏移量(不指定為0)###### row_count _count 查詢結果:###
*************************** 20. row *************************** Log_name: mysql-bin.000021 ----------------------------------------------> 查询的binlog日志文件名 Pos: 11197 ----------------------------------------------------------> pos起始点: Event_type: Query ----------------------------------------------------------> 事件类型:Query Server_id: 1 --------------------------------------------------------------> 标识是由哪台服务器执行的 End_log_pos: 11308 ----------------------------------------------------------> pos结束点:11308(即:下行的pos起始点) Info: use `zyyshop`; INSERT INTO `team2` VALUES (0,345,'asdf8er5') ---> 执行的sql语句 *************************** 21. row *************************** Log_name: mysql-bin.000021 Pos: 11308 ----------------------------------------------------------> pos起始点:11308(即:上行的pos结束点) Event_type: Query Server_id: 1 End_log_pos: 11417 Info: use `zyyshop`; /*!40000 ALTER TABLE `team2` ENABLE KEYS */ *************************** 22. row *************************** Log_name: mysql-bin.000021 Pos: 11417 Event_type: Query Server_id: 1 End_log_pos: 11510 Info: use `zyyshop`; DROP TABLE IF EXISTS `type`
登入後複製

这条语句可以将指定的binlog日志文件,分成有效事件行的方式返回,并可使用limit指定pos点的起始偏移,查询条数;

A.查询第一个(最早)的binlog日志:

mysql> show binlog events\G;

B.指定查询 mysql-bin.000021 这个文件:

mysql> show binlog events in 'mysql-bin.000021'\G;

C.指定查询 mysql-bin.000021 这个文件,从pos点:8224开始查起:

mysql> show binlog events in 'mysql-bin.000021' from 8224\G;

D.指定查询 mysql-bin.000021 这个文件,从pos点:8224开始查起,查询10条

mysql> show binlog events in 'mysql-bin.000021' from 8224 limit 10\G;

E.指定查询 mysql-bin.000021 这个文件,从pos点:8224开始查起,偏移2行,查询10条

mysql> show binlog events in 'mysql-bin.000021' from 8224 limit 2,10\G;

五、恢复binlog日志实验(zyyshop是数据库)

1.假设现在是凌晨4:00,我的计划任务开始执行一次完整的数据库备份:

将zyyshop数据库备份到 /root/BAK.zyyshop.sql 文件中:

# /usr/local/mysql/bin/mysqldump -uroot -p123456 -lF --log-error=/root/myDump.err -B zyyshop > /root/BAK.zyyshop.sql

......

大约过了若干分钟,备份完成了,我不用担心数据丢失了,因为我有备份了,嘎嘎~~~

由于我使用了-F选项,当备份工作刚开始时系统会刷新log日志,产生新的binlog日志来记录备份之后的数据库“增删改”操作,查看一下:

mysql> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000023 | 120 | | | +------------------+----------+--------------+------------------+
登入後複製

也就是说, mysql-bin.000023 是用来记录4:00之后对数据库的所有“增删改”操作。

2.早9:00上班了,业务的需求会对数据库进行各种“增删改”操作~~~~~~~

@ 比如:创建一个学生表并插入、修改了数据等等: CREATE TABLE IF NOT EXISTS `tt` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(16) NOT NULL, `sex` enum('m','w') NOT NULL DEFAULT 'm', `age` tinyint(3) unsigned NOT NULL, `classid` char(6) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
登入後複製

导入实验数据

mysql> insert into zyyshop.tt(`name`,`sex`,`age`,`classid`) values('yiyi','w',20,'cls1'),('xiaoer','m',22,'cls3'),('zhangsan','w',21,'cls5'),('lisi','m',20,'cls4'),('wangwu','w',26,'cls6');
登入後複製

查看数据

mysql> select * from zyyshop.tt; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | yiyi | w | 20 | cls1 | | 2 | xiaoer | m | 22 | cls3 | | 3 | zhangsan | w | 21 | cls5 | | 4 | lisi | m | 20 | cls4 | | 5 | wangwu | w | 26 | cls6 | +----+----------+-----+-----+---------+
登入後複製

中午时分又执行了修改数据操作

mysql> update zyyshop.tt set name='李四' where id=4; mysql> update zyyshop.tt set name='小二' where id=2;
登入後複製

修改后的结果:

mysql> select * from zyyshop.tt; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | yiyi | w | 20 | cls1 | | 2 | 小二 | m | 22 | cls3 | | 3 | zhangsan | w | 21 | cls5 | | 4 | 李四 | m | 20 | cls4 | | 5 | wangwu | w | 26 | cls6 | +----+----------+-----+-----+---------+
登入後複製

假设此时是下午18:00,莫名地执行了一条悲催的SQL语句,整个数据库都没了:

mysql> drop database zyyshop;

3.此刻杯具了,别慌!先仔细查看最后一个binlog日志,并记录下关键的pos点,到底是哪个pos点的操作导致了数据库的破坏(通常在最后几步);

备份一下最后一个binlog日志文件:

# ll /usr/local/mysql/data | grep mysql-bin # cp -v /usr/local/mysql/data/mysql-bin.000023 /root/
登入後複製

此时执行一次刷新日志索引操作,重新开始新的binlog日志记录文件,理论说 mysql-bin.000023 这个文件不会再有后续写入了(便于我们分析原因及查找pos点),以后所有数据库操作都会写入到下一个日志文件;

mysql> flush logs; mysql> show master status;
登入後複製

4.读取binlog日志,分析问题

方式一:使用mysqlbinlog读取binlog日志:

# /usr/local/mysql/bin/mysqlbinlog /usr/local/mysql/data/mysql-bin.000023

方式二:登录服务器,并查看(推荐):

mysql> show binlog events in 'mysql-bin.000023';

以下为末尾片段:

+------------------+------+------------+-----------+-------------+------------------------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+------+------------+-----------+-------------+------------------------------------------------------------+ | mysql-bin.000023 | 922 | Xid | 1 | 953 | COMMIT /* xid=3820 */ | | mysql-bin.000023 | 953 | Query | 1 | 1038 | BEGIN | | mysql-bin.000023 | 1038 | Query | 1 | 1164 | use `zyyshop`; update zyyshop.tt set name='李四' where id=4| | mysql-bin.000023 | 1164 | Xid | 1 | 1195 | COMMIT /* xid=3822 */ | | mysql-bin.000023 | 1195 | Query | 1 | 1280 | BEGIN | | mysql-bin.000023 | 1280 | Query | 1 | 1406 | use `zyyshop`; update zyyshop.tt set name='小二' where id=2| | mysql-bin.000023 | 1406 | Xid | 1 | 1437 | COMMIT /* xid=3823 */ | | mysql-bin.000023 | 1437 | Query | 1 | 1538 | drop database zyyshop | +------------------+------+------------+-----------+-------------+------------------------------------------------------------+
登入後複製

通过分析,造成数据库破坏的pos点区间是介于 1437--1538 之间,只要恢复到1437前就可。

5.现在把凌晨备份的数据恢复:

# /usr/local/mysql/bin/mysql -uroot -p123456 -v < /root/BAK.zyyshop.sql;

注: 至此截至当日凌晨(4:00)前的备份数据都恢复了。

但今天一整天(4:00--18:00)的数据肿么办呢?就得从前文提到的 mysql-bin.000023 新日志做文章了......

6.从binlog日志恢复数据

恢复语法格式:

# mysqlbinlog mysql-bin.0000xx | mysql -u用户名 -p密码 数据库名

常用选项:

--start-position=953 起始pos点

--stop-position=1437 结束pos点

--start-datetime="2013-11-29 13:18:54" 起始时间点

--stop-datetime="2013-11-29 13:21:53" 结束时间点

--database=zyyshop 指定只恢复zyyshop数据库(一台主机上往往有多个数据库,只限本地log日志)

不常用选项:

-u --user=name Connect to the remote server as username.连接到远程主机的用户名

-p --password[=name] Password to connect to remote server.连接到远程主机的密码

-h --host=name Get the binlog from server.从远程主机上获取binlog日志

--read-from-remote-server Read binary logs from a MySQL server.从某个MySQL服务器上读取binlog日志

小结:实际是将读出的binlog日志内容,通过管道符传递给mysql命令。这些命令、文件尽量写成绝对路径;

A.完全恢复(本例不靠谱,因为最后那条 drop database zyyshop 也在日志里,必须想办法把这条破坏语句排除掉,做部分恢复)

# /usr/local/mysql/bin/mysqlbinlog /usr/local/mysql/data/mysql-bin.000021 | /usr/local/mysql/bin/mysql -uroot -p123456 -v zyyshop
登入後複製

B.指定pos结束点恢复(部分恢复):

@ --stop-position=953 pos结束点

注:此pos结束点介于“导入实验数据”与更新“name='李四'”之间,这样可以恢复到更改“name='李四'”之前的“导入测试数据”

# /usr/local/mysql/bin/mysqlbinlog --stop-position=953 --database=zyyshop /usr/local/mysql/data/mysql-bin.000023 | /usr/local/mysql/bin/mysql -uroot -p123456 -v zyyshop
登入後複製

在另一终端登录查看结果(成功恢复了):

mysql> select * from zyyshop.tt; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | yiyi | w | 20 | cls1 | | 2 | xiaoer | m | 22 | cls3 | | 3 | zhangsan | w | 21 | cls5 | | 4 | lisi | m | 20 | cls4 | | 5 | wangwu | w | 26 | cls6 | +----+----------+-----+-----+---------+
登入後複製

C.指定pso点区间恢复(部分恢复):

更新 name='李四' 这条数据,日志区间是Pos[1038] --> End_log_pos[1164],按事务区间是:Pos[953] --> End_log_pos[1195];

更新 name='小二' 这条数据,日志区间是Pos[1280] --> End_log_pos[1406],按事务区间是:Pos[1195] --> End_log_pos[1437];

c1.单独恢复 name='李四' 这步操作,可这样:

# /usr/local/mysql/bin/mysqlbinlog --start-position=1038 --stop-position=1164 --database=zyyshop /usr/local/mysql/data/mysql-bin.000023 | /usr/local/mysql/bin/mysql -uroot -p123456 -v zyyshop
登入後複製

也可以按事务区间单独恢复,如下:

# /usr/local/mysql/bin/mysqlbinlog --start-position=953 --stop-position=1195 --database=zyyshop /usr/local/mysql/data/mysql-bin.000023 | /usr/local/mysql/bin/mysql -uroot -p123456 -v zyyshop
登入後複製

c2.单独恢复 name='小二' 这步操作,可这样:

# /usr/local/mysql/bin/mysqlbinlog --start-position=1280 --stop-position=1406 --database=zyyshop /usr/local/mysql/data/mysql-bin.000023 | /usr/local/mysql/bin/mysql -uroot -p123456 -v zyyshop
登入後複製

也可以按事务区间单独恢复,如下:

# /usr/local/mysql/bin/mysqlbinlog --start-position=1195 --stop-position=1437 --database=zyyshop /usr/local/mysql/data/mysql-bin.000023 | /usr/local/mysql/bin/mysql -uroot -p123456 -v zyyshop
登入後複製

c3.将 name='李四'、name='小二' 多步操作一起恢复,需要按事务区间,可这样:

# /usr/local/mysql/bin/mysqlbinlog --start-position=953 --stop-position=1437 --database=zyyshop /usr/local/mysql/data/mysql-bin.000023 | /usr/local/mysql/bin/mysql -uroot -p123456 -v zyyshop
登入後複製

D.在另一终端登录查看目前结果(两名称也恢复了):

mysql> select * from zyyshop.tt; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | yiyi | w | 20 | cls1 | | 2 | 小二 | m | 22 | cls3 | | 3 | zhangsan | w | 21 | cls5 | | 4 | 李四 | m | 20 | cls4 | | 5 | wangwu | w | 26 | cls6 | +----+----------+-----+-----+---------+
登入後複製

E.也可指定时间区间恢复(部分恢复):除了用pos点的办法进行恢复,也可以通过指定时间区间进行恢复,按时间恢复需要用mysqlbinlog命令读取binlog日志内容,找时间节点。

比如,我把刚恢复的tt表删除掉,再用时间区间点恢复

mysql> drop table tt; @ --start-datetime="2013-11-29 13:18:54" 起始时间点 @ --stop-datetime="2013-11-29 13:21:53" 结束时间点 # /usr/local/mysql/bin/mysqlbinlog --start-datetime="2013-11-29 13:18:54" --stop-datetime="2013-11-29 13:21:53" --database=zyyshop /usr/local/mysql/data/mysql-bin.000021 | /usr/local/mysql/bin/mysql -uroot -p123456 -v zyyshop
登入後複製

总结:所谓恢复,就是让mysql将保存在binlog日志中指定段落区间的sql语句逐个重新执行一次而已。

更多相关免费学习推荐:mysql教程(视频)

以上是認識MySQL的binlog日誌的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:cnblogs.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!