sql – 如何处理数据库中的并发更新? - 代码日志

sql – 如何处理数据库中的并发更新?

在SQL数据库中处理并发更新的常见方法是什么?

考虑一个简单的SQL模式(约束和默认值未显示..)

create table credits (
  int id,
  int creds,
  int user_id
);

意图是为用户存储某种类型的信用,例如像stackoverflow的声誉。

如何处理该表的并发更新?
几个选项:

> update credit set creds = 150 where userid = 1;

在这种情况下,应用程序检索当前值,计算新值(150)并执行更新。如果有人在同一时间做同样的事情,就会发生灾难。
我猜想包装当前值的retreival和更新在一个事务将解决,例如开始;从userid = 1的学分中选择凭证;应用程序逻辑来计算新值,更新学分集积分= 160,其中userid = 1;结束;在这种情况下,您可以检查新信用额度是否为0并且只要将其截断为0,如果否定的积分没有意义。
更新学分集合creds = creds – 150其中userid = 1;

这种情况不需要担心并发更新,因为数据库负责处理一致性问题,但是有一些缺陷使得信任会变得消极,这在某些应用程序中可能没有意义。

那么简单地说,处理上面概述的(相当简单的)问题的接受方法是什么?如果db抛出错误怎么办?

使用交易:

BEGIN WORK;
SELECT creds FROM credits WHERE userid = 1;
-- do your work
UPDATE credits SET creds = 150 WHERE userid = 1;
COMMIT;

一些重要的注意事项:

>并非所有数据库类型都支持事务。特别是,mysql的默认数据库类型MyISAM没有。如果你在mysql上使用InnoDB。
>由于您无法控制的原因,交易可能会中止。如果发生这种情况,您的应用程序必须准备从BEGIN WORK开始重新开始。
>您需要将隔离级别设置为SERIALIZABLE,否则第一个select可以读取其他事务尚未提交的数据(事务不像编程语言中的互斥体)。如果并发持续的SERIALIZABLE事务,某些数据库将会发生错误,您必须重新启动事务。
>一些DBMS提供SELECT .. FOR UPDATE,这将锁定通过select进行撤销的行直到事务结束。

将事务与SQL存储过程组合可以使后一部分更容易处理;应用程序只会在事务中调用单个存储过程,如果事务中止,则重新调用它。

http://stackoverflow.com/questions/1195858/how-to-deal-with-concurrent-updates-in-databases

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:sql – 如何处理数据库中的并发更新?