前言

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. SSH连接不上CentOS 主机配置文件导致的原因的解决方法

    一.CentOS之SSH的安装与配置 SSH 为 Secure Shell 的缩写,由 IETF 的网络工作小组(Network Working Group)所制定SSH 为建立在应用层和传输层基础上 ...

  2. 自己动手写一个自动登录脚本gg

    1.下载一个sshpass工具 2.安装sshpass,安装到tools文件夹 3.把tools文件夹的路径加入到/etc/bashrc vim   /etc/bashrc 最后一行  : expor ...

  3. textarea禁止拖拽

    <textarea style="resize:none;" ></textarea>'

  4. svg制作风车旋转

    首先用ai画一个简单的风车 例如: svg代码: <animateTransform attributeName="transform" begin="0s&quo ...

  5. 闭包中this指向window的原因

    var t={ b:1, w:function a(){ var b=2; alert(this.b); //弹出t对象的b属性 alert(b); //弹出a函数的b变量 return functi ...

  6. jQuery与原生js实现banner轮播图

    jQuery与原生js实现banner轮播图: (jq需自己加载)(图片需自己加载) <!DOCTYPE html> <html> <head> <meta ...

  7. Js作用域&作用域链

    js构建类 一 构建类的原则 构造函数 等于 原型的constructor //构造函数 function Hero(name,skill){ this.name = name; this.skill ...

  8. java的多线程初体验

    这里以车站售票作为模拟场景,多个票务人员同时出售某一列高铁(G250?)的车票,售票的基本保证有2点: 1.不能售出多于预定限额的车票. 2.不能售出具有相同座位的车票. 初学java,有不当的地方各 ...

  9. usaco training 4.2.2 The Perfect Stall 最佳牛栏 题解

    The Perfect Stall题解 Hal Burch Farmer John completed his new barn just last week, complete with all t ...

  10. vijos1080题解

    题目: 对于一个递归函数w(a,b,c) 如果a<=0 or b<=0 or c<=0就返回值1. 如果a>20 or b>20 or c>20就返回w(20,20 ...