【mysql】只使用数据库DB如何实现--预定系统(古法)电影院座位预定
生活随笔
收集整理的這篇文章主要介紹了
【mysql】只使用数据库DB如何实现--预定系统(古法)电影院座位预定
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?1. 預定業務流程(以電影院座位預定)
?
2. 用悲觀鎖實現
我們假設有一張表記錄【放映廳】--【座位】維度的數據,還有一些其他列字段如movie_session、userId、seat_status(booked or vacant)等;
case1:假設我選擇一個座位,然后進入付款頁面。此時,會話將獲得一個鎖,以便其他會話無法讀取記錄或對其進行更改。這種鎖定被稱為“獨占鎖定”。對于試圖從表中訪問鎖定記錄的任何其他用戶的會話,必須等待表中特定記錄的鎖被釋放。使用‘ FOR UPDATE’和 SELECT 查詢來獲取排他鎖。
- //A single transaction to book a tickets
begin; // 事務開始
seatsAvailable() -> Select * from booking where seat_number = ‘A1’ FOR UPDATE // 加排它鎖&當前讀
bookTickets() -> update booking set customer_id = ‘101’ , seat_status = ‘booked’ where seat_number = ‘A1’; // 支付后更改 A1 row 數據狀態
commit; // 提交事務
注意:另一種類型的鎖定是“共享鎖”,其中一個會話可以在該行已被其他會話獲取鎖時讀取該行。但是,在第一個會話釋放鎖之前,它不能進行更新。使用‘ FORSHARE’和 SELECT 查詢來獲取共享鎖。共享鎖并不適用我們的分析場景;
case2:多用戶同時預訂多個座位。一個用戶選擇A1至A4發起預定,與此同時,另一個用戶選擇的座位 A3至 A5發起預定。
- //用戶1 Transaction where user-1 books seats A1 to A4begin;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 A5begin;seatsAvailable() -> Select * from booking where seat_number IN (‘A3’, A4’, ‘A5’) FOR UPDATE SKIP 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重新選擇其他座位;
3.?小結
- 以上只是為了說明數據庫來做的話如何實現的;
- 現實場景中加鎖用的最多的還是分布式鎖,如redis實現鎖,來支持業務的高性能和擴展性。
- 當然也可以使用數據樂觀鎖,如版本號機制來完成加鎖的能力
總結
以上是生活随笔為你收集整理的【mysql】只使用数据库DB如何实现--预定系统(古法)电影院座位预定的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库语句
- 下一篇: 激光雷达目标检测 (上)