Loading
CLOUD09_SPACE
0%
INITIALIZING
友情链接
关于我
🗒️
English
Gorm的并发安全问题
DOC_ID // 36c226ONLINE

Gorm的并发安全问题

2023-6-20
UPDATED: 2026-5-26
技术分享
927 CHARS
#开发
CLOUD09

gorm的并发安全问题

最近负责一个小项目的后端,需要用到sql数据库,本着能偷懒就绝不多写一行代码的精神,我决定用gorm帮助我偷懒。 由于代码逻辑十分简单所以entity、dao等等各层写的不亦乐乎,但是多次高并发程序的开发经历告诉我事情没有这么简单,果然gorm并没有说自己对多线程操作保证安全…
下面是gorm关于并发安全的叙述 https://gorm.io/zh_CN/docs/method_chaining.html

链式方法

新建会话方法特指 gorm.DB.Session(&gorm.Session{})
链式方法一般都是返回当前类一个实例指针的方法,比如gorm源码中这两句:
对 *DB 类型实例的调用返回了一个 *DB指针 如果我要对 Session方法的返回值调用 Create方法, 可以这么写:
但是既然这Session返回了一个*DB指针,那么可以这样调用
这样写出的代码更优雅一些,但是 这不是本文章的重点,算是前置知识吧

gorm中并发安全的关键

gorm定义了一个 *DB 类型 这个类型里面有一个很重要的成员: DB.clone
gorm中还有另一个函数,大多数的链式方法首先会执行下面这个函数
我们把这个函数的逻辑简化一下:
我们每对*DB的方法进行一次调用都有可能对它*Statement字段进行修改,比如Limit方法修改了一次Statement( tx.Statement.AddClause(args) )
Where方法也会修改
如果两次条件不同的查询都使用同一个*DB,那么就会并发地对同一个Statement进行修改,就会出现安全问题,比如
他们向同一个statement写入了不同查询条件,最终的结果几乎一定会出错。 因此问题的关键就在于, 对不同的查询要使用不同的*DB,有一个很实用的方*DB.Session(), 如果传入的*gorm.Session{}结构体指针中NewDB字段为true,那么就会返回一个clone为1的新*DB,对这个*DB 的调用就不会影响到原来的*DB
或者诸位可以自己查看各个链式方法和终结方法的源码,确定该方法对老的*DB 会进行什么操作,只要能够保证不同的sql操作条件作用在不同的*DB 上就好了
NAVIGATION // Related Articles
Loading...
© 2021-2026 Echocean