国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

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

2024-07-24 12:47:20
字體:
來源:轉載
供稿:網友

問題背景:

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

 

當一個會員想續買會員(只能續買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_at
              END,
   end_at = CASE
            WHEN 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;

    So easy!

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

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 彭州市| 宁陵县| 措勤县| 天长市| 山东| 东乌珠穆沁旗| 晋江市| 剑阁县| 长春市| 阜阳市| 张家口市| 依安县| 陵水| 孟连| 建昌县| 石嘴山市| 景洪市| 西华县| 东乡县| 黄梅县| 彭阳县| 贞丰县| 屏东县| 碌曲县| 灵川县| 海兴县| 阿拉尔市| 贵德县| 方山县| 洛南县| 湖南省| 高清| 温泉县| 漾濞| 务川| 遂溪县| 嵊泗县| 乌鲁木齐县| 临沭县| 黑龙江省| 高邑县|