GORM不支持跨数据库统一设置隔离级别:MySQL/SQL Server可用Session().Begin()配合IsolationLevel参数,PostgreSQL必须在Begin后立即执行tx.Exec("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"),且需捕获40001错误重试。

GORM 本身不提供跨数据库统一的隔离级别设置能力,MySQL/SQL Server 可用 Session(&gorm.Session{IsolationLevel: ...}),PostgreSQL 必须走原生 SQL 执行 SET TRANSACTION ISOLATION LEVEL ...。
MySQL:用 Session 设置隔离级别有效
MySQL 支持 GORM 的 IsolationLevel 参数,且会在 BEGIN 后自动注入对应 SQL(如 SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ)。但要注意:
- 必须在事务开启后、任何查询/写入前调用,否则可能被忽略
- 仅对 MySQL 和 SQL Server 生效,PostgreSQL 完全无视该字段
- 支持的值来自标准 SQL 常量:
sql.LevelReadUncommitted、sql.LevelReadCommitted、sql.LevelRepeatableRead、sql.LevelSerializable - 示例写法:
tx := db.Session(&gorm.Session{IsolationLevel: sql.LevelRepeatableRead}).Begin()
PostgreSQL:必须手动执行 SET TRANSACTION 命令
PostgreSQL 不识别 GORM 的 IsolationLevel 字段。哪怕你传了 sql.LevelRepeatableRead,GORM 也不会生成或执行任何隔离级别设置语句——它默认使用数据库全局配置(通常是 READ COMMITTED)。
要真正生效,必须在 Begin() 之后、第一个业务操作之前,显式调用 tx.Exec():
- 顺序不能错:BEGIN → SET TRANSACTION → 业务操作 → Commit/Rollback
- 命令字符串必须完全匹配 PostgreSQL 语法,大小写不敏感但空格和关键词不能错,例如
"SET TRANSACTION ISOLATION LEVEL REPEATABLE READ" - 若执行失败(比如权限不足或语法错误),需立即
Rollback()并返回错误 - 示例片段:
tx := db.Begin()<br>if err := tx.Exec("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ").Error; err != nil {<br> tx.Rollback()<br> return err<br>}<br>// 后续 Create/Update 等操作...
隔离级别选哪个?别只看名字,要看实际行为
PostgreSQL 的 REPEATABLE READ 实际语义等价于 SQL 标准的 SERIALIZABLE,它能防止不可重复读和幻读,但代价是可能触发序列化失败(SQLSTATE 40001),需要应用层重试逻辑。
而 MySQL 的 REPEATABLE READ 默认不防止幻读(依赖间隙锁才可),行为与 PostgreSQL 不同。这意味着:
- 同一套 GORM 代码,在 MySQL 和 PostgreSQL 上设相同隔离级别,实际一致性保障并不一致
- 跨数据库迁移时,不能假设
IsolationLevel配置可复用 - 生产环境若用 PostgreSQL,务必在事务里捕获
pgerr.Code == "40001"并做有限重试,否则容易因序列化冲突直接报错中断
连接级 vs 事务级:别混淆作用域
db.Set("gorm:query_option", "...") 是连接级配置,影响所有后续查询,不是事务隔离级别设置手段。它常被误用于尝试设置隔离级别,但实际只对某些驱动的部分场景起作用(如 MySQL 的 SET SESSION),且无法控制事务边界。
真正可控、可预测的方式只有两种:
- MySQL/SQL Server:用
Session().Begin()+IsolationLevel - PostgreSQL:用
Begin()+Exec("SET TRANSACTION ...")
任何试图绕过事务生命周期、在连接池初始化时“一劳永逸”设隔离级别的做法,在高并发下都不可靠——因为连接会被复用,上一个事务的 SET 可能污染下一个。


















