第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

回滾不適用于 Go 語言事務(wù)包裝器

回滾不適用于 Go 語言事務(wù)包裝器

Go
慕勒3428872 2022-12-19 10:53:12
我最近開始學(xué)習(xí)圍棋。我發(fā)現(xiàn)了以下用于數(shù)據(jù)庫事務(wù)處理的包裝器的 Github 實現(xiàn),并決定嘗試一下。(來源)https://github.com/oreilly-japan/practical-go-programming/blob/master/ch09/transaction/wrapper/main.go我使用 PostgreSQL 作為數(shù)據(jù)庫。最初,它包含以下數(shù)據(jù)。testdb=> select * from products; product_id | price------------+------- 0001       |   200 0002       |   100 0003       |   150 0004       |   300(4 rows)進(jìn)程A成功后,故意讓進(jìn)程B失敗,期望事務(wù)A回滾。然而,當(dāng)我們運行它時,回滾并沒有發(fā)生,我們最終得到以下結(jié)果實際上,由于 B 失敗,進(jìn)程 A 應(yīng)該回滾,數(shù)據(jù)庫值應(yīng)該沒有變化。我已經(jīng)在一些地方插入了日志來確認(rèn)這一點,但我不確定。為什么回滾沒有執(zhí)行?
查看完整描述

1 回答

?
紅糖糍粑

TA貢獻(xiàn)1815條經(jīng)驗 獲得超6個贊

正如@Richard Huxton 所說,傳遞tx給一個函數(shù)f

以下是步驟:

  1. 添加一個字段struct txAdmin以容納*sql.Tx,所以txAdminDBTx字段

  2. 里面Transaction設(shè)置tx*txAdmin.Tx

  3. 每個查詢的內(nèi)部UpdateProduct使用*Service.tx.Tx

所以最后的代碼是這樣的:

package main


import (

    "context"

    "database/sql"

    "fmt"

    "log"


    _ "github.com/jackc/pgx/v4/stdlib"

)


// transaction-wrapper-start

type txAdmin struct {

    *sql.DB

    *sql.Tx

}


type Service struct {

    tx txAdmin

}


func (t *txAdmin) Transaction(ctx context.Context, f func(ctx context.Context) (err error)) error {

    log.Printf("transaction")

    tx, err := t.DB.BeginTx(ctx, nil)

    if err != nil {

        return err

    }


    // set tx to Tx

    t.Tx = tx


    defer tx.Rollback()

    if err := f(ctx); err != nil {

        log.Printf("transaction err")

        return fmt.Errorf("transaction query failed: %w", err)

    }


    log.Printf("commit")

    return tx.Commit()

}


func (s *Service) UpdateProduct(ctx context.Context, productID string) error {

    updateFunc := func(ctx context.Context) error {

        log.Printf("first process")

        // Process A

        if _, err := s.tx.Tx.ExecContext(ctx, "UPDATE products SET price = 200 WHERE product_id = $1", productID); err != nil {

            log.Printf("first err")

            return err

        }

        log.Printf("second process")


        // Process B(They are intentionally failing.)

        if _, err := s.tx.Tx.ExecContext(ctx, "...", productID); err != nil {

            log.Printf("second err")

            return err

        }

        return nil

    }

    log.Printf("update")

    return s.tx.Transaction(ctx, updateFunc)

}


// transaction-wrapper-end

func main() {

    data, err := sql.Open("pgx", "host=localhost port=5432 user=testuser dbname=testdb password=password sslmode=disable")

    if nil != err {

        log.Fatal(err)

    }


    database := Service{tx: txAdmin{DB: data}}


    ctx := context.Background()


    database.UpdateProduct(ctx, "0004")

}


查看完整回答
反對 回復(fù) 2022-12-19
  • 1 回答
  • 0 關(guān)注
  • 80 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號