Mysql 在给定场景中,我是否需要担心更新操作中同时请求的影响

Mysql 在给定场景中,我是否需要担心更新操作中同时请求的影响,mysql,sql,security,stored-procedures,database-design,Mysql,Sql,Security,Stored Procedures,Database Design,想象一下这个场景,我有一个网站,用户通过销售商品或点击广告等活动获得信用,或者我的用户表是这样的 users : id , username , credit 15 , alex , 1000 16 , jack , 1500 withdraws : id , user_id , amount 1 , 15 , 500 2 , 16 , 100 因此,现在用户可以请求在某种付款方式下提取他们的信用卡

想象一下这个场景,我有一个网站,用户通过销售商品或点击广告等活动获得信用,或者我的用户表是这样的

users : id , username , credit 
         15 , alex     , 1000 
         16 , jack     , 1500 
withdraws : 
id , user_id , amount 
1  ,  15      , 500 
2  ,  16      , 100 
因此,现在用户可以请求在某种付款方式下提取他们的信用卡。我的取款表是这样的

users : id , username , credit 
         15 , alex     , 1000 
         16 , jack     , 1500 
withdraws : 
id , user_id , amount 
1  ,  15      , 500 
2  ,  16      , 100 
我必须从他们的信用卡中扣除提款金额。。。我喜欢用扳机

CREATE TRIGGER  withdraw
  BEFORE INSERT
  ON withdraws
  FOR EACH ROW
BEGIN

     UPDATE  users SET credit = credit-NEW.amount WHERE id  = NEW.user_id;
END $$
为了确保用户在取款过程中不会得到负信用,我有这个触发器(当然,我也会在代码逻辑中检查)

创建触发器更新\u用户
更新前
关于用户
每行
开始
如果NEW.credit<0,则
信号SQLSTATE'45000'设置消息_TEXT='invalid credit error';
如果结束;
结束$$
现在我的问题是,是否有人故意或通过某种服务器错误同时发送多个取款请求,并且取款超过了他的信用。。。。如果是这样的话,我该如何预防呢

是否需要在每次撤消插入或类似操作之前锁定users表

更新:
如果我要锁定用户行并在整个操作中使用事务包装器。。。似乎合理,但触发器如何配合?我的意思是,显然我必须启动事务并在代码中完成/提交它(因为我讨厌存储过程,而且从不使用它们)这是否意味着我必须放弃触发器,并在代码中进行减法运算,或者尽管在不同的平台/位置启动/执行,触发器还是会在事务内部发生。我会通过意向锁来解决这个问题。看看我写的一个例子。这里有一个关于事务块的第1行到第5行之间发生的事情以及其他相关信息的叙述

您自然不会得到像那个例子中那样的增量导师。相反,您的代码将尽可能快地执行更新和提交


这些代码可以属于任何地方,而不仅仅是存储过程。它可以是和事件或触发器。DB引擎(比如INNODB)是确保两个人不能同时进入锁的机制。如何编写与此相关的代码取决于您。

这称为竞争条件,问题中的代码确实受此约束。但有趣的是,我认为如果触发器中没有其他情况发生,这不是一个可利用的漏洞,您可能只是在安全方面出错(有效的撤销可能会导致错误,但我认为无效的撤销不可能不会导致错误)


您仍然不应该这样做,应该通过添加锁(以牺牲一些性能为代价)来消除竞争条件。

thanx,我不知道它的名称。。。在我看来,减法是在每次插入后在数据库触发器中发生的,而不是在代码中,因此,由于同一个表中的两次插入不能同时发生(实际上,我只是在猜测!!你知道,由于自动递增id的缘故,插入应该有某种类型的que)2个触发器不能同时发生,所以基本上锁定用户行并在整个操作中使用事务包装器。。。似乎合理,但触发器如何配合?我的意思是,很明显,我必须启动事务并在代码中完成/提交它(你看,我讨厌存储过程,就像我喜欢触发器一样)。这是否意味着我必须放弃触发器并在代码中执行减法运算,或者,尽管启动/执行过程不同,触发器还是会在事务内部发生。。。平台/地点(我的英语不及格,希望你知道我的意思)我还有一个不相关的问题,就像我在@lengyelg问的:在我看来,减法发生在数据库触发器中,每次插入后都会发生,而不是在代码中,因此,由于同一个表中的两次插入不能同时发生(实际上我只是在猜测!!你知道,由于自动递增id的原因,应该有一些用于插入的que,我猜他们会在单个物理文件中写入)两个触发器不能同时发生我正试图完成另一个答案,我妈妈带着食物过来,胡说八道,所以我不能很好地集中注意力。过一会儿会给你回复。thanx,现在是早上5点,反正我要睡觉了所以…关于第二个问题,我刚刚意识到触发器发生在插入之前,所以我这无关紧要,但我还是很好奇,如果我说的是真的,理论上两个触发器可以在接近或同时开始,但向您显示我编写的Oracle序列链接的目的是向您显示意图锁。这将禁止服务器上的任何两个线程(同时)进入到受保护的Line3/Line4区域。在存储过程中,该区域是一个更新语句。但对您来说,它可能是一系列调用,但要尽可能快。出于对用户UX体验的礼貌,请快一点。