Sql 当更新基于先前选择的计数时,避免竞争条件
我担心数据库支持的应用程序中的竞争条件。我的应用程序允许用户在类中保留一个位置。如果所有的点都被选中,那么它们就会被列入等待名单。在大大简化的伪代码中,我做了如下工作:Sql 当更新基于先前选择的计数时,避免竞争条件,sql,sqlite,Sql,Sqlite,我担心数据库支持的应用程序中的竞争条件。我的应用程序允许用户在类中保留一个位置。如果所有的点都被选中,那么它们就会被列入等待名单。在大大简化的伪代码中,我做了如下工作: 1 spots = SELECT total_spots FROM classes WHERE class_id = 200; 2 regs = SELECT COUNT(*) FROM registrations WHERE class_id = 200; 3 wl = spots > regs 4 IN
1 spots = SELECT total_spots FROM classes WHERE class_id = 200;
2 regs = SELECT COUNT(*) FROM registrations WHERE class_id = 200;
3 wl = spots > regs
4 INSERT INTO registrations ( user_id, class_id, on_waitlist ) VALUES ( 500, 200, wl );
如果classes表中的total_spots发生了更改,或者另一个用户在我们读取第2行之后在registrations表上进行了插入,会发生什么情况
将整个事务包装在一个事务中是否足够?我读了一些关于MySQL中SELECT FOR UPDATE的内容。我目前正在使用SQLite,但如果需要,我可以迁移到MySQL。SQLite的事务
如果将整个内容包装到事务中,则同一数据库的其他连接无法同时进行任何更改。您也可以在插入中选择:
insert into registrations (user_id, class_id, on_waitlist)
values ( 500, 200,
(SELECT total_spots FROM classes WHERE class_id = 200) <
(SELECT COUNT(*) FROM registrations WHERE class_id = 200)
);
这将是我处理它的首选方法,但我给出的示例大大简化了。在允许注册之前,需要进行许多检查。我不确定我是否能在一个语句中获得所有更新。那么事务就是你的朋友。这难道不能保证所有更新都被执行或回滚吗。当我读取SQLite时,在事务中,您在第一次读取时会得到一个共享锁,在第一次写入时会得到一个保留锁。当您持有共享锁(即第4行中的更新之前)时,另一个进程不能写入吗?共享锁阻止其他任何人获取保留锁。