diff --git a/src/third_party/wiredtiger/src/btree/bt_cursor.c b/src/third_party/wiredtiger/src/btree/bt_cursor.c
index 1f3ac44..018eb6e 100644
--- a/src/third_party/wiredtiger/src/btree/bt_cursor.c
+++ b/src/third_party/wiredtiger/src/btree/bt_cursor.c
@@ -325,7 +325,7 @@ __wt_btcur_search(WT_CURSOR_BTREE *cbt)
 	valid = false;
 	if (F_ISSET(cbt, WT_CBT_ACTIVE) &&
 	    cbt->ref->page->read_gen != WT_READGEN_OLDEST) {
-		__wt_txn_cursor_op(session);
+		WT_ERR(__wt_txn_cursor_op(session));
 
 		WT_ERR(btree->type == BTREE_ROW ?
 		    __cursor_row_search(session, cbt, cbt->ref, false) :
@@ -405,7 +405,7 @@ __wt_btcur_search_near(WT_CURSOR_BTREE *cbt, int *exactp)
 	if (btree->type == BTREE_ROW &&
 	    F_ISSET(cbt, WT_CBT_ACTIVE) &&
 	    cbt->ref->page->read_gen != WT_READGEN_OLDEST) {
-		__wt_txn_cursor_op(session);
+		WT_ERR(__wt_txn_cursor_op(session));
 
 		WT_ERR(__cursor_row_search(session, cbt, cbt->ref, true));
 
diff --git a/src/third_party/wiredtiger/src/btree/bt_read.c b/src/third_party/wiredtiger/src/btree/bt_read.c
index 5cf6a9b..6a12036 100644
--- a/src/third_party/wiredtiger/src/btree/bt_read.c
+++ b/src/third_party/wiredtiger/src/btree/bt_read.c
@@ -326,7 +326,7 @@ __evict_force_check(WT_SESSION_IMPL *session, WT_REF *ref)
 	__wt_page_evict_soon(page);
 
 	/* Bump the oldest ID, we're about to do some visibility checks. */
-	__wt_txn_update_oldest(session, false);
+	WT_RET(__wt_txn_update_oldest(session, false));
 
 	/* If eviction cannot succeed, don't try. */
 	return (__wt_page_can_evict(session, ref, NULL));
diff --git a/src/third_party/wiredtiger/src/btree/bt_sync.c b/src/third_party/wiredtiger/src/btree/bt_sync.c
index 826589f..5d60c43 100644
--- a/src/third_party/wiredtiger/src/btree/bt_sync.c
+++ b/src/third_party/wiredtiger/src/btree/bt_sync.c
@@ -81,7 +81,7 @@ __sync_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
 			if (__wt_page_is_modified(page) &&
 			    WT_TXNID_LT(page->modify->update_txn, oldest_id)) {
 				if (txn->isolation == WT_ISO_READ_COMMITTED)
-					__wt_txn_get_snapshot(session);
+					WT_ERR(__wt_txn_get_snapshot(session));
 				leaf_bytes += page->memory_footprint;
 				++leaf_pages;
 				WT_ERR(__wt_reconcile(session, walk, NULL, 0));
@@ -100,7 +100,7 @@ __sync_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
 		 * the metadata shouldn't be that big, and (b) if we do ever
 		 */
 		if (txn->isolation == WT_ISO_READ_COMMITTED)
-			__wt_txn_get_snapshot(session);
+			WT_ERR(__wt_txn_get_snapshot(session));
 
 		/*
 		 * We cannot check the tree modified flag in the case of a
diff --git a/src/third_party/wiredtiger/src/conn/conn_open.c b/src/third_party/wiredtiger/src/conn/conn_open.c
index 38c3288..f5722d3 100644
--- a/src/third_party/wiredtiger/src/conn/conn_open.c
+++ b/src/third_party/wiredtiger/src/conn/conn_open.c
@@ -93,7 +93,7 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
 	 * transaction ID will catch up with the current ID.
 	 */
 	for (;;) {
-		__wt_txn_update_oldest(session, true);
+		WT_TRET(__wt_txn_update_oldest(session, true));
 		if (txn_global->oldest_id == txn_global->current)
 			break;
 		__wt_yield();
diff --git a/src/third_party/wiredtiger/src/cursor/cur_ds.c b/src/third_party/wiredtiger/src/cursor/cur_ds.c
index 804c24a..d2b8d81 100644
--- a/src/third_party/wiredtiger/src/cursor/cur_ds.c
+++ b/src/third_party/wiredtiger/src/cursor/cur_ds.c
@@ -16,7 +16,7 @@ static int
 __curds_txn_enter(WT_SESSION_IMPL *session)
 {
 	session->ncursors++;				/* XXX */
-	__wt_txn_cursor_op(session);
+	WT_RET(__wt_txn_cursor_op(session));
 
 	return (0);
 }
diff --git a/src/third_party/wiredtiger/src/evict/evict_file.c b/src/third_party/wiredtiger/src/evict/evict_file.c
index ca98b1b..1da2e95 100644
--- a/src/third_party/wiredtiger/src/evict/evict_file.c
+++ b/src/third_party/wiredtiger/src/evict/evict_file.c
@@ -26,7 +26,7 @@ __wt_evict_file(WT_SESSION_IMPL *session, WT_CACHE_OP syncop)
 	WT_RET(__wt_evict_file_exclusive_on(session));
 
 	/* Make sure the oldest transaction ID is up-to-date. */
-	__wt_txn_update_oldest(session, true);
+	WT_RET(__wt_txn_update_oldest(session, true));
 
 	/* Walk the tree, discarding pages. */
 	next_ref = NULL;
diff --git a/src/third_party/wiredtiger/src/evict/evict_lru.c b/src/third_party/wiredtiger/src/evict/evict_lru.c
index d3e32d7..be8cc1d 100644
--- a/src/third_party/wiredtiger/src/evict/evict_lru.c
+++ b/src/third_party/wiredtiger/src/evict/evict_lru.c
@@ -594,7 +594,7 @@ __evict_pass(WT_SESSION_IMPL *session)
 		 * of whether the cache is full, to prevent the oldest ID
 		 * falling too far behind.
 		 */
-		__wt_txn_update_oldest(session, true);
+		WT_RET(__wt_txn_update_oldest(session, loop > 0));
 
 		if (!__evict_update_work(session))
 			break;
diff --git a/src/third_party/wiredtiger/src/evict/evict_page.c b/src/third_party/wiredtiger/src/evict/evict_page.c
index f0d4752..2d20f53 100644
--- a/src/third_party/wiredtiger/src/evict/evict_page.c
+++ b/src/third_party/wiredtiger/src/evict/evict_page.c
@@ -420,7 +420,7 @@ __evict_review(
 		 * fallen behind current.
 		 */
 		if (modified)
-			__wt_txn_update_oldest(session, true);
+			WT_RET(__wt_txn_update_oldest(session, false));
 
 		if (!__wt_page_can_evict(session, ref, inmem_splitp))
 			return (EBUSY);
diff --git a/src/third_party/wiredtiger/src/include/cursor.i b/src/third_party/wiredtiger/src/include/cursor.i
index 8ab96c0..553dd03 100644
--- a/src/third_party/wiredtiger/src/include/cursor.i
+++ b/src/third_party/wiredtiger/src/include/cursor.i
@@ -270,7 +270,7 @@ __cursor_func_init(WT_CURSOR_BTREE *cbt, bool reenter)
 	 * to read.
 	 */
 	if (!F_ISSET(cbt, WT_CBT_NO_TXN))
-		__wt_txn_cursor_op(session);
+		WT_RET(__wt_txn_cursor_op(session));
 	return (0);
 }
 
diff --git a/src/third_party/wiredtiger/src/include/extern.h b/src/third_party/wiredtiger/src/include/extern.h
index 292bcfb..7927005 100644
--- a/src/third_party/wiredtiger/src/include/extern.h
+++ b/src/third_party/wiredtiger/src/include/extern.h
@@ -676,8 +676,8 @@ extern void __wt_stat_join_clear_single(WT_JOIN_STATS *stats);
 extern void __wt_stat_join_clear_all(WT_JOIN_STATS **stats);
 extern void __wt_stat_join_aggregate( WT_JOIN_STATS **from, WT_JOIN_STATS *to);
 extern void __wt_txn_release_snapshot(WT_SESSION_IMPL *session);
-extern void __wt_txn_get_snapshot(WT_SESSION_IMPL *session);
-extern void __wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force);
+extern int __wt_txn_get_snapshot(WT_SESSION_IMPL *session);
+extern int __wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force);
 extern int __wt_txn_config(WT_SESSION_IMPL *session, const char *cfg[]);
 extern void __wt_txn_release(WT_SESSION_IMPL *session);
 extern int __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]);
diff --git a/src/third_party/wiredtiger/src/include/serial.i b/src/third_party/wiredtiger/src/include/serial.i
index fa920de..c0cd9c8 100644
--- a/src/third_party/wiredtiger/src/include/serial.i
+++ b/src/third_party/wiredtiger/src/include/serial.i
@@ -306,7 +306,7 @@ __wt_update_serial(WT_SESSION_IMPL *session, WT_PAGE *page,
 	if ((txn = page->modify->obsolete_check_txn) != WT_TXN_NONE) {
 		if (!__wt_txn_visible_all(session, txn)) {
 			/* Try to move the oldest ID forward and re-check. */
-			__wt_txn_update_oldest(session, false);
+			WT_RET(__wt_txn_update_oldest(session, false));
 
 			if (!__wt_txn_visible_all(session, txn))
 				return (0);
diff --git a/src/third_party/wiredtiger/src/include/txn.h b/src/third_party/wiredtiger/src/include/txn.h
index 1e82e2d..d10738c 100644
--- a/src/third_party/wiredtiger/src/include/txn.h
+++ b/src/third_party/wiredtiger/src/include/txn.h
@@ -74,7 +74,7 @@ struct __wt_txn_global {
 	volatile uint64_t current;	/* Current transaction ID. */
 
 	/* The oldest running transaction ID (may race). */
-	uint64_t last_running;
+	volatile uint64_t last_running;
 
 	/*
 	 * The oldest transaction ID that is not yet visible to some
@@ -82,8 +82,11 @@ struct __wt_txn_global {
 	 */
 	volatile uint64_t oldest_id;
 
-	/* Count of scanning threads, or -1 for exclusive access. */
-	volatile int32_t scan_count;
+	/*
+	 * Prevents the oldest ID moving forwards while threads are scanning
+	 * the global transaction state.
+	 */
+	WT_RWLOCK *scan_rwlock;
 
 	/*
 	 * Track information about the running checkpoint. The transaction
diff --git a/src/third_party/wiredtiger/src/include/txn.i b/src/third_party/wiredtiger/src/include/txn.i
index f5ca44c..96f7426 100644
--- a/src/third_party/wiredtiger/src/include/txn.i
+++ b/src/third_party/wiredtiger/src/include/txn.i
@@ -261,14 +261,14 @@ __wt_txn_begin(WT_SESSION_IMPL *session, const char *cfg[])
 		 * eviction, it's better to do it beforehand.
 		 */
 		WT_RET(__wt_cache_eviction_check(session, false, NULL));
-
-		__wt_txn_get_snapshot(session);
+		WT_RET(__wt_txn_get_snapshot(session));
 	}
 
 	F_SET(txn, WT_TXN_RUNNING);
 	if (F_ISSET(S2C(session), WT_CONN_READONLY))
 		F_SET(txn, WT_TXN_READONLY);
-	return (false);
+
+	return (0);
 }
 
 /*
@@ -450,7 +450,7 @@ __wt_txn_read_last(WT_SESSION_IMPL *session)
  * __wt_txn_cursor_op --
  *	Called for each cursor operation.
  */
-static inline void
+static inline int
 __wt_txn_cursor_op(WT_SESSION_IMPL *session)
 {
 	WT_TXN *txn;
@@ -482,7 +482,9 @@ __wt_txn_cursor_op(WT_SESSION_IMPL *session)
 		if (txn_state->snap_min == WT_TXN_NONE)
 			txn_state->snap_min = txn_global->last_running;
 	} else if (!F_ISSET(txn, WT_TXN_HAS_SNAPSHOT))
-		__wt_txn_get_snapshot(session);
+		WT_RET(__wt_txn_get_snapshot(session));
+
+	return (0);
 }
 
 /*
diff --git a/src/third_party/wiredtiger/src/lsm/lsm_cursor.c b/src/third_party/wiredtiger/src/lsm/lsm_cursor.c
index e023b2b..9ca850d 100644
--- a/src/third_party/wiredtiger/src/lsm/lsm_cursor.c
+++ b/src/third_party/wiredtiger/src/lsm/lsm_cursor.c
@@ -210,7 +210,7 @@ __clsm_enter(WT_CURSOR_LSM *clsm, bool reset, bool update)
 				goto open;
 
 			if (txn->isolation == WT_ISO_SNAPSHOT)
-				__wt_txn_cursor_op(session);
+				WT_RET(__wt_txn_cursor_op(session));
 
 			/*
 			 * Figure out how many updates are required for
diff --git a/src/third_party/wiredtiger/src/lsm/lsm_work_unit.c b/src/third_party/wiredtiger/src/lsm/lsm_work_unit.c
index 87771e2..51cf2e9 100644
--- a/src/third_party/wiredtiger/src/lsm/lsm_work_unit.c
+++ b/src/third_party/wiredtiger/src/lsm/lsm_work_unit.c
@@ -289,7 +289,7 @@ __wt_lsm_checkpoint_chunk(WT_SESSION_IMPL *session,
 	}
 
 	/* Stop if a running transaction needs the chunk. */
-	__wt_txn_update_oldest(session, true);
+	WT_RET(__wt_txn_update_oldest(session, true));
 	if (chunk->switch_txn == WT_TXN_NONE ||
 	    !__wt_txn_visible_all(session, chunk->switch_txn)) {
 		WT_RET(__wt_verbose(session, WT_VERB_LSM,
diff --git a/src/third_party/wiredtiger/src/txn/txn.c b/src/third_party/wiredtiger/src/txn/txn.c
index 7a768a8..ab1cd62 100644
--- a/src/third_party/wiredtiger/src/txn/txn.c
+++ b/src/third_party/wiredtiger/src/txn/txn.c
@@ -108,17 +108,17 @@ __wt_txn_release_snapshot(WT_SESSION_IMPL *session)
  * __wt_txn_get_snapshot --
  *	Allocate a snapshot.
  */
-void
+int
 __wt_txn_get_snapshot(WT_SESSION_IMPL *session)
 {
 	WT_CONNECTION_IMPL *conn;
+	WT_DECL_RET;
 	WT_TXN *txn;
 	WT_TXN_GLOBAL *txn_global;
 	WT_TXN_STATE *s, *txn_state;
 	uint64_t current_id, id;
 	uint64_t prev_oldest_id, snap_min;
 	uint32_t i, n, session_cnt;
-	int32_t count;
 
 	conn = S2C(session);
 	txn = &session->txn;
@@ -126,15 +126,13 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session)
 	txn_state = WT_SESSION_TXN_STATE(session);
 
 	/*
-	 * We're going to scan.  Increment the count of scanners to prevent the
-	 * oldest ID from moving forwards.  Spin if the count is negative,
-	 * which indicates that some thread is moving the oldest ID forwards.
+	 * Spin waiting for the lock: the sleeps in our blocking readlock
+	 * implementation are too slow for scanning the transaction table.
 	 */
-	do {
-		if ((count = txn_global->scan_count) < 0)
-			WT_PAUSE();
-	} while (count < 0 ||
-	    !__wt_atomic_casiv32(&txn_global->scan_count, count, count + 1));
+	while ((ret =
+	    __wt_try_readlock(session, txn_global->scan_rwlock)) == EBUSY)
+		WT_PAUSE();
+	WT_RET(ret);
 
 	current_id = snap_min = txn_global->current;
 	prev_oldest_id = txn_global->oldest_id;
@@ -145,11 +143,9 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session)
 		__txn_sort_snapshot(session, 0, current_id);
 
 		/* Check that the oldest ID has not moved in the meantime. */
-		if (prev_oldest_id == txn_global->oldest_id) {
-			WT_ASSERT(session, txn_global->scan_count > 0);
-			(void)__wt_atomic_subiv32(&txn_global->scan_count, 1);
-			return;
-		}
+		WT_ASSERT(session, prev_oldest_id == txn_global->oldest_id);
+		WT_RET(__wt_readunlock(session, txn_global->scan_rwlock));
+		return (0);
 	}
 
 	/* Walk the array of concurrent transactions. */
@@ -182,67 +178,35 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session)
 	WT_ASSERT(session, prev_oldest_id == txn_global->oldest_id);
 	txn_state->snap_min = snap_min;
 
-	WT_ASSERT(session, txn_global->scan_count > 0);
-	(void)__wt_atomic_subiv32(&txn_global->scan_count, 1);
+	WT_RET(__wt_readunlock(session, txn_global->scan_rwlock));
 
 	__txn_sort_snapshot(session, n, current_id);
+	return (0);
 }
 
 /*
- * __wt_txn_update_oldest --
- *	Sweep the running transactions to update the oldest ID required.
- * !!!
- * If a data-source is calling the WT_EXTENSION_API.transaction_oldest
- * method (for the oldest transaction ID not yet visible to a running
- * transaction), and then comparing that oldest ID against committed
- * transactions to see if updates for a committed transaction are still
- * visible to running transactions, the oldest transaction ID may be
- * the same as the last committed transaction ID, if the transaction
- * state wasn't refreshed after the last transaction committed.  Push
- * past the last committed transaction.
-*/
-void
-__wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force)
+ * __txn_oldest_scan --
+ *	Sweep the running transactions to calculate the oldest ID required.
+ */
+static void
+__txn_oldest_scan(WT_SESSION_IMPL *session,
+    uint64_t *oldest_idp, uint64_t *last_runningp,
+    WT_SESSION_IMPL **oldest_sessionp)
 {
 	WT_CONNECTION_IMPL *conn;
 	WT_SESSION_IMPL *oldest_session;
 	WT_TXN_GLOBAL *txn_global;
 	WT_TXN_STATE *s;
-	uint64_t current_id, id, last_running, oldest_id, prev_oldest_id;
+	uint64_t id, last_running, oldest_id, prev_oldest_id;
 	uint32_t i, session_cnt;
-	int32_t count;
-	bool last_running_moved;
 
 	conn = S2C(session);
 	txn_global = &conn->txn_global;
-
-retry:
-	current_id = last_running = txn_global->current;
 	oldest_session = NULL;
-	prev_oldest_id = txn_global->oldest_id;
 
-	/*
-	 * For pure read-only workloads, or if the update isn't forced and the
-	 * oldest ID isn't too far behind, avoid scanning.
-	 */
-	if (prev_oldest_id == current_id ||
-	    (!force && WT_TXNID_LT(current_id, prev_oldest_id + 100)))
-		return;
-
-	/*
-	 * We're going to scan.  Increment the count of scanners to prevent the
-	 * oldest ID from moving forwards.  Spin if the count is negative,
-	 * which indicates that some thread is moving the oldest ID forwards.
-	 */
-	do {
-		if ((count = txn_global->scan_count) < 0)
-			WT_PAUSE();
-	} while (count < 0 ||
-	    !__wt_atomic_casiv32(&txn_global->scan_count, count, count + 1));
-
-	/* The oldest ID cannot change until the scan count goes to zero. */
+	/* The oldest ID cannot change while we are holding the scan lock. */
 	prev_oldest_id = txn_global->oldest_id;
-	current_id = oldest_id = last_running = txn_global->current;
+	oldest_id = last_running = txn_global->current;
 
 	/* Walk the array of concurrent transactions. */
 	WT_ORDERED_READ(session_cnt, conn->session_cnt);
@@ -264,7 +228,7 @@ retry:
 		 * !!!
 		 * Note: Don't ignore snap_min values older than the previous
 		 * oldest ID.  Read-uncommitted operations publish snap_min
-		 * values without incrementing scan_count to protect the global
+		 * values without acquiring the scan lock to protect the global
 		 * table.  See the comment in __wt_txn_cursor_op for
 		 * more details.
 		 */
@@ -283,76 +247,118 @@ retry:
 	    WT_TXNID_LT(id, oldest_id))
 		oldest_id = id;
 
-	/* Update the last running ID. */
-	last_running_moved =
-	    WT_TXNID_LT(txn_global->last_running, last_running);
+	*oldest_idp = oldest_id;
+	*oldest_sessionp = oldest_session;
+	*last_runningp = last_running;
+}
 
-	/* Update the oldest ID. */
-	if (WT_TXNID_LT(prev_oldest_id, oldest_id) || last_running_moved) {
-		/*
-		 * We know we want to update.  Check if we're racing.
-		 */
-		if (__wt_atomic_casiv32(&txn_global->scan_count, 1, -1)) {
-			WT_ORDERED_READ(session_cnt, conn->session_cnt);
-			for (i = 0, s = txn_global->states;
-			    i < session_cnt; i++, s++) {
-				if ((id = s->id) != WT_TXN_NONE &&
-				WT_TXNID_LT(id, last_running))
-					last_running = id;
-				if ((id = s->snap_min) != WT_TXN_NONE &&
-				WT_TXNID_LT(id, oldest_id))
-					oldest_id = id;
-			}
-
-			if (WT_TXNID_LT(last_running, oldest_id))
-				oldest_id = last_running;
+/*
+ * __wt_txn_update_oldest --
+ *	Sweep the running transactions to update the oldest ID required.
+ */
+int
+__wt_txn_update_oldest(WT_SESSION_IMPL *session, bool force)
+{
+	WT_CONNECTION_IMPL *conn;
+	WT_DECL_RET;
+	WT_SESSION_IMPL *oldest_session;
+	WT_TXN_GLOBAL *txn_global;
+	uint64_t current_id, last_running, oldest_id;
+	uint64_t prev_last_running, prev_oldest_id;
+
+	conn = S2C(session);
+	txn_global = &conn->txn_global;
+
+	current_id = last_running = txn_global->current;
+	prev_last_running = txn_global->last_running;
+	prev_oldest_id = txn_global->oldest_id;
+
+	/*
+	 * For pure read-only workloads, or if the update isn't forced and the
+	 * oldest ID isn't too far behind, avoid scanning.
+	 */
+	if (prev_oldest_id == current_id ||
+	    (!force && WT_TXNID_LT(current_id, prev_oldest_id + 100)))
+		return (0);
+
+	/* First do a read-only scan. */
+	if (force)
+		WT_RET(__wt_readlock(session, txn_global->scan_rwlock));
+	else if ((ret =
+	    __wt_try_readlock(session, txn_global->scan_rwlock)) != 0)
+		return (ret == EBUSY ? 0 : ret);
+	__txn_oldest_scan(session, &oldest_id, &last_running, &oldest_session);
+	WT_RET(__wt_readunlock(session, txn_global->scan_rwlock));
+
+	/*
+	 * If the state hasn't changed (or hasn't moved far enough for
+	 * non-forced updates), give up.
+	 */
+	if ((oldest_id == prev_oldest_id ||
+	    (!force && WT_TXNID_LT(oldest_id, prev_oldest_id + 100))) &&
+	    ((last_running == prev_last_running) ||
+	    (!force && WT_TXNID_LT(last_running, prev_last_running + 100))))
+		return (0);
+
+	/* It looks like an update is necessary, wait for exclusive access. */
+	if (force)
+		WT_RET(__wt_writelock(session, txn_global->scan_rwlock));
+	else if ((ret =
+	    __wt_try_writelock(session, txn_global->scan_rwlock)) != 0)
+		return (ret == EBUSY ? 0 : ret);
+
+	/*
+	 * If the oldest ID has been updated while we waited, don't bother
+	 * scanning.
+	 */
+	if (WT_TXNID_LE(oldest_id, txn_global->oldest_id) &&
+	    WT_TXNID_LE(last_running, txn_global->last_running))
+		goto done;
+
+	/*
+	 * Re-scan now that we have exclusive access.  This is necessary because
+	 * threads get transaction snapshots with read locks, and we have to be
+	 * sure that there isn't a thread that has got a snapshot locally but
+	 * not yet published its snap_min.
+	 */
+	__txn_oldest_scan(session, &oldest_id, &last_running, &oldest_session);
 
 #ifdef HAVE_DIAGNOSTIC
-			/*
-			 * Make sure the ID doesn't move past any named
-			 * snapshots.
-			 *
-			 * Don't include the read/assignment in the assert
-			 * statement.  Coverity complains if there are
-			 * assignments only done in diagnostic builds, and
-			 * when the read is from a volatile.
-			 */
-			id = txn_global->nsnap_oldest_id;
-			WT_ASSERT(session,
-			    id == WT_TXN_NONE || !WT_TXNID_LT(id, oldest_id));
+	{
+	/*
+	 * Make sure the ID doesn't move past any named snapshots.
+	 *
+	 * Don't include the read/assignment in the assert statement.  Coverity
+	 * complains if there are assignments only done in diagnostic builds,
+	 * and when the read is from a volatile.
+	 */
+	uint64_t id = txn_global->nsnap_oldest_id;
+	WT_ASSERT(session,
+	    id == WT_TXN_NONE || !WT_TXNID_LT(id, oldest_id));
+	}
 #endif
-			if (WT_TXNID_LT(txn_global->last_running, last_running))
-				txn_global->last_running = last_running;
-			if (WT_TXNID_LT(txn_global->oldest_id, oldest_id))
-				txn_global->oldest_id = oldest_id;
-			WT_ASSERT(session, txn_global->scan_count == -1);
-			txn_global->scan_count = 0;
-		} else {
-			/*
-			 * We wanted to update the oldest ID but we're racing
-			 * another thread.  Retry if this is a forced update.
-			 */
-			WT_ASSERT(session, txn_global->scan_count > 0);
-			(void)__wt_atomic_subiv32(&txn_global->scan_count, 1);
-			if (force) {
-				__wt_yield();
-				goto retry;
-			}
-		}
-	} else {
+	/* Update the oldest ID. */
+	if (WT_TXNID_LT(txn_global->oldest_id, oldest_id))
+		txn_global->oldest_id = oldest_id;
+	if (WT_TXNID_LT(txn_global->last_running, last_running)) {
+		txn_global->last_running = last_running;
+
+		/* Output a verbose message about long-running transactions,
+		 * but only when some progress is being made. */
 		if (WT_VERBOSE_ISSET(session, WT_VERB_TRANSACTION) &&
 		    current_id - oldest_id > 10000 && oldest_session != NULL) {
-			(void)__wt_verbose(session, WT_VERB_TRANSACTION,
+			WT_TRET(__wt_verbose(session, WT_VERB_TRANSACTION,
 			    "old snapshot %" PRIu64
 			    " pinned in session %" PRIu32 " [%s]"
 			    " with snap_min %" PRIu64 "\n",
 			    oldest_id, oldest_session->id,
 			    oldest_session->lastop,
-			    oldest_session->txn.snap_min);
+			    oldest_session->txn.snap_min));
 		}
-		WT_ASSERT(session, txn_global->scan_count > 0);
-		(void)__wt_atomic_subiv32(&txn_global->scan_count, 1);
 	}
+
+done:	WT_TRET(__wt_writeunlock(session, txn_global->scan_rwlock));
+	return (ret);
 }
 
 /*
@@ -736,6 +742,8 @@ __wt_txn_global_init(WT_SESSION_IMPL *session, const char *cfg[])
 	WT_RET(__wt_spin_init(session,
 	    &txn_global->id_lock, "transaction id lock"));
 	WT_RET(__wt_rwlock_alloc(session,
+	    &txn_global->scan_rwlock, "transaction scan lock"));
+	WT_RET(__wt_rwlock_alloc(session,
 	    &txn_global->nsnap_rwlock, "named snapshot lock"));
 	txn_global->nsnap_oldest_id = WT_TXN_NONE;
 	TAILQ_INIT(&txn_global->nsnaph);
@@ -768,6 +776,7 @@ __wt_txn_global_destroy(WT_SESSION_IMPL *session)
 		return (0);
 
 	__wt_spin_destroy(session, &txn_global->id_lock);
+	WT_TRET(__wt_rwlock_destroy(session, &txn_global->scan_rwlock));
 	WT_TRET(__wt_rwlock_destroy(session, &txn_global->nsnap_rwlock));
 	__wt_free(session, txn_global->states);
 
diff --git a/src/third_party/wiredtiger/src/txn/txn_ckpt.c b/src/third_party/wiredtiger/src/txn/txn_ckpt.c
index 27e18b2..d5c9137 100644
--- a/src/third_party/wiredtiger/src/txn/txn_ckpt.c
+++ b/src/third_party/wiredtiger/src/txn/txn_ckpt.c
@@ -404,7 +404,7 @@ __txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
 	 * This is particularly important for compact, so that all dirty pages
 	 * can be fully written.
 	 */
-	__wt_txn_update_oldest(session, true);
+	WT_ERR(__wt_txn_update_oldest(session, true));
 
 	/* Flush data-sources before we start the checkpoint. */
 	WT_ERR(__checkpoint_data_source(session, cfg));
@@ -1281,7 +1281,7 @@ __wt_checkpoint_close(WT_SESSION_IMPL *session, bool final)
 	 * for active readers.
 	 */
 	if (!btree->modified && !bulk) {
-		__wt_txn_update_oldest(session, true);
+		WT_RET(__wt_txn_update_oldest(session, true));
 		return (__wt_txn_visible_all(session, btree->rec_max_txn) ?
 		    __wt_cache_op(session, WT_SYNC_DISCARD) : EBUSY);
 	}
