Post view

減少DolphinPro 7.3.3連接MySQL資料庫的次數

任何一個正式運作的網站,都不會在網站運作中,試著更改某些程式碼來測試某些新的功能,或是試圖解決某些問題、安全性漏洞等。都會在另外的「地下網站」或是「鏡像網站」來進行各種測試、開發。我們的insoler當然也不例外。

我在試著解決這兩個問題的時候:

修正升級到MySQL Community Server 5.7.17造成「照片檔名」排序錯誤的問題

修正DolphinPro 7.3.3某些PHP程式以「;;」雙分號結尾的錯誤

發現只有我一個人可以連上的「地下社群網站」,從MySQLWorkbench或是phpMyAdmin可以看到竟然有好幾個相同的帳號連接MySQL!我搜尋整個Dolphin程式裡面的「mysql_connect」與「mysql_pconnect」發現確實是有好幾個連接資料庫指令。理論上,每次開啟網頁,應該只需要一個「mysql_connect」來連接MySQL資料庫才對。如果有不同的需求,也應該不能太多次,甚至是不斷連接MySQL才對。

首先我發現就算是只有我一個人可以連上的「地下社群網站」,只要打開forum討論區首頁,或是打開photos相片首頁,就很容易導致MySQL當機!雖然MySQL會自動重新啟動,但是到可以穩定運作之前,MySQL可能需要20-30秒的時間來重新啟動。

用BBEdit搜尋整個Dolphin-v.7.3.3,發現有3個mysql_connect連接指令,其中兩個是mysql_connect,一個是mysql_pconnect。

Dolphin-v.7.3.3/flash/modules/global/inc/db.inc.php:44:

        @$this->rLink = mysql_connect($dbHost, $this->sUser, $this->sPassword);

Dolphin-v.7.3.3/modules/boonex/forum/classes/BxDb.php:40:

        $this->link = @mysql_connect($full_host, $this->user, $this->password) or $this->error('Cannot connect to database');

Dolphin-v.7.3.3/inc/classes/BxDolDb.php:66:

        $this->link = @mysql_pconnect($full_host, $this->user, $this->password);

因為總共有3個mysql_connect連接指令,而且3個指令對於「無法連接MySQL」的處理方式也不同,難怪當「無法連接MySQL」的時候,在不同的網頁上會看到不同的「無法連接MySQL」的錯誤訊息!

首先處理forum討論區的「modules/boonex/forum/classes/BxDb.php」連接資料庫的部分。如果沒有特別的需求,forum討論區應該不需要自己另外連接MySQL資料庫才對!只要使用整個系統已經連上的MySQL即可。討論區自己另外連接MySQL可說是只會浪費「MySQL連接數」以及增加MySQL Server運作上的負擔。表面上這裡只有增加一次的「連接MySQL資料庫」而已,但如果網站上有幾萬、幾百萬個會員的時候呢?這個連接數量就會很可觀了。

原版classes/BxDb.ph程式碼的內容是這樣:

    /**

     * connect to database with appointed parameters

     */

    function connect()

    {

        $full_host = $this->host;

        $full_host .= $this->port ? ':'.$this->port : '';

        $full_host .= $this->socket ? ':'.$this->socket : '';

 

        $this->link = @mysql_connect($full_host, $this->user, $this->password) or $this->error('Cannot connect to database');

        if (!$this->link) {

            echo 'Could not connect to MySQL database. < br / >Did you properly edit inc/header.inc.php file ?';

            exit;;

        }

 

        if (!$this->select_db()) {

            echo 'Could not select MySQL database. < br / >Did you properly edit inc/header.inc.php file ?';

            exit;

        }

 

        mysql_query ("SET NAMES 'utf8'", $this->link);

    }

我修改成這樣:

    /**

     * connect to database with appointed parameters

     */

    function connect()

    {

        $full_host = $this->host;

        $full_host .= $this->port ? ':'.$this->port : '';

        $full_host .= $this->socket ? ':'.$this->socket : '';

 

        if (empty($GLOBALS['bx_db_link'])) { //BNW

            $GLOBALS['MySQL']->connect();

        }

        $this->link = $GLOBALS['bx_db_link'];

        if (!$this->link) {

            echo 'Could not connect to MySQL database. < br / >Did you properly edit inc/header.inc.php file ?';

            exit;

        }

 

        if (!$this->select_db()) {

            echo 'Could not select MySQL database. < br / >Did you properly edit inc/header.inc.php file ?';

            exit;

        }

 

        //mysql_query ("SET NAMES 'utf8'", $this->link);

    }

 

其中「if (empty($GLOBALS['bx_db_link']))」的意思是,如果沒有連接MySQL資料庫,才需要執行「$GLOBALS['MySQL']->connect();」的連接資料庫動作。但就算單獨開啟forum討論區首頁,也不可能在開啟討論區首頁以前沒有連接過MySQL!因此程式執行到這裡的時候,應該都已經連接好MySQL了。這樣就可以減少因為開啟forum討論區網頁,又另外連接MySQL一次的動作!

另外也減少一次mysql_query的查訊設定為utf8的動作。這個utf8設定可以在my.cnf裡面事先設定好。

在「flash/modules/global/inc/db.inc.php」也有這樣的連接MySQL伺服器的程式碼。同樣是不理會之前有沒有連接過MySQL,就直接連接一個新的MySQL:

    function connect()

    {

        if($this->bConnected) return;

        $dbHost = strlen($this->iPort) ? $this->sHost . ":" . $this->iPort : $this->sHost;

        $dbHost .= strlen($this->iSocket) ? ":" . $this->iSocket : "";

        @$this->rLink = mysql_connect($dbHost, $this->sUser, $this->sPassword);

        if($this->rLink)$this->bConnected = true;

        else $this->bConnected = false;

        @mysql_select_db($this->sDb, $this->rLink);

        mysql_query("SET NAMES 'utf8'", $this->rLink);

        mysql_query("SET sql_mode = ''", $this->rLink);

        mysql_query("SET @@local.wait_timeout=9000;", $this->rLink);

        mysql_query("SET @@local.interactive_timeout=9000;", $this->rLink);

    }

這個部分的程式碼我改成這樣,首先判斷整個網站的全域變數有沒有連接過MySQL?如果沒有連接MySQL的話,才連接MySQL。:

    function connect()

    {

        if($this->bConnected) return;

        $dbHost = strlen($this->iPort) ? $this->sHost . ":" . $this->iPort : $this->sHost;

        $dbHost .= strlen($this->iSocket) ? ":" . $this->iSocket : "";

        if (empty($GLOBALS['bx_db_link'])) { //BNW

            $MyCount = 1;

            do {

                $this->rLink = @mysql_connect($dbHost, $this->sUser, $this->sPassword);

                if ($this->rLink != false) break;

                $MyCount++;

                sleep(1);

            } while ($MyCount <= 60);

        } else {

            $this->rLink = $GLOBALS['bx_db_link'];

        }

        if($this->rLink)$this->bConnected = true;

        else $this->bConnected = false;

        @mysql_select_db($this->sDb, $this->rLink);

        //mysql_query("SET NAMES 'utf8'", $this->rLink);

        //mysql_query("SET sql_mode = ''", $this->rLink);

        //mysql_query("SET @@local.wait_timeout=9000;", $this->rLink);

        //mysql_query("SET @@local.interactive_timeout=9000;", $this->rLink);

    }

如果無法連接MySQL資料庫的話,會暫停1秒再重新嘗試連線,如果連接60秒都無法連接資料庫才會產生錯誤訊息。

所以我也用同樣的方式來修改「inc/classes/BxDolDb.php」。原版的程式碼是這樣:

    /**

     * connect to database with appointed parameters

     */

    function connect()

    {

        $full_host = $this->host;

        $full_host .= $this->port ? ':'.$this->port : '';

        $full_host .= $this->socket ? ':'.$this->socket : '';

 

        $this->link = @mysql_pconnect($full_host, $this->user, $this->password);

        if (!$this->link)

            $this->error('Database connect failed', true);

 

        if (!$this->select_db())

            $this->error('Database select failed', true);        

 

        mysql_query("SET NAMES 'utf8'", $this->link);

        mysql_query("SET sql_mode = ''", $this->link);

 

        $GLOBALS['bx_db_link'] = $this->link;

    }

我修改好的連接MySQL資料庫程式碼,改成這樣:

    /**

     * connect to database with appointed parameters

     */

    function connect()

    {

        $full_host = $this->host;

        $full_host .= $this->port ? ':'.$this->port : '';

        $full_host .= $this->socket ? ':'.$this->socket : '';

        if (empty($GLOBALS['bx_db_link'])) { //BNW

            $MyCount = 1;

            do {

                $this->link = @mysql_connect($full_host, $this->user, $this->password);

                if ($this->link != false) break;

                $MyCount++;

                sleep(1);

            } while ($MyCount <= 60);

        } else {

            $this->link = $GLOBALS['bx_db_link'];

        }

        if (!$this->link)

            $this->error('Database connect failed', true);

 

        if (!$this->select_db())

            $this->error('Database select failed', true);        

 

        //mysql_query("SET NAMES 'utf8'", $this->link);

        //mysql_query("SET sql_mode = ''", $this->link);

 

        $GLOBALS['bx_db_link'] = $this->link;

    }

不需要執行的「SET NAMES 'utf8'」與「SET sql_mode = ''」也被我用註解的方式關閉。

盡量減少MySQL資料庫的連接、設定動作以後,觀察一個星期多的時間,看起來MySQL比以前穩定了許多。covermouth

當然,在「非同步處理上傳照片」的程式碼裡面,連接資料庫的程式碼也與上面這一段很類似。

$MyCount = 1;

do {

        $mysql = @mysql_connect($db['host'], $db['user'], $db['passwd']);

        if ($mysql != false) {

            @mysql_select_db($db['db'], $mysql);

            break;

        }

        $MyCount++;

        sleep(10);

} while ($MyCount <= 30);

if ($MyCount >= 30) exit;

「非同步處理上傳照片」因為是在Web Server的背景執行,不會影響普通的user,所以當無法連接MySQL資料庫的時候,會先執行「sleep(10);」睡眠10秒,然後再重新嘗試連接MySQL資料庫。要是不斷錯誤達到30次,才會正式放棄,結束程式。

蘇言霖 2017/01/11 4 1144
Comments
Order by: 
Per page:
 
  •  ayaka: 
     

    個人看這個系統實際上沒有考慮過parallel的問題shock,多數的處理都是依賴php thread的形式的進行的。

    當時一直想重寫一個相簿軟體來加速RAW的upload和轉換,但是一直沒有空動手。

     
     2017/02/071 replies1 replies 
    0 points
     
Rate
0 votes
Post info
蘇言霖
「超級懶貓級」社群網站站長
2017/01/11 (2633 days ago)
Actions