Skip to content

Deadlock when updating keys while iterating over them #315

@jogramming

Description

@jogramming

I don't see it stated anywhere that updating values while iterating isn't supported, so i'm assuming i'm not doing anything wrong?

Using the latest git version as of typing.

Running the following for a while (usually 10 seconds for me) will cause a deadlock (when the counter stays at 0 every second):

package main

import (
	"fmt"
	"github.com/dgraph-io/badger"
	"math/rand"
	"os"
	"os/signal"
	"sync/atomic"
	"syscall"
	"time"
)

var (
	DB          *badger.DB
	updateCount = new(int64)
)

func panicErr(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	opts := badger.DefaultOptions
	opts.Dir = "db"
	opts.ValueDir = "db"
	opts.SyncWrites = false

	var err error
	DB, err = badger.Open(opts)
	panicErr(err)

	Load(0, 0xffff)
	go ReaderWriter()

	sc := make(chan os.Signal, 1)
	signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)

	ticker := time.NewTicker(time.Second)
	for {
		select {
		case <-sc:
			DB.Close()
			return
		case <-ticker.C:
			numRead := atomic.SwapInt64(updateCount, 0)
			fmt.Println("Read: ", numRead)
		}
	}
}

const vauleSize = 0xff

func Load(startOffset int64, amount int64) {

	d := make([]byte, vauleSize)

	for i := int64(0); i < amount; i++ {
		panicErr(DB.Update(func(txn *badger.Txn) error {
			rand.Read(d)
			return txn.Set([]byte(fmt.Sprint(i+startOffset)), d)
		}))
	}
}

func ReaderWriter() {
	for {
		// Iterate over the db reading and upadting values
		err := DB.Update(func(txn *badger.Txn) error {

			opts := badger.DefaultIteratorOptions
			opts.PrefetchValues = false
			it := txn.NewIterator(opts)
			defer it.Close()
			i := 0
			for it.Rewind(); it.Valid(); it.Next() {

				i++
				if i >= 100000 {
					break
				}

				atomic.AddInt64(updateCount, 1)

				item := it.Item()
				key := item.Key()

				newValue := make([]byte, vauleSize)
				rand.Read(newValue)
				item.Value()
				err := txn.Set(key, newValue)
				if err != nil {
					return err
				}
			}

			return nil
		})
		panicErr(err)
	}
}

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions