并发原子选择更新

时间:2015-03-12 20:27:35

标签: python sql sqlalchemy

我如何使用sqlalchemy做这样的事情?

user = session.query("select * from user")
if user.state == "active"
    session.query("update user set state = 'inactive' where id = %d" % user.id)

我需要将select和update更新为一个原子操作。在操作进行时,另一个程序不能选择/更新用户。

我怎样才能同时做到这一点?

注意:我需要知道我们是否成功改变了状态。

我怎样才能做到这一点?

我做错了吗?

它应该是存储过程吗?

我应该使用数据库“锁定”吗?

2 个答案:

答案 0 :(得分:2)

您可以通过设置isolation level的Serializable来实现此目的,done on a specific session with SQLAlchemy可以{{3}}使用public static DataTable AsDataTable<T>(this IEnumerable<T> rows) { var dt = new DataTable(); var infos = typeof(T).GetProperties(); foreach (var info in infos) dt.Columns.Add(new DataColumn(info.Name, info.PropertyType)); foreach (var r in rows) { var nr = dt.NewRow(); for (int i = 0; i < infos.Length; ++i) { nr[i] = infos[i].GetValue(r); } dt.Rows.Add(nr); } return dt; } public static EnumerableRowCollection<DataRow> AsDataRows<T>(this IEnumerable<T> rows) => rows.AsDataTable().AsEnumerable(); 。如果两个连接冲突(它们都在另一个写入之前读取),则提交事务将失败,并且您可以循环直到它通过。

session.connection(execution_options={'isolation_level': 'SERIALIZABLE'})

答案 1 :(得分:0)

如果您的数据库支持 SELECT FOR UPDATE  (即:PostgreSQL)你可以使用:

user = session.query("select * from user where id = %d for update" % theId)
if user.state == "active"
    session.query("update user set state = 'inactive' where id = %d" % user.id)