diff --git a/mvcc/backend/batch_tx.go b/mvcc/backend/batch_tx.go index 287f79083e8b..d097dc7f1187 100644 --- a/mvcc/backend/batch_tx.go +++ b/mvcc/backend/batch_tx.go @@ -162,9 +162,14 @@ func (t *batchTx) commit(stop bool) { if t.pending == 0 && !stop { t.backend.mu.RLock() defer t.backend.mu.RUnlock() + t.tx, err = t.backend.db.Begin(true) + if err != nil { + plog.Fatalf("cannot begin tx (%s)", err) + } atomic.StoreInt64(&t.backend.size, t.tx.Size()) return } + start := time.Now() // gofail: var beforeCommit struct{} err = t.tx.Commit() diff --git a/mvcc/backend/batch_tx_test.go b/mvcc/backend/batch_tx_test.go index 582cbf84e7ac..cc120e370858 100644 --- a/mvcc/backend/batch_tx_test.go +++ b/mvcc/backend/batch_tx_test.go @@ -195,3 +195,15 @@ func TestBatchTxBatchLimitCommit(t *testing.T) { return nil }) } + +// TestBatchTxCommitSize tests *batchTx.tx.Size call after *batchTx.Commit does not panic. +// *bolt.Tx commit initializes *bolt.Tx.meta and *bolt.Tx.db as nil. And if *batchTx is not +// properly initialized, it panics with nil pointer reference. +func TestBatchTxCommitSize(t *testing.T) { + b, tmpPath := NewTmpBackend(time.Hour, 100) + defer cleanup(b, tmpPath) + + if _, err := b.Hash(make(map[IgnoreKey]struct{})); err != nil { + t.Fatal(err) + } +}