MySQL存储过程秒杀扣减库存
CREATE TABLE seckill(
`seckill_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '商品库存id',
`name` VARCHAR(120) NOT NULL COMMENT '商品名称',
`number` INT NOT NULL COMMENT '库存数量',
`start_time` TIMESTAMP NOT NULL COMMENT '秒杀开始时间',
`end_time` TIMESTAMP NOT NULL COMMENT '秒杀结束时间',
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '秒杀创建时间',
PRIMARY KEY (`seckill_id`),
KEY `idx_start_time` (`start_time`),
KEY `idx_end_time` (`end_time`),
KEY `idx_create_time` (`create_time`)
)ENGINE=INNODB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='秒杀库存表';
INSERT INTO
seckill(NAME, number, start_time, end_time)
VALUES
('1000元秒杀iphone6', 100, '2015-11-01 00:00:00', '2015-11-02 00:00:00'),
('500元秒杀ipad2', 200, '2015-11-01 00:00:00', '2015-11-02 00:00:00'),
('300元秒杀小米4', 300, '2015-11-01 00:00:00', '2015-11-02 00:00:00'),
('200元秒杀红米note', 400, '2015-11-01 00:00:00', '2015-11-02 00:00:00');
CREATE TABLE success_killed(
`seckill_id` BIGINT NOT NULL COMMENT '商品库存id',
`user_phone` BIGINT NOT NULL COMMENT '用户手机号',
`state` TINYINT NOT NULL DEFAULT -1 COMMENT '状态信息:-1无效,0成功,1已付款,2已发货',
`create_time` TIMESTAMP NOT NULL COMMENT '创建时间',
PRIMARY KEY (`seckill_id`, `user_phone`),
KEY `idx_create_time` (`create_time`)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='秒杀库存表';
DELIMITER $$
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(1001, 13631231234, now(), @r_result);
SELECT @r_result;