bmatsuo / lmdb-go

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

How readonly txn.Reset and txn.Renew use? #86

Closed ghost closed 7 years ago

ghost commented 8 years ago

I create a read-only txn in a goroutine, then this txn will called in another goroutine frequently.

The scene is:

  1. four writer goroutines write to the db, then four reader goroutines read this db(this four readers don't share txn.)
  2. each time, a reader read some data from db (such as 20 key one time),if db has not enough data, return, after 50ms, read again.

so I call txn.Reset after I create txn in a goroutine, before read call txn.Renew, after read call txn.Reset again. But some time, txn.Renew return error:

mdb_cursor_renew: invalid argument

So

  1. How to use these two funcs?
  2. Need I call cursor.Renew after txn.Renew?
bmatsuo commented 8 years ago

So are you using a cursor in your read transactions? I'm not immediately sure why mdb_cursor_renew is in that error message.

The order of txn operations sounds fine... Begin, Reset, Renew, Get, Reset, Renew, Get, Reset, Renew, ..., Abort. If cursors are not involved I believe that should work.

When you are using cursors you should make sure to call txn.Renew() before calling cursor.Renew(txn) -- make sure the transaction you are giving the cursor is "open". If you call those methods in reverse order you will probably get an error like the one you provided.

ghost commented 8 years ago

@bmatsuo after txn.Reset and before txn.Renew, may GC free this txn?

bmatsuo commented 8 years ago

@zwb-ict no, the GC will not free the txn. As far as I know the primary benefit of reseting/renewing transactions is to reduce allocations and bookkeeping. It wouldn't be very useful if the GC destroyed the transaction between calls.

You should also make sure that txn.Abort() is called when you are done with the Txn object because the C library needs to clean up the transaction and do its final bookkeeping.

ghost commented 7 years ago

@bmatsuo this caused by open the same env in multi goroutines.