面试题答案
一键面试可能出现的挑战
- 并发写入冲突:多个事务同时尝试插入或更新数据,可能导致外键约束冲突。例如,一个事务尝试插入一条引用不存在主键记录的外键数据,而另一个事务正在删除该主键记录,这就会引发冲突。
- 性能问题:外键约束检查会增加写操作的开销。每次插入、更新或删除操作都需要额外查询相关表来验证外键关系,在高并发写场景下,这可能会严重影响性能。
- 级联操作复杂性:当使用级联更新或删除时,可能会导致意外的数据变化。比如,一个表的主键更新,触发关联表的外键级联更新,如果处理不当,可能影响到其他依赖关系,导致数据不一致。
应对措施
- 事务管理:
- 使用
BEGIN TRANSACTION
、COMMIT
和ROLLBACK
来控制事务。在进行可能涉及外键约束的操作时,将相关操作封装在一个事务内,确保数据一致性。例如:
- 使用
BEGIN TRANSACTION;
INSERT INTO child_table (child_id, foreign_key_id) VALUES (1, 10);
UPDATE parent_table SET primary_key = 10 WHERE primary_key = 5;
COMMIT;
- 采用适当的事务隔离级别,SQLite 默认使用 `PRAGMA isolation_level = 'DEFERRED';`,可根据需求调整为 `IMMEDIATE` 或 `EXCLUSIVE`。`IMMEDIATE` 会在事务开始时就获取排它锁,减少并发冲突;`EXCLUSIVE` 则更为严格,在事务期间禁止其他事务读写。
2. 优化性能: - 合理创建索引,对外键列创建索引可以加快外键约束检查的速度。例如:
CREATE INDEX idx_foreign_key ON child_table (foreign_key_id);
- 批量操作代替单个操作,减少外键检查的次数。例如,一次插入多条记录而不是多次单个插入。
3. 级联操作控制: - 在创建表时谨慎定义级联操作。例如:
CREATE TABLE parent_table (
primary_key INTEGER PRIMARY KEY,
...
);
CREATE TABLE child_table (
child_id INTEGER PRIMARY KEY,
foreign_key_id INTEGER,
FOREIGN KEY (foreign_key_id) REFERENCES parent_table(primary_key) ON UPDATE CASCADE ON DELETE CASCADE
);
- 预先检查级联操作可能带来的影响,通过视图或临时表模拟级联操作结果,确认无误后再执行。