2017-07-30 63 views
4

有一個名爲function.php的文件,我打電話到我的網站的所有頁面require_once。該文件包含超過一百個函數。如何在PHP中處理太多的數據庫連接而不增加最大連接數?

我從mysqli_connect(),右max_user_connections錯誤表明

mysqli_query() expects parameter 1 to be mysqli, boolean given

錯誤後,當有太多的遊客或搜索引擎機器人爬行快。

功能文件是這樣的:

<?php 
function db_connect(){ 
    $link=mysqli_connect("host","dbuser","dbpass","dbname"); 
    if (mysqli_connect_errno()) { 
     echo "Failed to connect to MySQL: " . mysqli_connect_error(); 
    } 
    mysqli_query($link,"set names 'utf8'"); 
} 

db_connect(); 

function func_1(){ 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 

function func_2(){ 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 

. 
. 
. 

function func_100(){ 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 
?> 

最後我關閉數據庫連接。因爲我已經檢查了每個用戶的最大連接數,我的數據庫是50,主機提供商不會改變它(這就足夠了,他們說)。

那麼,一般如何處理這個問題呢? (簡單的PHP或OOP)

+0

我不知道發生了什麼問題 - 我懷疑錯誤是在你沒有向我們顯示的代碼的某個部分 - ,但是你的'db_connect'函數將一個連接分配給一個局部變量,然後永遠不會傳遞出來。這會燒你的地方! –

+0

對不起,我忘了。我在需要的代碼中使用「全局$鏈接」。它通常工作正常,但有時我得到這個錯誤。 – Rasoul

回答

-1

你這裏有多種選擇:

首先,您使用的是$鏈接變量超出範圍。您可以使用此代碼修復它:

<?php 
$link = null; 
function db_connect(){ 
    global $link; 
    $link=mysqli_connect("host","dbuser","dbpass","dbname"); 
    if (mysqli_connect_errno()) { 
     echo "Failed to connect to MySQL: " . mysqli_connect_error(); 
    } 
    mysqli_query($link,"set names 'utf8'"); 
} 

db_connect(); 

function func_1(){ 
    global $link; 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 

function func_2(){ 
    global $link; 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 

. 
. 
. 

function func_100(){ 
    global $link; 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 
?> 

第二:(如O.Jones所建議的)。你只依靠require_once。您可以檢查是否連接創建之前堅固,這一點:

if (!$link) db_connect(); 

(對於這種情況,獲得該文件之外聲明的$鏈接變量,一個總是叫一個)

三:PHP自動管理連接,並在最後一個字節提供給客戶端後銷燬。也許,如果你在不再需要的時候用mysqli_close函數自己關閉連接,你可以解決問題。你可以在這裏查看關於如何使用這個功能的文檔:http://php.net/manual/en/mysqli.close.php

如果問題仍然存在,也許你需要使用持久連接,從你的php到你的數據庫的連接較少。您可以通過「p:」(不帶引號)來實現這一功能。例如,連接到sql.myserver.com,你需要使用:

$link=mysqli_connect("p:sql.myserver.com","dbuser","dbpass","dbname"); 

你能得到關於與PHP手冊中的mysqli此頁面上的持久連接的詳細信息:http://php.net/manual/en/mysqli.persistconns.php

+0

'global'是一個[糟糕的解決方案](https://stackoverflow.com/documentation/php/194/variables/2496/global-variable-best-practices) – Machavity

+0

爲什麼是-1?也許全球並不是更好的選擇,但至少是沒有重做所有代碼的解決方案。如果您有更好的選擇,請發佈它。我可以學習它。但是,對於一個沒有建設性的批評者,我不能再學習或解決這個問題。 –

+0

因爲你正在傳播一種糟糕的代碼方式。如果某人在其他地方使用'$ link'會怎麼樣?你的代碼突然停止工作。你還建議一些其他不好的:持續連接。從經驗來看,持久性不會在終止時釋放,這對於網站來說是一件壞事。這樣做實際上會加劇問題,因爲PHP仍然會在持久化之上創建**新**連接。 – Machavity

0

你顯然在處理每個網頁請求的過程中,打開多個到您的MySQL服務器的連接。

在您的代碼文件中定義了db_connect()函數之後,即可調用該函數。這可能會導致它被稱爲比必要的更頻繁。每次調用它時,它都會從連接池中消耗稀缺資源。

取而代之,請執行一些操作以確保該函數一次由代碼處理每個頁面調用。最好將MySQL連接作爲處理邏輯的一部分,而不是依靠require_once來完成。確保在完成使用後關閉打開的連接。

當你確定你必須在每個頁面打開正在處理最多一個MySQL連接,那麼你可能需要減少 PHP文件,你的Web服務器可以同時處理的數量。這可以通過調整Apache Web服務器參數MaxClients和/或MaxRequestsPerChild來完成。另一個流行的Web服務器nginx具有相似的參數。減少此容量不會損害用戶,因爲Web服務器處理來自隊列的頁面請求。

+0

他們可以使用類似if(!$ link)的東西來避免創建多個連接,但是如果他們真的只使用require_once,那不是問題。但是,這是一個更好的編碼的好點,我增加了我的迴應。 –

0

如果由於無效原因導致連接數太多,請修復它。看看連接何時關閉以及如何進行。看看連接的持久性。如果確定這些都沒問題,那麼你有太多的連接,那麼你可能需要在一個支持它的環境中爲你的服務器開發一個多線程的獨立應用程序,並在那裏使用10個持久連接線程。此應用程序將使用一個隊列來知道需要從數據庫中詢問什麼,以及在工作線程完成進程,獲取結果,將其發送給請求者並繼續下一項從隊列中。

0

我會變鈍的。因爲這裏沒有編碼解決方案

因爲我已經檢查了每個用戶對於我的數據庫的最大連接數是50,主機提供商不會改變它(這就足夠了,他們說)。

我懷疑你是在一些便宜/免費的託管解決方案,他們可以保持廉價/免費,因爲他們油門你。 50對於比較流行的個人Wordpress站點(例如每天1000次訪問)來說是很好的選擇。但是超出這一點很容易。 PHP正在創建超過50個併發連接。這是一個資源問題,你只能通過增加可用連接數來解決它。

由於您當前的主機不會這樣做,您需要移動到可以的位置。無論是或者接受你的一些訪問者不會得到他們期待的網頁。

+0

你是對的,但它不是很便宜的主機(不適合我!!)。我只是爲目前的情況尋找最佳解決方案。 – Rasoul

+0

你好@Machavity ...請問,你能解釋一下我,爲什麼你要刪除我回答過的編輯問題中的所有「訂單」標籤? … 有什麼不對? ...謝謝 – LoicTheAztec

+0

@LoicTheAztec https://meta.stackoverflow.com/a/324444/2370483 – Machavity

0

使用singleton可以只爲$link或全部function.php

0

我想補充的方法getLink您在所有查詢中使用呼籲:

function getLink() { 
    static $link; 

    if(! $link) 
     $link = db_onnection() ; 

    return $link; 
} 

,然後在查詢:

mysqli_query(getLink(), "SELECT id,..."); 

此外,這是單例模式這是一個變化反模式!