+    def _db_modified(self, maildir, notmuch, ret_prepare=None):
+        # populate the database for the initial query
+        with dbmod.Database.create(maildir.path, config=notmuch2.Database.CONFIG.EMPTY) as db:
+            for i in range(32):
+                pathname = maildir.deliver(body = str(i))[1]
+                msg = db.add(str(pathname))[0]
+                msg.tags.add(str(i))
+
+        with dbmod.Database(maildir.path, 'ro', config=notmuch2.Database.CONFIG.EMPTY) as db:
+            # prepare value to be returned to caller
+            ret = ret_prepare(db) if ret_prepare else db
+
+            # modify the database sufficiently to trigger DatabaseModifiedException
+            for i in range(16):
+                with dbmod.Database(maildir.path, 'rw', config=notmuch2.Database.CONFIG.EMPTY) as db_rw:
+                    pathname = maildir.deliver(body = str(i))[1]
+                    db_rw.add(str(pathname))
+
+            yield ret
+
+    @pytest.fixture
+    def db_modified(self, maildir, notmuch):
+        "A db triggering DatabaseModifiedException."
+        yield from self._db_modified(maildir, notmuch)
+
+    @pytest.fixture
+    def db_modified_messages(self, maildir, notmuch):
+        "A tuple of (db, messages) triggering DatabaseModifiedException."
+        yield from self._db_modified(maildir, notmuch, lambda db: (db, db.messages('*')))
+
+    @pytest.fixture
+    def db_modified_threads(self, maildir, notmuch):
+        "A tuple of (db, threads) triggering DatabaseModifiedException."
+        yield from self._db_modified(maildir, notmuch, lambda db: (db, db.threads('*')))
+