Go LevelDB中重复键的覆盖/抛出错误

When using the following code below I expect to have only one entry in the db. I use the syndtr/goleveldb LevelDB implementation for Go.

for count := 0; count < 5; count++ {
    err := db.Put([]byte("key"), []byte("value"))
    if err != nil {
        t.Error(err)
    }
}

Instead, a hexdump reveals that there are 5 entries:

00000000  a8 ef d2 d4 17 00 01 01  00 00 00 00 00 00 00 01  |................|
00000010  00 00 00 01 03 6b 65 79  05 76 61 6c 75 65 10 23  |.....key.value.#|
00000020  44 b5 17 00 01 02 00 00  00 00 00 00 00 01 00 00  |D...............|
00000030  00 01 03 6b 65 79 05 76  61 6c 75 65 77 be 34 95  |...key.valuew.4.|
00000040  17 00 01 03 00 00 00 00  00 00 00 01 00 00 00 01  |................|
00000050  03 6b 65 79 05 76 61 6c  75 65 08 35 86 60 17 00  |.key.value.5.`..|
00000060  01 04 00 00 00 00 00 00  00 01 00 00 00 01 03 6b  |...............k|
00000070  65 79 05 76 61 6c 75 65  6f 8c f6 00 17 00 01 05  |ey.valueo.......|
00000080  00 00 00 00 00 00 00 01  00 00 00 01 03 6b 65 79  |.............key|
00000090  05 76 61 6c 75 65                                 |.value|
00000096

From my understanding LevelDB should by default overwrite any duplicate key or at least throw an error.

How can I control when the value gets overwritten or how can I get an error (other than checking db.Has(key) every time that I db.Put(key)? Does compaction have anything to do with this?

1个回答

LevelDB is a log-structured merge-tree and has transaction logs (the ones you were inspecting with hexdump). With this code you can validate that only one value is present for your key:

package main

import ( "fmt"
"github.com/syndtr/goleveldb/leveldb"
)

func main () {
        db, err := leveldb.OpenFile("mydb.test", nil)
        if err != nil { fmt.Println(err) }

        for count := 0; count < 5; count++ {
                err := db.Put([]byte("keys"), []byte("values"), nil)
                if err != nil {
                    fmt.Println(err)
                }
        }

        iter := db.NewIterator(nil, nil)
        for iter.Next() {
                key := iter.Key()
                value := iter.Value()
                fmt.Println(string(key), string(value))
        }
        iter.Release()

        defer db.Close()
}

How can I control when the value gets overwritten?

You can't, if the key is present, its value gets overwritten

立即提问
相关内容推荐