关于GORM事务是否支持行锁/表锁及实现方式的问询
GORM事务中行锁与表锁的实现方式
GORM本身不单独实现锁机制,它依托底层数据库(比如MySQL、PostgreSQL)的原生锁能力,通过自身API或原生SQL触发锁操作,具体实现方式如下:
行锁实现
行锁一般在查询阶段触发,常用类型有排他锁(FOR UPDATE)和共享锁(FOR SHARE/LOCK IN SHARE MODE),GORM可通过Clauses方法添加锁语句:
排他锁(FOR UPDATE)
tx := db.Begin() var user User // 针对id=1的行加排他锁,其他事务无法修改或加排他锁 tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&user, "id = ?", 1) // 执行修改操作 user.Nickname = "新昵称" tx.Save(&user) tx.Commit()
共享锁(FOR SHARE)
tx := db.Begin() var user User // 针对id=1的行加共享锁,其他事务可以读但无法修改 tx.Clauses(clause.Locking{Strength: "SHARE"}).Take(&user, 1) // 执行查询类操作 fmt.Println(user.Name) tx.Commit()
表锁实现
表锁需要直接执行数据库原生锁语句,GORM通过Exec或Raw方法实现,以MySQL为例:
读表锁
tx := db.Begin() // 给users表加读锁,其他事务可以读但无法写 tx.Exec("LOCK TABLES users READ") // 执行批量查询 var users []User tx.Find(&users) // 解锁 tx.Exec("UNLOCK TABLES") tx.Commit()
写表锁
tx := db.Begin() // 给users表加写锁,其他事务无法读或写 tx.Exec("LOCK TABLES users WRITE") // 执行批量插入 tx.Create(&[]User{{Name: "用户A"}, {Name: "用户B"}}) // 解锁 tx.Exec("UNLOCK TABLES") tx.Commit()
注意:锁的生效逻辑完全依赖数据库本身特性,比如MySQL的InnoDB引擎支持行锁,而MyISAM仅支持表锁,使用前要确认数据库存储引擎的锁能力。
内容的提问来源于stack exchange,提问作者דברי
相关产品推荐
相关产品推荐

