mysql的存储过程会自动开启一个事务吗?

问题描述

mysql的存储过程会自动开启一个事务吗

问题出现的环境背景及自己尝试过哪些方法

问题是这样的,有一段代码,这段代码开启了事务,整个请求就开启了这一个事务,这个事务中间有调用一个存储过程,这个存储过程就是更新了一些数据,存储过程里面是没有显示开启事务的,就begin,end就完了。
这个事务里面有更新一条数据,执行完后,代码里面又有个操作去更新存储过程里面刚刚更新过了的同一条数据,这里就发生了锁等待超时了。

你期待的结果是什么?实际看到的错误信息又是什么?

我想问的是,调用执行存储过程,存储过程里面没有开启事务,它会自动开启一个新的事务吗?而且没有自动提交。
导致后面操作相同数据的时候拿不到锁。

我通过查看MySQL的锁情况和代码测试,发现确实是存储过程开启了一个新的事务,执行完后也没有提交,一直挂在那里。

阅读 4.8k
1 个回答

当你决定使用存储过程的时候,那么整个事务是在MYSQL端完成的。

对于事务竞争优化的主要一点就是减少事务锁时间。

你选择了使用存储过程就可以不用再代码中开启事务,深度优化即将事务SQL在MYSQL端执行(存储过程)

以下是类似的秒杀事务落地的存储过程

-- 秒杀执行存储过程
DELIMITER $$ -- ; 转换为 $$
-- 定义存储过程 in 输入参数   out 输出参数
-- ROW_COUNT 返回上一条修改类型sql(delete、insert、update)的影响函数
-- row_count 0 未修改数据 >0修改的函数 <0 SQL错误、未执行修改sql
CREATE 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;

这属于并发优化的阶段了,不要过度依赖存储过程,其一般用于简单的逻辑

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题