数据库表加锁

By admin, 12 十二月, 2016

一直以来我都没有考虑过些SQL语句是需要自己处理锁的问题。最近一段和钱有关的代码收到攻击才让我意识到问题的严重性。

受攻击的代码大概是这样子的:

 

SQL查询余额

if (余额 > 0) {

  执行提现操作

  减去余额

}

攻击者同时发送了多个提现请求,提现请求在判断是否有余额的时候都显示有余额,然后都允许提现。事实上,这里面其中一个请求提现完之后就不够余额了,但是其它进程都不知道这个情况。要避免这种情况的发生,需要对查询余额和扣减余额的操作做成原子操作,在查询和扣减操作之间不允许余额再发生变动。

MySQL中有"SELECT ... FOR UPDATE"去解决这种情况,需配合Transacion来实现,参考:http://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

要验证锁是否生效不需要模拟同时发请求的情况,模拟了也不确定是否成功。可以在查询之后sleep 60秒再更余额,在60秒内发送两个请求就能重现问题了。

标签

评论

Restricted HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <img src>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。
验证码
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
请输入"Drupal10"