Implementation of Dirty read in Berkeley DB

Source: Internet
Author: User
Tags goto

Dirty Reader How not to be writor block live?

If the database supports dirty read, all open Dbhandle are configured with db_read_uncommitted;

When the thread gets the write lock and finishes processing (such as Splite one page), it drops to was_write lock. Wwrite Lock and dirty reader will not conflict;

Requests to the dirty read lock will be processed preferentially;

Dirty read Lock is released immediately after the read is completed; Why? Because TXN retains the read lock for Repeatable read.

If the cursor is read_uncommitted, the Lock_mode will be changed to db_lock_read_uncommitted (DB_META.C, Db_lget) when processing a request for a read lock;

Txn abort when the Was_write lock is re-upgraded to the write lock. Because Abort->undo need to write page. (TXN.C, Txn_abort ())

code reading:

Db.h

typedefenum{db_lock_ng=0,/*Not granted.*/Db_lock_read=1,/*Shared/read.*/Db_lock_write=2,/*Exclusive/write.*/db_lock_wait=3,/*Wait for Event*//For queue AMDb_lock_iwrite=4,/*Intent exclusive/write.*///Intent lock for hierarchy lockDb_lock_iread=5,/*Intent to Share/read.*/DB_LOCK_IWR=6,/*Intent to read and write.*/db_lock_read_uncommitted=7,/*degree 1 isolation.*/Db_lock_wwrite=8        /*was written.*/} db_lockmode_t;

LOCK/LOCK_REGION.C:

#defineDb_lock_riw_n 9Static Constu_int8_t db_riw_conflicts[] = {/*N R W WT IW IR riw DR WW*//*N*/  0,0,0,0,0,0,0,0,0,/*R*/  0,0,1,0,1,0,1,0,1,/*W*/  0,1,1,1,1,1,1,1,1,/*WT*/  0,0,0,0,0,0,0,0,0,/*IW*/  0,1,1,0,0,0,0,1,1,/*IR*/  0,0,1,0,0,0,0,0,1,/*Riw*/  0,1,1,0,0,0,0,1,1,/*DR*/  0,0,1,0,1,0,1,0,0,//dirty read and Was_write do not conflict/*WW*/  0,1,1,0,1,1,1,0,1};

LOCK.C, __lock_get_internal (): Dirty read lock priority processing

LP = Sh_tailq_first (&sh_obj->holders, __db_lock); Sh_off= R_offset (&lt->Reginfo, Sh_locker);
Traversing the holder list for(; lp = NULL; LP =Sh_tailq_next (LP, Links, __db_lock)) { if(Sh_off = = lp->holder) {//has been lockedif(Lp->mode = = Lock_mode && Lp->status = =Db_lstat_held) {LP->refcount++; Lock->off = R_offset (&lt->reginfo, LP); Lock->gen = lp->Gen; Lock->mode = lp->mode; GotoDone ; } Else{ihold=1; } } Else if(__lock_same_family (LT, R_addr (&lt->reginfo, lp->holder), Sh_locker) Ihold=1; Else if(CONFLICTS (LT, region, lp->mode, Lock_mode)) Break; Else if(Lp->mode = = Db_lock_read | | lp->mode = =db_lock_wwrite) {Grant_dirty=1;//Holder list only read lock; or a WW lock holder= lp->Holder; } } if(LP! =NULL) {//conflicting holderif(Ihold | | Lf_isset (db_lock_upgrade) | | Lock_mode = =db_lock_read_uncommitted) Action=Head ;//dirty read request first, put waiter queue headerElseAction=TAIL; } Else { if(Lf_isset (db_lock_upgrade)) Action=UPGRADE; Else if(Ihold) Action=GRANT; Else {
Conflict-free holder; Traverse the Waiter List Sh_tailq_foreach (LP,&sh_obj->Waiters, links, __db_lock)if(Lp->holder! = Sh_off && CONFLICTS (LT, region, lp->mode, Lock_mode)) Break; if(LP = =NULL)//conflict-free waiter action=GRANT; Else if(Grant_dirty && Lock_mode = =db_lock_read_uncommitted) {LP= Sh_tailq_first (&sh_obj->waiters, __db_lock); if(Lp->mode = = Db_lock_write && Lp->holder = =holder) Action=SECOND;//Waiter The table header is a upgrade request. The current DR is placed in the secondElseAction=Grant;//approve Dr Lock request. } Else if(Lock_mode = =db_lock_read_uncommitted)
Here is the DR request, but!grant_dirty (no READ/WW holder). There are conflict-free holder;
A conflict of waiter. ?????? Action=SECOND; ElseAction=TAIL; } }

DB_META.C,-write lock downgrade Wwrite Lock:
__db_lget () Dbc->lock.pgno = Pgno; ...Switch (action) {Defaultif (has_timeout)Goto Do_couple; RET = __lock_get (env, Dbc->locker, Lkflags, &DBC->LOCK_DBT, mode, LOCKP);The general treatmentBreakCase lck_downgrade:couple[0].op = Db_lock_get; couple[0].obj =NULL; couple[0].lock = *LOCKP; couple[0].mode = Db_lock_wwrite;Request a new Wwrite lock Umrw_set (couple[0].timeout); i++;/* Fallthrough */Case lck_couple:do_couple:couple[i].op = has_timeout? Db_lock_get_timeout:db_lock_get; Couple[i].obj = &dbc->lock_dbt; Couple[i].mode = mode;A new lock on the incoming Pgno request, Umrw_set (couple[i].timeout); i++;if (has_timeout) couple[0].timeout = F_isset (DBC, dbc_recover)?0:txn->lock_timeout;if (action = = Lck_couple | | action = = lck_downgrade) {couple[i].op = Db_lock_put;Release the original lock (downgrade words, is the original write lock, thereby achieving a lock downgrade) Couple[i].lock = *LOCKP; i++; RET = __lock_vec (env, Dbc->locker, lkflags, couple, I, &REQP);if (ret = =0 | | REQP = = &couple[i-1]) *lockp = i = =1? couple[0].lock:couple[i-2].lock;I! = 1 identifies Lck_downgrade and returns a new Wwrite lockBreak }__db_lput ()if (F_isset (DBC->DBP, db_am_read_uncommitted) &&! F_isset (DBC, dbc_error) && Lockp->mode = = db_lock_write) action = Lck_downgrade;Elseif (Dbc->txn = =NULL) action = lck_couple;The couple here is meant to be released directly. Non-transaction situationElseif (F_isset (DBC, dbc_read_committed | dbc_was_read_committed) && Lockp->mode = = db_lock_read) action = lck_couple;read_commited, and read lockElseif (Lockp->mode = = db_lock_read_uncommitted) action = lck_couple;read_uncommitted, read lock, Direct releaseelse action =0; env = dbc->env;Switch (action) {Case Lck_couple:ret = __lock_put (env, LOCKP);BreakCase lck_downgrade:couple[0].op = Db_lock_get; couple[0].obj =NULL; couple[0].mode = Db_lock_wwrite;//get a WW lock Couple[0].lock = *LOCKP; Umrw_set (Couple[0].timeout); Couple[1].op = DB_LOCK_PUT; Couple[1].lock = *LOCKP; //release the original lock (write lock) ret = __lock_vec (env, Dbc->locker, 0, couple, Span class= "Hljs-number" >2, &REQP); if (ret = 0 | | reqp = = &couple[1] ) *lockp = Couple[0].lock; break; default:ret = 0; //well, here. If the default isolation level, keep read lock, write lock does not downgrade, also here. break;} return (ret);}            

Implementation of Dirty read in Berkeley DB

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.