
我们假设有一张表记录【放映厅】--【座位】维度的数据,还有一些其他列字段如movie_session、userId、seat_status(booked or vacant)等;
case1:假设我选择一个座位,然后进入付款页面。此时,会话将获得一个锁,以便其他会话无法读取记录或对其进行更改。这种锁定被称为“独占锁定”。对于试图从表中访问锁定记录的任何其他用户的会话,必须等待表中特定记录的锁被释放。使用‘ FOR UPDATE’和 SELECT 查询来获取排他锁。
注意:另一种类型的锁定是“共享锁”,其中一个会话可以在该行已被其他会话获取锁时读取该行。但是,在第一个会话释放锁之前,它不能进行更新。使用‘ FORSHARE’和 SELECT 查询来获取共享锁。共享锁并不适用我们的分析场景;
case2:多用户同时预订多个座位。一个用户选择A1至A4发起预定,与此同时,另一个用户选择的座位 A3至 A5发起预定。
//用户1 Transaction where user-1 books seats A1 to A4 begin; seatsAvailable() -> Select * from booking where seat_number IN (‘A1’,‘A2’, A3’, ‘A4’) FOR UPDATE // 锁定数据行范围 bookTickets() -> update booking set customer_id = ‘101’ , seat_status = ‘booked’ where seat_number IN (‘A1’,‘A2’, A3’, ‘A4’) ; // 支付 commit;
//用户2 A single transaction where user-2 tries to book seats A3 to A5 begin; seatsAvailable() -> Select * from booking where seat_number IN (‘A3’, A4’, ‘A5’) FOR UPDATESKIP LOCKED; // 如果加SKIP LOCKED只会锁定A5行,否则获取锁失败返回 bookTickets() -> update booking set customer_id = ‘102’ , seat_status = ‘booked’ where seat_number IN (‘A3’, A4’, ‘A5’) // commit;
如果用户1优先获取了,A1-A4的行锁,在用户2则无法提交预定订单(因为A3,A4已经被加了排它锁),锁定失败,需要用户2重新选择其他座位;