再來還些債…
前陣子我們家在看一些 PHP 的版本差異,也順便拆一些地雷。
先說記憶體耗用,我們用下面這段程式在一些 PHP 版本上執行,觀察記憶體耗用:
<?php
$a = memory_get_usage();
echo "begin:\t$a" . PHP_EOL;
$arr = array();
for ( $i = 0; $i < 100000; $i++ ) {
array_push($arr, $i);
}
$b = memory_get_usage();
echo "end:\t$b" . PHP_EOL;
echo "diff:\t" . ($b - $a) . PHP_EOL;
在 PHP 5.1 ( on 32-bit Linux ) 觀察到的記憶體差距值大約是 5.8 MB,在 PHP 5.3 ~ 5.6 ( on 64-bit Linux ) 觀察到的記憶體差距值大約是 14 MB,而 PHP 7.1 ~ 7.2 ( on 64-bit Linux ) 觀察到的記憶體差距值大約是 4 MB。
至於 PHP 的 MySQL driver/library 方面…
參考官方提供的 Overview of the MySQL PHP drivers : Buffered and Unbuffered queries ;PHP 的所有的 MySQL extensions 預設使用 buffered mode,所以在撈取大量資料時,PHP 執行完 SQL statement 就會耗用大量記憶體。
另外,在官方提供的 Overview of the MySQL PHP drivers : Choosing a library 可以看到,PHP 5.3 以前的預設 MySQL driver ( libmysqlclient ) 沒使用 PHP 的原生記憶體管理,PHP 5.3 之後的預設 MySQL driver ( mysqlnd; MySQL Native Driver) 才開始用。
對這些行為,我們另外生了一段測試程式:
<?php
$a = memory_get_usage();
echo "begin:\t\t$a" . PHP_EOL;
$dbConn = new PDO(.....);
$b = memory_get_usage();
echo "new PdoMySQL:\t$b\t\tDiff: " . ($b - $a) . PHP_EOL;
$st = $dbConn->query("SELECT * FROM testTable LIMIT 30000");
$b = memory_get_usage();
echo "get Stmt:\t$b\tDiff: " . ($b - $a) . PHP_EOL;
$row1 = $st->fetch();
$b = memory_get_usage();
echo "fetch once:\t$b\tDiff: " . ($b - $a) . PHP_EOL;
$row2 = $st->fetch();
$b = memory_get_usage();
echo "fetch twice:\t$b\tDiff: " . ($b - $a) . PHP_EOL;
$st->closeCursor();
$b = memory_get_usage();
echo "closeCursor:\t$b\t\tDiff: " . ($b - $a) . PHP_EOL;
$row3 = $st->fetch();
$b = memory_get_usage();
echo "fetch:\t\t$b\t\tDiff: " . ($b - $a) . PHP_EOL;
var_dump($row3);
在 PHP 7.1 ( with mysqlnd , 64-bit Linux ) 的數據如下:
begin: 355552
new PdoMySQL: 378784 Diff: 23232
get Stmt: 25866944 Diff: 25511392
fetch once: 25868752 Diff: 25513200
fetch twice: 25870568 Diff: 25515016
closeCursor: 384104 Diff: 28552
fetch: 384104 Diff: 28552
bool(false)
在 PHP 5.1 ( with libmysqlclient , 32-bit Linux ) 的數據則是:
begin: 50432
new PdoMySQL: 85752 Diff: 35320
get Stmt: 92184 Diff: 41752
fetch once: 93584 Diff: 43152
fetch twice: 95248 Diff: 44816
closeCursor: 95312 Diff: 44880
fetch: 95400 Diff: 44968
bool(false)
應該有為數不少的 PHP developers 曾經踩過這種記憶體相關的地雷…
5 月 14 2023
Percona XtraBackup 8.0.32 released
其實 Percona XtraBackup 8.0.32 最初在 2023 年 2 月就有釋出,只是一直在忙,就沒寫 blog;最近處理了幾台 MySQL server,順道提一下…
特別寫這篇是因為 8.0.32-25 的 release note 有這段(我認為它很重要):
簡單說… 就是:「若 MySQL server 的版本已更新為 8.0.32,又使用 Percona XtraBackup 作備份,請搭配 8.0.32-25 版」
主因如下…
MySQL server 自 8.0.29 之後支援以下這組語法,若沒指定 ALGORITHM,預設就會是 INSTANT:
(ADD COLUMN 自 8.0.12 就開始支援,也成為預設;兩者在未調整前的預設 ALGORITHM 都是 INPLACE)
這樣的調整導致 Percona XtraBackup 在做備份時出錯,於是便有了 Percona XtraBackup 8.0.29 and INSTANT ADD/DROP Columns 這篇文章;我在留言處有留下解決方式(用 pt-online-schema-change)。
目前 MySQL server 的最新版本是 8.0.33,而 Percona XtraBackup 則是 8.0.32-26;目前這樣的搭配運作正常。
By Joe Horn • Database 0 • Tags: MySQL, Percona Toolkit, Percona XtraBackup