On 10 May 2016 12:55 p.m., "Naoki INADA" <songof...@gmail.com> wrote:
>
>
> But we have one problem about it: sending query is succeeded even if MySQL server
> had shut down the connection. And when conn.Read() returns io.EOF, there are no way
> to determine we can safely retry sending query which is not idempotent with new connection.
A Write() to a TCP connection will return an error if the kernel knows the connection is already closed(just like select() does)
But if the other end of the connection didn't properly close the connection then you have to wait for TCP timeout.
The most straight forward thing to do is just Write() to the connection, wait for a response and handle the error.
It looks like the mysql protocol has a PING command (https://dev.mysql.com/doc/internals/en/com-ping.html) which does give you something to send to test a connection before sending an actual sql query. Perhaps that would be better for your usecase.
But in general if your application level protocol (HTTP, mysql) doesn't allow you to reconnect and ask whether a request completed then there is no way to be certain whether it did or not.
On 10 May 2016 12:55 p.m., "Naoki INADA" <songof...@gmail.com> wrote:
>
>
> But we have one problem about it: sending query is succeeded even if MySQL server
> had shut down the connection. And when conn.Read() returns io.EOF, there are no way
> to determine we can safely retry sending query which is not idempotent with new connection.A Write() to a TCP connection will return an error if the kernel knows the connection is already closed(just like select() does)
But if the other end of the connection didn't properly close the connection then you have to wait for TCP timeout.
The most straight forward thing to do is just Write() to the connection, wait for a response and handle the error.
It looks like the mysql protocol has a PING command (https://dev.mysql.com/doc/internals/en/com-ping.html) which does give you something to send to test a connection before sending an actual sql query. Perhaps that would be better for your usecase.
But in general if your application level protocol (HTTP, mysql) doesn't allow you to reconnect and ask whether a request completed then there is no way to be certain whether it did or not.
2016-05-10 7:03 GMT+02:00 INADA Naoki <songof...@gmail.com>:
>> But in general if your application level protocol (HTTP, mysql) doesn't
>> allow you to reconnect and ask whether a request completed then there is no
>> way to be certain whether it did or not.
>
> I'm not protocol designer.
You will need application level responses to determine this. If you
perform an operation over TCP and get a successful response back (from
the application on the other side), it was successful. If you get a
connection error it may have been successful or not, you can't tell
and should retry.
> There is usually no point in verifying that the
connection is still alive before performing your operation, as it may
equally well close just after your verification.
> "PING" commands and
similar can be useful to keep a connection from timing out, and making
sure that the server was alive and well at least a short while ago. :)
I think my point is that even if you could do that, the best the OS
can offer is "I think so, at least I haven't heard otherwise" and you
might still get a "connection reset" error one millisecond later when
actually trying to use the connection.
Regular PINGs on an otherwise unused connection are
of course useful to detect it going down and to keep it alive to begin
with.
2016-05-10 13:26 GMT+02:00 <ma...@joh.to>:
> Consider that the connection might have TCP keepalives enabled and the OS
> actually already figured out that the connection is dead. Or the other end
> just closed the connection normally in the meanwhile. There are plenty of
> cases where it'd be useful to just check if the OS knows that the connection
> is clearly gone, without entering the realm of "I don't really know".
Read() will have returned an error immediately when the connection was closed.
From what I can tell, a zero byte Read() blocks even when there is
nothing to read. So combined with SetReadDeadline() it can do what you
want, not that I know if this guaranteed to be the case, and I
certainly don't recommend doing it.
That is, taking your example from above: https://play.golang.org/p/p65CnSwDvV
//jb