Merge pull request #2282 from wiredtiger/WT-2193
WT-2193 Handle read-committed metadata checkpoints during snapshot transactions
This commit is contained in:
@@ -22,16 +22,17 @@ __sync_file(WT_SESSION_IMPL *session, int syncop)
|
||||
WT_PAGE_MODIFY *mod;
|
||||
WT_REF *walk;
|
||||
WT_TXN *txn;
|
||||
uint64_t internal_bytes, leaf_bytes;
|
||||
uint64_t internal_pages, leaf_pages;
|
||||
uint64_t internal_bytes, internal_pages, leaf_bytes, leaf_pages;
|
||||
uint64_t saved_snap_min;
|
||||
uint32_t flags;
|
||||
bool evict_reset;
|
||||
|
||||
btree = S2BT(session);
|
||||
|
||||
flags = WT_READ_CACHE | WT_READ_NO_GEN;
|
||||
walk = NULL;
|
||||
txn = &session->txn;
|
||||
saved_snap_min = WT_SESSION_TXN_STATE(session)->snap_min;
|
||||
flags = WT_READ_CACHE | WT_READ_NO_GEN;
|
||||
|
||||
internal_bytes = leaf_bytes = 0;
|
||||
internal_pages = leaf_pages = 0;
|
||||
@@ -79,6 +80,19 @@ __sync_file(WT_SESSION_IMPL *session, int syncop)
|
||||
}
|
||||
break;
|
||||
case WT_SYNC_CHECKPOINT:
|
||||
/*
|
||||
* If we are flushing a file at read-committed isolation, which
|
||||
* is of particular interest for flushing the metadata to make
|
||||
* schema-changing operation durable, get a transactional
|
||||
* snapshot now.
|
||||
*
|
||||
* All changes committed up to this point should be included.
|
||||
* We don't update the snapshot in between pages because (a)
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* We cannot check the tree modified flag in the case of a
|
||||
* checkpoint, the checkpoint code has already cleared it.
|
||||
@@ -174,7 +188,12 @@ err: /* On error, clear any left-over tree walk. */
|
||||
if (walk != NULL)
|
||||
WT_TRET(__wt_page_release(session, walk, flags));
|
||||
|
||||
if (txn->isolation == WT_ISO_READ_COMMITTED && session->ncursors == 0)
|
||||
/*
|
||||
* If we got a snapshot in order to write pages, and there was no
|
||||
* snapshot active when we started, release it.
|
||||
*/
|
||||
if (txn->isolation == WT_ISO_READ_COMMITTED &&
|
||||
saved_snap_min == WT_TXN_NONE)
|
||||
__wt_txn_release_snapshot(session);
|
||||
|
||||
if (btree->checkpointing != WT_CKPT_OFF) {
|
||||
|
||||
@@ -126,6 +126,9 @@ __wt_connection_close(WT_CONNECTION_IMPL *conn)
|
||||
/* Close open data handles. */
|
||||
WT_TRET(__wt_conn_dhandle_discard(session));
|
||||
|
||||
/* Shut down metadata tracking, required before creating tables. */
|
||||
WT_TRET(__wt_meta_track_destroy(session));
|
||||
|
||||
/*
|
||||
* Now that all data handles are closed, tell logging that a checkpoint
|
||||
* has completed then shut down the log manager (only after closing
|
||||
@@ -252,6 +255,9 @@ __wt_connection_workers(WT_SESSION_IMPL *session, const char *cfg[])
|
||||
*/
|
||||
WT_RET(__wt_logmgr_open(session));
|
||||
|
||||
/* Initialize metadata tracking, required before creating tables. */
|
||||
WT_RET(__wt_meta_track_init(session));
|
||||
|
||||
/* Create the lookaside table. */
|
||||
WT_RET(__wt_las_create(session));
|
||||
|
||||
|
||||
@@ -363,6 +363,8 @@ struct __wt_connection_impl {
|
||||
uint32_t log_prealloc; /* Log file pre-allocation */
|
||||
uint32_t txn_logsync; /* Log sync configuration */
|
||||
|
||||
WT_SESSION_IMPL *meta_ckpt_session;/* Metadata checkpoint session */
|
||||
|
||||
WT_SESSION_IMPL *sweep_session; /* Handle sweep session */
|
||||
wt_thread_t sweep_tid; /* Handle sweep thread */
|
||||
int sweep_tid_set; /* Handle sweep thread set */
|
||||
|
||||
@@ -456,6 +456,8 @@ extern int __wt_meta_track_update(WT_SESSION_IMPL *session, const char *key);
|
||||
extern int __wt_meta_track_fileop( WT_SESSION_IMPL *session, const char *olduri, const char *newuri);
|
||||
extern int __wt_meta_track_drop( WT_SESSION_IMPL *session, const char *filename);
|
||||
extern int __wt_meta_track_handle_lock(WT_SESSION_IMPL *session, bool created);
|
||||
extern int __wt_meta_track_init(WT_SESSION_IMPL *session);
|
||||
extern int __wt_meta_track_destroy(WT_SESSION_IMPL *session);
|
||||
extern int __wt_turtle_init(WT_SESSION_IMPL *session);
|
||||
extern int __wt_turtle_read(WT_SESSION_IMPL *session, const char *key, char **valuep);
|
||||
extern int __wt_turtle_update( WT_SESSION_IMPL *session, const char *key, const char *value);
|
||||
|
||||
@@ -231,6 +231,7 @@ __wt_meta_track_off(WT_SESSION_IMPL *session, bool need_sync, bool unroll)
|
||||
{
|
||||
WT_DECL_RET;
|
||||
WT_META_TRACK *trk, *trk_orig;
|
||||
WT_SESSION_IMPL *ckpt_session;
|
||||
|
||||
WT_ASSERT(session,
|
||||
WT_META_TRACKING(session) && session->meta_track_nest > 0);
|
||||
@@ -275,9 +276,18 @@ __wt_meta_track_off(WT_SESSION_IMPL *session, bool need_sync, bool unroll)
|
||||
session, false, WT_TXN_LOG_CKPT_SYNC, NULL));
|
||||
WT_RET(ret);
|
||||
} else {
|
||||
WT_WITH_DHANDLE(session, session->meta_dhandle,
|
||||
WT_WITH_TXN_ISOLATION(session, WT_ISO_READ_COMMITTED,
|
||||
ret = __wt_checkpoint(session, NULL)));
|
||||
WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_SCHEMA));
|
||||
ckpt_session = S2C(session)->meta_ckpt_session;
|
||||
/*
|
||||
* If this operation is part of a running transaction, that
|
||||
* should be included in the checkpoint.
|
||||
*/
|
||||
ckpt_session->txn.id = session->txn.id;
|
||||
F_SET(ckpt_session, WT_SESSION_LOCKED_SCHEMA);
|
||||
WT_WITH_DHANDLE(ckpt_session, session->meta_dhandle, ret =
|
||||
__wt_checkpoint(ckpt_session, NULL));
|
||||
F_CLR(ckpt_session, WT_SESSION_LOCKED_SCHEMA);
|
||||
ckpt_session->txn.id = WT_TXN_NONE;
|
||||
WT_RET(ret);
|
||||
WT_WITH_DHANDLE(session, session->meta_dhandle,
|
||||
ret = __wt_checkpoint_sync(session, NULL));
|
||||
@@ -458,3 +468,52 @@ __wt_meta_track_handle_lock(WT_SESSION_IMPL *session, bool created)
|
||||
trk->created = created;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __wt_meta_track_init --
|
||||
* Intialize metadata tracking.
|
||||
*/
|
||||
int
|
||||
__wt_meta_track_init(WT_SESSION_IMPL *session)
|
||||
{
|
||||
WT_CONNECTION_IMPL *conn;
|
||||
|
||||
conn = S2C(session);
|
||||
if (!FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED)) {
|
||||
WT_RET(__wt_open_internal_session(conn,
|
||||
"metadata-ckpt", false, WT_SESSION_NO_DATA_HANDLES,
|
||||
&conn->meta_ckpt_session));
|
||||
|
||||
/*
|
||||
* Sessions default to read-committed isolation, we rely on
|
||||
* that for the correctness of metadata checkpoints.
|
||||
*/
|
||||
WT_ASSERT(session, conn->meta_ckpt_session->txn.isolation ==
|
||||
WT_ISO_READ_COMMITTED);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __wt_meta_track_destroy --
|
||||
* Release resources allocated for metadata tracking.
|
||||
*/
|
||||
int
|
||||
__wt_meta_track_destroy(WT_SESSION_IMPL *session)
|
||||
{
|
||||
WT_CONNECTION_IMPL *conn;
|
||||
WT_DECL_RET;
|
||||
WT_SESSION *wt_session;
|
||||
|
||||
conn = S2C(session);
|
||||
|
||||
/* Close the session used for metadata checkpoints. */
|
||||
if (conn->meta_ckpt_session != NULL) {
|
||||
wt_session = &conn->meta_ckpt_session->iface;
|
||||
WT_TRET(wt_session->close(wt_session, NULL));
|
||||
conn->meta_ckpt_session = NULL;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user