前言

MySqlbinlog一般用于我们对数据的恢复,以及从数据库对主数据库的复制和更新。

假设此时我们有一个需要查询和读取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,用于提取我们所需要的DDLparseSql用于解析我们提取出来的sqlgetTableColumns用于获取表的字段(主要是针对row模式下的@1,@2之类)。

当我们执行Binlog.phpstart方法之后,就可以把DDL写入到'./data/mysql.sql'中了,非常方便。

如何通过binlog获取我们想要的MySql语句?的更多相关文章

  1. 答:SQLServer DBA 三十问之六:Job信息我们可以通过哪些表获取;系统正在运行的语句可以通过哪些视图获取;如何获取某个T-SQL语句的IO、Time等信息;

    6. Job信息我们可以通过哪些表获取:系统正在运行的语句可以通过哪些视图获取:如何获取某个T-SQL语句的IO.Time等信息: 我的MSDB数据库中有全部的表: sys.all_columns,s ...

  2. PHP获取当前服务器信息的基本语句

    下面是PHP获取当前服务器信息的基本语句. PHP程式版本: <?PHP echo PHP_VERSION; ?> ZEND版本: <?PHP echo zend_version() ...

  3. Yii2获取当前程序执行的sql语句

    1.Yii2获取当前程序执行的sql语句: $query = model::find();         $dataProvider = new ActiveDataProvider([       ...

  4. 如何获取自己想要模拟的APP的相关图片?

    一.首先打开iTunes APP,找到自己想要模拟实现的APP,并下载 二.找到下载的APP在iTunes中的位置 三.选中对应的APP,点击右键选择在Finder中显示,会打开对应的文件窗口,打开对 ...

  5. 百度地图sdk sha1秘钥获取有种想吐的赶脚

    撸代码坐的腰算背疼还只是弄一个不是项目里边需要的升级版本的so 日 需要sha1 指纹秘钥,还有项目包, 才能用百度地图sdk 这个找sha1  获取废了20分钟, 显示全盘找keytool.exe ...

  6. iOS 在不添加库的情况下 通过抽象类来获取自己想要的方法

    #define SYSTEM_VERSION_MORE_THAN_BFDATA(v) ([[[UIDevice currentDevice] systemVersion] compare:v opti ...

  7. 引人遐想,用 Python 获取你想要的 “某个人” 摄像头照片

    仅用来学习,希望给你们有提供到学习上的作用. 1.安装库 需要安装python3.5以上版本,在官网下载即可.然后安装库opencv-python,安装方式为打开终端输入命令行. 2.更改收件人和发件 ...

  8. AFLW如何获取你想要的21点人脸关键点数据

    目前人脸检测和人脸的关键点的数据库根据关键点个数:5,20,21,29,68等.https://blog.csdn.net/XZZPPP/article/details/74939823该网页详细列出 ...

  9. Oracle获取干净的建表DDL语句,不含其它存储、表空间、段属性

    早上一个同事资讯怎么获取到建表语句而且是不带存储那种SQL.Oracle自己提供了一个函数DBMS_METADATA.GET_DDL,但是获取到的建表语句含有存储.表空间.以及一些其他段的属性.如图: ...

随机推荐

  1. ASP.NET MVC5(五):身份验证、授权

    使用Authorize特性进行身份验证 通常情况下,应用程序都是要求用户登录系统之后才能访问某些特定的部分.在ASP.NET MVC中,可以通过使用Authorize特性来实现,甚至可以对整个应用程序 ...

  2. supervisor 安装配置

    Supervisor介绍 Supervisor 允许其用户在UNIX类操作系统上控制多个进程. 块如下: 方便 需要为每个进程实例编写rc.d脚本通常是不方便的. rc.d脚本是进程初始化/自动启动/ ...

  3. WebService小记

    这个问题找了好多地方都没有结果,自己暂且总结一下吧,也不算是解决问题的根本途径,但是也不失为一种办法.当时用了wsimport  wsdl2java xfire 都没有解决,大牛能解决的话,欢迎留言. ...

  4. laravel中token的使用方式

    在form表单里提交表单时,可 <form action="" method="post"> <?php  echo csrf_field() ...

  5. java中打印输出数组

    import java.util.Arrays; public class ArrayDemo { public static void main(String[] args) { int size ...

  6. 【LeetCode】206. Reverse Linked List

    题目: Reverse a singly linked list. 提示: 此题不难,可以用迭代或者递归两种方法求解.记得要把原来的链表头的next置为NULL: 代码: 迭代: /** * Defi ...

  7. 【CC2530入门教程-06】CC2530的ADC工作原理与应用

    第6课  CC2530的ADC工作原理与应用 广东职业技术学院  欧浩源 一.A/D转换的基本工作原理 将时间上连续变化的模拟量转化为脉冲有无的数字量,这一过程就叫做数字化,实现数字化的关键设备是AD ...

  8. Linux系统网卡设置

    由于做了虚拟机的克隆,发现克隆机和被克隆机的MAC地址相同了,下面我将要介绍一下linux中网卡的配置步骤,我使用的linux是CentOS release 6.9 (Final) 1.root用户编 ...

  9. Asp.net MVC-3-执行过程

    本篇主要讲述MVC处理请求时创建Controller和执行Action的完整过程. 创建Controller 先查看MvcHandler中处理请求的方法BeginProcessRequest: pro ...

  10. MySQL实现自动使用uuid作为主键以及解决不能调用触发器的一点思路

    这里使用触发程序实现此功能. 触发程序语法如下: Create trigger <tri_name> {before|after} {insert|update|delete} On &l ...