插件窝 干货文章 自动抽题时,如何解决删除记录后主键 ID 与题目数量不一致的问题?

自动抽题时,如何解决删除记录后主键 ID 与题目数量不一致的问题?

删除 方案 连续性 questions 505    来源:    2025-03-30

解决删除记录后主键ID与题目数量不一致的问题

问题分析

在自动抽题系统中,当删除记录后,数据库主键ID(通常是自增ID)会保持递增,而题目数量减少,导致ID不连续。这可能导致以下问题: 1. 随机抽题时可能选择到已删除的ID 2. 统计题目数量时可能产生误导 3. 前端显示ID不连续影响用户体验

解决方案

方案1:使用逻辑删除而非物理删除

  • 实现方式:添加is_deleted字段标记删除状态
  • 优点
    • 保持ID连续性
    • 可恢复删除的数据
  • 缺点
    • 数据库会积累"已删除"数据
    • 查询时需要额外过滤条件
-- 示例表结构
CREATE TABLE questions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    content TEXT,
    is_deleted TINYINT DEFAULT 0,
    deleted_at TIMESTAMP NULL
);

方案2:重新组织ID序列

  • 实现方式:删除记录后执行ID重组
  • 优点
    • 保持ID连续且与实际记录一致
  • 缺点
    • 操作复杂,影响性能
    • 可能影响外键关系
-- MySQL示例
SET @count = 0;
UPDATE questions SET id = @count:= @count + 1 ORDER BY id;
ALTER TABLE questions AUTO_INCREMENT = 1;

方案3:使用UUID或其他非自增主键

  • 实现方式:使用UUID或哈希值作为主键
  • 优点
    • 完全避免ID连续性问题
    • 分布式系统友好
  • 缺点
    • 占用更多存储空间
    • 索引效率略低
CREATE TABLE questions (
    id CHAR(36) PRIMARY KEY,
    content TEXT
);

方案4:抽题时不依赖ID连续性

  • 实现方式
    1. 先获取有效题目ID列表
    2. 从有效ID中随机选择
  • 优点
    • 不改变现有数据库结构
    • 实现简单
  • 缺点
    • 需要额外查询
# Python示例
def get_random_questions(n):
    valid_ids = [q.id for q in Question.objects.filter(is_deleted=False)]
    selected_ids = random.sample(valid_ids, min(n, len(valid_ids)))
    return Question.objects.filter(id__in=selected_ids)

推荐方案

根据实际场景选择: - 小型系统:方案1(逻辑删除)或方案4 - 需要严格ID连续性的系统:方案2 - 大型分布式系统:方案3

大多数情况下,方案1(逻辑删除)+方案4(基于有效ID抽题)的组合是最佳实践,既能保持数据完整性,又不会过度影响性能。