当更新基于先前选择的计数时避免竞争条件

问题描述 投票:0回答:3

我担心数据库支持的应用程序中的竞争条件。我的应用程序允许用户预订课程名额。如果所有名额均已满,则将被列入候补名单。在大大简化的伪代码中,我正在做类似的事情:

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 ); 

如果

total_spots
表中的
classes
发生更改,或者另一个用户在我们读取
registrations
表(第 2 行)后对其进行 INSERT,会发生什么情况。

将整个事情包装在一个交易中是否足够?我读过一些关于 MySQL 中的

SELECT FOR UPDATE
的内容。我目前正在使用 SQLite,但如果需要,我可以迁移到 MySQL。

sql sqlite
3个回答
1
投票

SQLite 的事务是完全原子的

如果将整个事务包装在事务中,则同一数据库的其他连接无法同时进行任何更改。


1
投票

您还可以在插入内容中选择:

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)
 );

0
投票

根据我在 SQLite 中的实验,竞争条件不会发生,因此不会发生 丢失更新写入倾斜,因为隔离级别是

SERIALIZABLE
(默认),即使隔离级别是
READ UNCOMMITTED
很奇怪。 *我的回答解释了更多。

© www.soinside.com 2019 - 2024. All rights reserved.