Skip to content

Commit 9c8d6a5

Browse files
authored
Reduce "busy buffer" logs (#1641)
Reduce the use of `errBadConnNoWrite` to improve maintainability. ResetSession() and IsValid() checks if the buffer is busy. This reduces the risk of busy buffer error during connection in use. In principle, the risk of this is zero. So I removed errBadConnNoWrite when checking the busy buffer. After this change, only `writePacke()` returns errBadConnNoWrite. Additionally, I do not send COM_QUIT when readPacket() encounter read error. It caused "busy buffer" error too and hide real errors.
1 parent 41a5fa2 commit 9c8d6a5

File tree

3 files changed

+26
-33
lines changed

3 files changed

+26
-33
lines changed

buffer.go

+5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ func newBuffer(nc net.Conn) buffer {
4343
}
4444
}
4545

46+
// busy returns true if the buffer contains some read data.
47+
func (b *buffer) busy() bool {
48+
return b.length > 0
49+
}
50+
4651
// flip replaces the active buffer with the background buffer
4752
// this is a delayed flip that simply increases the buffer counter;
4853
// the actual flip will be performed the next time we call `buffer.fill`

connection.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,14 @@ func (mc *mysqlConn) Close() (err error) {
121121
if !mc.closed.Load() {
122122
err = mc.writeCommandPacket(comQuit)
123123
}
124+
mc.close()
125+
return
126+
}
124127

128+
// close closes the network connection and clear results without sending COM_QUIT.
129+
func (mc *mysqlConn) close() {
125130
mc.cleanup()
126131
mc.clearResult()
127-
return
128132
}
129133

130134
// Closes the network connection and unsets internal variables. Do not call this
@@ -637,7 +641,7 @@ func (mc *mysqlConn) CheckNamedValue(nv *driver.NamedValue) (err error) {
637641
// ResetSession implements driver.SessionResetter.
638642
// (From Go 1.10)
639643
func (mc *mysqlConn) ResetSession(ctx context.Context) error {
640-
if mc.closed.Load() {
644+
if mc.closed.Load() || mc.buf.busy() {
641645
return driver.ErrBadConn
642646
}
643647

@@ -671,7 +675,7 @@ func (mc *mysqlConn) ResetSession(ctx context.Context) error {
671675
// IsValid implements driver.Validator interface
672676
// (From Go 1.15)
673677
func (mc *mysqlConn) IsValid() bool {
674-
return !mc.closed.Load()
678+
return !mc.closed.Load() && !mc.buf.busy()
675679
}
676680

677681
var _ driver.SessionResetter = &mysqlConn{}

packets.go

+14-30
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
3232
// read packet header
3333
data, err := mc.buf.readNext(4)
3434
if err != nil {
35+
mc.close()
3536
if cerr := mc.canceled.Value(); cerr != nil {
3637
return nil, cerr
3738
}
3839
mc.log(err)
39-
mc.Close()
4040
return nil, ErrInvalidConn
4141
}
4242

@@ -45,7 +45,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
4545

4646
// check packet sync [8 bit]
4747
if data[3] != mc.sequence {
48-
mc.Close()
48+
mc.close()
4949
if data[3] > mc.sequence {
5050
return nil, ErrPktSyncMul
5151
}
@@ -59,7 +59,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
5959
// there was no previous packet
6060
if prevData == nil {
6161
mc.log(ErrMalformPkt)
62-
mc.Close()
62+
mc.close()
6363
return nil, ErrInvalidConn
6464
}
6565

@@ -69,11 +69,11 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
6969
// read packet body [pktLen bytes]
7070
data, err = mc.buf.readNext(pktLen)
7171
if err != nil {
72+
mc.close()
7273
if cerr := mc.canceled.Value(); cerr != nil {
7374
return nil, cerr
7475
}
7576
mc.log(err)
76-
mc.Close()
7777
return nil, ErrInvalidConn
7878
}
7979

@@ -125,10 +125,10 @@ func (mc *mysqlConn) writePacket(data []byte) error {
125125

126126
n, err := mc.netConn.Write(data[:4+size])
127127
if err != nil {
128+
mc.cleanup()
128129
if cerr := mc.canceled.Value(); cerr != nil {
129130
return cerr
130131
}
131-
mc.cleanup()
132132
if n == 0 && pktLen == len(data)-4 {
133133
// only for the first loop iteration when nothing was written yet
134134
mc.log(err)
@@ -162,11 +162,6 @@ func (mc *mysqlConn) writePacket(data []byte) error {
162162
func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err error) {
163163
data, err = mc.readPacket()
164164
if err != nil {
165-
// for init we can rewrite this to ErrBadConn for sql.Driver to retry, since
166-
// in connection initialization we don't risk retrying non-idempotent actions.
167-
if err == ErrInvalidConn {
168-
return nil, "", driver.ErrBadConn
169-
}
170165
return
171166
}
172167

@@ -312,9 +307,8 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
312307
// Calculate packet length and get buffer with that size
313308
data, err := mc.buf.takeBuffer(pktLen + 4)
314309
if err != nil {
315-
// cannot take the buffer. Something must be wrong with the connection
316-
mc.log(err)
317-
return errBadConnNoWrite
310+
mc.cleanup()
311+
return err
318312
}
319313

320314
// ClientFlags [32 bit]
@@ -404,9 +398,8 @@ func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte) error {
404398
pktLen := 4 + len(authData)
405399
data, err := mc.buf.takeBuffer(pktLen)
406400
if err != nil {
407-
// cannot take the buffer. Something must be wrong with the connection
408-
mc.log(err)
409-
return errBadConnNoWrite
401+
mc.cleanup()
402+
return err
410403
}
411404

412405
// Add the auth data [EOF]
@@ -424,9 +417,7 @@ func (mc *mysqlConn) writeCommandPacket(command byte) error {
424417

425418
data, err := mc.buf.takeSmallBuffer(4 + 1)
426419
if err != nil {
427-
// cannot take the buffer. Something must be wrong with the connection
428-
mc.log(err)
429-
return errBadConnNoWrite
420+
return err
430421
}
431422

432423
// Add command byte
@@ -443,9 +434,7 @@ func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error {
443434
pktLen := 1 + len(arg)
444435
data, err := mc.buf.takeBuffer(pktLen + 4)
445436
if err != nil {
446-
// cannot take the buffer. Something must be wrong with the connection
447-
mc.log(err)
448-
return errBadConnNoWrite
437+
return err
449438
}
450439

451440
// Add command byte
@@ -464,9 +453,7 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
464453

465454
data, err := mc.buf.takeSmallBuffer(4 + 1 + 4)
466455
if err != nil {
467-
// cannot take the buffer. Something must be wrong with the connection
468-
mc.log(err)
469-
return errBadConnNoWrite
456+
return err
470457
}
471458

472459
// Add command byte
@@ -1007,9 +994,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
1007994
// In this case the len(data) == cap(data) which is used to optimise the flow below.
1008995
}
1009996
if err != nil {
1010-
// cannot take the buffer. Something must be wrong with the connection
1011-
mc.log(err)
1012-
return errBadConnNoWrite
997+
return err
1013998
}
1014999

10151000
// command [1 byte]
@@ -1207,8 +1192,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
12071192
if valuesCap != cap(paramValues) {
12081193
data = append(data[:pos], paramValues...)
12091194
if err = mc.buf.store(data); err != nil {
1210-
mc.log(err)
1211-
return errBadConnNoWrite
1195+
return err
12121196
}
12131197
}
12141198

0 commit comments

Comments
 (0)