TransactionDB is not safe-concurrent on writes!
savsgio opened this issue · comments
Sergio VS commented
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
Sergio VS commented
The panic is only raised when write into a transaction. If i write into db directly works fine.
Linh Tran Tuan commented
@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.