尝试了解数据库事务是如何在 Spring 和数据库中实现的。我一直在编写大量查询并使用 @Transactional
,但从未真正尝试考虑数据库级别上发生的情况。
假设我们有这段代码:
@Service
public class ReservationService {
private static final int SEAT_LIMIT = 50;
private SeatsRepository seatsRepository;
@Transactional
public String reservate(User user){
int currentSeatsReservations = seatsRepository.getCurrentSeatsReservations();
if (SEAT_LIMIT - currentSeatsReservations >= 1){
//make new seat reservation
seatsRepository.addNewSeatReservation(System.currentTimeMillis(), user.getId());
return "Congrats! You just made your reservation";
}
return "All seats are already booked";
}
@Repository
interface SeatsRepository{
@Query(value = "SELECT COUNT(id) as CURRENT_TOTAL_SEATS_TAKEN FROM seats;", nativeQuery = true)
int getCurrentSeatsReservations();
@Query(value = "INSERT INTO seats(timestamp, user_id) VALUES (:timestamp, :userId);", nativeQuery = true)
void addNewSeatReservation(long timestamp, int userId);
}
}
我确实知道 MySQL 默认隔离是 REPEATABLE_READ。但是,如果出现如图所示的以下情况,这将如何发挥作用?
让我们想象一下,我们有一个简单且单一的航类来填补座位。假设有50个座位。预订遵循先到先得的原则。通过在简单的 seats
表中插入新行来进行预订。
可以在图像上看到表格。
这种情况可能吗?我知道在数据库级别上一切都发生得很快,但假设左侧事务 (T1) 由于某种原因比右侧事务 (T2) 慢。由于我们处于 REPEATABLE_READ 隔离级别,因此不会发生 DIRTY_READ、NON_REPEATABLE_READS 和 PHATOM_READS(作为并发问题)。
附注如果有关于该主题的好书或 Udemy 类(class)的推荐,我们将不胜感激。不过我是个初学者。
最佳答案
START TRANSACTION;
SELECT ... FOR UPDATE;
...
UPDATE ...;
COMMIT;
请注意用于更新
。它增加了额外的锁定,以防止出现您所描述的问题。
(我认为 transaction_isolation_mode 对于您的示例并不重要。)
关于mysql - 了解 Spring 中的事务和数据库级别的事务吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73198996/