樂觀鎖與CAS,MVCC

  • 樂觀鎖

如一個金融系統(tǒng)须肆,當某個操作員讀取用戶的數(shù)據匿乃,并在讀出的用戶數(shù)據的基礎上進行修改時(如更改用戶帳戶余額),
如果采用悲觀鎖機制豌汇,也就意味著整個操作過程中(從操作員讀出數(shù)據幢炸、開始修改直至提交修改結果的全過程,甚至還包括操作員中途去煮咖啡的時間)拒贱,數(shù)據庫記錄始終處于加鎖狀態(tài)宛徊,可以想見,如果面對幾百上千個并發(fā)逻澳,這樣的情況將導致怎樣的后果闸天。
樂觀鎖機制在一定程度上解決了這個問題。
樂觀鎖斜做,大多是基于數(shù)據版本 ( Version )記錄機制實現(xiàn)苞氮。何謂數(shù)據版本?
即為數(shù)據增加一個版本標識瓤逼,在基于數(shù)據庫表的版本解決方案中笼吟,一般是通過為數(shù)據庫表增加一個 “version” 字段來實現(xiàn)。
讀取出數(shù)據時霸旗,將此版本號一同讀出贷帮,之后更新時,對此版本號加一诱告。
此時撵枢,將提交數(shù)據的版本數(shù)據與數(shù)據庫表對應記錄的當前版本信息進行比對,
如果提交的數(shù)據版本號大于數(shù)據庫表當前版本號,則予以更新锄禽,否則認為是過期數(shù)據潜必。
對于上面修改用戶帳戶信息的例子而言,假設數(shù)據庫中帳戶信息表中有一個 version 字段沟绪,當前值為 1 刮便;而當前帳戶余額字段( balance )為 $100 。

  1. 操作員 A 此時將其讀出( version=1 )绽慈,并從其帳戶余額中扣除 $50( $100-$50 )恨旱。
  2. 在操作員 A 操作的過程中,操作員B 也讀入此用戶信息( version=1 )坝疼,并從其帳戶余額中扣除 $20 ( $100-$20 )搜贤。
  3. 操作員 A 完成了修改工作,將數(shù)據版本號加一( version=2 )钝凶,
    連同帳戶扣除后余額( balance=$50 )仪芒,提交至數(shù)據庫更新,此時由于提交數(shù)據版本大于數(shù)據庫記錄當前版本耕陷,數(shù)據被更新掂名,數(shù)據庫記錄 version 更新為 2 。
  4. 操作員 B 完成了操作哟沫,也將版本號加一( version=2 )試圖向數(shù)據庫提交數(shù)據( balance=$80 )饺蔑,但此時比對數(shù)據庫記錄版本時發(fā)現(xiàn),操作員 B 提交的數(shù)據版本號為 2 嗜诀,數(shù)據庫記錄當前版本也為 2 猾警,不滿足 “ 提交版本必須大于記錄當前版本才能執(zhí)行更新 “ 的樂觀鎖策略,因此隆敢,操作員 B 的提交被駁回发皿。
    這樣,就避免了操作員 B 用基于 version=1 的舊數(shù)據修改的結果覆蓋操作員A 的操作結果的可能拂蝎。

轉載自樂觀鎖
另外參考:一分鐘教你知道樂觀鎖和悲觀鎖的區(qū)別

  • CAS:compare and swap
    CAS的含義是穴墅,我認為V的值應該為A,如果是温自,那么將V的值更新為B玄货,否則不修改并告訴V的值實際為多少。(Java并發(fā)編程實戰(zhàn)P263)
    附上java.util.concurrent.atomic.AtomicLong中的源碼
    public final long getAndAccumulate(long x,
                                       LongBinaryOperator accumulatorFunction) {
        long prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsLong(prev, x);
        } while (!compareAndSet(prev, next));
        return prev;
    }
    public final boolean compareAndSet(long expect, long update) {
        return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
    }

還有兩個鏈接CAS(Compare and Swap)理解捣作,非阻塞同步算法與CAS(Compare and Swap)無鎖算法

  • MVCC:multiversion concurrency control
    我們知道誉结,mysql的innodb采用的是行鎖鹅士,而且采用了多版本并發(fā)控制來提高讀操作的性能券躁。
    什么是多版本并發(fā)控制呢 ?其實就是在每一行記錄的后面增加兩個隱藏列,記錄創(chuàng)建版本號和刪除版本號也拜,
    而每一個事務在啟動的時候以舒,都有一個唯一的遞增的版本號。

1慢哈、在插入操作時 : 記錄的創(chuàng)建版本號就是事務版本號蔓钟。
比如我插入一條記錄, 事務id 假設是1 ,那么記錄如下:也就是說卵贱,創(chuàng)建版本號就是事務版本號滥沫。

id name create version delete version
1 test 1

2、在更新操作的時候键俱,采用的是先標記舊的那行記錄為已刪除兰绣,并且刪除版本號是事務版本號,然后插入一行新的記錄的方式编振。

比如缀辩,針對上面那行記錄,事務Id為2 要把name字段更新

update table set name= 'new_value' where id=1;

id name create version delete version
1 test 1 2
1 new_value 2

3踪央、刪除操作的時候臀玄,就把事務版本號作為刪除版本號。比如

delete from table where id=1;

id name create version delete version
1 new_value 2 3

4畅蹂、查詢操作:
從上面的描述可以看到健无,在查詢時要符合以下兩個條件的記錄才能被事務查詢出來:

  1. 刪除版本號 大于 當前事務版本號,就是說刪除操作是在當前事務啟動之后做的魁莉。
  2. 創(chuàng)建版本號 小于或者等于 當前事務版本號 睬涧,就是說記錄創(chuàng)建是在事務中(等于的情況)或者事務啟動之前。
    這樣就保證了各個事務互不影響旗唁。從這里也可以體會到一種提高系統(tǒng)性能的思路畦浓,就是:
    通過版本號來減少鎖的爭用。
    另外检疫,只有read-committed和 repeatable-read 兩種事務隔離級別才能使用MVCC
    read-uncommited由于是讀到未提交的讶请,所以不存在版本的問題
    而serializable 則會對所有讀取的行加鎖。
    轉載自mysql的mvcc(多版本并發(fā)控制)
    屎媳,另外參考innodb 多版本并發(fā)控制原理詳解
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末夺溢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子烛谊,更是在濱河造成了極大的恐慌风响,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丹禀,死亡現(xiàn)場離奇詭異状勤,居然都是意外死亡鞋怀,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門持搜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來密似,“玉大人,你說我怎么就攤上這事葫盼〔须纾” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵贫导,是天一觀的道長抛猫。 經常有香客問我,道長孩灯,這世上最難降的妖魔是什么邑滨? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮钱反,結果婚禮上掖看,老公的妹妹穿的比我還像新娘。我一直安慰自己面哥,他們只是感情好哎壳,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著尚卫,像睡著了一般归榕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吱涉,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天刹泄,我揣著相機與錄音,去河邊找鬼怎爵。 笑死特石,一個胖子當著我的面吹牛,可吹牛的內容都是我干的鳖链。 我是一名探鬼主播姆蘸,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼芙委!你這毒婦竟也來了逞敷?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤灌侣,失蹤者是張志新(化名)和其女友劉穎推捐,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侧啼,經...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡牛柒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年愕秫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焰络。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖符喝,靈堂內的尸體忽然破棺而出闪彼,到底是詐尸還是另有隱情,我是刑警寧澤协饲,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布畏腕,位于F島的核電站,受9級特大地震影響茉稠,放射性物質發(fā)生泄漏描馅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一而线、第九天 我趴在偏房一處隱蔽的房頂上張望铭污。 院中可真熱鬧,春花似錦膀篮、人聲如沸嘹狞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽磅网。三九已至,卻和暖如春筷屡,著一層夾襖步出監(jiān)牢的瞬間涧偷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工毙死, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留燎潮,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓扼倘,卻偏偏與公主長得像跟啤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子唉锌,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內容