MySQL-MySQL实现计数器如何在高并发场景下更新并保持数据正确性
一张表 两个字段 一个id 一个useCount
表里存了100个id 每个id对应自己的useCount
业务场景是:当id每使用一次 useCount要加1。 当useCount大于1000时 这个id就不能在被使用了(换句话说 无法从数据库中查出)
在高并发情况下,会遇到一种问题:
假设数据表中有一条记录为 id=123456; useCount=999
a与b两个连接并发查询这个id 123456 都执行下列sql:
select * from table where id=123456 and useCount < 1000
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
insert into test values(123456, 1)
on duplicate key update useCount=if(useCount < 1000, useCount + 1, useCount);
然后根据affected rows来判断是否有影响一行,如果有则....,否则....。
使用悲观锁:
select * from table where id=123456 and useCount < 1000 for update;
则 b 连接的事务 会被 a连接的事务block; 直到a的事务结束,b的select才能返回.
使用乐观锁:
每次update判断 useCount;
假设a,b连接都拿到 id 123456的useCount是999, update语句写为:
update table set useCount=useCount+1 where id=123456 and useCount=999;
程序中查询上述update返回值,如果为1则表明更新了一条记录, update成功;
如果为0, 则表示没有更新任何记录, 即useCount值已经被更改了, 则重新查询useCount,重新提交update.
关于update语句返回值:
java/jdbc见:
http://docs.oracle.com/javase/6/docs/api/java/sql/PreparedStatement.html#executeUpdate%28%29
php见:
http://www.php.net/manual/en/mysqli.affected-rows.php