一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Go 的 MySQL 預(yù)處理、MySQL 事務(wù)

 菜籽愛(ài)編程 2022-04-27

預(yù)處理是什么

在普通 SQL 語(yǔ)句執(zhí)行過(guò)程中,客戶端會(huì)對(duì) SQL 語(yǔ)句進(jìn)行占位符替換,從而得到要執(zhí)行的完整 SQL 語(yǔ)句,客戶端再將此 SQL 語(yǔ)句發(fā)送到服務(wù)端執(zhí)行,服務(wù)端最后把結(jié)果返回給客戶端。

而預(yù)處理,則是將 SQL 語(yǔ)句分為命令部分以及數(shù)據(jù)部分,客戶端先把命令部分發(fā)送給服務(wù)器,服務(wù)器先進(jìn)行預(yù)處理,而后客戶端才把數(shù)據(jù)部分發(fā)送給服務(wù)器,由服務(wù)器對(duì) SQL 語(yǔ)句進(jìn)行占位符替換并執(zhí)行,最后將結(jié)果返回給客戶端。

預(yù)處理可以提高服務(wù)器的性能,提前讓服務(wù)器編譯,一次編譯多次執(zhí)行,甚至可以避免 SQL 注入問(wèn)題。

Go 實(shí)現(xiàn) MySQL 預(yù)處理

在上一期《Go 操作 MySQL 數(shù)據(jù)庫(kù)》中,很多例子都使用了預(yù)處理。Go 中的 Prepare() 方法會(huì)將 SQL 語(yǔ)句發(fā)送給服務(wù)器,返回一個(gè)準(zhǔn)備好的狀態(tài)用于之后的查詢和命令,返回值可以同時(shí)執(zhí)行多個(gè)查詢和命令:

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

下面是一個(gè)查詢操作預(yù)處理的例子:

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() {
 // 連接數(shù)據(jù)庫(kù)
 db, _ := sql.Open("mysql""root:root@(127.0.0.1:3306)/godb_test?charset=utf8mb4")

 // Ping() 驗(yàn)證與數(shù)據(jù)庫(kù)的連接是否仍處于活動(dòng)狀態(tài),并在必要時(shí)建立連接
 err := db.Ping()

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

 // 延遲調(diào)用關(guān)閉數(shù)據(jù)庫(kù) 阻止新的查詢
 defer db.Close()

 // 準(zhǔn)備 SQL 語(yǔ)句
 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()

 // 讀取結(jié)果集中的數(shù)據(jù)
 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 實(shí)現(xiàn) MySQL 事務(wù)

Go 語(yǔ)言中使用下面的方法實(shí)現(xiàn) MySQL 事務(wù)操作:

// 開(kāi)啟事務(wù)方法
func (db *DB) Begin() (*Tx, error) {
 return db.BeginTx(context.Background(), nil)
}

// 回滾事務(wù)方法
func (tx *Tx) Rollback() error {
 return tx.rollback(false)
}

// 提交事務(wù)方法
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, 01) {
  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
}

下面是一個(gè)事務(wù)操作的例子,該事務(wù)操作確保兩次更新操作要么同時(shí)成功要么同時(shí)失?。?/p>

package main

import (
 "database/sql"
 "fmt"

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

func main() {
 // 連接數(shù)據(jù)庫(kù)
 db, _ := sql.Open("mysql""root:root@(127.0.0.1:3306)/godb_test?charset=utf8mb4")

 // Ping() 驗(yàn)證與數(shù)據(jù)庫(kù)的連接是否仍處于活動(dòng)狀態(tài),并在必要時(shí)建立連接
 err := db.Ping()

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

 // 延遲調(diào)用關(guān)閉數(shù)據(jù)庫(kù) 阻止新的查詢
 defer db.Close()

 // 開(kāi)啟事務(wù)
 t, err := db.Begin()
 if err != nil {
  if t != nil {
   // 回滾
   t.Rollback()
  }
  fmt.Println("Begin transaction failed")
  return
 }

 // 準(zhǔn)備 SQL 語(yǔ)句
 sqlStr := "update acl_user set nick_name = ?, age = ? where id = ? and is_deleted = 0"
 // 執(zhí)行 SQL 語(yǔ)句
 _, err = t.Exec(sqlStr, "AAA"60102)

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

 // 準(zhǔn)備 SQL 語(yǔ)句
 sqlStr2 := "update acl_user set nick_name = ?, age = ? where id = ? and is_deleted = 0"
 // 執(zhí)行 SQL 語(yǔ)句
 _, err = t.Exec(sqlStr2, "BBB"50103)

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

 // 提交事務(wù)
 err = t.Commit()

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

 fmt.Println("Exec transaction Success")

}

??希望對(duì)你有幫助,期待你的關(guān)注??

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    国产二级一级内射视频播放| 欧美精品二区中文乱码字幕高清| 国产又粗又硬又长又爽的剧情| 大尺度激情福利视频在线观看| 九九热在线免费在线观看| 亚洲高清中文字幕一区二区三区| 最新午夜福利视频偷拍| 91人妻人人做人碰人人九色| 欧美在线观看视频免费不卡| 欧美日韩亚洲巨色人妻| 少妇丰满a一区二区三区| 国产精品一级香蕉一区| 九九热视频网在线观看| 日韩特级黄片免费在线观看| 久久国产精品熟女一区二区三区| 亚洲国产天堂av成人在线播放| 国产av一区二区三区四区五区| 一本久道久久综合中文字幕| 亚洲熟女诱惑一区二区| 台湾综合熟女一区二区| 成人午夜免费观看视频| 大尺度剧情国产在线视频| 一级片黄色一区二区三区| 国产又黄又爽又粗视频在线| 好吊日成人免费视频公开| 大胆裸体写真一区二区| 国产丝袜美女诱惑一区二区| 精品国产一区二区欧美| 搡老熟女老女人一区二区| 日本 一区二区 在线| 黄色美女日本的美女日人| 午夜福利视频六七十路熟女| 91插插插外国一区二区| 国产三级视频不卡在线观看| 亚洲视频一区自拍偷拍另类| 国产欧美韩日一区二区三区| 亚洲欧美一二区日韩高清在线| 黄色激情视频中文字幕| 天堂网中文字幕在线观看| 中文字幕久久精品亚洲乱码| 夜色福利久久精品福利|