如何通过binlog获取我们想要的MySql语句?
前言
MySql的binlog一般用于我们对数据的恢复,以及从数据库对主数据库的复制和更新。
假设此时我们有一个需要查询和读取Mysql最近操作DDL的信息,我们需要怎么处理?
聪明的你可能已经想到了,我们可以使用mysqlbinlog工具读取啊!的确,mysqlbinlog对于statement或者mixed格式的binlog文件确实会很方便读取,但是你要知道,从Mysql5.7.7开始,row就是默认的binlog_format,此时我们再要去直接通过肉眼去看,恐怕就不是那么容易了。

即使我们在通过mysqlbinlog解析时加上-v参数,也只能显示出这样的效果:

于是,我写了一个binlog2sql的初级版本,来实现sql语句的转换。
实现
实现过程不是很复杂,主要是通过mysqlbinlog来提取我们需要的DDL语句,然后我们再通过我们的方法来把这些语句转化为我们可以识别的sql语句。
核心代码:
/**
* @return $this
*/
protected function selectFromBinLog()
{
$fillFile = Util::getFile(__DIR__ . '/data/file.sql');
file_put_contents($fillFile, "");
exec("mysqlbinlog -v --database='" . Conf::__DATABASE__ . "' $this->_binlog_basename/$this->_binlog_file | grep -E -i '###|UPDATE|INSERT|DELETE' >> $fillFile");
return $this;
}
/**
* @return $this
*/
protected function parseSql()
{
$fillFileHandler = fopen(__DIR__ . '/data/file.sql', 'r');
$sqlArr = [];
if ($this->_type == 'ROW') {
$match = NULL;
$sqlStr = "";
while (($sql = fgets($fillFileHandler)) !== false) {
if (($match = preg_match('/UPDATE|INSERT|DELETE/', $sql)) || strrpos($sql, 'end_log_pos') !== false) {
# 如果有指定表
if ($match && $this->_table && strpos($sql, $this->_table) === false) continue;
$sqlStr == '' || array_push($sqlArr, $sqlStr);
$sqlStr = $match ? trim(substr($sql, 3, -1)) . " " : "";
} elseif (strpos($sql, '@') !== false || strpos($sql, 'SET')) {
$sqlStr .= trim(substr($sql, 3, -1)) . " ";
}
}
$sqlStr == '' || array_push($sqlArr, $sqlStr);
} else {
# statement 和 mixed格式一样
while (($sql = fgets($fillFileHandler)) !== false) {
$sql = trim($sql);
if (preg_match('/(UPDATE|INSERT|DELETE)\s+/', $sql)) {
array_push($sqlArr, $sql);
}
}
}
$sqlArr = array_map(function ($value) {
return preg_replace_callback('/(@(\d+))/', function ($matches) use ($value) {
$parts = explode('.', $value);
return $this->getTableColumns(explode('`', array_pop($parts))[1])[$matches[2] - 1];
}, $value);
}, $sqlArr);
$mysqlFile = Util::getFile(__DIR__ . '/data/mysql.sql');
array_map(function ($value) use ($mysqlFile) {
file_put_contents($mysqlFile, $value . PHP_EOL, FILE_APPEND);
}, $sqlArr);
fclose($fillFileHandler);
return $this;
}
/**
* @param $table
* @return array
*/
protected function getTableColumns($table)
{
if (array_key_exists($table, $this->_tableColumns))
return $this->_tableColumns[$table];
$tableInfo = $this->select("show full columns from $table");
if (empty($tableInfo)) Util::dd("$table 不存在");
return $this->_tableColumns[$table] = array_column($tableInfo, 'Field');
}
其中有三个主要的方法,selectFromBinLog用于执行mysqlbinlog,用于提取我们所需要的DDL,parseSql用于解析我们提取出来的sql,getTableColumns用于获取表的字段(主要是针对row模式下的@1,@2之类)。
当我们执行Binlog.php的start方法之后,就可以把DDL写入到'./data/mysql.sql'中了,非常方便。

如何通过binlog获取我们想要的MySql语句?的更多相关文章
- 答:SQLServer DBA 三十问之六:Job信息我们可以通过哪些表获取;系统正在运行的语句可以通过哪些视图获取;如何获取某个T-SQL语句的IO、Time等信息;
6. Job信息我们可以通过哪些表获取:系统正在运行的语句可以通过哪些视图获取:如何获取某个T-SQL语句的IO.Time等信息: 我的MSDB数据库中有全部的表: sys.all_columns,s ...
- PHP获取当前服务器信息的基本语句
下面是PHP获取当前服务器信息的基本语句. PHP程式版本: <?PHP echo PHP_VERSION; ?> ZEND版本: <?PHP echo zend_version() ...
- Yii2获取当前程序执行的sql语句
1.Yii2获取当前程序执行的sql语句: $query = model::find(); $dataProvider = new ActiveDataProvider([ ...
- 如何获取自己想要模拟的APP的相关图片?
一.首先打开iTunes APP,找到自己想要模拟实现的APP,并下载 二.找到下载的APP在iTunes中的位置 三.选中对应的APP,点击右键选择在Finder中显示,会打开对应的文件窗口,打开对 ...
- 百度地图sdk sha1秘钥获取有种想吐的赶脚
撸代码坐的腰算背疼还只是弄一个不是项目里边需要的升级版本的so 日 需要sha1 指纹秘钥,还有项目包, 才能用百度地图sdk 这个找sha1 获取废了20分钟, 显示全盘找keytool.exe ...
- iOS 在不添加库的情况下 通过抽象类来获取自己想要的方法
#define SYSTEM_VERSION_MORE_THAN_BFDATA(v) ([[[UIDevice currentDevice] systemVersion] compare:v opti ...
- 引人遐想,用 Python 获取你想要的 “某个人” 摄像头照片
仅用来学习,希望给你们有提供到学习上的作用. 1.安装库 需要安装python3.5以上版本,在官网下载即可.然后安装库opencv-python,安装方式为打开终端输入命令行. 2.更改收件人和发件 ...
- AFLW如何获取你想要的21点人脸关键点数据
目前人脸检测和人脸的关键点的数据库根据关键点个数:5,20,21,29,68等.https://blog.csdn.net/XZZPPP/article/details/74939823该网页详细列出 ...
- Oracle获取干净的建表DDL语句,不含其它存储、表空间、段属性
早上一个同事资讯怎么获取到建表语句而且是不带存储那种SQL.Oracle自己提供了一个函数DBMS_METADATA.GET_DDL,但是获取到的建表语句含有存储.表空间.以及一些其他段的属性.如图: ...
随机推荐
- java wait 和notify
这几天自己学习了一下线程的知识,wait 方法使当前的线程等待,notify 方法 唤醒当前的线程的方法 th 线程在5的时候进行wait,此时主线程继续执行, 主线程执行到9的时候 唤醒 th 线程 ...
- MVP架构
一.介绍 MVP(Model View Presenter)架构是从著名的MVC(Model View Controller)架构演变而来的.对于在Android应用中开发就可以视为是MVC架构,布局 ...
- textarea禁止拖拽
<textarea style="resize:none;" ></textarea>'
- 【Android Developers Training】 101. 显示快速联系人挂件(Quick Contact Badge)
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- C++ inline函数与编译器设置
1. 经过测试#define与inline的速度几乎没有区别. 2. inline函数更为安全,有效避免了#define二义性问题.inline是真正的函数,而#define只是在字符串意义上的宏替换 ...
- Educational Codeforces Round 23.C
C. Really Big Numbers time limit per test 1 second memory limit per test 256 megabytes input standar ...
- Maven pom.xml配置详解
POM的全称是“ProjectObjectModel(项目对象模型)”. 声明规范 <projectxmlns="http://maven.apache.org/POM/4.0.0&q ...
- Bootstrap模态弹出框
前面的话 在 Bootstrap 框架中把模态弹出框统一称为 Modal.这种弹出框效果在大多数 Web 网站的交互中都可见.比如点击一个按钮弹出一个框,弹出的框可能是一段文件描述,也可能带有按钮操作 ...
- Java xml 解析
1. XML框架结构 Java SE 6 平台提供的 XML 处理主要包括两个功能:XML 处理(JAXP,Java Architecture XML Processing)和 XML 绑定(JAXB ...
- 【SqlServer系列】开启Sqlserver远程访问
1 概述 已发布[SqlServer系列]文章如下: [SqlServer系列]SQLSERVER安装教程 [SqlServer系列]数据库三大范式 [SqlServer系列]表单查询 [SqlS ...