在SQL数据库中处理并发更新的常用方法是什么?
考虑一个简单的SQL模式(约束和默认值未显示..)之类的
create table credits (
int id,
int creds,
int user_id
);
Run Code Online (Sandbox Code Playgroud)
目的是为用户存储某种信用,例如stackoverflow的声誉.
如何处理该表的并发更新?一些选择:
update credits set creds= 150 where userid = 1;
在这种情况下,应用程序检索当前值,计算新值(150)并执行更新.如果其他人同时做同样的事情,那么这就是灾难.我猜测包装当前值的撤销和事务中的更新将解决这个问题,例如,Begin; select creds from credits where userid=1; do application logic to calculate new value, update credits set credits = 160 where userid = 1; end;
在这种情况下,您可以检查新信用是否<0,如果负信用没有意义,则将其截断为0.
update credits set creds = creds - 150 where userid=1;
这种情况不需要担心并发更新,因为数据库负责一致性问题,但是有一些缺陷,即信用很高兴会变成负面的,这可能对某些应用程序没有意义.
那么简单地说,处理上面提到的(非常简单的)问题的公认方法是什么,如果db抛出错误怎么办?
我摆弄了psycopg2,虽然有一个.commit()和.rollback()没有.begin()或者类似的东西来启动一个事务,或者看起来好像?我希望能做到
db.begin() # possible even set the isolation level here
curs = db.cursor()
cursor.execute('select etc... for update')
...
cursor.execute('update ... etc.')
db.commit();
Run Code Online (Sandbox Code Playgroud)
那么,交易如何与psycopg2一起使用?我如何设置/更改隔离级别?
我是对的,如果你正在做的话,你只需要一个using()用于最外层的流
MemoryStream mstr = new MemoryStream();
using(StreamWriter w = new StreamWriter(mstr)) {
....
}
Run Code Online (Sandbox Code Playgroud)
由于处理StreamWriter还应该处理/关闭底层流,没有必要这样做?:
using(MemoryStream mstr = new MemoryStream())
using(StreamWriter w = new StreamWriter(mstr)) {
....
}
Run Code Online (Sandbox Code Playgroud)
(注意这些只是示例,关于如何处理包装的流,而不是寻找像使用StringWriter等的替代方案)