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