diff --git a/src/btree/bt_curnext.c b/src/btree/bt_curnext.c
index 6a85ccf6c..b02a68649 100644
--- a/src/btree/bt_curnext.c
+++ b/src/btree/bt_curnext.c
@@ -224,8 +224,10 @@ restart_read:	/* Find the matching WT_COL slot. */
 		cbt->ins_head = WT_COL_UPDATE_SLOT(page, cbt->slot);
 		cbt->ins = __col_insert_search_match(cbt->ins_head, cbt->recno);
 		upd = NULL;
-		if (cbt->ins != NULL)
-			WT_RET(__wt_txn_read(session, cbt->ins->upd, &upd));
+		if (cbt->ins != NULL) {
+			cbt->upd_c[cbt->upd_v % WT_CDBG_MAX].recno = cbt->recno;
+			WT_RET(__wt_txn_read_cbt(session, cbt->ins->upd, &upd, cbt));
+		}
 		if (upd != NULL) {
 			if (upd->type == WT_UPDATE_TOMBSTONE) {
 				if (upd->txnid != WT_TXN_NONE &&
@@ -630,6 +632,8 @@ __wt_btcur_next(WT_CURSOR_BTREE *cbt, bool truncating)
 
 	WT_STAT_CONN_INCR(session, cursor_next);
 	WT_STAT_DATA_INCR(session, cursor_next);
+	memset(&cbt->upd_c[0], 0, sizeof(cbt->upd_c));
+	cbt->upd_v = 0;
 
 	flags = WT_READ_NO_SPLIT | WT_READ_SKIP_INTL;	/* tree walk flags */
 	if (truncating)
diff --git a/src/btree/bt_debug.c b/src/btree/bt_debug.c
index ef4084928..8cbc8c105 100644
--- a/src/btree/bt_debug.c
+++ b/src/btree/bt_debug.c
@@ -711,6 +711,24 @@ __wt_debug_page(
 	return (ret);
 }
 
+static int
+__debug_upd(WT_DBG *ds, WT_CURSOR_BTREE *cbt)
+{
+	struct WT_CDBG *c;
+	uint32_t end, i;
+
+	WT_RET(ds->f(ds, "UPDATES VISITED %" PRIu32 ":\n", cbt->upd_v));
+	end = cbt->upd_v % WT_CDBG_MAX;
+	for (i = 0; i < end; ++i) {
+		c = &cbt->upd_c[i];
+		WT_RET(ds->f(ds,
+		    "upd[%" PRIu32 "]: recno %" PRIu64
+		    " txnid %" PRIu64 " %s\n",
+		    i, c->recno, c->txnid, c->msg));
+	}
+	return (0);
+}
+
 /*
  * __wt_debug_cursor_page --
  *	Dump the in-memory information for a cursor-referenced page.
@@ -718,12 +736,40 @@ __wt_debug_page(
 int
 __wt_debug_cursor_page(void *cursor_arg, const char *ofile)
 {
+	WT_BTREE *btree;
 	WT_CURSOR *cursor;
 	WT_CURSOR_BTREE *cbt;
+#if 1
+	WT_DBG *ds, _ds;
+	WT_DECL_RET;
+	WT_SESSION_IMPL *session;
+#endif
 
 	cursor = cursor_arg;
 	cbt = cursor_arg;
+#if 0
 	return (__wt_debug_page(cursor->session, cbt->btree, cbt->ref, ofile));
+#else
+	btree = cbt->btree;
+	/*
+	 * Allow an explicit btree as an argument, as one may not yet be set on
+	 * the session.
+	 */
+	session = (WT_SESSION_IMPL *)cursor->session;
+	if (btree == NULL)
+		btree = S2BT(session);
+
+	ds = &_ds;
+	WT_WITH_BTREE(session, btree, ret = __debug_config(session, ds, ofile));
+	WT_RET(ret);
+
+	WT_RET(__debug_upd(ds, cbt));
+	WT_WITH_BTREE(session, btree,
+	    ret = __debug_page(ds, cbt->ref, WT_DEBUG_TREE_LEAF));
+
+	WT_TRET(__debug_wrapup(ds));
+	return (ret);
+#endif
 }
 
 /*
@@ -750,6 +796,46 @@ __debug_tree(
 	return (ret);
 }
 
+static int
+__debug_session_txn(WT_DBG *ds)
+{
+	WT_SESSION_IMPL *session;
+	WT_TXN *txn;
+	WT_TXN_GLOBAL *txn_global;
+	uint32_t i;
+
+	session = ds->session;
+	txn = &session->txn;
+	txn_global = &S2C(session)->txn_global;
+
+	WT_RET(ds->f(ds, "GLOBAL STATE:\n"));
+	WT_RET(ds->f(ds, "   current ID: %" PRIu64, txn_global->current));
+	WT_RET(ds->f(ds, "   last running ID: %" PRIu64,
+	    txn_global->last_running));
+	WT_RET(ds->f(ds, "   oldest ID: %" PRIu64, txn_global->oldest_id));
+	WT_RET(ds->f(ds, "   checkpoint running: %s",
+	    txn_global->checkpoint_running ? "yes" : "no"));
+	WT_RET(ds->f(ds, "   checkpoint pinned ID: %" PRIu64,
+	    txn_global->checkpoint_state.pinned_id));
+	WT_RET(ds->f(ds, "   checkpoint txn ID: %" PRIu64 "\n",
+	    txn_global->checkpoint_state.id));
+	WT_RET(ds->f(ds, "SESSION: %p", session));
+	WT_RET(ds->f(ds, "   txn ID: %" PRIu64, txn->id));
+	WT_RET(ds->f(ds, "   snap min: %" PRIu64, txn->snap_min));
+	WT_RET(ds->f(ds, "   snap max: %" PRIu64, txn->snap_max));
+	WT_RET(ds->f(ds, "   flags: 0x%08" PRIx32, txn->flags));
+	WT_RET(ds->f(ds, "   isolation: %s\n",
+	    txn->isolation == WT_ISO_SNAPSHOT ? "SNAPSHOT" : "NOT SNAPSHOT"));
+	if (F_ISSET(txn, WT_TXN_HAS_SNAPSHOT)) {
+		WT_RET(ds->f(ds, "   snap count: %" PRIu32 "\n",
+		    txn->snapshot_count));
+		for (i = 0; i < txn->snapshot_count; ++i)
+			WT_RET(ds->f(ds, "   snap[%" PRIu32 "] id: %" PRIu64 "\n",
+			    i, txn->snapshot[i]));
+	}
+	return (0);
+}
+
 /*
  * __debug_page --
  *	Dump the in-memory information for an in-memory page.
@@ -762,6 +848,10 @@ __debug_page(WT_DBG *ds, WT_REF *ref, uint32_t flags)
 
 	session = ds->session;
 
+	/* Dump txn info. */
+	WT_RET(ds->f(ds, "BTREE: %s\n", S2BT(session)->dhandle->name));
+	WT_RET(__debug_session_txn(ds));
+
 	/* Dump the page metadata. */
 	WT_WITH_PAGE_INDEX(session, ret = __debug_page_metadata(ds, ref));
 	WT_RET(ret);
diff --git a/src/include/cursor.h b/src/include/cursor.h
index 33d6660e6..873c7ad89 100644
--- a/src/include/cursor.h
+++ b/src/include/cursor.h
@@ -87,6 +87,13 @@ struct __wt_cursor_backup {
 };
 #define	WT_CURSOR_BACKUP_ID(cursor)	(((WT_CURSOR_BACKUP *)(cursor))->maxid)
 
+struct WT_CDBG {
+	uint64_t recno;
+	uint64_t txnid;
+	const char *msg;
+};
+#define	WT_CDBG_MAX 1024
+
 struct __wt_cursor_btree {
 	WT_CURSOR iface;
 
@@ -230,6 +237,8 @@ struct __wt_cursor_btree {
 	WT_ITEM *lastkey, _lastkey;
 	uint64_t lastrecno;
 #endif
+	struct WT_CDBG upd_c[WT_CDBG_MAX];
+	uint32_t upd_v;
 
 /* AUTOMATIC FLAG VALUE GENERATION START */
 #define	WT_CBT_ACTIVE		0x001u	/* Active in the tree */
diff --git a/src/include/extern.h b/src/include/extern.h
index 7e0df3af7..c53da7d1e 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -1014,6 +1014,7 @@ static inline int __wt_txn_modify(WT_SESSION_IMPL *session, WT_UPDATE *upd) WT_G
 static inline int __wt_txn_modify_page_delete(WT_SESSION_IMPL *session, WT_REF *ref) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
 static inline int __wt_txn_op_set_key(WT_SESSION_IMPL *session, const WT_ITEM *key) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
 static inline int __wt_txn_read(WT_SESSION_IMPL *session, WT_UPDATE *upd, WT_UPDATE **updp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+static inline int __wt_txn_read_cbt(WT_SESSION_IMPL *session, WT_UPDATE *upd, WT_UPDATE **updp, WT_CURSOR_BTREE *cbt) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
 static inline int __wt_txn_resolve_prepared_op( WT_SESSION_IMPL *session, WT_TXN_OP *op, bool commit, int64_t *resolved_update_countp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
 static inline int __wt_txn_search_check(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
 static inline int __wt_txn_update_check(WT_SESSION_IMPL *session, WT_UPDATE *upd) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
diff --git a/src/include/txn.i b/src/include/txn.i
index d6c515f00..e8bb7556a 100644
--- a/src/include/txn.i
+++ b/src/include/txn.i
@@ -862,6 +862,48 @@ __wt_txn_upd_visible(WT_SESSION_IMPL *session, WT_UPDATE *upd)
 	return (__wt_txn_upd_visible_type(session, upd) == WT_VISIBLE_TRUE);
 }
 
+/*
+ * __wt_txn_read_cbt --
+ *	Get the first visible update in a list (or NULL if none are visible).
+ */
+static inline int
+__wt_txn_read_cbt(WT_SESSION_IMPL *session, WT_UPDATE *upd, WT_UPDATE **updp,
+    WT_CURSOR_BTREE *cbt)
+{
+	static WT_UPDATE tombstone = {
+		.txnid = WT_TXN_NONE, .type = WT_UPDATE_TOMBSTONE
+	};
+	WT_VISIBLE_TYPE upd_visible;
+	bool skipped_birthmark;
+
+	*updp = NULL;
+	for (skipped_birthmark = false; upd != NULL; upd = upd->next) {
+		/* Skip reserved place-holders, they're never visible. */
+		cbt->upd_c[cbt->upd_v % WT_CDBG_MAX].txnid = upd->txnid;
+		if (upd->type != WT_UPDATE_RESERVE) {
+			upd_visible = __wt_txn_upd_visible_type(session, upd);
+			if (upd_visible == WT_VISIBLE_TRUE) {
+				cbt->upd_c[cbt->upd_v++ % WT_CDBG_MAX].msg =
+				    "visible";
+				break;
+			}
+			if (upd_visible == WT_VISIBLE_PREPARE)
+				return (WT_PREPARE_CONFLICT);
+		}
+		cbt->upd_c[cbt->upd_v++ % WT_CDBG_MAX].msg =
+		    "not visible";
+		/* An invisible birthmark is equivalent to a tombstone. */
+		if (upd->type == WT_UPDATE_BIRTHMARK)
+			skipped_birthmark = true;
+	}
+
+	if (upd == NULL && skipped_birthmark)
+		upd = &tombstone;
+
+	*updp = upd == NULL || upd->type == WT_UPDATE_BIRTHMARK ? NULL : upd;
+	return (0);
+}
+
 /*
  * __wt_txn_read --
  *	Get the first visible update in a list (or NULL if none are visible).
diff --git a/test/checkpoint/checkpointer.c b/test/checkpoint/checkpointer.c
index 311c21eff..8eb95e3e7 100644
--- a/test/checkpoint/checkpointer.c
+++ b/test/checkpoint/checkpointer.c
@@ -31,7 +31,7 @@
 static WT_THREAD_RET checkpointer(void *);
 static WT_THREAD_RET clock_thread(void *);
 static int compare_cursors(
-    WT_CURSOR *, const char *, WT_CURSOR *, const char *);
+    WT_CURSOR *, const char *, WT_CURSOR *, const char *, int);
 static int diagnose_key_error(WT_CURSOR *, int, WT_CURSOR *, int);
 static int real_checkpointer(void);
 static int verify_consistency(WT_SESSION *, bool);
@@ -181,7 +181,7 @@ real_checkpointer(void)
 			goto done;
 
 		/* Verify the content of the checkpoint. */
-		if ((ret = verify_consistency(session, true)) != 0)
+		if (0 && (ret = verify_consistency(session, true)) != 0)
 			return (log_print_err(
 			    "verify_consistency (offline)", ret, 1));
 
@@ -290,7 +290,7 @@ verify_consistency(WT_SESSION *session, bool use_checkpoint)
 			type0 = type_to_string(g.cookies[0].type);
 			typei = type_to_string(g.cookies[i].type);
 			if ((ret = compare_cursors(
-			    cursors[0], type0, cursors[i], typei)) != 0) {
+			    cursors[0], type0, cursors[i], typei, i)) != 0) {
 				(void)diagnose_key_error(
 				    cursors[0], 0, cursors[i], i);
 				(void)log_print_err(
@@ -317,6 +317,7 @@ err:	for (i = 0; i < g.ntables; i++) {
 	return (ret);
 }
 
+int mism = 0;
 /*
  * compare_cursors --
  *     Compare the key/value pairs from two cursors.
@@ -324,11 +325,13 @@ err:	for (i = 0; i < g.ntables; i++) {
 static int
 compare_cursors(
     WT_CURSOR *cursor1, const char *type1,
-    WT_CURSOR *cursor2, const char *type2)
+    WT_CURSOR *cursor2, const char *type2, int i)
 {
+	WT_SESSION *s1, *s2;
 	uint64_t key1, key2;
 	int ret;
 	char buf[128], *val1, *val2;
+	char o1[32], o2[32];
 
 	ret = 0;
 	memset(buf, 0, 128);
@@ -353,8 +356,17 @@ compare_cursors(
 		return (0);
 
 	printf("Key/value mismatch: %" PRIu64 "/%s from a %s table is not %"
-	    PRIu64 "/%s from a %s table\n",
-	    key1, val1, type1, key2, val2, type2);
+	    PRIu64 "/%s from a %s table %d\n",
+	    key1, val1, type1, key2, val2, type2, i);
+	s1 = cursor1->session;
+	s2 = cursor2->session;
+	snprintf(o1, 32, "%s/page.cursor1.%d", g.home, mism);
+	snprintf(o2, 32, "%s/page.cursor2.%d", g.home, mism);
+	++mism;
+	printf("====== Cursor 1 page: %s =====\n", o1);
+	testutil_check(__wt_debug_cursor_page(cursor1, o1));
+	printf("====== Cursor 2 page: %s =====\n", o2);
+	testutil_check(__wt_debug_cursor_page(cursor2, o2));
 
 	return (ret);
 }
diff --git a/test/checkpoint/test_checkpoint.c b/test/checkpoint/test_checkpoint.c
index c30af666c..6fe4750f4 100644
--- a/test/checkpoint/test_checkpoint.c
+++ b/test/checkpoint/test_checkpoint.c
@@ -222,6 +222,7 @@ wt_connect(const char *config_open)
 	else
 		testutil_check(__wt_snprintf(config, sizeof(config),
 		    "create,cache_cursors=false,statistics=(fast),"	\
+		    "log=(enabled),debug_mode=(table_logging=true,checkpoint_retention=3),"     \
 		    "statistics_log=(json,wait=1),error_prefix=\"%s\""	\
 		    "%s%s%s",
 		    progname,
diff --git a/test/checkpoint/workers.c b/test/checkpoint/workers.c
index e9966cec1..cf3da6e43 100644
--- a/test/checkpoint/workers.c
+++ b/test/checkpoint/workers.c
@@ -252,9 +252,11 @@ real_worker(void)
 		}
 	has_cursors = true;
 
+#if 0
 	if (g.use_timestamps)
 		begin_cfg = "read_timestamp=1,roundup_timestamps=(read=true)";
 	else
+#endif
 		begin_cfg = NULL;
 
 	for (i = 0; i < g.nops && g.running; ++i, __wt_yield()) {
@@ -266,6 +268,8 @@ real_worker(void)
 		}
 		keyno = __wt_random(&rnd) % g.nkeys + 1;
 		if (g.use_timestamps && i % 23 == 0) {
+			printf("REAL_WORKER: close/reopen cursors\n");
+			fflush(stdout);
 			if (__wt_try_readlock(
 			    (WT_SESSION_IMPL *)session, &g.clock_lock) != 0) {
 				testutil_check(
@@ -279,10 +283,12 @@ real_worker(void)
 				testutil_check(session->begin_transaction(
 				    session, begin_cfg));
 			}
+#if 0
 			testutil_check(__wt_snprintf(
 			    buf, sizeof(buf), "commit_timestamp=%x", g.ts + 1));
 			testutil_check(
 			    session->timestamp_transaction(session, buf));
+#endif
 			__wt_readunlock(
 			    (WT_SESSION_IMPL *)session, &g.clock_lock);
 
