如何ping mysql客户端?



我如何创建一个服务器端脚本ping客户端mysql和windows的形式,看看他们是否仍然登录?例如,ping客户端,他们必须做一些事情来验证他们仍然在线。

您不能直接从服务器ping客户端,但有一些选项。

对超时

我认为在任何情况下你必须使用服务器端超时(wait_timeout),这个超时可以设置服务器宽或从客户端连接,例如:

SET SESSION wait_timeout = 60

这是必需的,因为客户端可能突然消失,甚至没有关闭tcp连接,显式超时将帮助mysql关闭连接,并在客户端不活动的wait_timeout秒后释放资源。根据mysql手动默认超时相当大:28800秒。

有一个缺点。如果在正常操作期间,您的客户端可能超过wait_timeout秒处于非活动状态,那么客户端应该知道如何处理关闭的连接(当数据库告诉它已经离开时重新连接),或者它应该发送"ping"查询(如select 1)至少每wait_timeout - 1秒执行一次。

使用get_lock()函数

从mysql 5.7(以及从10.0.2开始的mariadb)开始,您可以使用多个用户级锁。

通过GET_LOCK()获得的锁将通过执行RELEASE_LOCK()显式释放,或者在会话(正常或异常)终止时隐式释放。当事务提交或回滚时,使用GET_LOCK()获得的锁不会被释放。

所以想法是在客户端连接上发出get_lock查询,例如:

SELECT GET_LOCK('logged_in_{CLIENT_ID}', timeout)

您可以将timeout设置为0并立即告诉客户端无法登录,或者您可以等待(阻塞)最多wait_timeout秒,以确保确实有另一个客户端持有锁。

此锁将在客户端断开连接或等待超时后由服务器自动释放。如果锁是空闲的,get_lock()将返回1,否则(等待超时秒后)将返回0

使用进程id

如果你不想使用锁,可以使用进程的PID。

当客户端连接而不是写islogged = 'YES'时,您可以使用当前CONNECTION_ID()作为值。在登录之前,您可以检查当前客户端是否没有像这样的活动进程

SELECT islogged FROM logged
INNER JOIN information_schema.processlist ON
processlist.id = logged.islogged
WHERE
client_id = ...

如果上面的查询没有返回任何结果,那么你可以将新的pid插入到日志表

REPLACE INTO logged SET islogged = CONNECTION_ID(), client_id = ...

我更喜欢使用get_lock(),因为它看起来更容易,没有并发问题,并且允许实现等待。

不要忘记超时是必要的,你必须处理重新连接或发送常规ping以避免意外的"服务器已经离开"。client.

最新更新