为了账号安全,请及时绑定邮箱和手机立即绑定

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 关注
  • 2043 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号