架構選擇:三種連接方式對比
| 方式 | 架構 | 性能 | 適用場景 |
| UnixODBC + DB2 ODBC 驅動 | PHP → UnixODBC → DB2 ODBC → DB2 Server | 一般(雙層轉換) | 通用性最強,支持多種數據庫 |
| ibm_db2 擴展 | PHP → DB2 CLI 直接調用 | 優秀 | 專用 DB2 項目,功能最全 |
| PDO_ODBC + DB2 CLI | PHP → PDO → DB2 CLI | 良好 | 需要 PDO 抽象層的項目 |
方案一:編譯 PHP 統一 ODBC 擴展(--with-ibm-db2)
前置條件
- DB2 Client 9.7+ / Data Server Client
- DB2 實例環境變量已設置(`db2profile`)
- Apache 2.0+ / 2.2+ / 2.4+
編譯參數
./configure \
--with-apxs2=/usr/local/apache2/bin/apxs \
--with-ibm-db2=/opt/ibm/db2/V11.5 \
--enable-pdo \
--with-pdo-odbc=ibm-db2,/opt/ibm/db2/V11.5 \
--with-odbc=ibm-db2,/opt/ibm/db2/V11.5 \
...其他參數
make && make install
關鍵點
--with-ibm-db2 直接鏈接 DB2 CLI,**繞過 ODBC Driver Manager**,性能提升 20-30%
- 同時啟用
pdo_odbc 和 odbc 兩個擴展,均指向 DB2 CLI
- DB2 客戶端需包含 `sql.h`, `sqlext.h`, `db2cli.h` 頭文件
方案二:PDO_IBM / ibm_db2 擴展(現代推薦)
PECL 安裝
# ibm_db2 (原生 CLI)
pecl install ibm_db2
# PDO_IBM (PDO 接口)
pecl install PDO_IBM
php.ini 配置
extension=ibm_db2.so
extension=pdo_ibm.so
[ibm_db2]
ibm_db2.instance_name = DB2INST1
ibm_db2.database = SAMPLE
連接代碼最佳實踐
1. ibm_db2 連接
<?php
$conn = db2_connect('SAMPLE', 'db2inst1', 'password', [
'autocommit' => DB2_AUTOCOMMIT_ON,
'cursor' => DB2_SCROLLABLE, // 可滾動游標
]);
if (!$conn) {
die('連接失敗: ' . db2_conn_errormsg());
}
// 預處理語句
$stmt = db2_prepare($conn, 'SELECT * FROM users WHERE id = ? AND status = ?');
db2_execute($stmt, [1, 'active']);
while ($row = db2_fetch_assoc($stmt)) {
print_r($row);
}
db2_close($conn);
?>
2. PDO_IBM 連接
<?php
$dsn = 'ibm:DRIVER={IBM DB2 ODBC DRIVER};DATABASE=SAMPLE;HOSTNAME=192.168.1.100;PORT=50000;PROTOCOL=TCPIP;UID=db2inst1;PWD=password;';
try {
$pdo = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([1]);
$user = $stmt->fetch();
} catch (PDOException $e) {
error_log('DB2連接失敗: ' . $e->getMessage());
}
?>
性能優化關鍵點
| 問題 | 原因 | 解決 |
| 可滾動游標慢 | DB2 默認前向游標,滾動需臨時表 | 僅在必要時使用 DB2_SCROLLABLE,普通查詢用默認前向游標 |
| 存儲過程限制 | ODBC 對存儲過程參數支持有限 | 改用 ibm_db2 直接調用 db2_proc_call |
| 連接池缺失 | PHP 無內置連接池 | 使用持久連接 db2_pconnect 或外部池 |
| 大數據集內存溢出 | 一次性 fetch 所有行 | 分頁查詢 + 游標逐行處理 |
常見錯誤排查
<?php
// 診斷腳本
echo "DB2 CLI 版本: " . db2_client_info($conn)->DRIVER_VER . "\n";
echo "服務器版本: " . db2_server_info($conn)->DBMS_VER . "\n";
// 檢查驅動加載
php -m | grep -i db2
// 測試連接字符串
db2cli validate -dsn SAMPLE -connect -user db2inst1 -passwd password
遷移建議:從舊版本升級
- PHP 4 → 5/7/8:移除 `mysql_*` 改用 PDO/ibm_db2
- Apache 1.3 → 2.4:MPM 從 prefork 切換到 event/worker,需確保 DB2 CLI 線程安全
- DB2 V7/V8 → V11.5:利用純 XML 特性、JSON 函數、時間旅行查詢
- 32 位 → 64 位:重新編譯所有擴展,注意 `sqluint64` 類型變化
核心建議:**新項目首選 `ibm_db2` 或 `PDO_IBM`**,避開 UnixODBC 中間層,直接調用 DB2 CLI 獲得最佳性能與功能支持。