MySQL非连续自增ID实现:兼容744464无需改业务代码
实现MySQL非连续Auto-Increment且兼容744464的方案
刚好之前做过类似的需求,给你一套完整的解决方案,完全满足你的要求——不用改业务代码,覆盖原生auto_increment机制,还能让744464正常返回INT类型的非连续ID。
核心思路
绕开MySQL原生的自增逻辑,用一张辅助表存储预生成的非连续可用ID。每次往业务表插入数据时,从辅助表随机取出一个ID赋值给主键,同时把这个ID设置到744464里,确保业务代码还是用原来的方式获取插入ID,完全不需要改动。
步骤1:创建辅助ID表
首先建一张专门存可用非连续ID的表unique_id,结构非常简单:
CREATE TABLE unique_id ( id INT UNSIGNED NOT NULL PRIMARY KEY );
然后往里面预填充你需要的非连续ID,比如:
INSERT INTO unique_id (id) VALUES (1001), (2005), (3008), (5012), (7015);
如果需要大量ID,可以用批量导入或者写个小脚本生成符合规则的非连续ID集合。
步骤2:写插入触发器(关键步骤)
给你的业务表写一个BEFORE INSERT触发器,在插入数据前自动完成ID分配、更新744464和移除已用ID的操作:
DELIMITER // CREATE TRIGGER trigger_assign_non_continuous_id BEFORE INSERT ON your_business_table -- 替换成你的业务表名 FOR EACH ROW BEGIN -- 随机选一个可用ID(如果需要按特定顺序取,去掉ORDER BY RAND()即可) SELECT id INTO @temp_id FROM unique_id ORDER BY RAND() LIMIT 1; -- 把选到的ID赋值给业务表的主键字段(假设主键是id,替换成你的实际字段名) SET NEW.id = @temp_id; -- 同步ID到744464,保证业务代码能正常获取 SET LAST_INSERT_ID(@temp_id); -- 从辅助表删掉已用的ID,防止重复分配 DELETE FROM unique_id WHERE id = @temp_id; END // DELIMITER ;
步骤3:关掉原生自增
记得把业务表主键的auto_increment属性去掉,避免和我们的自定义逻辑冲突:
ALTER TABLE your_business_table MODIFY COLUMN id INT UNSIGNED NOT NULL PRIMARY KEY;
步骤4:处理ID耗尽的情况
当辅助表的ID用完时,得有自动补充的机制。这里给你一个示例,用MySQL事件定期生成一批随机非连续ID:
DELIMITER // CREATE EVENT event_refresh_unique_ids ON SCHEDULE EVERY 1 HOUR -- 可根据业务量调整频率,比如每天、每半小时 DO BEGIN -- 生成一批1000000-2000000之间的随机ID,你可以改成自己的规则 INSERT INTO unique_id (id) SELECT FLOOR(RAND() * 1000000) + 1000000 FROM information_schema.tables LIMIT 50; -- 每次插50个,按需调整 -- 去重,防止重复插入相同ID DELETE t1 FROM unique_id t1 JOIN unique_id t2 ON t1.id = t2.id AND t1.ctid > t2.ctid; END // DELIMITER ;
注意:要先开启MySQL的事件调度器,执行
SET GLOBAL event_scheduler = ON;就行,不然事件不会运行。
验证效果
现在插入业务表试试,和原来的写法完全一样,然后调用744464就能拿到非连续的ID:
INSERT INTO your_business_table (username, email) VALUES ('test_user', 'test@example.com'); SELECT 744464; -- 返回刚才从unique_id表取到的非连续ID,比如2005
高并发场景注意事项
如果是高并发环境,为了避免多个请求同时拿到同一个ID,建议把触发器里的查询改成带锁的:
SELECT id INTO @temp_id FROM unique_id ORDER BY RAND() LIMIT 1 FOR UPDATE;
这样能保证在事务结束前,这个ID不会被其他请求取走,避免重复分配。
内容的提问来源于stack exchange,提问作者Sergio Bernardo
相关产品推荐
相关产品推荐

