
1) 【一句话结论】
设计用户配置表需明确主键(如id)、外键(user_id关联用户表)、字段类型(key/value为TEXT,加version字段做乐观锁),通过事务管理结合索引优化查询,并依据读写比例选择乐观锁(低并发)或悲观锁(高写入),同时考虑SQLite的WAL日志机制保证事务一致性。
2) 【原理/概念讲解】
表结构设计遵循“唯一标识、业务关联、类型适配”原则。主键(如自增id)确保数据唯一,外键(user_id)建立用户与配置的关联。索引通过B-树结构加速查询,复合索引(如user_id+key)能高效定位特定用户配置。事务在并发控制中至关重要,SQLite的WAL日志(Write-Ahead Logging)机制在事务提交时先写入日志,再更新数据,避免数据丢失。乐观锁假设数据未被修改,通过版本号验证一致性;悲观锁假设数据会被修改,直接加锁(如行级锁)阻止冲突。类比:表结构是数据的“骨架”,索引是查询的“导航”,事务是操作的“保险箱”,乐观锁是“版本检查门卫”,悲观锁是“资源锁”。
3) 【对比与适用场景】
| 特性 | 乐观锁(Version-based) | 悲观锁(Lock-based) |
|---|---|---|
| 定义 | 假设数据未被修改,通过版本号验证一致性 | 假设数据会被修改,直接加锁阻止写入 |
| 机制 | 更新时检查版本号是否一致,不一致则重试 | 读取时加锁,写入时释放锁 |
| 适用场景 | 低并发环境,频繁读取(如配置查询),写入较少 | 高并发写入频繁,需要强一致性(如实时数据更新) |
| 注意点 | 版本冲突率高时,重试次数增加,性能下降;需合理设计版本号更新策略(如批量更新时检查版本号范围) | 锁竞争导致性能瓶颈,需控制锁粒度(如行级锁而非表级锁),避免死锁 |
| 锁粒度 | 无锁(仅版本号验证) | 行级锁(或表级锁,需谨慎选择) |
4) 【示例】
用户配置表设计(SQLite):
CREATE TABLE config (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL, -- 外键关联用户表
key TEXT NOT NULL,
value TEXT NOT NULL,
version INTEGER DEFAULT 1, -- 乐观锁版本号
create_time INTEGER DEFAULT (strftime('%s', 'now')) -- 创建时间戳
);
-- 建立复合索引,加速查询特定用户配置
CREATE INDEX idx_user_key ON config (user_id, key);
并发写入(乐观锁流程,需在事务内执行):
查询优化:查询时使用复合索引,如:
SELECT value FROM config WHERE user_id = ? AND key = ?;
5) 【面试口播版答案】
“面试官您好,针对PC客户端用SQLite存储用户配置,设计表结构时核心是明确主键、外键及字段类型。比如用户配置表用id作为主键,user_id关联用户表,key存储配置键,value存储配置值,加上version字段做乐观锁。查询优化方面,为user_id和key建立复合索引,加速特定用户的配置查询。并发写入用乐观锁,流程是先读取数据获取版本号,更新时检查版本是否一致,不一致则重试(如指数退避),避免数据冲突。比如更新配置时,先查当前版本,更新后版本+1,若检查失败则回滚。同时考虑SQLite的WAL日志机制,事务提交时先写入日志再更新数据,保证数据一致性。如果写入频繁,也可考虑悲观锁,用行级锁控制锁粒度,但需注意避免死锁。”
6) 【追问清单】
7) 【常见坑/雷区】