国产探花免费观看_亚洲丰满少妇自慰呻吟_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操作。

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 封丘县| 佛山市| 旺苍县| 军事| 镇平县| 时尚| 古田县| 宜宾县| 定西市| 伊金霍洛旗| 蚌埠市| 滁州市| 全椒县| 容城县| 汤阴县| 莆田市| 礼泉县| 常宁市| 红河县| 满洲里市| 肇庆市| 榆林市| 武宁县| 通江县| 特克斯县| 龙游县| 巩义市| 肥东县| 杭锦后旗| 祁连县| 梓潼县| 湖南省| 平泉县| 武功县| 金华市| 确山县| 博罗县| 栾川县| 鹤岗市| 怀来县| 隆子县|