Description
I'm a maintainer of go-sql-driver/mysql.
Since MySQL protocol is a request-response protocol, we don't have dedicated goroutine for Write()
and Read()
. We call them in the goroutine executing DB.Query()
.
Sometimes, DB connection is closed from a server or other middlewares.
But we can not detect connection closed by peer until we call Read()
.
Since we send a query before reading result, we can not retry the query. Otherwise, the query may be executed twice. See also: https://golang.org/pkg/database/sql/driver/
To prevent duplicate operations, ErrBadConn should NOT be returned if there's a possibility that the database server might have performed the operation. Even if the server sends back an error, you shouldn't return ErrBadConn.
If we can detect connection closed by peer before sending a query, we can retry safely. But there is no easy way to do it now.
- Dedicated reader goroutine increase complexity. It will increase memory usage because we can not use same buffer for Read() and Write(). It will increase allocation because received data should be passed to the goroutine executing
DB.Query()
. conn.SetReadDeadline(time.Now().Add(time.Millisecond)); conn.Read()
introduces unnecessary sleep for normal case.- Using SyscallConn is not easy, especially for cross platform.
So I want a easy way to check EOF. I have two ideas about it:
c.Readable() bool
-- Returns true whenc.Read()
will not block.c.ReadNonblock(buff []bytes) (int, error)
-- Nonblocking variants ofc.Read()
.