From 6dc724cf03d5792a72f74c73c445c55dc1e2761c Mon Sep 17 00:00:00 2001 From: James Ravn Date: Mon, 6 Apr 2020 22:46:16 +0100 Subject: [PATCH] Clarify transaction section (#59) Even nested read-only transactions can cause deadlocks. This is due to golang's RWMutex behaviour. It doesn't allow readers to acquire a lock if a write lock is pending. It's possible for a child read-only transaction to block trying to acquire `mmaplock.RLock`, while a writer is trying to acquire `mmaplock.Lock`. As a result, the parent transaction never releases its read lock on `mmaplock`, and the application deadlocks. This wasn't clear to me from the provided docs, which just mentions read/write and read transactions being nested. --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2dff376..c9e64b1 100644 --- a/README.md +++ b/README.md @@ -152,11 +152,12 @@ are not thread safe. To work with data in multiple goroutines you must start a transaction for each one or use locking to ensure only one goroutine accesses a transaction at a time. Creating transaction from the `DB` is thread safe. -Read-only transactions and read-write transactions should not depend on one -another and generally shouldn't be opened simultaneously in the same goroutine. -This can cause a deadlock as the read-write transaction needs to periodically -re-map the data file but it cannot do so while a read-only transaction is open. - +Transactions should not depend on one another and generally shouldn't be opened +simultaneously in the same goroutine. This can cause a deadlock as the read-write +transaction needs to periodically re-map the data file but it cannot do so while +any read-only transaction is open. Even a nested read-only transaction can cause +a deadlock, as the child transaction can block the parent transaction from releasing +its resources. #### Read-write transactions