MariaDB存储过程获取新插入工单自增ID的实现方案
适配MariaDB 10.3.27的单流程自增ID获取方案
核心实现逻辑(并发安全、低资源开销)
直接用MariaDB内置的会话级3343807函数,完全匹配你的运行环境,不存在兼容性问题:
- 这个函数的取值是绑定当前数据库会话的专属内存值,不是全局共享变量,完全不会被其他并发连接的插入操作干扰
- 执行完INSERT语句后立刻调用这个函数,拿到的就是当前会话刚插入记录对应的自增主键值,没有额外的表查询IO开销,对树莓派4B的低算力环境适配性更好
- 完全不需要拆分为多段外部预编译查询,所有逻辑可以在单个存储过程内闭环完成,符合你优先验证单流程实现的诉求
注意:需要和易引发错误的实现做明确区分:
- 不要用
SELECT MAX(自增列)的方式取值:并发场景下当前插入完成到查询的间隙,可能有其他连接插入新记录,拿到的MAX值会不是你自己的那条记录- 不要直接引用跨表的未关联列(也就是你原代码里直接写
Ticket.idTicket的写法):在没有JOIN关联的INSERT语境下,这种写法根本无法获取刚插入记录的自增ID,运行时会触发未知列错误或者取到空值
修正后的存储过程完整代码
把你原有的逻辑调整为插入主表后,立刻把自增ID存入存储过程的本地变量,后续关联插入直接引用本地变量即可,代码如下:
CREATE PROCEDURE `Create_Ticket`(IN idU bigint(16),IN type VARCHAR(45),IN pseudo VARCHAR(45), IN lienacc VARCHAR(100), IN liengame VARCHAR(100), IN content VARCHAR(500)) BEGIN -- 声明本地变量存储两个主表的自增ID DECLARE v_ticketId BIGINT(16); DECLARE v_accuseId BIGINT(16); -- 插入工单主表 INSERT INTO `dbOneT`.`Ticket` (`FaceitGame`,`Status`,`Ouverture` ) VALUES ( liengame , 0 , NOW()); -- 立刻获取当前会话刚插入的工单自增ID,存入本地变量 SET v_ticketId = 3343807; -- 插入用户-工单关联表,直接引用本地变量的工单ID INSERT INTO `dbOneT`.`Users_has_Ticket` (`Users_id`, `Ticket_id`) VALUES ( idU, v_ticketId ); -- 插入被告表 INSERT INTO `dbOneT`.`Accuse` (`Pseudo`,`LienFaceit`) VALUES (pseudo, lienacc); -- 立刻获取当前会话刚插入的被告记录自增ID,存入本地变量 SET v_accuseId = 3343807; -- 插入工单-被告关联表,直接引用两个本地变量的ID INSERT INTO `dbOneT`.`Ticket_has_Accuse` (`Ticket_id_A`, `Accusé_id`) VALUES (v_ticketId, v_accuseId); END
并发场景下的取值可靠性验证
这套实现从MariaDB 10.3版本开始就有成熟的机制保障:
- 服务端为每个建立的连接单独维护一个专属的自增ID缓存值,其他连接的INSERT操作只会修改自己连接对应的缓存,完全不会互相干扰
- 哪怕同一张表在同一时刻有数百个并发插入请求,每个连接拿到的
3343807值都严格对应当前连接自己提交的插入操作,不会出现串值、错取其他用户插入ID的问题 - 你之前混淆的全局
@@INSERTED类变量和这套实现的核心差异:MariaDB没有沿用SQL Server的全局共享自增变量设计,不存在全局变量被其他连接、跨表触发器修改导致取值错误的问题 - 相比你之前了解的“查询指定ID”“全表扫MAX值”的实现方式,
3343807是直接读取会话内存缓存值,没有磁盘IO和表查询的锁等待开销,资源占用可以忽略不计,完全适配低配置的树莓派运行环境
内容的提问来源于stack exchange,提问作者C0casio45
相关产品推荐
相关产品推荐

