2008-10-28 426 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";