在给定方案中,我是否需要担心UPDATE操作中同时请求的影响

hre*_*tic 5 mysql sql security database-design stored-procedures

想象一下这个场景,我有一个网站,用户通过销售他们的项目或点击广告或任何我的用户表将是这样的活动得到信任

users : id , username , credit 
         15 , alex     , 1000 
         16 , jack     , 1500 
Run Code Online (Sandbox Code Playgroud)

所以现在用户可以要求在某种支付方式中提取信用卡,我的提款表就是这样的

withdraws : 
id , user_id , amount 
1  ,  15      , 500 
2  ,  16      , 100 
Run Code Online (Sandbox Code Playgroud)

我不得不从他们的信用中扣除提款金额...我喜欢用触发器做这件事

CREATE TRIGGER  withdraw
  BEFORE INSERT
  ON withdraws
  FOR EACH ROW
BEGIN

     UPDATE  users SET credit = credit-NEW.amount WHERE id  = NEW.user_id;
END $$
Run Code Online (Sandbox Code Playgroud)

并确保用户在撤销过程中不能以负面信用结束我有这个触发器(诅咒我也会在代码逻辑中检查这一点)

CREATE TRIGGER  update_user
  BEFORE UPDATE
  ON users
  FOR EACH ROW
BEGIN

    IF NEW.credit < 0 THEN 
          SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'invalid credit error'; 
    END IF;


END $$
Run Code Online (Sandbox Code Playgroud)

现在我的问题是,有可能有人故意或通过某种服务器错误同时发送多个撤销请求,并撤回超过他的信用....如果是这样我怎么能阻止这个?

在每次撤销插入或类似之前我需要锁定用户表吗?

更新: 如果我要锁定用户行并使用事务包装器进行整个操作......看起来合理但触发器如何适应?我的意思是显然我必须启动事务并在代码中完成/提交它(因为我讨厌存储过程并且从不使用它们)这是否意味着我必须放弃触发器并在代码中执行减法或以某种方式触发发生尽管在不同的平台/地点开始/执行,但内部交易

Dre*_*rew 1

我会通过意向锁来解决这个问题。看看我在这里写的一个例子。其中有关于事务块的第​​ 1 行到第 5 行之间发生的情况的叙述以及其他相关信息。

您自然不会像该示例中那样获得增量器。相反,您的代码将尽快执行更新并进行提交。

该代码可以属于任何地方,而不仅仅是存储过程中。它可以是事件或触发器。DB Engine(例如 INNODB)是确保两个人无法同时进入该 LOCK 的机制。如何编写与此相关的代码取决于您。