Cheapest way to to determine if a MySQL connection is still alive

前端 未结 3 1553
天命终不由人
天命终不由人 2020-12-14 20:48

I have a pool of MySQL connections for a web-based data service. When it starts to service a request, it takes a connection from the pool to use. The problem is that if ther

3条回答
  •  佛祖请我去吃肉
    2020-12-14 21:19

    You will not know the real state of the connection without going over the wire, and SELECT 1 is a good enough candidate (arguably you could come up with a shorter command which takes less time to parse, but compared to network or even loopback latency those savings would be insignificant.)

    This being said, I would argue that pinging a connection before checking it out from the pool is not the best approach.

    You should probably simply have your connection pool manager enforce its own keep-alive (timeout) policy to avoid being disconnected by the server (short of a more serious intervening connectivity issue, which could affect you smack in the middle of regular operations anyway -- and which your connection pool manager would be unable to help with anyway), as well as in order not to hog the database (think filehandles and memory usage) needlessly.

    It is therefore questionable, in my opinion, what value testing for connectivity condition before checking out a connection from the pool really has. It may be worth testing connection status before a connection is checked in back into the pool, but that can be done implicitly by simply marking the connection as dirty when an SQL hard error (or equivalent exception) arises (unless the API you are using already exposes a is-bad-like call for you.)

    I would therefore recommend:

    • implementing a client-side keep-alive policty
    • not performing any checks when checking out connections from the pool
    • performing dirty checks before a connection is returned to the pool
    • let the application code deal with other (non-timeout) exceptional connection conditions

    UPDATE

    It would appear from your comments that you really really want to ping the connection (I assume that is because you don't have full control over, or knowledge of, timeout characteristics on the MySQL server or intervening network equipment such as proxies etc.)

    In this case you can use DO 1 as an alternative to SELECT 1; it is marginally faster -- shorter to parse, and it does not return actual data (although you will get the TCP acks, so you will still do the roundtrip validating that the connection is still established.)

    UPDATE 2

    Regarding Joshua's post, here's packet capture traces for various scenarios:

    SELECT 1;
    13:51:01.463112 IP client.45893 > server.mysql: P 2270604498:2270604511(13) ack 2531191393 win 1460 
    13:51:01.463682 IP server.mysql > client.45893: P 1:57(56) ack 13 win 65306 
    13:51:01.463698 IP client.45893 > server.mysql: . ack 57 win 1460 
    
    DO 1;
    13:51:27.415520 IP client.45893 > server.mysql: P 13:22(9) ack 57 win 1460 
    13:51:27.415931 IP server.mysql > client.45893: P 57:68(11) ack 22 win 65297 
    13:51:27.415948 IP client.45893 > server.mysql: . ack 68 win 1460 
    
    mysql_ping
    14:54:05.545860 IP client.46156 > server.mysql: P 69:74(5) ack 78 win 1460 
    14:54:05.546076 IP server.mysql > client.46156: P 78:89(11) ack 74 win 65462 
    14:54:05.546092 IP client.46156 > server.mysql: . ack 89 win 1460 
    

    As you can see, except for the fact that the mysql_ping packet is 5 bytes instead of DO 1;'s 9 bytes, the number of roundtrips (and consequently, network-induced latency) is exactly the same. The only extra cost you are paying with DO 1 as opposed to mysql_ping is the parsing of DO 1, which is trivial.

提交回复
热议问题