我目前有超过 100 个处于睡眠状态的连接。
某些连接必须保持在睡眠状态(并且不要关闭),因为它是永久连接,但其他一些连接(使用不同的用户名)来自某个 php 脚本,我希望它们很快超时。
是否可以为每个用户设置 wait_timeout?如果是,如何?
没有针对每个用户的超时配置,但您可以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
在一个会话中更改不会影响其他并发会话。
您应该在 中设置以下变量my.conf
:
[mysqld]
interactive_timeout=180
wait_timeout=180
wait_timeout
是自动连接的超时(在我看来,Web 服务器上超过 30 个太多了)。
interactive_timeout
是空闲会话的控制台交互超时。
另一种可能性:MySQL 支持两个不同的超时变量,wait_timeout
用于非交互式客户端和interactive_timeout
交互式客户端。
交互式和非交互式客户端之间的区别似乎只是您CLIENT_INTERACTIVE
在连接时是否指定了选项。
我不知道这是否对您有帮助,因为您需要以某种方式在其参数mysql_real_connect()
中传递该选项。client_flag
我不确定您使用的是什么语言或界面,所以我不知道它是否允许您指定此连接标志。
无论如何,如果您可以传递该客户端标志,并且您只需要两种不同类型的用户,那么您可以在 MySQL 服务器配置wait_timeout
中interactive_timeout
进行不同的配置,然后在您希望给定会话立即超时时使用具有较短值的用户.
如果使用Connector/J ,则可以在客户端的 JDBC URL中使用sessionVariables ,如下所示:jdbc:mysql://hostname:3306/schema?sessionVariables=wait_timeout=600
其他语言的其他连接器可能会允许相同。
每当用户登录时都会执行init_connect,因此我们可以编写小case语句并根据用户设置值。请注意,超级用户不会执行 init_connect。
mysql> SET GLOBAL init_connect="SET @@wait_timeout = CASE WHEN CURRENT_USER() LIKE 'app1@%' THEN '30' ELSE @@wait_timeout END";
我检查了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,要关闭持久连接(我认为这是默认设置),请使用以下命令连接到您的数据库:
$pdo = new PDO($dsn, $user, $pass, Array(PDO::ATTR_PERSISTENT => false));
如果您希望脚本使用持久连接,但在睡眠模式下打开到数据库的连接太多,您应该考虑配置您的 Apache 的, MaxServers
,MaxSpareServers
以便在不需要它们时不要有太多的挂起。MinSpareServers
StartServers
http://www.percona.com/doc/percona-toolkit/2.1/pt-kill.html
可以使用 pt-kill 杀死每个用户的连接。您可以安排这个或设置一个后台作业来处理这个。