Problem: gettxoutsetinfo, scantxoutset, and dumptxoutset retain LevelDB iterators after releasing cs_main.
While those iterators are live, AssumeUTXO cache rebalancing can call ResizeCache(), replace m_db, and cause LevelDB to abort.
The issue was [reported during review of #35465](https://github.com/bitcoin/bitcoin/pull/35465#discussion_r3428902672).
Fix: Each cursor holds a shared lock on m_db_mutex for its lifetime.
Compaction takes the same shared lock, allowing it to run alongside cursors.
ResizeCache() takes the lock exclusively and waits for both before replacing m_db.
Checked shared-lock wrappers and non-LIFO lock tracking preserve Core's locking diagnostics, including for the existing signature-cache and parallel cuckoo-cache users migrated in this series.
Risk: ResizeCache() holds cs_main while it waits, so a long-running UTXO scan can stall validation, message processing, and RPCs that need that lock during cache rebalancing.
Current callers destroy cursors on the thread that created them. A cursor holder must not acquire cs_main unless it already holds it.
This is a concrete example of the lifetime interactions created by rebalancing the snapshot and background chainstates, as discussed in #35054. The fix protects the current lifecycle and can be reviewed independently of the discussion about making snapshot trust explicit and simplifying background validation in #32377.