工作小总结&小工具类

mysql表中有个版本号字段,需要增加,是插入前每次查询最大版本号+1后插入,还有没有其他更好方案?

疑问:我的表结构如下:CREATETABLE`ai_answer_version`( `id`varchar(64)NOTNULLCOMMENT'id', `base_record_id`varchar(64)NOTNULLCOMMENT'关联原问题的基础记录ID(首次回答的record_id)', `version_record_id

疑问:我的表结构如下: CREATE TABLE `ai_answer_version` (  `id` varchar(64) NOT NULL COMMENT 'id',  `base_record_id` varchar(64) NOT NULL COMMENT '关联原问题的基础记录ID(首次回答的record_id)',  `version_record_id` varchar(64) NOT NULL COMMENT '当前版本的record_id',  `version_num` tinyint(4) NOT NULL COMMENT '版本号',  `del_flag` tinyint(4) DEFAULT NULL COMMENT '删除标志(0:未删除,1:已删除)',  `create_time` datetime DEFAULT NULL COMMENT '生成时间',  `update_time` datetime DEFAULT NULL COMMENT '更新时间',  PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='回答版本关联表'; 现在我遇到的问题: 当base_record_id已经存在了version_num=version_num+1. 我现在做法是:每次插入前,先查询到最大的version_num,然后+1.之后set对象后,在insert 有没有更好的方案?每次都查询一下,会存在性能问题吧?


答案:

我理解你现在的需求是:针对同一个base_record_id,在插入新记录时自动生成递增的version_num,但你担心“先查询最大版本号再插入”的方式会有性能和并发问题,想找更优的解决方案。

现有方案的问题

你当前的做法(查询→计算→插入)存在两个主要问题:

  1. 性能开销:每次插入需要两次数据库交互(查询+插入),增加了网络往返和IO开销。

  2. 并发安全问题:高并发下可能出现“幻读”,导致多个请求获取到相同的最大version_num,最终插入重复的版本号。


更优的解决方案

方案1:使用INSERT ... SELECT合并操作(推荐)

将“查询最大版本号”和“插入新记录”合并为一条SQL语句,减少数据库交互次数,同时利用数据库的原子性保证并发安全。

示例SQL:

INSERT INTO ai_answer_version (
    id, 
    base_record_id, 
    version_record_id, 
    version_num, 
    del_flag, 
    create_time, 
    update_time
)
SELECT 
    '新生成的ID',  -- 替换为实际ID(如UUID)
    '目标base_record_id',  -- 替换为实际的base_record_id
    '当前版本的record_id',  -- 替换为实际的version_record_id
    IFNULL(MAX(version_num), 0) + 1,  -- 若没有记录则从1开始
    0,
    NOW(),
    NOW()
FROM ai_answer_version 
WHERE base_record_id = '目标base_record_id'  -- 限定当前base_record_id
  AND del_flag = 0;  -- 排除已删除记录

优化点:

  • 原子性:查询和插入在一条SQL中完成,数据库会保证操作的原子性,避免并发下的版本号重复。

  • 减少交互:从两次数据库往返减少为一次,提升性能。

  • 索引优化:为base_record_id + del_flag建立联合索引(INDEX idx_base_del (base_record_id, del_flag)),可以让MAX(version_num)的查询效率大幅提升。

方案2:使用数据库触发器

将版本号生成逻辑放在数据库端,通过触发器自动计算version_num,对应用层透明。

创建触发器:

-- 先为base_record_id+del_flag建立索引(必须,

原创不易,完成人机校验,阅读全文

相关推荐