一个用户多条记录,以最后记录产生新的余额记录

原贴:  点击打开链接
-- 测试表及测试数据开始
USE tempdb
GO
IF OBJECT_ID('t') IS NOT NULL DROP TABLE t
CREATE TABLE t(
	id INT IDENTITY(1,1) PRIMARY KEY ,
	userId INT NOT NULL,
	consume INT NOT NULL,
	balance INT NOT NULL
)
--第一条记录视为交费,交费直接插入就好,不需要任何逻辑
INSERT INTO t(userId,consume,balance) VALUES(120,9,1000)
-- 测试表及测试数据结束


----- 插入消费记录 BEGIN -----
-- 用 SqlQueryStress 工具测试 50线程,每线程循环10次
DECLARE @userId INT,@consume INT
SET @userId=120
SET @consume=1
 
INSERT INTO t(userId,consume,balance)
SELECT @userId,@consume,balance-@consume
FROM t 
WHERE userId=@userId
AND id = (SELECT MAX(id) FROM t WITH(TABLOCK) WHERE userId=@userId)
--注:上面With 后面只能加 TABLOCK ,其它锁都会有问题无法通过后面的验证
----- 插入消费记录 END -----


----- 验证开始 -----
--验证是否有操作失误的记录(消费了余额不可能不变化)
SELECT * FROM t a WHERE EXISTS(
	SELECT * FROM t b WHERE a.id!=b.id AND a.balance=b.balance
)
--无记录

SELECT TOP 1 * FROM t ORDER BY id DESC
/*
id	userId	consume	balance
501	  120	  1       500
*/
----- 验证结束 -----


后记:

TABLOCK的效率是最低的,不过按楼主的需求,只有表锁才能满足要求了。

建议用户表中增加一个字段:余额,每次更新用户表, 只需要锁定一行, 而且根本不需要写显式的锁和事务。 效率高很多。

更新完用户表, 往现在的这个表里面插入一条记录即可。


附:锁的相关知识:点击打开链接


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值