升级Spring Boot后spring_session_attributes_pk唯一键冲突如何解决?
异常触发原因
- 核心是Spring Session版本迭代后的逻辑变更:你升级Spring Boot到2.2.2后,配套的Spring Session JDBC模块调整了会话属性的写入逻辑,旧版本(对应Spring Boot 2.1.x)会先查询属性是否存在,存在走更新、不存在走插入;新版本取消了前置查询校验,直接尝试插入,当同一个会话的同一个属性被多个并发请求同时写入时,就会触发
spring_session_attributes_pk唯一键冲突。 - 额外匹配你的场景:你自定义了会话表前缀为
APP_,需先确认是否已在配置中指定spring.session.jdbc.table-name=APP_SPRING_SESSION,如果配置缺失,Spring Session会操作默认的SPRING_SESSION表,也可能出现逻辑异常。 - 数据库适配问题:Spring Session 2.2.x版本默认没有对PostgreSQL做特殊的写入逻辑适配,没有使用PostgreSQL原生的
ON CONFLICTupsert能力,插入冲突时直接抛出异常,不会自动走更新流程。
修复方案
方案1:自定义写入SQL适配PostgreSQL(最快生效)
在你的Spring Session配置类中覆盖默认的插入属性SQL,使用PostgreSQL的冲突更新语法,无需升级依赖:
@Configuration public class SpringSessionConfig extends JdbcHttpSessionConfiguration { @PostConstruct public void customizeSessionSql() { // 替换为你实际的表名,冲突时直接更新属性值 String customInsertAttrSql = "INSERT INTO APP_SPRING_SESSION_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) " + "SELECT PRIMARY_ID, ?, ? FROM APP_SPRING_SESSION WHERE SESSION_ID = ? " + "ON CONFLICT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME) DO UPDATE SET ATTRIBUTE_BYTES = EXCLUDED.ATTRIBUTE_BYTES"; setInsertAttributeSql(customInsertAttrSql); } }
配置完成后需检查确认spring.session.jdbc.table-name参数已正确设置为APP_SPRING_SESSION。
方案2:升级Spring Session版本
该问题是Spring Session 2.2.x的已知问题,官方在2.4.0及以上版本完成了修复,会自动适配PostgreSQL、MySQL等不同数据库的upsert逻辑,你可以直接将Spring Session依赖升级到2.4.0+版本即可。
方案3:全局异常拦截临时规避
如果暂时不想调整依赖和配置,可以在全局异常处理器中捕获DuplicateKeyException,针对会话属性写入的冲突异常直接忽略或做1-2次重试即可,冲突场景下属性已经被其他请求写入成功,不影响业务逻辑正常运行。
内容的提问来源于stack exchange,提问作者user3400346
相关产品推荐
相关产品推荐

