面试题答案
一键面试策略思路
- 使用事务保证数据一致性:在对订单表
orders
进行更新操作(新增订单、修改订单金额)时,开启事务。将对orders
表的操作和对monthly_order_summary
表的更新操作放在同一个事务中。这样可以确保要么所有操作都成功,要么都失败,从而保证数据的一致性。 - 定期汇总与实时更新结合:
- 实时更新:对于新增订单,在事务中直接更新
monthly_order_summary
表相应月份的订单数量和总金额。例如,新增一个订单时,根据订单日期确定所属月份,然后在monthly_order_summary
表中找到对应的月份记录,将订单数量加 1,订单总金额加上该订单的金额。 - 定期汇总:在业务低峰期(如凌晨),运行一个定时任务,对一定时间段内(如一个月)的订单数据进行重新汇总。这样可以处理一些可能由于并发操作导致的细微不一致问题,同时也可以优化汇总表的数据。
- 实时更新:对于新增订单,在事务中直接更新
- 使用锁机制处理高并发冲突:
- 乐观锁:在
monthly_order_summary
表中添加一个版本号字段(如version
)。在更新汇总表数据时,先读取当前版本号,更新数据时带上该版本号,并将版本号加 1。如果更新时发现数据库中的版本号与读取的版本号不一致,说明数据在读取后被其他事务修改过,此时回滚当前事务并重新尝试更新操作。 - 悲观锁:在对
orders
表进行更新操作前,对monthly_order_summary
表中相应月份的记录加排它锁(SELECT... FOR UPDATE
)。这样可以防止其他事务同时修改该汇总记录,避免数据冲突。但要注意,悲观锁可能会导致并发性能下降,应谨慎使用。
- 乐观锁:在
涉及的 MySQL 技术
- 事务:
- 开启事务:使用
START TRANSACTION
语句开启一个事务。 - 提交事务:当对
orders
表和monthly_order_summary
表的操作都完成且没有错误时,使用COMMIT
语句提交事务,将所有操作持久化到数据库。 - 回滚事务:如果在事务执行过程中出现错误,使用
ROLLBACK
语句回滚事务,撤销所有已执行的操作,确保数据一致性。 示例代码:
- 开启事务:使用
START TRANSACTION;
-- 对orders表进行新增或修改操作
INSERT INTO orders (order_id, order_date, order_amount) VALUES ('123', '2023 - 10 - 01', 100);
-- 根据订单日期确定月份,更新monthly_order_summary表
UPDATE monthly_order_summary
SET order_count = order_count + 1, total_amount = total_amount + 100, version = version + 1
WHERE month = '2023 - 10' AND version = (SELECT version FROM monthly_order_summary WHERE month = '2023 - 10');
COMMIT;
- 锁机制:
- 乐观锁示例:如上述代码中,通过
version
字段实现乐观锁。在更新汇总表数据时,通过条件WHERE month = '2023 - 10' AND version = (SELECT version FROM monthly_order_summary WHERE month = '2023 - 10')
来确保版本号一致。 - 悲观锁示例:
- 乐观锁示例:如上述代码中,通过
START TRANSACTION;
-- 对monthly_order_summary表中相应月份记录加排它锁
SELECT * FROM monthly_order_summary WHERE month = '2023 - 10' FOR UPDATE;
-- 对orders表进行新增或修改操作
INSERT INTO orders (order_id, order_date, order_amount) VALUES ('123', '2023 - 10 - 01', 100);
-- 更新monthly_order_summary表
UPDATE monthly_order_summary
SET order_count = order_count + 1, total_amount = total_amount + 100
WHERE month = '2023 - 10';
COMMIT;
通过以上策略和 MySQL 技术,可以在保证数据一致性的同时,尽量提高高并发场景下的查询性能,并避免数据冲突。