-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Description
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (go version)?
go1.9.2 darwin/amd64
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (go env)?
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/kirk/golang"
GORACE=""
GOROOT="/usr/local/opt/go/libexec"
GOTOOLDIR="/usr/local/opt/go/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/j7/yr_n5r6j5jx4jb856mkk7kzr0000gp/T/go-build290212909=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"What did you do?
When context is canceled or timeout, the db transaction is leaked which cannot be commit or rollback in some extreme scenario. It may cause massive lock wait timeouts and high load on the underlying database.
The following describes the basic flow:
Goroutine 1
Call (*DB) BeginTx begins a transaction with a userContext. In (*DB)BeginTx, a new goroutine (*Tx)awaitDone which monitor context and rollback tx if needed will be created.
Goroutine 2(awaitDone)
block on tx.ctx.Done()
Goroutine 1
Execute some insert or update sqls on the database
Goroutine 1
Commit the transaction, (*Tx)Commit set the atomic variable tx.done to 1.
Goroutine 3(maybe global timer)
Cancel userContext which be passed to Tx
Goroutine 1
(*Tx)Commit checks tx.ctx.Done(). Due to context has been canceled, it will return context.Canceled or context.DeadlineExceeded error immediately and abort the real COMMIT of transaction.
Goroutine 2
Release with tx.ctx.Done() signal, execute (*Tx)rollback. However the atomic variable tx.done is 1 currently, it will return ErrTxDone error immediately and abort the real ROLLBACK of transaction.
What did you expect to see?
Rollback the transaction
What did you see instead?
The transaction hangs up and massive db lock wait timeouts