在上部分文章中我们对GORM进行了介绍并且实现了对MySQL的增删改查操作,下面我们将介绍GORM的事务、Hook以及生态扩展。
1 事务
1.1 概念
事务(Transaction)是数据库管理系统(DBMS)中的一个重要概念,用于管理对数据库的一系列操作,以确保数据的一致性和完整性。事务将一组数据库操作(如插入、更新、删除等)组合成一个单元,要么全部执行成功,要么全部回滚(撤销),以确保数据在多个操作之间保持一致状态。
事务通常具备以下四个特性,通常称为 ACID 特性:
- 原子性(Atomicity) :
原子性指的是事务中的所有操作要么全部成功执行,要么全部失败回滚,没有中间状态。如果事务在执行过程中出现故障,所有已执行的操作都将回滚,以保持数据库的一致性。 - 一致性(Consistency) :
一致性确保事务执行前后数据库的状态是一致的。事务将数据库从一个一致状态转移到另一个一致状态,而不会破坏数据的完整性和规则。 - 隔离性(Isolation) :
隔离性指的是多个并发事务之间是相互隔离的,每个事务执行时,看起来好像是独占地使用数据库。隔离性防止事务之间的相互干扰,避免了并发执行时可能出现的问题。 - 持久性(Durability) :
持久性确保一旦事务成功提交,其结果将持久地保存在数据库中,即使系统崩溃也不会丢失。持久性通常通过将事务的操作日志记录到持久性存储中来实现。
1.2 Begin、Commit、Rollback法
使用db.Begin()开启事务,即tx:=db.Begin(),之后的操作都是使用tx操作而不是使用db,在关键步骤记得要判断异常检测添加回滚(tx.Rollback()),所有操作添加完后记得提交事务(tx.Commit())。如下所示:
1.3 Tansaction法
为防止忘写Rollback和Commit导致链接泄露,GO提供了Tansaction方法避免忘写Rollback和Commit导致链接泄露,即err:=db.Tansaction(function),function的参数及返回值类型为func(*gorm.DB)error。Tansaction方法如下所示:
另外,我们可以看到,在Tansaction方法我们也可以使用前面所使用的Begin、Commit、Rollback法。
2 Hook
2.1 概念
在 GORM中,Hooks 是一种机制,允许开发者在模型的不同生命周期事件发生时插入自定义的逻辑。Hook 可以让开发者在数据库操作(如创建、更新、删除)之前或之后执行特定的代码,以便实现额外的功能或处理特定的需求,约等于MySQL中的触发器。另外注意以下几点:
- GORM在提供了CURD的Hook 能力。
- Hook是在创建、查询、更新、删除等操作之前、之后自动调用的函数。
- 如果任何Hook返回错误,GORM将停止后续的操作并回滚事务。
- 使用Hook会降低性能
2.2 示例
package models
import (
"gorm.io/gorm"
)
type User struct {
gorm.Model
Username string
Email string
}
func (user *User) BeforeCreate(tx *gorm.DB) (err error) {
// 在创建之前对数据进行处理
return nil
}
func (user *User) AfterCreate(tx *gorm.DB) (err error) {
// 在创建之后执行操作
return nil
}
2.3 常见的 Hook和它们对应的生命周期事件
- BeforeCreate: 在创建新记录之前触发。可以在这个钩子中执行一些初始化操作,设置默认值等。
- AfterCreate: 在创建新记录之后触发。适用于创建之后需要执行的操作。
- BeforeUpdate: 在更新记录之前触发。可用于在更新之前进行验证、记录修改等操作。
- AfterUpdate: 在更新记录之后触发。适用于更新之后需要执行的操作。
- BeforeDelete: 在删除记录之前触发。可用于执行删除前的验证或记录相关信息。
- AfterDelete: 在删除记录之后触发。适用于删除之后需要执行的操作。
- BeforeFind: 在查询之前触发。可以用于添加查询条件或对查询进行修改。
- AfterFind: 在查询之后触发。适用于在查询结果返回后执行的操作。
2.3 性能提高
对于写操作(创建、更新、删除),为了确保数据的完整性,GORM会将它们封装在事务内运行但这会降低性能,我们可以使用SkipDefaultTransaction关闭默认事务。使用PrepareStmt缓存预编译语句可以提高后续调用的速度。如下所示:
3 GORM的生态拓展
- GORM 代码生成工具:
这是一个用于生成 GORM 模型代码的工具,可以根据数据库表结构自动生成相应的 Go 语言模型代码,减少手动编写模型的工作量。
-
- GitHub 链接:gen
- GORM 分片库方案:
GORM 分片库方案允许将数据库表数据分布在多个物理数据库上,从而实现更高的扩展性和负载均衡。
-
- GitHub 链接:sharding
- GORM 手动索引:
GORM 手动索引拓展允许您在模型上手动指定数据库索引,从而控制索引的创建和使用,以满足特定的查询性能需求。
-
- GitHub 链接:hints
- GORM 乐观锁:
GORM 乐观锁拓展为 GORM 模型添加了乐观锁的支持,以防止并发更新时的数据冲突问题。它使用版本号或时间戳来实现乐观锁。
-
- GitHub 链接:optimisticlock
- GORM 读写分离:
GORM 读写分离拓展允许您在应用程序中实现数据库的读写分离策略,将读操作分发到从数据库,而将写操作发送到主数据库。
-
- GitHub 链接:dbresolver
- GORM OpenTelemetry 扩展:
GORM OpenTelemetry 扩展可以与 OpenTelemetry 集成,用于监控 GORM 数据库操作并收集性能指标和跟踪数据。
-
- GitHub 链接:opentelemetry