
1) 【一句话结论】针对夏商集团库存管理需求,采用数据库事务(ACID)结合行级悲观锁(加排他锁)与乐观锁(版本号)双机制,通过B+树索引加速库存查询,配置事务日志同步策略(如innodb_flush_log_at_trx_commit=1)保障数据实时性,并结合Redis分布式锁减少高并发锁竞争,确保订单创建时库存充足检查的原子性,库存扣减后数据实时更新,最终实现库存数据准确性。
2) 【原理/概念讲解】老师口吻解释核心概念:
数据库事务的原子性:库存扣减需“要么全部完成要么全部不执行”,类比银行转账,必须先扣款后转账,否则资金不一致。一致性:数据从有效状态转换到另一有效状态,事务保证。
锁机制:
SELECT ... FOR UPDATE),锁定资源,防止并发冲突,适合高并发、必须避免超卖的场景(如库存扣减)。product_id、version列建B+树索引,加速库存查询和版本号比较,提升性能。innodb_flush_log_at_trx_commit=1,确保事务日志立即写入磁盘,减少从库数据不一致,保障实时性。3) 【对比与适用场景】
| 方案 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 悲观锁(行级锁) | 操作前加排他锁 | 严格控制并发,保证数据一致性 | 库存扣减(高并发,必须避免超卖) | 可能导致性能瓶颈,锁粒度过大 |
| 乐观锁(版本号) | 通过版本号比较,无锁 | 并发性能高,适合读多写少 | 库存查询频繁,扣减操作较少 | 需处理冲突(版本号不一致时回滚) |
| 事务隔离级别(REPEATABLE READ) | 避免脏读、不可重复读 | 保证事务一致性 | 需要严格一致性场景 | 可能导致幻读(可通过间隙锁解决) |
| 分布式锁(Redis) | 跨服务协调锁 | 减少锁竞争,提高并发 | 高并发下事务执行 | 需考虑锁超时、死锁问题 |
4) 【示例】
stock(库存表):product_id(商品ID,PK)、quantity(库存量,INT)、version(版本号,INT,默认1)。order(订单表):order_id(订单ID,PK)、product_id(商品ID,FK)、order_quantity(订单数量,INT)、create_time(DATETIME)。-- 步骤1:获取Redis分布式锁(锁key:stock_lock:product_id)
SETNX stock_lock:product_id, 1, EX 10; -- 10秒超时
IF NOT $LOCK_SUCCESS THEN RETURN; -- 锁获取失败,重试或放弃
BEGIN TRANSACTION;
-- 步骤2:检查库存(加行级锁)
SELECT quantity FROM stock WHERE product_id = ? FOR UPDATE;
IF quantity >= order_quantity THEN
-- 步骤3:扣减库存并更新版本号
UPDATE stock SET quantity = quantity - order_quantity, version = version + 1
WHERE product_id = ? AND version = ?;
-- 步骤4:插入订单
INSERT INTO order (product_id, order_quantity) VALUES (?, ?);
END IF;
COMMIT;
-- 步骤5:释放Redis锁
DEL stock_lock:product_id;
(注:分布式锁保证事务执行期间其他服务无法修改库存,减少锁竞争)5) 【面试口播版答案】(约90秒)
“面试官您好,针对夏商集团库存管理需求,核心是保证订单创建时库存充足且扣减后数据实时更新,我设计如下方案:
首先,数据库表结构:库存表(stock)包含商品ID、当前库存量、版本号;订单表(order)包含订单ID、商品ID、订单数量。通过商品ID建立主键和B+树索引,加速库存查询。
其次,事务处理:采用数据库事务(ACID),确保库存扣减和订单插入是原子操作。比如,检查库存时,先加行级排他锁(SELECT ... FOR UPDATE),防止其他事务同时修改库存,扣减后更新版本号,保证数据一致性。
然后,锁机制:结合悲观锁(行级锁)与乐观锁(版本号),高并发下用悲观锁保证一致性,低并发或查询频繁时用乐观锁减少锁竞争。
接着,索引优化:在库存表的product_id和version列建立B+树索引,加速库存查询和版本号比较,提升系统性能。
再然后,解决复制延迟:通过设置innodb_flush_log_at_trx_commit=1,确保事务日志立即写入磁盘,减少从库数据不一致,保障库存扣减后数据实时更新。
最后,高并发锁竞争:引入Redis分布式锁,订单创建时先获取锁,再执行数据库事务,避免多事务同时修改库存,提高并发处理能力。这样,订单创建时能快速判断库存是否充足,扣减后数据实时更新,满足业务需求。”
6) 【追问清单】
REPEATABLE READ(MySQL),避免脏读,同时保证一致性,虽然可能存在幻读,但通过间隙锁(如SELECT ... FOR UPDATE加锁范围)可缓解。7) 【常见坑/雷区】
READ UNCOMMITTED),导致脏读。