dbstuff 是 UCHome (Comsenz) 早期版本使用的 MySQL 封裝類,基於 mysql_* 扩展,提供連接管理、查詢執行、結果集獲取、調試統計、錯誤處理等核心功能。代碼風格典型的「單文件萬能類」,適合快速開發,但存在明顯技術債務。
function connect($dbhost, $dbuser, $dbpw, $dbname='', $pconnect=0, $halt=TRUE) {
if ($pconnect) {
$this->link = @mysql_pconnect($dbhost, $dbuser, $dbpw); // 持久連接
} else {
$this->link = @mysql_connect($dbhost, $dbuser, $dbpw, 1); // 第4參數 new_link=true,強制新連接
}
if (!$this->link) $halt && $this->halt('Can not connect to MySQL Server');
// MySQL 4.1+ 字符集設置
if ($this->version() > '4.1') {
if ($this->charset) {
@mysql_query("SET character_set_connection=$this->charset, character_set_results=$this->charset, character_set_client=binary", $this->link);
}
if ($this->version() > '5.0.1') {
@mysql_query("SET sql_mode=''", $this->link); // 關閉嚴格模式,兼容舊代碼
}
}
if ($dbname) @mysql_select_db($dbname, $this->link);
}
關鍵點:
-mysql_pconnect進程級連接復用,需配合 Apache Prefork MPM,PHP-FPM 不支援。
-character_set_client=binary避免客戶端編碼干擾,由服務端按connection/results轉碼。
-sql_mode=''關閉 ONLY_FULL_GROUP_BY 等嚴格檢查,**隱患:數據完整性保護失效**。
function query($sql, $type='') {
if (D_BUG) { // 常量開關
$sqlstarttime = microtime(true) * 1000;
}
$func = ($type == 'UNBUFFERED' && function_exists('mysql_unbuffered_query'))
? 'mysql_unbuffered_query' : 'mysql_query';
if (!($query = $func($sql, $this->link)) && $type != 'SILENT') {
$this->halt('MySQL Query Error', $sql);
}
if (D_BUG) {
$sqlendtime = microtime(true) * 1000;
$sqltime = round($sqlendtime - $sqlstarttime, 3);
$explain = [];
if ($query && preg_match('/^(select )/i', $sql)) {
$explain = mysql_fetch_assoc(mysql_query('EXPLAIN '.$sql, $this->link));
}
$_SGLOBAL['debug_query'][] = [
'sql' => $sql, 'time' => $sqltime,
'info' => mysql_info(), 'explain' => $explain
];
}
$this->querynum++;
return $query;
}
亮點:
-UNBUFFERED模式適用於大結果集流式讀取,避免記憶體暴漲。
- 自動EXPLAINSELECT 語句,開發期即時發現全表掃描。
- 統計querynum、耗時、mysql_info(),構建簡易 APM。
function halt($message='', $sql='') {
$dberror = $this->error();
$dberrno = $this->errno();
$help_link = "https://faq.comsenz.com/?type=mysql&dberrno=".rawurlencode($dberrno)."&dberror=".rawurlencode($dberror);
echo "";
exit();
}
fetch_array($query, MYSQL_ASSOC):預設關聯數組。affected_rows()、insert_id():寫入確認必備。free_result():釋放記憶體,防洩漏。version():獲取服務端版本,驅動兼容判斷依據。| 問題 | 風險等級 | 建議修復 |
|---|---|---|
使用已棄用 mysql_* 扩展 | 🔴 高 | 全量遷移至 PDO / MySQLi,啟用預處理防注入 |
@ 抑制錯誤,配合 halt() 強制退出 | 🟠 中 | 改用異常處理,區分可恢復/不可恢復錯誤 |
SET sql_mode='' 關閉嚴格模式 | 🔴 高 | 修正不兼容 SQL,保持嚴格模式開啟 |
mysql_pconnect 在 PHP-FPM 下無效甚至洩漏連接 | 🟠 中 | 移除持久連接選項,使用連接池中間件 |
EXPLAIN 自動執行可能加重主庫負載 | 🟡 低 | 僅開發環境開啟,生產關閉 D_BUG |
| 無預處理介面,SQL 拼接風險極大 | 🔴 高 | 新增 prepare()/execute() 方法 |
單例/全局變量 $_SGLOBAL 耦合調試數據 | 🟡 低 | 注入 Logger 介面,解耦 |
PDOInterface 兼容層,逐步替換調用點。Read/Write Connection Pool(如 ProxySQL、PHP 連接池)。QueryBuilder 產出 SQL + 參數,Executor 執行。DBConnectionException、DBQueryException、DBConstraintException。dbstuff 是 Discuz!/UCHome 早期生態的縮影:**功能完備、調試貼心、但緊耦合 mysql_* 扩展、缺乏預處理、錯誤處理粗暴**。對於存量項目,建議**凍結功能、僅做安全修補**,新業務模塊**強制使用 PDO/MySQLi + 預處理 + 連接池**,逐步完成技術棧現代化。