日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

MySQL中SELECT+UPDATE處理并發更新問題解決方案

瀏覽:27日期:2023-10-17 08:07:13

這篇文章主要介紹了MySQL中SELECT+UPDATE處理并發更新問題解決方案分享,需要的朋友可以參考下。

問題背景

假設MySQL數據庫有一張會員表vip_member(InnoDB表),結構如下:

MySQL中SELECT+UPDATE處理并發更新問題解決方案

當一個會員想續買會員(只能續買1個月、3個月或6個月)時,必須滿足以下業務要求:

如果end_at早于當前時間,則設置start_at為當前時間,end_at為當前時間加上續買的月數如果end_at等于或晚于當前時間,則設置end_at=end_at+續買的月數續買后active_status必須為1(即被激活)問題分析

對于上面這種情況,我們一般會先SELECT查出這條記錄,然后根據查出記錄的end_at再UPDATE start_at和end_at,偽代碼如下(為uid是1001的會員續1個月):

vipMember = SELECT * FROM vip_member WHERE uid=1001 LIMIT 1 # 查uid為1001的會員 if vipMember.end_at < NOW(): UPDATE vip_member SET start_at=NOW(), end_at=DATE_ADD(NOW(), INTERVAL 1 MONTH), active_status=1, updated_at=NOW() WHERE uid=1001 else: UPDATE vip_member SET end_at=DATE_ADD(end_at, INTERVAL 1 MONTH), active_status=1, updated_at=NOW() WHERE uid=1001

假如同時有兩個線程執行上面的代碼,很顯然存在“數據覆蓋”問題(即一個是續1個月,一個續2個月,但最終可能只續了2個月,而不是加起來的3個月)。

解決方案

A、我想到的第一種方案是把SELECT和UPDATE合成一條SQL

如下:

UPDATE vip_member SET start_at = CASE WHEN end_at < NOW() THEN NOW()ELSE start_atEND, end_at = CASEWHEN end_at < NOW()THEN DATE_ADD(NOW(), INTERVAL #duration:INTEGER# MONTH)ELSE DATE_ADD(end_at, INTERVAL #duration:INTEGER# MONTH)END, active_status=1, updated_at=NOW()WHERE uid=#uid:BIGINT#LIMIT 1;

B、第二種方案:事務,即用一個事務來包裹上面的SELECT+UPDATE操作

那么是否包上事務就萬事大吉了呢?

顯然不是。因為如果同時有兩個事務都分別SELECT到相同的vip_member記錄,那么一樣的會發生數據覆蓋問題。那有什么辦法可以解決呢?難道要設置事務隔離級別為SERIALIZABLE,考慮到性能不現實。

我們知道InnoDB支持行鎖。查看MySQL官方文檔(innodb locking reads)了解到InnoDB在讀取行數據時可以加兩種鎖:讀共享鎖和寫獨占鎖。

讀共享鎖是通過下面這樣的SQL獲得的:

SELECT * FROM parent WHERE NAME = ’Jones’ LOCK IN SHARE MODE;

如果事務A獲得了先獲得了讀共享鎖,那么事務B之后仍然可以讀取加了讀共享鎖的行數據,但必須等事務A commit或者roll back之后才可以更新或者刪除加了讀共享鎖的行數據。

SELECT counter_field FROM child_codes FOR UPDATE;UPDATE child_codes SET counter_field = counter_field + 1;

如果事務A先獲得了某行的寫共享鎖,那么事務B就必須等待事務A commit或者roll back之后才可以訪問行數據。

顯然要解決會員狀態更新問題,不能加讀共享鎖,只能加寫共享鎖,即將前面的SQL改寫成如下:

vipMember = SELECT * FROM vip_member WHERE uid=1001 LIMIT 1 FOR UPDATE # 查uid為1001的會員if vipMember.end_at < NOW(): UPDATE vip_member SET start_at=NOW(), end_at=DATE_ADD(NOW(), INTERVAL 1 MONTH), active_status=1, updated_at=NOW() WHERE uid=1001else: UPDATE vip_member SET end_at=DATE_ADD(end_at, INTERVAL 1 MONTH), active_status=1, updated_at=NOW() WHERE uid=1001

另外這里特別提醒下:UPDATE/DELETE SQL盡量帶上WHERE條件并在WHERE條件中設定索引過濾條件,否則會鎖表,性能可想而知有多差了。

C、第三種方案:樂觀鎖,類CAS機制

第二種加鎖方案是一種悲觀鎖機制。而且SELECT...FOR UPDATE方式也不太常用,聯想到CAS實現的樂觀鎖機制,于是我想到了第三種解決方案:樂觀鎖。

具體來說也挺簡單,首先SELECT SQL不作任何修改,然后在UPDATE SQL的WHERE條件中加上SELECT出來的vip_memer的end_at條件。如下:

vipMember = SELECT * FROM vip_member WHERE uid=1001 LIMIT 1 # 查uid為1001的會員cur_end_at = vipMember.end_atif vipMember.end_at < NOW(): UPDATE vip_member SET start_at=NOW(), end_at=DATE_ADD(NOW(), INTERVAL 1 MONTH), active_status=1, updated_at=NOW() WHERE uid=1001 AND end_at=cur_end_atelse: UPDATE vip_member SET end_at=DATE_ADD(end_at, INTERVAL 1 MONTH), active_status=1, updated_at=NOW() WHERE uid=1001 AND end_at=cur_end_at

這樣可以根據UPDATE返回值來判斷是否更新成功,如果返回值是0則表明存在并發更新,那么只需要重試一下就好了。

方案比較

三種方案各自優劣也許眾說紛紜,只說說我自己的看法:

第一種方案利用一條比較復雜的SQL解決問題,不利于維護,因為把具體業務糅在SQL里了,以后修改業務時不但需要讀懂這條SQL,還很有可能會修改成更復雜的SQL第二種方案寫獨占鎖,可以解決問題,但不常用第三種方案應該是比較中庸的解決方案,并且甚至可以不加事務,也是我個人推薦的方案

此外,樂觀鎖和悲觀鎖的選擇一般是這樣的(參考了文末第二篇資料):

如果對讀的響應度要求非常高,比如證券交易系統,那么適合用樂觀鎖,因為悲觀鎖會阻塞讀如果讀遠多于寫,那么也適合用樂觀鎖,因為用悲觀鎖會導致大量讀被少量的寫阻塞如果寫操作頻繁并且沖突比例很高,那么適合用悲觀寫獨占鎖
標簽: MySQL 數據庫
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
青青久久av| 91成人超碰| 亚洲欧洲av| 日韩av网站免费在线| 亚洲+小说+欧美+激情+另类| 蜜臀va亚洲va欧美va天堂| 在线日韩成人| 青青国产精品| 精品久久影院| 亚洲国内欧美| 综合国产精品| 国产精品17p| 日韩中文影院| 亚洲一区二区毛片| 在线国产精品一区| 亚洲精品系列| 日韩88av| 亚洲在线国产日韩欧美| 日韩精品三区四区| 成人精品国产亚洲| 国产亚洲在线观看| 91精品麻豆| 伊人精品一区| 欧美有码在线| 亚洲国产专区| 国产激情综合| 国产亚洲福利| 成人在线观看免费视频| 久久国产高清| 国产精品亚洲二区| 欧美日韩国产高清电影| 欧美日韩午夜电影网| 日韩精品欧美激情一区二区| 亚洲精选成人| 另类中文字幕国产精品| 四虎成人精品一区二区免费网站| 欧美国产不卡| 亚洲人成在线影院| 久久久人人人| 麻豆精品99| 99久久久久| 中文字幕av一区二区三区四区| 电影亚洲精品噜噜在线观看| 成人羞羞在线观看网站| 亚洲激情国产| 免费看黄色91| 亚洲ab电影| 日韩视频二区| 欧美手机在线| 日韩在线欧美| 另类小说一区二区三区| 亚洲精品美女91| 丝袜国产日韩另类美女| 自拍日韩欧美| 蜜臀av免费一区二区三区| 福利精品在线| 精品一区二区三区中文字幕在线| 四虎精品永久免费| 日本aⅴ免费视频一区二区三区| 欧美亚洲国产精品久久| 97视频热人人精品免费| 成人台湾亚洲精品一区二区| 久久精品女人| 成人在线免费观看91| 高清一区二区三区av| 国产拍在线视频| 成人午夜国产| 不卡在线一区| 久久亚洲影院| 91九色综合| 精品三级在线| 天堂а√在线最新版中文在线| 国产精品国产三级国产在线观看| 精品中文字幕一区二区三区| 国产精品日本一区二区三区在线| 国产欧美日韩影院| 中文字幕在线看片| 激情综合自拍| 日韩视频1区| 国语精品一区| 欧美不卡在线| 日韩高清二区| 天堂√中文最新版在线| 欧美日韩视频网站| 99国产精品| 美日韩精品视频| 国产精品久久免费视频| 久久久国产精品一区二区中文| 亚洲综合国产| 国产午夜久久av| 在线天堂资源www在线污| 婷婷成人在线| 国产图片一区| 欧美日韩激情| 国产精品3区| 性欧美长视频| 国产一二在线播放| 日本久久一区| 在线日韩中文| 九九99久久精品在免费线bt| 免费日韩av片| 麻豆视频在线观看免费网站黄| 在线精品福利| 亚洲激精日韩激精欧美精品| 国产精品日本一区二区不卡视频| 婷婷亚洲五月色综合| 欧美国产日本| 青草国产精品久久久久久| 在线一区视频观看| 卡一卡二国产精品| 日韩av网站在线观看| 国产亚洲一区在线| 久久91导航| 国产精品99一区二区三| 国产日韩一区二区三区在线 | 黄色成人在线网址| 国产日韩中文在线中文字幕 | 日本成人中文字幕| 国产视频久久| 欧美成人久久| 秋霞国产精品| 97国产精品| 欧美激情国产在线| 精品国产a一区二区三区v免费| 欧美日韩中出| 国产毛片久久久| 国产精品久久777777毛茸茸| 欧美日本久久| 久久精品国内一区二区三区| 日本在线观看不卡视频| 日本精品在线播放| 欧美精品三级在线| 国产精品2区| 日韩精品永久网址| 四虎884aa成人精品最新| 日韩精品午夜| 每日更新成人在线视频| 亚洲精品亚洲人成在线观看| 欧美日韩一区二区三区四区在线观看| 中文字幕av一区二区三区人| 欧美影院精品| 在线看片福利| 国产农村妇女精品一区二区| 亚洲一区二区三区在线免费| 亚洲丝袜美腿一区| 国产精品2区| 国产91一区| 日韩在线网址| 国产精品成人一区二区网站软件| 国产va在线视频| 亚洲欧美日韩国产一区| 久久国产欧美日韩精品| 欧美韩日一区| 久久午夜精品一区二区| 国产精品调教| 九一精品国产| 7m精品国产导航在线| 97国产成人高清在线观看| 日韩亚洲精品在线| 日本综合精品一区| bbw在线视频| 日本成人手机在线| 亚洲成人精品| 日本少妇一区| 亚洲综合精品| 涩涩av在线| 国产欧美日韩一区二区三区在线| 欧美xxxx中国| 国产精品三级| 免费日本视频一区| 日韩精品dvd| 国产欧美激情| 久热精品在线| 91精品啪在线观看国产18| 亚洲天堂免费| 九九在线精品| 99久久久久| 日韩成人精品一区| 国产欧美日韩精品高清二区综合区 | 综合五月婷婷| 久久激情一区| 国产一区二区三区不卡av| 91精品国产自产观看在线| 99热精品在线| 欧美在线网站| 欧美日韩中文一区二区| 久久久久久色| 日韩不卡一区二区三区| 日韩午夜在线| 久久影院一区| 久久一区二区中文字幕| 成人精品天堂一区二区三区| 国产精品久久久免费| 日韩精品中文字幕一区二区| 蜜桃视频第一区免费观看| 九色精品91| re久久精品视频| 黄色成人91| 首页欧美精品中文字幕| 中文字幕日本一区二区|