C實現PHP的mysql資料庫連線池
阿新 • • 發佈:2019-02-07
一、導語
連線池在JAVA中應用的很廣泛,而在PHP中很少使用。 以Mysql為例,JAVA中使用連線池的原因之一是避免重複新建、釋放連線資源帶來的開銷。而在PHP中都是直連,因為這部分開銷對於C API而言效能上是沒有問題的。 那麼既然PHP直連已經沒有效能問題,那為何還要多次一舉開發mysql的資料庫連線池擴充套件呢?因為根本的目的是在於理解PHP的TS(Tthread Safe執行緒安全)與NTS(Not Thread Safe非執行緒安全)執行模式,而並非資料庫連線池這個功能。二、原理
連線池的基本思想是在系統載入時,初始化預設數量的連線物件儲存在記憶體中,當有客戶端需要訪問資料庫時,根據場景選擇是分配、新建、等待、失敗返回連線物件。使用完畢之後,連線將被重新放置回連線池中等待下一個請求的再分配,而不是釋放記憶體。 連線池中連線的建立、釋放都由連線池自身來管理,同時可以通過設定初始化最小連線數、最大連線數、最大空閒時間等來配置連線池。 注:在此擴充套件中,提供了最小連線數(min_connection)、最大連線數(max_connection)的設定三、實現思路
dbpools中的元素型別為
struct _mysql_node{
MYSQL *mysql;//連線資源控制代碼
int is_used;//標記是否被佔用
int result_id;//記錄my_mysql_query的查詢結果集
} mysql_node;
2.通過獲取配置檔案中設定的min_connection初始化dbpools3.定義全域性變數db_pools_length(目前擁有連結數)、db_pools_use_length(目前被使用的連結數),通過這兩個值來確定分配資源的情景
注:正因為使用全域性變數實現連線池,通過修改全域性變數的狀態來選擇資源連線,決定了該擴充套件必須執行在共享全域性變數的ZTS(Zend Thread Safe)執行緒安全模式下。(例如IIS或Apache MPM Worker模式)
如果希望支援多程序,可以通過程序間通訊來設定全域性變數,實現執行緒池。 實現思路圖:
四、理解PHP執行緒與程序的工作模式
(一)多程序工作模式 PHP的多程序工作模式以Apache apxs舉例。 apache啟動時,會fork出N個子程序用來等待接受處理客戶端的請求。程序之間相互隔離,全域性變數也無法直接訪問(可以通過程序間通訊訪問)。這樣的好處是能夠保證PHP環境的長時間穩定, 即使有部分程序因記憶體洩漏而崩潰也不會影響其他程序。由於PHP相當於粘合劑,它實際相當於集合多個庫的API,例如集合了libcurl、libmemcache、libzip等,要保證所有的庫都正常執行是比較困難的。 那麼為了保證PHP的高可靠性,這種多程序的模式就是首選。六、使用此擴充套件前提條件與方法
1.widnwos下IIS Server或Apache多執行緒模式,php5.3.* 2.修改php.ini,新增 [my_mysql]my_mysql.host = localhost
my_mysql.user = root
my_mysql.password =
my_mysql.port = 3306
my_mysql.max_connection = 200 //最大連線數
my_mysql.min_connection = 100 //預設最小連線數 看到這裡的配置,能看出來這個資料庫連線池擴充套件沒有實現多資料來源的連線池。因為目的不在連線池本身,所以也沒有特地去寫多資料來源的功能。 3.修改php.ini,新增 extension=php_my_mysql.dll 4.重啟apache server 七、相關下載
擴充套件測試結果
測試配置: [my_mysql]my_mysql.max_connection = 2 //最大連線數
my_mysql.min_connection = 1 //預設最小連線數 使用三個瀏覽器,執行下列測試指令碼:
<?php
/**
* 從資料庫連線池中取得一個連結資源
* 可能產生如下情景
* 1.如果有空閒連線則直接返回連結資源
* 2.如果沒有空閒連線,並且連線數沒有超過最大連線數,則擴充連線池並返回新建的連結資源
* 3.如果沒有空閒連線同時已經是最大連線數,則進入等待,超過1.5s仍沒有空閒資源則超時返回NULL.
*
* 失敗返回NULL
*/
$db = my_mysql_get_conn();
if($db === false){
exit('dbpool is exhushed.');
}
/**
* 選擇資料庫
* @param resource $db
* @param string $db_name 資料庫名稱
*/
my_mysql_select_db($db, 'test');
/**
* ping資料庫
*/
my_mysql_ping($db);
/**
* 執行SQL語句,可以執行INSERT、SHOW、SELECT、UPDATE、DELETE等語句
* @param resource $db
* @param string $sql SQL
*/
my_mysql_query($db, "INSERT INTO test VALUES(id, 'dbpool', 'test dbpool')");
// //獲取上一條INSERT語句返回的自增ID
$id = my_mysql_get_insert_id($db);
echo $id;
$result = my_mysql_query($db, "SELECT * FROM test");
/**
* 將查詢結果轉換為二維陣列
* @param resource $db
*/
$arr = my_mysql_fetch_assoc($result);
print_r($arr);
sleep(3);
var_dump($db);//sleep之後,必須輸出$db,否則會因為PHP的解析優化,sleep過程中已經將$db釋放,就沒有辦法測試連線被佔用的情況。
測試結果圖:
返回warning的,是由於連線池資源被佔用完,會進入等待。如果1.5s仍沒有等待到資源,則返回dbpool is exhushed。