如何简单分析MySQL中的binlog和redo

分类:编程技术 时间:2024-02-20 16:00 浏览:0 评论:0
0
如何简单分析MySQL中的binlog和redo?很多新手对此并不是很清楚。为了帮助大家解决这个问题,下面小编就为大家详细讲解一下。有这方面需要的人可以过来学习。我希望你能学到一些东西。报酬。

有一个小问题可能很多人都想到过,那就是MySQL既然已经有了binlog,为什么还需要redo呢?这个问题看似很简单,但是仔细一看,还是有一些问题的。有点值得注意。

对于数据恢复,尤其是异常宕机的情况下,重启时如何恢复以及恢复的数据基础就显得尤为重要。在MySQL中,有Checkpoint技术来做一个基本的Checkpoint控制,也称为LSN,对于事务型数据库,大多采用write advance log策略,即当前事务提交时,先写入redo,然后再写入相应的页面被修改。如果发生停机rs,数据将会丢失。有时,数据恢复可以通过重做日志来完成,但是MySQL和其他一些数据库的特殊之处在于binlog。它不使用检查点实现。我们可以想象一种情况,当事务提交时,信息会被写入进入redo,而在这个操作过程中,binlog的写入实际上是同步的。如果重做日志缓冲区中的重做信息可能无法刷新到磁盘,则可能会发生停机,从而可能导致从库的数据丢失。 binlog传输的数据变更已经应用,但是redo还没有来得及提交,可能会造成数据不一致。如果数据库在异常状态下启动,就会开启数据恢复模式,从库的数据可能会丢失。出现不一致的情况。

这种情况听起来有点特殊,但是对于我们理解redo和binlog的问题很有帮助。我们来做个测试,仅使用用于在测试环境中进行调试。

首先,为了减少数据变化的影响,我们先做一个flushlogs操作,尽可能少的保留数据变化的新日志内容

主库侧切换日志:
flush log;

查看binlog情况,使用show master status或者show binlog。
mysql> 显示主状态\G
******************************** 1. 行 ** *** ************************
  :1,
25ee7482- 07cd-11e7-a40c-0026b935eb76:1- 1502468
1 row in set (0.00 sec)

我们得到mysql服务的进程号。
# ps -ef|grep -w mysqld|grep -v grep|awk '{print $2}'
1751

我们创建一个表测试字段,其中包含 id 和 name(id int,name varchar(20))

已经有4条数据如下:

mysql> select *from test.test;
+---- --+ ------+
|编号 |姓名 |
+------+------+
| 1 |啊|
| 2 | bb |
| 3 |抄送|
| 4 | dd |
+------+--------+
4 行s in set (0.00 sec)


此时从库和主库查看到的数据已同步。这是我们测试的基础。

我们可以通过gdb进行简单的调试。
# gdb -p 1751

会立即进入调试模式,我们可以设置断点。

设置断点之前我们插入2条数据,此时slave数据库也有5条数据。

mysql> 插入测试值(5,'ee');
查询正常,1 行受影响(0.00 秒)

mysql> 插入测试值(6 ,'ff');
查询OK,1行受影响(0.00秒)

然后设置断点,这个是关键。
(gdb) b MYSQL_BIN_LOG::process_commit_stage_queue
0xec73ca处的断点1:文件/export/home/pb2/build/sb_0-21378219-1480347226.17/mysql-5.7.17/sql/binlog.cc,行8430.(2个位置)

然后尝试在主数据库中插入一条记录
insert into testvalues(7,'gg');
毫无疑问,这条语句将挂住。因为我们的断点是在提交的时候。

这时候我们向前迈出一小步,使用c即是 continue

(gdb) c
继续。
【切换到线程0x409c0940(LWP) 1798)]

断点 1,mysql_bin_log :: proces_commit_stage_queue (this = 0x1e8ba00,THD = 0xec254e0,first = 0xec254e0)
AT/Export/HOME/HOME/HOME/HOME/HOME/ pb2 /build/sb_0-21378219-1480347226.17/MySQL- 5.7.17/sql/binlog.cc:8430
8430 /export/home/pb2/build/sb_0-21378219-1480347226.17/mysql-5.7.17/sql/ binlog.cc:没有这样的文件或目录。
在/export/home/pb2/build/sb_0-21378219-1480347226.17/mysql-5.7.17/sql/binlog.cc
此时, SQL语句仍然处于hang状态,但是从堆栈中可以看到binlog写入完成


此时从库已经应用了数据变更,共有7条此时的数据。
我们还可以抓取binlog来查看是否有数据写入其中。
[root@grtest s1]# /usr/local/mysql/bin/mysqlbinlog -vv binlog.0000014
可以清楚地看到这样一条语句:

...

BINLOG '
DK3KWBPqDAAALgAAAHcDAAAAAOUAAAAAAAEBHRlc3QABHRlc3QAAgMPAhQAAw==< br/>DK3KWB7qDAAAJwAAAJ4DAAAAAOUAAAAAAAEAAgAC//wHAAAAAmdn
'/*!*/;
### INSERT INTO `test`.`test`
### SET
### @ 1=7 /* INT meta=0 nullable=1 is_null=0 */
### @2='gg' /* VARSTRING(20 ) meta=20 nullable=1 is_null=0 */
# at 926
#170316 23:19:40 server id 3306 end_log_pos 953 Xid = 55
COMMIT/*!*/;
我们此时模拟停机情况,杀死进程

kill -9 1751 29617

然后重命名binlog并关闭log_bin
[root@grtest s1]# mv binlog.000014 binlog.000014.bak
再第一次启动后,你会发现此时主库中还有6条数据,但是从库中却有7条数据。
如果我们把binlog改回来,打开log_bin并启动主库
mv binlog.000014.bak binlog.000014

然后再查一下数据,你会发现主从库有这个时候的数据,其实是不一样的。数据库中的数据明显多了,这从一个侧面体现了我们最初的想法。在异常宕机的情况下,redo数据还没有刷新到redo文件,此时就已经写入binlog了,所以就是在这样一个关键点,导致主从数据不一致。

当然,我是抱着调试的态度来做测试的,还有很多技巧需要巩固。

阅读以上内容对您有帮助吗?如果您想了解更多相关知识或阅读更多相关文章,请关注行业资讯频道。感谢您的支持。

1. 本站所有资源来源于用户上传或网络,仅作为参考研究使用,如有侵权请邮件联系站长!
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > 如何简单分析MySQL中的binlog和redo

用户评论