diff options
author | sueloverso <sue@mongodb.com> | 2017-08-11 07:06:33 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-11 07:06:33 -0400 |
commit | 80c6cee91faf84c4772a98c40e60d0a6890ccb52 (patch) | |
tree | 15bcf5f8f5c64eaba452360817a3fe67cc71b0b0 | |
parent | f85cd47fb290b4a3939714f52f5232a33da26e21 (diff) | |
download | mongo-80c6cee91faf84c4772a98c40e60d0a6890ccb52.tar.gz |
WT-3499 Add a visibility rwlock between transactions and checkpoints. (#3575)
* WT-3499 Add a visibility rwlock between transactions and checkpoints.
* Typo
* Just acquire/release the lock immediately for synchronization.
-rw-r--r-- | src/include/txn.h | 3 | ||||
-rw-r--r-- | src/txn/txn.c | 17 | ||||
-rw-r--r-- | src/txn/txn_log.c | 11 |
3 files changed, 30 insertions, 1 deletions
diff --git a/src/include/txn.h b/src/include/txn.h index 61ab343151c..f3e377b3380 100644 --- a/src/include/txn.h +++ b/src/include/txn.h @@ -105,6 +105,9 @@ struct __wt_txn_global { /* Protects the active transaction states. */ WT_RWLOCK rwlock; + /* Protects logging, checkpoints and transaction visibility. */ + WT_RWLOCK visibility_rwlock; + /* List of transactions sorted by commit timestamp. */ WT_RWLOCK commit_timestamp_rwlock; TAILQ_HEAD(__wt_txn_cts_qh, __wt_txn) commit_timestamph; diff --git a/src/txn/txn.c b/src/txn/txn.c index 24e7ccff2b1..9d4677a46f6 100644 --- a/src/txn/txn.c +++ b/src/txn/txn.c @@ -575,11 +575,12 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) bool update_timestamp; #endif u_int i; - bool did_update; + bool did_update, locked; txn = &session->txn; conn = S2C(session); did_update = txn->mod_count != 0; + locked = false; WT_ASSERT(session, F_ISSET(txn, WT_TXN_RUNNING)); WT_ASSERT(session, !F_ISSET(txn, WT_TXN_ERROR) || !did_update); @@ -665,6 +666,14 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) * This is particularly important for checkpoints. */ __wt_txn_release_snapshot(session); + /* + * We hold the visibility lock for reading from the time + * we write our log record until the time we release our + * transaction so that the LSN any checkpoint gets will + * always reflect visible data. + */ + __wt_readlock(session, &txn_global->visibility_rwlock); + locked = true; WT_ERR(__wt_txn_log_commit(session, cfg)); } @@ -727,6 +736,8 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) #endif __wt_txn_release(session); + if (locked) + __wt_readunlock(session, &txn_global->visibility_rwlock); #ifdef HAVE_TIMESTAMPS /* First check if we've already committed something in the future. */ @@ -763,6 +774,8 @@ err: /* * !!! * Nothing can fail after this point. */ + if (locked) + __wt_readunlock(session, &txn_global->visibility_rwlock); WT_TRET(__wt_txn_rollback(session, cfg)); return (ret); } @@ -933,6 +946,7 @@ __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_init(session, &txn_global->rwlock)); + WT_RET(__wt_rwlock_init(session, &txn_global->visibility_rwlock)); WT_RET(__wt_rwlock_init(session, &txn_global->commit_timestamp_rwlock)); TAILQ_INIT(&txn_global->commit_timestamph); @@ -974,6 +988,7 @@ __wt_txn_global_destroy(WT_SESSION_IMPL *session) __wt_rwlock_destroy(session, &txn_global->commit_timestamp_rwlock); __wt_rwlock_destroy(session, &txn_global->read_timestamp_rwlock); __wt_rwlock_destroy(session, &txn_global->nsnap_rwlock); + __wt_rwlock_destroy(session, &txn_global->visibility_rwlock); __wt_free(session, txn_global->states); } diff --git a/src/txn/txn_log.c b/src/txn/txn_log.c index 1fc74fb53a1..a03047b5392 100644 --- a/src/txn/txn_log.c +++ b/src/txn/txn_log.c @@ -357,12 +357,14 @@ __wt_txn_checkpoint_log( WT_ITEM *ckpt_snapshot, empty; WT_LSN *ckpt_lsn; WT_TXN *txn; + WT_TXN_GLOBAL *txn_global; uint8_t *end, *p; size_t recsize; uint32_t i, rectype; const char *fmt; conn = S2C(session); + txn_global = &conn->txn_global; txn = &session->txn; ckpt_lsn = &txn->ckpt_lsn; @@ -408,6 +410,15 @@ __wt_txn_checkpoint_log( } /* + * We take and immediately release the visibility lock. + * Acquiring the write lock guarantees that any transaction + * that has written to the log has also made its transaction + * visible at this time. + */ + __wt_writelock(session, &txn_global->visibility_rwlock); + __wt_writeunlock(session, &txn_global->visibility_rwlock); + + /* * We need to make sure that the log records in the checkpoint * LSN are on disk. In particular to make sure that the * current log file exists. |