mysql insert 并发问题

问题:我有两张表,一张是优惠券活动表,另一个是用户领取优惠券的明细表。如下
CREATETABLE`coupon_activity`(
`act_id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',
`act_code`char(6)NOTNULLDEFAULT''COMMENT'活动编码',
`coup_issue_num`int(11)NOTNULLDEFAULT'0'COMMENT'优惠券发行量',
`coup_per_num`int(11)NOTNULLDEFAULT'0'COMMENT'单个用户可领取数',
PRIMARYKEY(`act_id`),
UNIQUEKEY`act_code_idx`(`act_code`)COMMENT'活动编码唯一索引'
)ENGINE=InnoDBDEFAULTCHARSET=utf8COMMENT='优惠券活动表';
CREATETABLE`coupon_detail`(
`coup_id`int(11)NOTNULLAUTO_INCREMENT,
`act_code`char(6)NOTNULLDEFAULT''COMMENT'活动编号',
`coup_code`char(6)NOTNULLDEFAULT''COMMENT'优惠券编码',
`coup_user_id`int(11)NOTNULLDEFAULT'0'COMMENT'领取券用户id',
PRIMARYKEY(`coup_id`),
UNIQUEKEY`coup_code_idx`(`coup_code`)USINGBTREECOMMENT'优惠券编码唯一索引',
KEY`coup_user_idx`(`coup_user_id`)USINGBTREECOMMENT'用户id普通索引',
KEY`act_code_idx`(`act_code`)USINGBTREECOMMENT'活动编码普通索引'
)ENGINE=InnoDBDEFAULTCHARSET=utf8COMMENT='优惠券明细表';
假如现在有一个编码为act_code='000000'的优惠券活动,限定的没每个人只能领一张券,现在用户id=10的用户来领取该活动的券,在不考虑并发时的代码如下(#{}里面的字段表示前面的sql语句查出来的值):
begin;
select*fromcoupon_activitywhereact_code='000000';
//当前10号用户领取该活动优惠券的数量
selectcount(coup_id)ascount_perfromcoupon_detailwherecoup_user_id=10andact_code=#{act_code};
//插入明细表当前用户领取量是否小于每个用户可领取数
if(#{count_per}<#{coup_per_num}){
insertintocoupon_detailvalues(1,act_code,'000000',10);
}
commit;
那么如果有两个事务进来的话,就会出现这种情况,两个事务读取的数据都是0,那么if语句就能通过,然后两个事务都成功insert,这样这个用户就多领取了一张优惠券。
备注:
备注用悲观锁的话,会发生死锁。
乐观锁的话,因为是insert语句,不是单单一条update语句,无法做到操作的时候进行校验。
只能领取一张券的话,可以使用联合唯一索引解决,但是业务上还会有可领取2张的,甚至更多
望各位mysql大大帮忙解决下,或者说还有其他更好的解决并发的方法,这个问题纠结好久了。
HUX布斯
浏览 294回答 2
2回答

Cats萌萌

提供一个思路供参考,写一条复杂的insert语句如下:insertintocoupon_detailselect1,act_code,'000000',10from(selectcount(coup_id)ascount_perfromcoupon_detailwherecoup_user_id=10andact_code=#{act_code})TMPwhereTMP.count_per
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript