2008-10-28 421 views
18

我目前有超過100個處於睡眠狀態的連接。如何根據MySQL中的用戶登錄設置連接超時時間

某些連接必須保持睡眠狀態(並且不要關閉),因爲它是永久連接,但其他一些連接(使用不同的用戶名)來自某些PHP腳本,我希望它們超時很快。

是否可以爲每個用戶設置一個wait_timeout?如果是的話,怎麼樣?

回答

27

沒有按用戶超時配置,但可以動態設置wait_timeout值。也就是說,在作爲給定用戶建立連接之後,可以發出語句將超時值更改爲該用戶會話所需的值。

嘗試了以下實驗在MySQL命令行的客戶端:

mysql> SHOW VARIABLES LIKE 'wait_timeout'; 

...示出了28800(即,8個小時),這是默認wait_timout

mysql> SET SESSION wait_timeout = 60; 
mysql> SHOW VARIABLES LIKE 'wait_timeout'; 

...顯示60

然後你可以退出會議,重新連接,並再次默認wait_timeout是28800因此它僅限於當前會話的範圍。

您也可以打開第二個窗口並啓動一個單獨的mysql客戶端會話,以證明在一個會話中更改wait_timeout不會影響其他併發會話。

0

我檢查了mysql.user表,它看起來並不像有它設置有:

+-----------------------+-----------------------------------+------+-----+---------+-------+ 
| Field     | Type        | Null | Key | Default | Extra | 
+-----------------------+-----------------------------------+------+-----+---------+-------+ 
| Host     | char(60)       | NO | PRI |   |  | 
| User     | char(16)       | NO | PRI |   |  | 
| Password    | char(41)       | NO |  |   |  | 
| Select_priv   | enum('N','Y')      | NO |  | N  |  | 
| Insert_priv   | enum('N','Y')      | NO |  | N  |  | 
| Update_priv   | enum('N','Y')      | NO |  | N  |  | 
| Delete_priv   | enum('N','Y')      | NO |  | N  |  | 
| Create_priv   | enum('N','Y')      | NO |  | N  |  | 
| Drop_priv    | enum('N','Y')      | NO |  | N  |  | 
| Reload_priv   | enum('N','Y')      | NO |  | N  |  | 
| Shutdown_priv   | enum('N','Y')      | NO |  | N  |  | 
| Process_priv   | enum('N','Y')      | NO |  | N  |  | 
| File_priv    | enum('N','Y')      | NO |  | N  |  | 
| Grant_priv   | enum('N','Y')      | NO |  | N  |  | 
| References_priv  | enum('N','Y')      | NO |  | N  |  | 
| Index_priv   | enum('N','Y')      | NO |  | N  |  | 
| Alter_priv   | enum('N','Y')      | NO |  | N  |  | 
| Show_db_priv   | enum('N','Y')      | NO |  | N  |  | 
| Super_priv   | enum('N','Y')      | NO |  | N  |  | 
| Create_tmp_table_priv | enum('N','Y')      | NO |  | N  |  | 
| Lock_tables_priv  | enum('N','Y')      | NO |  | N  |  | 
| Execute_priv   | enum('N','Y')      | NO |  | N  |  | 
| Repl_slave_priv  | enum('N','Y')      | NO |  | N  |  | 
| Repl_client_priv  | enum('N','Y')      | NO |  | N  |  | 
| Create_view_priv  | enum('N','Y')      | NO |  | N  |  | 
| Show_view_priv  | enum('N','Y')      | NO |  | N  |  | 
| Create_routine_priv | enum('N','Y')      | NO |  | N  |  | 
| Alter_routine_priv | enum('N','Y')      | NO |  | N  |  | 
| Create_user_priv  | enum('N','Y')      | NO |  | N  |  | 
| ssl_type    | enum('','ANY','X509','SPECIFIED') | NO |  |   |  | 
| ssl_cipher   | blob        | NO |  |   |  | 
| x509_issuer   | blob        | NO |  |   |  | 
| x509_subject   | blob        | NO |  |   |  | 
| max_questions   | int(11) unsigned     | NO |  | 0  |  | 
| max_updates   | int(11) unsigned     | NO |  | 0  |  | 
| max_connections  | int(11) unsigned     | NO |  | 0  |  | 
| max_user_connections | int(11) unsigned     | NO |  | 0  |  | 
+-----------------------+-----------------------------------+------+-----+---------+-------+ 
37 rows in set (0.00 sec) 

根據您是否正在使用庫MySQLi或PDO,你的PHP MySQL連接要麼掛斷當請求執行時,或者在Apache進程池中共享。

例如,與PDO,關閉持久連接(我認爲這是默認的),連接到您的DB:

$ PDO =新PDO($ DSN,$用戶,$通行證,陣列(PDO :: ATTR_PERSISTENT => false));

如果你希望你的腳本使用永久連接,但你必須開到睡眠模式的數據庫連接過多,你應該考慮配置您的Apache的MaxServersMaxSpareServersMinSpareServersStartServers使沒有那麼多流連時他們不需要。

2

另一種可能性:MySQL支持兩種不同的超時變量,非交互式客戶端爲wait_timeout,交互式客戶端爲interactive_timeout

交互式客戶端和非交互式客戶端之間的區別似乎只是連接時是否指定了CLIENT_INTERACTIVE選項。

我不知道這是否有助於您,因爲您需要以某種方式使mysql_real_connect()在其參數client_flag中通過該選項。我不確定你使用的是什麼語言或界面,所以我不知道它是否允許你指定這個連接標誌。

無論如何,如果你可以通過該客戶端的標誌,而你只需要兩種不同類型的用戶,那麼你可以在MySQL服務器配置配置wait_timeoutinteractive_timeout不同,然後當你想使用帶有較短值的一個給定會話以及時超時。

5

您應該設置在my.conf以下變量:

[mysqld] 
interactive_timeout=180 
wait_timeout=180 

wait_timeout自動連接超時(在我的Web服務器上的意見超過30實在是太多了)。
interactive_timeout對於空閒會話是控制檯交互超時

+0

許多(大多數?)Web服務器使用連接池。在這種情況下,180可能太低。 – 2016-11-20 02:13:43

2

如果使用Connector/J,您可以使用sessionVariables在客戶端的JDBC URL像這樣:jdbc:mysql://hostname:3306/schema?sessionVariables=wait_timeout=600

其他語言的其他連接器可能會允許相同。

0

init_connect將在用戶登錄時執行,因此我們可以編寫小型語句並根據用戶設置值。請注意,超級用戶不會執行init_connect。

mysql> SET GLOBAL init_connect="SET @@wait_timeout = CASE WHEN CURRENT_USER() LIKE '[email protected]%' THEN '30' ELSE @@wait_timeout END";