linxGnu / grocksdb

RocksDB wrapper for Go. Support 9.x, 8.x, 7.x, 6.x, etc

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TransactionDB is not safe-concurrent on writes!

savsgio opened this issue · comments

Hi @linxGnu,

When I write into the same rocksdb file with 2 gorutines, i have this unexpected panic.

// configure
func (db *DB) init() error {
	cache := grocksdb.NewLRUCache(8 * common.MiB)

	blockBaseTableOptions := grocksdb.NewDefaultBlockBasedTableOptions()
	blockBaseTableOptions.SetBlockCache(cache)

	opts := grocksdb.NewDefaultOptions()
	opts.SetCreateIfMissing(true)
	opts.SetBlockBasedTableFactory(blockBaseTableOptions)
	opts.SetWriteBufferSize(4 * common.MiB)

	txDBOpts := grocksdb.NewDefaultTransactionDBOptions()

	rdb, err := grocksdb.OpenTransactionDb(opts, txDBOpts, db.path)
	if err != nil {
		return errors.Wrap(err, "failed to open db")
	}

	db.db = rdb
	db.ro = grocksdb.NewDefaultReadOptions()
	db.wo = grocksdb.NewDefaultWriteOptions()
	db.txOpts = grocksdb.NewDefaultTransactionOptions()

	db.ro.SetFillCache(true)
	db.wo.SetSync(db.fsync)

	return nil
}
// test writes
func run(database *rocksdb.DB, chRenewTx chan struct{}) {
	for i := 0; i < expectedTotalMessages; i++ {
		for j := 0; j < 5; j++ {
			key := []byte("key-" + strconv.Itoa(i) + "-" + strconv.Itoa(j))
			value := []byte("value-" + strconv.Itoa(i) + "-" + strconv.Itoa(j))

			if _, err := database.Get(key); err != nil {
				panic(err)
			}

			if err := database.Set(key, value); err != nil {
				panic(err)
			}

			if i > 0 && (i+j)%messagesToCommit == 0 {
				chRenewTx <- struct{}{}
			}
		}
	}
}

func main() {
	database, err := rocksdbwrapper.New("./.db_data", false)
	if err != nil {
		panic(err)
	}

	if err := database.Begin(); err != nil {
		panic(err)
	}

	chRenewTx := make(chan struct{}, 1000)

	go func() {
		for range chRenewTx {
			// fmt.Println("Renewing tx...")
			if err := database.RenewTransaction(); err != nil {
				panic(err)
			}
		}
	}()

	now := time.Now()

	go run(database, chRenewTx) // If i disable this gorutine, does not panic!
	run(database, chRenewTx)

	since := time.Since(now)

	fmt.Println("Time:", since)
	fmt.Println("Rate:", float64(expectedTotalMessages)/since.Seconds())
}
main(11175,0x700008e78000) malloc: *** error for object 0x5028c00: pointer being freed was not allocated
main(11175,0x700008e78000) malloc: *** set a breakpoint in malloc_error_break to debug
SIGABRT: abort
PC=0x7fff2061092e m=3 sigcode=0

goroutine 0 [idle]:
runtime: unknown pc 0x7fff2061092e
stack: frame={sp:0x700008e77ad8, fp:0x0} stack=[0x700008df8350,0x700008e77f50)
0000700008e779d8:  00007fff2048dba3  0000000000000000 
0000700008e779e8:  0000700008e77a38  0000700008e77a30 
0000700008e779f8:  0000000004ff8000  0000700008e78000 
0000700008e77a08:  00007ffeefbff465  00007fff2048db2e 
0000700008e77a18:  0000000000000050  0000700008e77b00 
0000700008e77a28:  00007fff20683627  0000003000000018 
0000700008e77a38:  0000700008e77b10  0000700008e77a50 
0000700008e77a48:  00007fff2068376d  0000000000000000 
0000700008e77a58:  0000000000000000  00007fff2048db2e 
0000700008e77a68:  0000000004ff804b  0000000000000000 
0000700008e77a78:  0000000000000000  0000700008e77c68 
0000700008e77a88:  0000700008e77af8  0000000004ff7028 
0000700008e77a98:  0000000000000050  00007fff809382a0 
0000700008e77aa8:  00007fff8096bae8  00007fff2054d896 
0000700008e77ab8:  0000000000000000  0000700008e77b00 
0000700008e77ac8:  00007fff205502c6  0000000000000000 
0000700008e77ad8: <00007fff2063f5bd  0000000000000003 
0000700008e77ae8:  0000000004ff7028  0000700008e77b20 
0000700008e77af8:  0000000000000000  0000700008e77b40 
0000700008e77b08:  00007fff20594411  0000000004ff7028 
0000700008e77b18:  00007fff2060b829  00007ffffffff9df 
0000700008e77b28:  ffffffff04ff7000  0000000004ff7000 
0000700008e77b38:  0000000000000000  0000700008e77ba0 
0000700008e77b48:  00007fff204741f5  000000002d004b10 
0000700008e77b58:  0000700008e78000  0000700008e77c60 
0000700008e77b68:  0000000000000000  00007fff2048b93d 
0000700008e77b78:  00000000000017fd  00000000000017fd 
0000700008e77b88:  0000000000003000  000000002c830040 
0000700008e77b98:  000000002e00c200  0000700008e77c80 
0000700008e77ba8:  00007fff2047734a  0000000400000000 
0000700008e77bb8:  0000000004dc7380  0000000005028c00 
0000700008e77bc8:  0000000000001400  0000000005000000 
runtime: unknown pc 0x7fff2061092e
stack: frame={sp:0x700008e77ad8, fp:0x0} stack=[0x700008df8350,0x700008e77f50)
0000700008e779d8:  00007fff2048dba3  0000000000000000 
0000700008e779e8:  0000700008e77a38  0000700008e77a30 
0000700008e779f8:  0000000004ff8000  0000700008e78000 
0000700008e77a08:  00007ffeefbff465  00007fff2048db2e 
0000700008e77a18:  0000000000000050  0000700008e77b00 
0000700008e77a28:  00007fff20683627  0000003000000018 
0000700008e77a38:  0000700008e77b10  0000700008e77a50 
0000700008e77a48:  00007fff2068376d  0000000000000000 
0000700008e77a58:  0000000000000000  00007fff2048db2e 
0000700008e77a68:  0000000004ff804b  0000000000000000 
0000700008e77a78:  0000000000000000  0000700008e77c68 
0000700008e77a88:  0000700008e77af8  0000000004ff7028 
0000700008e77a98:  0000000000000050  00007fff809382a0 
0000700008e77aa8:  00007fff8096bae8  00007fff2054d896 
0000700008e77ab8:  0000000000000000  0000700008e77b00 
0000700008e77ac8:  00007fff205502c6  0000000000000000 
0000700008e77ad8: <00007fff2063f5bd  0000000000000003 
0000700008e77ae8:  0000000004ff7028  0000700008e77b20 
0000700008e77af8:  0000000000000000  0000700008e77b40 
0000700008e77b08:  00007fff20594411  0000000004ff7028 
0000700008e77b18:  00007fff2060b829  00007ffffffff9df 
0000700008e77b28:  ffffffff04ff7000  0000000004ff7000 
0000700008e77b38:  0000000000000000  0000700008e77ba0 
0000700008e77b48:  00007fff204741f5  000000002d004b10 
0000700008e77b58:  0000700008e78000  0000700008e77c60 
0000700008e77b68:  0000000000000000  00007fff2048b93d 
0000700008e77b78:  00000000000017fd  00000000000017fd 
0000700008e77b88:  0000000000003000  000000002c830040 
0000700008e77b98:  000000002e00c200  0000700008e77c80 
0000700008e77ba8:  00007fff2047734a  0000000400000000 
0000700008e77bb8:  0000000004dc7380  0000000005028c00 
0000700008e77bc8:  0000000000001400  0000000005000000 

goroutine 7 [syscall]:
runtime.cgocall(0x4161b70, 0xc00005ed80, 0xc0000109d8)
        /usr/local/go/src/runtime/cgocall.go:154 +0x5b fp=0xc00005ed50 sp=0xc00005ed18 pc=0x400445b
github.com/linxGnu/grocksdb._Cfunc_rocksdb_transaction_put(0xc50a970, 0xc000173528, 0x8, 0xc000173530, 0xa, 0xc0000109d8)
        _cgo_gotypes.go:8175 +0x45 fp=0xc00005ed80 sp=0xc00005ed50 pc=0x4153625
github.com/linxGnu/grocksdb.(*Transaction).Put.func2(0xc0001820a0, 0xc000173528, 0xc000173528, 0x8, 0x8, 0xc000173530, 0xc000173530, 0xa, 0x10, 0xc0000109d8)
        /usr/local/godeps/pkg/mod/github.com/linx!gnu/grocksdb@v1.6.37/transaction.go:128 +0xcb fp=0xc00005edc8 sp=0xc00005ed80 pc=0x415674b
github.com/linxGnu/grocksdb.(*Transaction).Put(0xc0001820a0, 0xc000173528, 0x8, 0x8, 0xc000173530, 0xa, 0x10, 0x0, 0x0)
        /usr/local/godeps/pkg/mod/github.com/linx!gnu/grocksdb@v1.6.37/transaction.go:128 +0x105 fp=0xc00005ee40 sp=0xc00005edc8 pc=0x4155865
gitlab.com/etoshi/backend/normalizer-r2d2/pkg/db/providers/rocksdb.(*DB).Set(0xc00002c540, 0xc000173528, 0x8, 0x8, 0xc000173530, 0xa, 0x10, 0x0, 0x0)
        /Users/sergio/Code/backend/normalizer-r2d2/pkg/db/providers/rocksdb/rocksdb.go:160 +0x1dd fp=0xc00005eec8 sp=0xc00005ee40 pc=0x4159d7d
main.run(0xc00002c540, 0xc00007c240)
        /Users/sergio/Code/backend/normalizer-r2d2/_examples/foo/main.go:28 +0x2d5 fp=0xc00005efd0 sp=0xc00005eec8 pc=0x415a6b5
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1371 +0x1 fp=0xc00005efd8 sp=0xc00005efd0 pc=0x406a401
created by main.main
        /Users/sergio/Code/backend/normalizer-r2d2/_examples/foo/main.go:62 +0x133

goroutine 1 [runnable]:
github.com/linxGnu/grocksdb._Cfunc_rocksdb_free(0xc510d30)
        _cgo_gotypes.go:2661 +0x3c
github.com/linxGnu/grocksdb.(*Slice).Free.func1(0xc000600000)
        /usr/local/godeps/pkg/mod/github.com/linx!gnu/grocksdb@v1.6.37/slice.go:53 +0x55
github.com/linxGnu/grocksdb.(*Slice).Free(0xc000600000)
        /usr/local/godeps/pkg/mod/github.com/linx!gnu/grocksdb@v1.6.37/slice.go:53 +0x3b
gitlab.com/etoshi/backend/normalizer-r2d2/pkg/db/providers/rocksdb.(*DB).get(0xc00002c540, 0xc000580000, 0x8, 0x8, 0x4051925, 0xc000580010, 0xc00016fe58, 0xa, 0x10)
        /Users/sergio/Code/backend/normalizer-r2d2/pkg/db/providers/rocksdb/rocksdb.go:205 +0x165
gitlab.com/etoshi/backend/normalizer-r2d2/pkg/db/providers/rocksdb.(*DB).Get(0xc00002c540, 0xc000580000, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0)
        /Users/sergio/Code/backend/normalizer-r2d2/pkg/db/providers/rocksdb/rocksdb.go:214 +0xaf
main.run(0xc00002c540, 0xc00007c240)
        /Users/sergio/Code/backend/normalizer-r2d2/_examples/foo/main.go:24 +0x269
main.main()
        /Users/sergio/Code/backend/normalizer-r2d2/_examples/foo/main.go:63 +0x14b

goroutine 6 [chan receive]:
main.main.func1(0xc00007c240, 0xc00002c540)
        /Users/sergio/Code/backend/normalizer-r2d2/_examples/foo/main.go:52 +0x35
created by main.main
        /Users/sergio/Code/backend/normalizer-r2d2/_examples/foo/main.go:51 +0xe5

rax    0x0
rbx    0x700008e78000
rcx    0x700008e77ad8
rdx    0x0
rdi    0x903
rsi    0x6
rbp    0x700008e77b00
rsp    0x700008e77ad8
r8     0x0
r9     0x0
r10    0x700008e78000
r11    0x246
r12    0x903
r13    0x50
r14    0x6
r15    0x16
rip    0x7fff2061092e
rflags 0x246
cs     0x7
fs     0x0
gs     0x0
exit status 2

The panic is only raised when write into a transaction. If i write into db directly works fine.

@savsgio I believe opening TransactionDB and DB is not a good practice and rocksdb also not recommend that. Please use either TransactionDB or DB, not both.