首页 > 数据库 >Go 的 MySQL 预处理、MySQL 事务

Go 的 MySQL 预处理、MySQL 事务

时间:2022-11-25 12:08:19浏览次数:51  
标签:return err tx fmt SQL db MySQL Go 预处理

Go 的 MySQL 预处理、MySQL 事务_mysql

预处理是什么

Go 的 MySQL 预处理、MySQL 事务_mysql_02


在普通 SQL 语句执行过程中,客户端会对 SQL 语句进行占位符替换,从而得到要执行的完整 SQL 语句,客户端再将此 SQL 语句发送到服务端执行,服务端最后把结果返回给客户端。

而预处理,则是将 SQL 语句分为命令部分以及数据部分,客户端先把命令部分发送给服务器,服务器先进行预处理,而后客户端才把数据部分发送给服务器,由服务器对 SQL 语句进行占位符替换并执行,最后将结果返回给客户端。

预处理可以提高服务器的性能,提前让服务器编译,一次编译多次执行,甚至可以避免 SQL 注入问题。


Go 的 MySQL 预处理、MySQL 事务_mysql

Go 实现 MySQL 预处理

Go 的 MySQL 预处理、MySQL 事务_mysql_02


在上一期​​《Go 操作 MySQL 数据库》​​​中,很多例子都使用了预处理。Go 中的 ​​Prepare()​​ 方法会将 SQL 语句发送给服务器,返回一个准备好的状态用于之后的查询和命令,返回值可以同时执行多个查询和命令:

func (db *DB) Prepare(query string) (*Stmt, error) {
return db.PrepareContext(context.Background(), query)
}

下面是一个查询操作预处理的例子:

package main

import (
"database/sql"
"fmt"

_ "github.com/go-sql-driver/mysql"
)

type User struct {
id int
phone string
nickName string
age int
}

func main() {
// 连接数据库
db, _ := sql.Open("mysql", "root:root@(127.0.0.1:3306)/godb_test?charset=utf8mb4")

// Ping() 验证与数据库的连接是否仍处于活动状态,并在必要时建立连接
err := db.Ping()

if err != nil {
fmt.Println("Database connection failed")
return
}

// 延迟调用关闭数据库 阻止新的查询
defer db.Close()

// 准备 SQL 语句
sqlStr := "select id, nick_name, phone, age from acl_user where id > ? and is_deleted = 0"

stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Println("Prepare failed")
return
}

defer stmt.Close()
rows, err := stmt.Query("100")

if err != nil {
fmt.Println("Query failed")
return
}

defer rows.Close()

// 读取结果集中的数据
for rows.Next() {
var user User
err := rows.Scan(&user.id, &user.nickName, &user.phone, &user.age)
if err != nil {
fmt.Println("Scan failed")
return
}
fmt.Println(user)
}

}

Go 的 MySQL 预处理、MySQL 事务_mysql

Go 实现 MySQL 事务

Go 的 MySQL 预处理、MySQL 事务_mysql_02


Go 语言中使用下面的方法实现 MySQL 事务操作:

// 开启事务方法
func (db *DB) Begin() (*Tx, error) {
return db.BeginTx(context.Background(), nil)
}

// 回滚事务方法
func (tx *Tx) Rollback() error {
return tx.rollback(false)
}

// 提交事务方法
func (tx *Tx) Commit() error {
select {
default:
case <-tx.ctx.Done():
if atomic.LoadInt32(&tx.done) == 1 {
return ErrTxDone
}
return tx.ctx.Err()
}
if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) {
return ErrTxDone
}

tx.cancel()
tx.closemu.Lock()
tx.closemu.Unlock()

var err error
withLock(tx.dc, func() {
err = tx.txi.Commit()
})
if err != driver.ErrBadConn {
tx.closePrepared()
}
tx.close(err)
return err
}

下面是一个事务操作的例子,该事务操作确保两次更新操作要么同时成功要么同时失败:

package main

import (
"database/sql"
"fmt"

_ "github.com/go-sql-driver/mysql"
)

func main() {
// 连接数据库
db, _ := sql.Open("mysql", "root:root@(127.0.0.1:3306)/godb_test?charset=utf8mb4")

// Ping() 验证与数据库的连接是否仍处于活动状态,并在必要时建立连接
err := db.Ping()

if err != nil {
fmt.Println("Database connection failed")
return
}

// 延迟调用关闭数据库 阻止新的查询
defer db.Close()

// 开启事务
t, err := db.Begin()
if err != nil {
if t != nil {
// 回滚
t.Rollback()
}
fmt.Println("Begin transaction failed")
return
}

// 准备 SQL 语句
sqlStr := "update acl_user set nick_name = ?, age = ? where id = ? and is_deleted = 0"
// 执行 SQL 语句
_, err = t.Exec(sqlStr, "AAA", 60, 102)

if err != nil {
// 回滚
t.Rollback()
fmt.Println("Exec failed")
return
}

// 准备 SQL 语句
sqlStr2 := "update acl_user set nick_name = ?, age = ? where id = ? and is_deleted = 0"
// 执行 SQL 语句
_, err = t.Exec(sqlStr2, "BBB", 50, 103)

if err != nil {
// 回滚
t.Rollback()
fmt.Println("Exec failed")
return
}

// 提交事务
err = t.Commit()

if err != nil {
// 回滚
t.Rollback()
fmt.Println("Commit failed")
return
}

fmt.Println("Exec transaction Success")

}




标签:return,err,tx,fmt,SQL,db,MySQL,Go,预处理
From: https://blog.51cto.com/u_15891283/5886189

相关文章

  • 【MySQL数据库开发之三】MySQL 获得数据库和表的信息、日期计算、对表的删除修改等操
    本站文章均为​​ 李华明Himi ​​​原创,转载务必在明显处注明通过上一篇的介绍,大家可以创建自己的数据库和表以及插入表中数据等等,本章继续介绍更多的数据库的相关操作;......
  • go实现投票并实时打印投票信息
    packagemainimport"fmt"varstudents[]Studentvarflagbool=truetypeStudentstruct{noint//候选人编号namestring//候选热姓名countint//得票数}fun......
  • 【MySQL数据库开发之二】MySQL 基础语句的书写与一些数据库操作(创建使用数据库、表)!
    本站文章均为​​ 李华明Himi ​​​原创,转载务必在明显处注明本篇Himi简单介绍一些MySQL数据库的基础操作;注:mysql语句对大小写不敏感,语句以分号“;”标识语句结束;1. ......
  • 使用Xenon实现MySQL高可用集群
    使用Xenon实现MySQL高可用集群1、Xenon介绍 https://github.com/radondb/xenon#VIP就是对外提供服务的IP,比如jdbc配置就是写这个VIPxenon架构介绍 ,每个MySQL节点安装......
  • 4 django_Adimn账户
    1.创建管理员账号退出服务器输入命令pythonmanage.pycreatesuperuser启动服务器pythonmanage.pyrunserver输入网址:http://127.0.0.1:8000/admin/logi......
  • mysql商品评论表
    CREATEDATABASEshop;USEshop;CREATETABLEsh_goods(idINTUNSIGNEDPRIMARYKEYAUTO_INCREMENTCOMMENT'商品id',category_idINTUNSIGNEDNOTNULLDEFAULT0......
  • gcc_预处理_编译_汇编_连接
    +------------------+|gcc-E||----------------->||---------------------------------+|gcc......
  • GO mod not found
    Goget下载包的时候,会报错:go.modfilenotfoundincurrentdirectoryoranyparentdirectory.解决方法:初始化项目,比如我的项目名称叫GOWORKSPACEPSD:\goWorkSp......
  • 第13节-MySQL事件调度器
    14.1、事件调度器使用场景数据库管理是一项重要且烦琐的工作,许多日常管理任务往往会频繁地﹑周期性地执行,例如定期维护索引﹑定时刷新数据﹑定时关闭帐户﹑定义打开或关闭数据库......
  • Go语言开发环境搭建
    1go下载安装地址:https://golang.google.cn/dl/安装路径自己选一个,比如D:/go,qita安装都选下一步即可安装完把D:/go/bin添加到系统环境变量,就可以了,在CMD中输入......