diff --git a/src/wallet/bdb.h b/src/wallet/bdb.h
--- a/src/wallet/bdb.h
+++ b/src/wallet/bdb.h
@@ -90,6 +90,8 @@
 /** Return whether a BDB wallet database is currently loaded. */
 bool IsBDBWalletLoaded(const fs::path &wallet_path);
 
+class BerkeleyBatch;
+
 /**
  * An instance of this class represents one database.
  * For BerkeleyDB this is just a (env, strFile) tuple.
@@ -172,6 +174,10 @@
      */
     std::unique_ptr<Db> m_db;
 
+    /** Make a BerkeleyBatch connected to this database */
+    std::unique_ptr<BerkeleyBatch> MakeBatch(const char *mode,
+                                             bool flush_on_close);
+
 private:
     std::string strFile;
 
diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp
--- a/src/wallet/bdb.cpp
+++ b/src/wallet/bdb.cpp
@@ -917,3 +917,8 @@
     int ret = pdb->exists(activeTxn, datKey, 0);
     return ret == 0;
 }
+
+std::unique_ptr<BerkeleyBatch>
+BerkeleyDatabase::MakeBatch(const char *mode, bool flush_on_close) {
+    return std::make_unique<BerkeleyBatch>(*this, mode, flush_on_close);
+}
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -180,23 +180,23 @@
 private:
     template <typename K, typename T>
     bool WriteIC(const K &key, const T &value, bool fOverwrite = true) {
-        if (!m_batch.Write(key, value, fOverwrite)) {
+        if (!m_batch->Write(key, value, fOverwrite)) {
             return false;
         }
         m_database.IncrementUpdateCounter();
         if (m_database.nUpdateCounter % 1000 == 0) {
-            m_batch.Flush();
+            m_batch->Flush();
         }
         return true;
     }
 
     template <typename K> bool EraseIC(const K &key) {
-        if (!m_batch.Erase(key)) {
+        if (!m_batch->Erase(key)) {
             return false;
         }
         m_database.IncrementUpdateCounter();
         if (m_database.nUpdateCounter % 1000 == 0) {
-            m_batch.Flush();
+            m_batch->Flush();
         }
         return true;
     }
@@ -204,7 +204,8 @@
 public:
     explicit WalletBatch(WalletDatabase &database, const char *pszMode = "r+",
                          bool _fFlushOnClose = true)
-        : m_batch(database, pszMode, _fFlushOnClose), m_database(database) {}
+        : m_batch(database.MakeBatch(pszMode, _fFlushOnClose)),
+          m_database(database) {}
     WalletBatch(const WalletBatch &) = delete;
     WalletBatch &operator=(const WalletBatch &) = delete;
 
@@ -288,7 +289,7 @@
     bool TxnAbort();
 
 private:
-    BerkeleyBatch m_batch;
+    std::unique_ptr<BerkeleyBatch> m_batch;
     WalletDatabase &m_database;
 };
 
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -138,7 +138,7 @@
     if (!WriteIC(key, std::make_pair(vchCryptedSecret, checksum), false)) {
         // It may already exist, so try writing just the checksum
         std::vector<uint8_t> val;
-        if (!m_batch.Read(key, val)) {
+        if (!m_batch->Read(key, val)) {
             return false;
         }
         if (!WriteIC(key, std::make_pair(val, checksum), true)) {
@@ -182,10 +182,10 @@
 }
 
 bool WalletBatch::ReadBestBlock(CBlockLocator &locator) {
-    if (m_batch.Read(DBKeys::BESTBLOCK, locator) && !locator.vHave.empty()) {
+    if (m_batch->Read(DBKeys::BESTBLOCK, locator) && !locator.vHave.empty()) {
         return true;
     }
-    return m_batch.Read(DBKeys::BESTBLOCK_NOMERKLE, locator);
+    return m_batch->Read(DBKeys::BESTBLOCK_NOMERKLE, locator);
 }
 
 bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext) {
@@ -193,7 +193,7 @@
 }
 
 bool WalletBatch::ReadPool(int64_t nPool, CKeyPool &keypool) {
-    return m_batch.Read(std::make_pair(DBKeys::POOL, nPool), keypool);
+    return m_batch->Read(std::make_pair(DBKeys::POOL, nPool), keypool);
 }
 
 bool WalletBatch::WritePool(int64_t nPool, const CKeyPool &keypool) {
@@ -764,7 +764,7 @@
     LOCK(pwallet->cs_wallet);
     try {
         int nMinVersion = 0;
-        if (m_batch.Read(DBKeys::MINVERSION, nMinVersion)) {
+        if (m_batch->Read(DBKeys::MINVERSION, nMinVersion)) {
             if (nMinVersion > FEATURE_LATEST) {
                 return DBErrors::TOO_NEW;
             }
@@ -772,7 +772,7 @@
         }
 
         // Get cursor
-        if (!m_batch.StartCursor()) {
+        if (!m_batch->StartCursor()) {
             pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
             return DBErrors::CORRUPT;
         }
@@ -782,12 +782,12 @@
             CDataStream ssKey(SER_DISK, CLIENT_VERSION);
             CDataStream ssValue(SER_DISK, CLIENT_VERSION);
             bool complete;
-            bool ret = m_batch.ReadAtCursor(ssKey, ssValue, complete);
+            bool ret = m_batch->ReadAtCursor(ssKey, ssValue, complete);
             if (complete) {
                 break;
             }
             if (!ret) {
-                m_batch.CloseCursor();
+                m_batch->CloseCursor();
                 pwallet->WalletLogPrintf(
                     "Error reading next record from wallet database\n");
                 return DBErrors::CORRUPT;
@@ -822,7 +822,7 @@
     } catch (...) {
         result = DBErrors::CORRUPT;
     }
-    m_batch.CloseCursor();
+    m_batch->CloseCursor();
 
     // Set the active ScriptPubKeyMans
     for (auto spk_man_pair : wss.m_active_external_spks) {
@@ -869,7 +869,7 @@
     // Last client version to open this wallet, was previously the file version
     // number
     int last_client = CLIENT_VERSION;
-    m_batch.Read(DBKeys::VERSION, last_client);
+    m_batch->Read(DBKeys::VERSION, last_client);
 
     int wallet_version = pwallet->GetVersion();
     pwallet->WalletLogPrintf("Wallet File Version = %d\n",
@@ -901,7 +901,7 @@
 
     if (last_client < CLIENT_VERSION) {
         // Update
-        m_batch.Write(DBKeys::VERSION, CLIENT_VERSION);
+        m_batch->Write(DBKeys::VERSION, CLIENT_VERSION);
     }
 
     if (wss.fAnyUnordered) {
@@ -944,14 +944,14 @@
 
     try {
         int nMinVersion = 0;
-        if (m_batch.Read(DBKeys::MINVERSION, nMinVersion)) {
+        if (m_batch->Read(DBKeys::MINVERSION, nMinVersion)) {
             if (nMinVersion > FEATURE_LATEST) {
                 return DBErrors::TOO_NEW;
             }
         }
 
         // Get cursor
-        if (!m_batch.StartCursor()) {
+        if (!m_batch->StartCursor()) {
             LogPrintf("Error getting wallet database cursor\n");
             return DBErrors::CORRUPT;
         }
@@ -961,13 +961,13 @@
             CDataStream ssKey(SER_DISK, CLIENT_VERSION);
             CDataStream ssValue(SER_DISK, CLIENT_VERSION);
             bool complete;
-            bool ret = m_batch.ReadAtCursor(ssKey, ssValue, complete);
+            bool ret = m_batch->ReadAtCursor(ssKey, ssValue, complete);
             if (complete) {
                 break;
             }
 
             if (!ret) {
-                m_batch.CloseCursor();
+                m_batch->CloseCursor();
                 LogPrintf("Error reading next record from wallet database\n");
                 return DBErrors::CORRUPT;
             }
@@ -985,7 +985,7 @@
     } catch (...) {
         result = DBErrors::CORRUPT;
     }
-    m_batch.CloseCursor();
+    m_batch->CloseCursor();
 
     return result;
 }
@@ -1109,15 +1109,15 @@
 }
 
 bool WalletBatch::TxnBegin() {
-    return m_batch.TxnBegin();
+    return m_batch->TxnBegin();
 }
 
 bool WalletBatch::TxnCommit() {
-    return m_batch.TxnCommit();
+    return m_batch->TxnCommit();
 }
 
 bool WalletBatch::TxnAbort() {
-    return m_batch.TxnAbort();
+    return m_batch->TxnAbort();
 }
 
 bool IsWalletLoaded(const fs::path &wallet_path) {