首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Drupal 7 多數據庫連接配置與常見問題排查指南

     編輯:PHP 相關知識

Drupal 7 支持同時連接多個數據庫,但配置不當易導致「表不存在」「數據寫入錯誤庫」「連接交叉」等疑難雜症。本文系統梳理配置方法、切換機制、常見坑點與解決方案。

一、配置多數據庫連接

在 settings.php 中將 $db_url 定義為關聯數組:

$db_url['default'] = 'mysql://user:pass@localhost/drupal_main';
$db_url['external'] = 'mysql://user:pass@localhost/external_db';
$db_url['legacy']  = 'pgsql://user:pass@localhost/legacy_data'; // 支持不同驅動

二、運行時切換活躍連接

<?php
// 切換到 external 數據庫
db_set_active('external');

// 執行查詢(使用 external 連接)
$result = db_query("SELECT * FROM {external_table} WHERE id = :id", [':id' => 123]);

// 重要:用完立即切回默認連接!
db_set_active('default');

關鍵原則:

  • 成對調用: 每個 db_set_active('xxx') 必須配對 db_set_active('default')
  • 異常安全: 用 try/finally 確保切回
  • 嚴禁嵌套: 避免在未切回時再次切換,導致連接棧混亂
// 安全模式
db_set_active('external');
try {
  // ... 數據庫操作 ...
} finally {
  db_set_active('default');
}

三、常見問題與解決方案

1. 連接交叉:查詢在錯誤數據庫執行

現象: SQL 語法正確但報「Table 'main_db.external_table' doesn't exist」

原因: 忘記 db_set_active('default'),後續代碼仍在 external 連接上執行

排查: 搜索代碼中所有 db_set_active,確保成對出現,異常路徑也覆蓋

2. 表前綴與跨庫查詢

Drupal 通過 {table_name} 自動添加前綴,但前綴綁定於當前活躍連接的配置。

// 正確:在 external 連接下,{users} 解析為 external_db.prefix_users
db_set_active('external');
db_query("SELECT * FROM {users}"); // 使用 external 的前綴配置

// 錯誤:在 default 連接下查 external 表
db_set_active('default');
db_query("SELECT * FROM {external_table}"); // 解析為 main_db.prefix_external_table → 不存在

3. 共享用戶表:$db_prefix 跨庫映射

多站點共用用戶表時,在 settings.php 配置前綴映射:

$db_prefix = array(
  'default'       => '',           // 主站表無前綴
  'users'         => 'shared.',    // users 表指向 shared_db.shared_users
  'sessions'      => 'shared.',
  'role'          => 'shared.',
  'users_roles'   => 'shared.',
  // 格式:'表名' => '數據庫名.前綴' 或 '前綴'
);

效果: 所有站點操作 {users} 實際讀寫 shared_db.shared_users,實現單點登錄 (SSO) 基礎。

4. 直接指定數據庫.表名(繞過前綴系統)

// 明確指定 external_db 表
db_query("SELECT uid FROM external_db.z_table WHERE name = :name", [':name' => 'admin']);
// 注意:不使用 {table} 語法,直接寫死庫.表

5. 模塊/函數級臨時添加連接

function mymodule_external_operation() {
  global $db_url; // 必須 global 聲明
  
  // 動態添加連接(僅當前請求有效)
  $db_url['temp_log'] = 'mysqli://log_user:pass@log_host/log_db';
  
  db_set_active('temp_log');
  try {
    db_insert('access_log')->fields([...])->execute();
  } finally {
    db_set_active('default');
  }
}

四、最佳實踐清單

  1. 封裝切換邏輯: 創建服務類 DatabaseSwitcher 統一管理 setActive()/restore()
  2. 異常安全: 所有切換操作包裝在 try/finally 中
  3. 連接命名規範: 使用語義化鍵名(external, legacy, analytics)而非 db1, db2
  4. 文檔記錄: 模塊 README 列明依賴的外部數據庫連接鍵名
  5. 測試覆蓋: 單元測試 Mock db_set_active 驗證切換邏輯

五、Drupal 8/9/10 遷移提示

  • 服務容器管理連接:\Drupal::service('database')->getConnection('external')
  • 不再有全局 db_set_active(),改用 $connection = \Drupal::database('external'); $connection->query(...)
  • 設定檔 settings.php 中 $databases 陣列結構變更

規範管理多數據庫連接,是構建穩健 Drupal 多系統集成應用的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved