bmatsuo / lmdb-go

Bindings for the LMDB C library
BSD 3-Clause "New" or "Revised" License
157 stars 59 forks source link

How offset and when should ReaderCheck be called? #82

Closed ghost closed 8 years ago

ghost commented 8 years ago

Should I call ReaderCheck everytime before

func (env *Env) Update(fn TxnOp) error 

and

func (env *Env) View(fn TxnOp) error 
lmb commented 8 years ago

No, managed transactions know how to clean up after themselves. If you are worried about crashed processes you can just call ReaderCheck once, after you have opened the DB. That way stale reader slots from a crashed process will be cleaned.

bmatsuo commented 8 years ago

@lmdb I don't think that's completely correct. If a single (daemon) process accesses the database then yes, calling ReaderCheck once when the process starts should be sufficient. As long as the process does not leak view transactions (by misusing the API for unmanaged Txns) then the process would be wasting cycles calling ReaderCheck again later in the same lifecycle.

@zwb-ict If multiple processes access the database environment concurrently then I think it's wise for all processing which create update Txns to call ReaderCheck periodically. But I would not suggest calling it for every write. The frequency with which the method must be called is application specific.

edit: reader processes should also check for stale readers at startup, later during runtime as well if unmanaged view transactions are used.

A method I have used in the past to call ReaderCheck is to call it repeatedly from its own goroutine in a loop triggered by a time.Tick channel. You may choose a duration for the channel timer that works for your application.

edit: YMMV with the above technique. There are other ways to implement periodic checks.

Good luck.

ghost commented 8 years ago

@bmatsuo Can env be used between multi goroutine and why? It seems that txn cann't

A thread can only use one transaction at a time, plus any child transactions. Each transaction belongs to one thread.

bmatsuo commented 8 years ago

@zwb-ict Yes, an Env type can be used from multiple goroutines. And in general, as you point out, Txn objects cannot be shared between goroutines (it doesn't matter if you synchronize their usage or not.

However, a View Txn (Readonly) may be used in multiple goroutines as long as the uses are synchronized in some way. This is because lmdb-go made the decision to open every Env with the C flag MDB_NOTLS. This is documented in the godoc for Env.Open.

This detail is discussed immediately following the passage you have quoted.

A thread can only use one transaction at a time, plus any child transactions. Each transaction belongs to one thread. See below. The #MDB_NOTLS flag changes this for read-only transactions.

You can see more information about MDB_NOTLS in the documentation for mdb_env_open. I hope this helps.

ghost commented 8 years ago

@lmb @bmatsuo Thank you.