事務(wù)之實(shí)際例子(廢棄)

1、前言

平時(shí)開發(fā)我們經(jīng)常使用 Spring 事務(wù)期虾,而 Spring 默認(rèn)使用 mysql 的事務(wù)驴一。mysql 事務(wù)默認(rèn)的隔離級(jí)別為:可重復(fù)讀。我們就以可重復(fù)讀為例子看一下代碼(事務(wù)的隔離性是用鎖做的甚牲,如果不是操作同一行數(shù)據(jù)就不會(huì)鎖)义郑。

@Transactional
public void testTransaction(String name) {
        // select * from user where 'delete' =  0 order by id asc limit 1;
        User user = userMapper.selectUser();
        if(user != null){
            Boolean oldStatus = user.getStatus();
            user.setName(name);
            user.setStatus(Boolean.TRUE);

            // 樂(lè)觀鎖更新 update user set name = #{user.name} and status = #{user.status} where id = #{user.id} and status = #{oldStatus}
            userMapper.updateUser(user, oldStatus);
        }

        User user1 = userMapper.select(user.getId());
        logger.info(user1.getName());
    }

2、分析

上面代碼的意思是:查詢最早的一條狀態(tài)為0的數(shù)據(jù)丈钙,然后設(shè)置狀態(tài)為1非驮,最后使用樂(lè)觀鎖更新,提交事務(wù)雏赦。

這種代碼在我們平時(shí)開發(fā)中非常常見(jiàn)院尔,有時(shí)候因?yàn)榭赡苡卸鄠€(gè)數(shù)據(jù)庫(kù)操作,這個(gè)方法會(huì)加上 @Transactional 注解來(lái)使用事務(wù)喉誊,保證事務(wù)的原子性邀摆。我們可能太注意原子性,而忽略了事務(wù)的隔離性伍茄。在默認(rèn)情況下栋盹,mysql 的隔離性為可重復(fù)讀(一個(gè)事務(wù)在最開始讀到的數(shù)據(jù)在事務(wù)執(zhí)行過(guò)程中不隨著其他事務(wù)的操作而改變)。

這段代碼在實(shí)際運(yùn)行中會(huì)有什么問(wèn)題敷矫?我聽到了以下幾個(gè)不同的意見(jiàn):

  • 1.這段代碼會(huì)鎖表
  • 2.在事務(wù)1執(zhí)行 userMapper.updateUser(user, oldStatus) 后事務(wù)沒(méi)提交之前例获,事務(wù)2執(zhí)行 userMapper.selectUser() 是不能防止查找同一條數(shù)據(jù)
  • 3.在事務(wù)1、2查到同一條數(shù)據(jù)曹仗,事務(wù)1執(zhí)行 userMapper.updateUser(user, oldStatus) 沒(méi)提交之前榨汤,事務(wù)2執(zhí)行 userMapper.updateUser(user, oldStatus) 會(huì)卡住,但是1執(zhí)行完畢之后怎茫,最后事務(wù)2什么都不會(huì)更新

上面三個(gè)說(shuō)法哪個(gè)正確呢收壕?

  • 1.說(shuō)法1是錯(cuò)誤的妓灌,一般鎖表的情況下很多,除非表就一條數(shù)據(jù)蜜宪,否則的話虫埂,在可重復(fù)讀的情況下,mysql 對(duì)于程序不是修改同一條數(shù)據(jù)不會(huì)鎖灼匝椤(親測(cè))描馅,修改同一行數(shù)據(jù)只會(huì)鎖行县踢,更不可能鎖表。
  • 2.說(shuō)法2是正確的,因?yàn)槭聞?wù)1沒(méi)提交之前(雖然已經(jīng)執(zhí)行了 update)谈截,可重復(fù)讀的情況下婴削,數(shù)據(jù)修改對(duì)于其他事務(wù)是不可見(jiàn)的晦炊,事務(wù)2仍然能夠查詢相同的數(shù)據(jù)
  • 3.說(shuō)法3是正確的击狮,在同一條數(shù)據(jù)的情況下,修改同一條數(shù)據(jù)會(huì)卡住栗精,修改不同數(shù)據(jù)不會(huì)闯参。因?yàn)橄刃薷牡臄?shù)據(jù)會(huì)拿到行鎖,直到提交才會(huì)釋放悲立。后面拿到行鎖的事務(wù)鹿寨,因?yàn)槲疫@邊有一個(gè)樂(lè)觀鎖修改,前面事務(wù)已經(jīng)修改狀態(tài)薪夕,而這個(gè)事務(wù)會(huì)查不到改狀態(tài)的數(shù)據(jù)脚草,從而不修改數(shù)據(jù)。

說(shuō)了那么多其實(shí)就像說(shuō)明一點(diǎn)原献,而平時(shí)開發(fā)中馏慨,如果用到了事務(wù),針對(duì)數(shù)據(jù)庫(kù)狀態(tài)的問(wèn)題要多多考慮姑隅。我為什么會(huì)說(shuō)這話写隶,因?yàn)榫驮谥芪逦覀冇懻撁鎲纬厣暾?qǐng)修改的問(wèn)題,我說(shuō):只要我先拿到這條數(shù)據(jù)讲仰,后更新狀態(tài)為其他慕趴,別人就拿不到了。但是被別人當(dāng)場(chǎng)反駁:你的事務(wù)沒(méi)提交鄙陡,不能防止別人查不到這條數(shù)據(jù)冕房。所以讓我的方案頓時(shí)失效,雖然后面可以重新開一個(gè)事務(wù)趁矾,在另外的事務(wù)中做這個(gè)事耙册,或者將鎖提升到事務(wù)外部,用 redis 來(lái)控制取面單毫捣。但主要我是沒(méi)有考慮好事務(wù)的問(wèn)題详拙,所以導(dǎo)致我想問(wèn)題異常簡(jiǎn)單帝际。。溪厘。胡本。牌柄。

3畸悬、幻讀

在這里說(shuō)一個(gè)幻讀的定義的矯正。

很多人說(shuō)幻讀是可重復(fù)讀的情況下珊佣,事務(wù)1執(zhí)行事務(wù)蹋宦,先 select 沒(méi)有,后 insert咒锻,但是事務(wù)1還未提交冷冗;事務(wù)2也是先 select 沒(méi)有,后 select 發(fā)現(xiàn)多一條數(shù)據(jù)惑艇。這里以 A(id, name) 操作如下:

事務(wù)1 事務(wù)2
開啟事務(wù) 開啟事務(wù)
select * from A where id = 1(啥數(shù)據(jù)都沒(méi)有) select * from A where id = 1 (啥數(shù)據(jù)都沒(méi)有)
insert into A values(1, 'ppp')
select * from A where id = 1 (突然發(fā)現(xiàn)多了一條數(shù)據(jù))
事務(wù)提交 事務(wù)提交

說(shuō)實(shí)話蒿辙,上面的說(shuō)法無(wú)比扯淡。既然都是可重復(fù)讀了滨巴,在事務(wù)2在一個(gè)事務(wù)中怎么讀取跟原來(lái)不同的結(jié)果呢思灌?都違背了可重復(fù)讀的定義(否管 innerdb 咋實(shí)現(xiàn)的)。

正確的結(jié)果如下:

事務(wù)1 事務(wù)2
開啟事務(wù) 開啟事務(wù)
select * from A where id = 1(啥數(shù)據(jù)都沒(méi)有) select * from A where id = 1 (啥數(shù)據(jù)都沒(méi)有)
insert into A values(1, 'ppp')
select * from A where id = 1 (還是啥數(shù)據(jù)都沒(méi)有)
insert into A values(1, 'ppp') (報(bào)主鍵沖突恭取,插入失斕┏ァ)
事務(wù)提交 事務(wù)提交

所以,幻讀并不是指同一個(gè)事務(wù)執(zhí)行兩次相同的select語(yǔ)句得到的結(jié)果不同, 而是指select時(shí)不存在某記錄,但準(zhǔn)備插入時(shí)發(fā)現(xiàn)此記錄已存在,無(wú)法插入,這就產(chǎn)生了幻讀蜈垮。

4耗跛、資料

這里有一篇美團(tuán)的文章,事務(wù)講的特別好:https://tech.meituan.com/2014/08/20/innodb-lock.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末攒发,一起剝皮案震驚了整個(gè)濱河市调塌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惠猿,老刑警劉巖烟阐,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異紊扬,居然都是意外死亡蜒茄,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門餐屎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)檀葛,“玉大人,你說(shuō)我怎么就攤上這事腹缩∮炝” “怎么了空扎?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)润讥。 經(jīng)常有香客問(wèn)我转锈,道長(zhǎng),這世上最難降的妖魔是什么楚殿? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任撮慨,我火速辦了婚禮,結(jié)果婚禮上脆粥,老公的妹妹穿的比我還像新娘砌溺。我一直安慰自己,他們只是感情好变隔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布规伐。 她就那樣靜靜地躺著,像睡著了一般匣缘。 火紅的嫁衣襯著肌膚如雪猖闪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天肌厨,我揣著相機(jī)與錄音培慌,去河邊找鬼。 笑死夏哭,一個(gè)胖子當(dāng)著我的面吹牛检柬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播竖配,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼何址,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了进胯?” 一聲冷哼從身側(cè)響起用爪,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎胁镐,沒(méi)想到半個(gè)月后偎血,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盯漂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年颇玷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片就缆。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡帖渠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出竭宰,到底是詐尸還是另有隱情空郊,我是刑警寧澤份招,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站狞甚,受9級(jí)特大地震影響锁摔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哼审,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一谐腰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧棺蛛,春花似錦怔蚌、人聲如沸巩步。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)椅野。三九已至终畅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間竟闪,已是汗流浹背离福。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留炼蛤,地道東北人妖爷。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像理朋,于是被迫代替她去往敵國(guó)和親絮识。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容