diff --git a/Golang/go-sqlx.md b/Golang/go-sqlx.md index ce0bedb..88effe7 100644 --- a/Golang/go-sqlx.md +++ b/Golang/go-sqlx.md @@ -239,4 +239,31 @@ Exec操作和Query操作在归还连接到连接池的时机有所不同: - `Exec`: `Exec`方法在`server返回执行结果给client之后`,`client根据返回结果构建并返回sql.Result之前`,将会将连接返回给连接池 - `Query`: `Query`方法和`Exec`方法不同,其返回信息中包含结果集,必须等待结果集`迭代完成`或`手动调用rows.Close`方法之后,才会归还连接给连接池 +## Transactions +为了使用事务,必须通过`DB.Begin()`方法创建事务,如下代码将`不会起作用`: +```go +// this will not work if connection pool > 1 +db.MustExec("BEGIN;") +db.MustExec(...) +db.MustExec("COMMIT;") +``` +> 在通过`Exec`执行语句时,每次都是从数据库获取连接,并在执行完后将连接返还到连接池中。 +> +> `连接池并不保证第二次Exec执行时获取的连接和第一次Exec时获取的来连接相同`。可能`db.MustExec("BEGIN;")`在获取连接->执行->将连接返还连接池后,第二次调用`db.MustExec(...)`时,从数据库获取的连接并不是`Must("BEGIN;")`执行时所在的连接。 + +可以按照如下示例来使用事务: +```go +tx, err := db.Begin() +err = tx.Exec(...) +err = tx.Commit() +``` +类似的,sqlx同样提供了`Beginx()`方法和`MustBegin`方法,其会返回`sqlx.Tx`而不是`sql.Tx`,示例如下: +```go +tx := db.MustBegin() +tx.MustExec(...) +err = tx.Commit() +``` +由于事务是连接状态,Tx对象必须绑定并控制连接池中的一个连接。Tx对象将会在生命周期内维持该connection,仅当commit或rollback被调用时才将连接释放。 + +在对Tx对象进行使用时,应当确保调用`commit`或`rollback`中的一个方法,否则连接将会被持有,直至发生垃圾回收。