亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

mysql的存儲過程會自動開啟一個事務嗎?

mysql的存儲過程會自動開啟一個事務嗎?

qq_笑_17 2018-07-03 11:33:56
mysql的存儲過程會自動開啟一個事務嗎有一段代碼,這段代碼開啟了事務,整個請求就開啟了這一個事務,這個事務中間有調用一個存儲過程,這個存儲過程就是更新了一些數據,存儲過程里面是沒有顯示開啟事務的,就begin,end就完了。這個事務里面有更新一條數據,執行完后,代碼里面又有個操作去更新存儲過程里面剛剛更新過了的同一條數據,這里就發生了鎖等待超時了。我想問的是,調用執行存儲過程,存儲過程里面沒有開啟事務,它會自動開啟一個新的事務嗎?而且沒有自動提交。導致后面操作相同數據的時候拿不到鎖。我通過查看MySQL的鎖情況和代碼測試,發現確實是存儲過程開啟了一個新的事務,執行完后也沒有提交,一直掛在那里。
查看完整描述

1 回答

?
倚天杖

TA貢獻1828條經驗 獲得超3個贊

當你決定使用存儲過程的時候,那么整個事務是在MYSQL端完成的。

對于事務競爭優化的主要一點就是減少事務鎖時間。

你選擇了使用存儲過程就可以不用再代碼中開啟事務,深度優化即將事務SQL在MYSQL端執行(存儲過程)

以下是類似的秒殺事務落地的存儲過程

-- 秒殺執行存儲過程
DELIMITER $$ -- ; 轉換為 $$
-- 定義存儲過程 in 輸入參數   out 輸出參數
-- ROW_COUNT 返回上一條修改類型sql(delete、insert、update)的影響函數
-- row_count 0 未修改數據 >0修改的函數 <0 SQL錯誤、未執行修改sqlCREATE PROCEDURE `seckill`.`execute_seckill`  (in v_seckill_id bigint,in v_phone bigint,    in v_kill_time TIMESTAMP ,out r_result int)
  BEGIN
    DECLARE insert_count int DEFAULT 0;
    START TRANSACTION ;
    insert ignore into success_killed
      (seckill_id,user_phone,create_time)
      VALUES (v_seckill_id,v_phone,v_kill_time)
          select ROW_COUNT() into insert_count;
              if (insert_count = 0) THEN
      ROLLBACK;
            set r_result = -1;
    ElSEIF(insert_count < 0) THEN
      ROLLBACK;
            set r_result = -2;    
            ELSE
      UPDATE seckill
            set number = number - 1
      where seckill_id = v_seckill_id
              and end_time > v_kill_time
                      and start_time < v_kill_time
                              and number > 0; 
                                     SELECT row_count() into insert_count;
                                             if (insert_count = 0) THEN
          ROLLBACK;
                    set r_result = 0;
        ElSEIF(insert_count < 0) THEN
          ROLLBACK;
                    set r_result = -2; 
                           ELSE
          COMMIT; 
                   SET r_result = 1; 
                          END if; 
                             END if; 
                              END;
$$
-- 存儲過程定義結束

DELIMITER ;set @r_result=-3;
-- 執行存儲過程
call execute_seckill(1003,18820116735,now(),@r_result);

-- 獲取結果select @r_result;

這屬于并發優化的階段了,不要過度依賴存儲過程,其一般用于簡單的邏輯

查看完整回答
反對 回復 2018-07-20
  • 1 回答
  • 0 關注
  • 2018 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號