badgerdb生产使用需显式设置dir和valuedir、写操作必须用true参数开启事务、读取值须调用valuecopy、关闭前必须调用close(),否则易致数据丢失、panic或文件损坏。
badgerdb 能直接用作生产级本地 kv 存储,但默认配置下容易因误关数据库或未设值类型导致数据丢失、读取为空或 panic。
打开数据库时必须指定 Dir 和 ValueDir
BadgerDB 区分键索引(Dir)和值存储(ValueDir),两者路径可以相同,但不能省略。若只传一个路径,或传空字符串,badger.Open() 会静默创建临时目录,进程退出后数据即消失。
- 正确写法:
opt := badger.DefaultOptions("/tmp/badger")<br>opt.ValueDir = "/tmp/badger" - 错误写法:
badger.Open(badger.DefaultOptions(""))或badger.Open(badger.DefaultOptions("/tmp/badger"))(没显式设ValueDir) - 若想复用同一目录,务必显式赋值,避免依赖旧版行为
写入前必须用 db.NewTransaction(true) 开启写事务
BadgerDB 不提供直接 Put 接口,所有写操作必须包裹在写事务中。漏掉 true 参数(即传 false)会得到只读事务,调用 Set 时 panic 报错 "cannot perform write on read-only transaction"。
- 写事务:
txn := db.NewTransaction(true)→txn.Set([]byte("k"), []byte("v"))→txn.Commit() - 读事务:
txn := db.NewTransaction(false)→ 只能用Get,不能Set - 忘记
Commit()不会报错,但数据不会落盘;建议用defer txn.Discard()配合if err != nil提前返回
读取值需手动调用 Item.ValueCopy(nil)
BadgerDB 的 Item.Value() 返回的是内部内存切片,生命周期绑定于事务。事务结束后再访问该切片会读到脏数据或 panic。必须用 ValueCopy 拷贝一份独立副本。
- 安全读法:
item, err := txn.Get([]byte("k"))<br>if err == nil {<br> val, err := item.ValueCopy(nil)<br> if err == nil {<br> fmt.Printf("%s", val) // val 是独立字节切片<br> }<br>} - 危险写法:
item.Value()直接用在txn.Commit()之后 → 数据可能已被覆写 -
ValueCopy(nil)内部会分配新内存,无需预估长度;传非nil切片可复用底层数组,但要注意容量是否足够
关闭数据库前必须调用 db.Close(),且不能重复 Close
BadgerDB 使用 mmap 和后台 goroutine 管理文件,不调用 Close() 就退出进程,会导致 value log 文件损坏、下次启动失败(报错 "manifest has unsupported version" 或 "checksum mismatch")。重复 Close() 会 panic。
- 务必在程序退出前(如
main结束、signal.Notify捕获SIGINT后)调用一次db.Close() - 不要在 defer 中对全局
*badger.DB多次 deferClose(),容易重复调用 - 如果用
panic流程控制,需确保Close()在 recover 前已执行
最常被跳过的其实是 ValueDir 显式设置和 ValueCopy —— 这两个点不踩坑,BadgerDB 的本地 KV 就算稳住了。











