每日内涵图,唤醒你迎接美好的一天
正文:
文章分为以下几个要点
问题描述以及解决过程
MySQL锁机制
数据库加锁分析
下面讨论的都是基于MySQL的InnoDB。
0. 问题描述以及解决过程
因为涉及到公司利益问题,所以下面很多代码和数据库信息,进行了缩减和修改,望见谅。
业务场景是优惠券系统规则规定了一个优惠券活动最多可发行多少张优惠券和每个用户最多可领取优惠券数量。
下面列出两张表的结构。
活动表
CREATE TABLE `coupon_activity` (
`act_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`act_code` char(6) NOT NULL DEFAULT ''
COMMENT '活动编码',
`coup_issue_num` int(11) NOT NULL DEFAULT '0'
COMMENT '优惠券发行量',
`coup_per_num` int(11) NOT NULL DEFAULT '0'
COMMENT '单个用户可领取数',
PRIMARY KEY (`act_id`),
UNIQUE KEY `act_code_idx` (`act_code`)
COMMENT '活动编码唯一索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
优惠券明细表
CREATE TABLE `coupon_detail` (
`coup_id` int(11) NOT NULL AUTO_INCREMENT,
`act_code` char(6) NOT NULL DEFAULT ''
COMMENT '活动编号',
`coup_code` char(6) NOT NULL DEFAULT ''
COMMENT '优惠券编码',
`coup_user_id` int(11) NOT NULL DEFAULT '0'
COMMENT '领取券用户id',
PRIMARY KEY (`coup_id`),
UNIQUE KEY `coup_code_idx` (`coup_code`)
USING BTREE COMMENT '优惠券编码唯一索引',
KEY `coup_user_idx` (`coup_user_id`)
USING BTREE COMMENT '用户id普通索引',
KEY `act_code_idx` (`act_code`)
USING BTREE COMMENT '活动编码普通索引'
) ENGINE=InnoDB DEFAULT CHARSET
=utf8 COMMENT='优惠券明细表';
假设一个优惠券活动设置的最大发行量为1000张优惠券,单个用户最多可领取1张优惠券。如下
insert into coupon_activity values (1,'000000',1000,1,0);
不考虑到并发的话,用户10领取act_code=’000000’活动的优惠券 执行的sql如下。注意#{}里面的字段表示之前的sql查询出来的字段。
begin;
select * from coupon_activity where act_code = '000000';
select count(coup_id) as count_all
from coupon_detail where act_code = #{act_code};
select count(coup_id) as count_per from
coupon_detail where coup_user_id =
10 and act_code = #{act_code};
//插入明细表 首先判断是否当前领用量小于活动发行量,
当前用户领取量是否小于每个用户可领取数
if(#{count_all} |