當前位置:
首頁 > 知識 > 如何通過binlog獲取我們想要的MySql語句?

如何通過binlog獲取我們想要的MySql語句?

前言

MySqlbinlog一般用於我們對數據的恢復,以及從資料庫對主資料庫的複製和更新。

假設此時我們有一個需要查詢和讀取Mysql最近操作DDL的信息,我們需要怎麼處理?

聰明的你可能已經想到了,我們可以使用mysqlbinlog工具讀取啊!的確,mysqlbinlog對於statement或者mixed格式的binlog文件確實會很方便讀取,但是你要知道,從Mysql5.7.7開始,row就是默認的binlog_format,此時我們再要去直接通過肉眼去看,恐怕就不是那麼容易了。

如何通過binlog獲取我們想要的MySql語句?

即使我們在通過mysqlbinlog解析時加上-v參數,也只能顯示出這樣的效果:

如何通過binlog獲取我們想要的MySql語句?

於是,我寫了一個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語句?

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

js數組去重方法分析與總結
JS獲取子、父、兄節點方法總結
vue學習筆記(1)——組件化實現todoList
mysql中varchar和char區別
隨筆-64 文章-0 評論-26

TAG:科技優家 |

您可能感興趣

想要開心起來就聽她的歌—Meghan Trainor
新一季的 Stella McCartney x adidas 跑鞋來了!男生看完都想要!
想要Angelababy的微笑唇?不用手術就可以!
我想要兩顆西柚。什麼?I want to see you
想要易烊千璽同款Style?這雙Pharrell x adidas Tennis Hu讓你 「爆紅」 !
Adrianne Ho 近期上腳的 adidas 新鞋,是不是你想要的那雙?
蘋果:想要用HomePod?先買台iPhone吧!
想要!最新Baselworld表款願望清單
點餐英語-我想要一張六人桌,並不是I need a six people table
4月不防晒還想要美白?Are you dreaming?
關於Gucci你想要的可能不只是他們家的logoT哦
I wanna+我想要……
想要的全給你!最適合用來記錄生活的——Gopro Hero 6 Black
僅在紐約再次發售!想要入手 adidas Futurecraft 4D 真的難!
那麼實穿又個性 Michael Kors太知道女人想要的衣櫥了
官圖曝光!你們都想要的 Nike Zoom Kobe 1 Protro 下周發售!
這就是我想要的iPhone X Plus,可摺疊可彎曲
冬季穿搭想要簡潔又精緻,那跟Olivia Palermo學起來
你肯定想要的黑金 Nike Kobe 1 Protro,德羅贊上腳了!
Henry劉憲華Monster歌詞欣賞 想要讓你依賴卻再給你傷害