博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何通过binlog获取我们想要的MySql语句?
阅读量:5251 次
发布时间:2019-06-14

本文共 3257 字,大约阅读时间需要 10 分钟。

前言

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

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

d9630274-0be7-465a-8a0d-46dbe3d2441a.png

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

f764edef-7cbd-421a-a6ea-d468aa803353.png

于是,我写了一个的初级版本,来实现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'中了,非常方便。

99b20b6e-d44e-4838-9827-e7c02d3fd69e.png

转载于:https://www.cnblogs.com/nineyang/p/7323878.html

你可能感兴趣的文章
国外常见互联网盈利创新模式
查看>>
Oracle-05
查看>>
linux grep 搜索查找
查看>>
Not enough free disk space on disk '/boot'(转载)
查看>>
android 签名
查看>>
vue项目中使用百度统计
查看>>
android:scaleType属性
查看>>
SuperEPC
查看>>
mysql-5.7 innodb 的并行任务调度详解
查看>>
shell脚本
查看>>
Upload Image to .NET Core 2.1 API
查看>>
Js时间处理
查看>>
Java项目xml相关配置
查看>>
三维变换概述
查看>>
第三次作业
查看>>
vue route 跳转
查看>>
【雷电】源代码分析(二)-- 进入游戏攻击
查看>>
Entityframework:“System.Data.Entity.Internal.AppConfig”的类型初始值设定项引发异常。...
查看>>
Linux中防火墙centos
查看>>
mysql新建用户,用户授权,删除用户,修改密码
查看>>