Skip to content

database/sql: transaction leak #22976

@kirk91

Description

@kirk91

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions