ธุรกรรม
ยืนยันหรือย้อนกลับธุรกรรม
ธุรกรรม เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
เหตุผลที่ต้องใช้ธุรกรรม
ธุรกรรม จัดกลุ่มคำสั่งหลายรายการไว้ด้วยกัน เพื่อให้ทั้งหมดสำเร็จหรือทั้งหมดล้มเหลวไปพร้อมกัน วิธีนี้ช่วยให้ข้อมูลสอดคล้องกัน เช่น การโอนเงินระหว่างบัญชีสองบัญชีโดยไม่ทำให้เงินสูญหายระหว่างทาง
- เป็นอะตอม: ทำทั้งหมดหรือไม่ทำเลย
- สถานะสอดคล้องกัน
- แยกจากธุรกรรมอื่น
การเริ่มธุรกรรมด้วย Begin
Begin เริ่มธุรกรรมและส่งคืนค่า *sql.Tx คุณเรียกใช้คำสั่งบน Tx ไม่ใช่บนกลุ่มการเชื่อมต่อ เพื่อให้คำสั่งเหล่านั้นใช้การเชื่อมต่อเดียวและธุรกรรมเดียวกัน
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}คำสั่งบน Tx
เรียกใช้ tx.Exec และ tx.Query ได้เช่นเดียวกับการเรียกใช้บนฐานข้อมูล แต่ทุกอย่างจะทำงานภายในธุรกรรมจนกว่าจะยืนยันหรือย้อนกลับธุรกรรม
_, err = tx.Exec("UPDATE accounts SET balance = balance - $1 WHERE id = $2", 100, 1)ยืนยันธุรกรรม
tx.Commit() ทำให้การเปลี่ยนแปลงทั้งหมดมีผลถาวรและผู้อื่นมองเห็นได้ หากส่งคืนข้อผิดพลาด แสดงว่าธุรกรรมนั้นยังไม่ถูกนำไปใช้
if err := tx.Commit(); err != nil {
log.Fatal(err)
}ย้อนกลับธุรกรรม
หากขั้นตอนใดล้มเหลว ให้เรียก tx.Rollback() เพื่อยกเลิกการเปลี่ยนแปลงทั้งหมดนับตั้งแต่ Begin ฐานข้อมูลจะกลับสู่สถานะเดิมราวกับว่าไม่มีอะไรเกิดขึ้น
if err != nil {
tx.Rollback()
return err
}รูปแบบ defer Rollback
รูปแบบการเขียนที่รัดกุมคือเลื่อนการทำงานของ Rollback ไว้ทันทีหลังจาก Begin การเรียก Rollback หลังจากยืนยันธุรกรรมสำเร็จแล้วจะไม่ทำอะไรและไม่ก่อผลเสีย ดังนั้นรูปแบบนี้จึงรับประกันการคืนทรัพยากรในทุกเส้นทางที่เกิดข้อผิดพลาด
tx, err := db.Begin()
if err != nil { return err }
defer tx.Rollback()
// ... do work ...
return tx.Commit()ตัวอย่างการโอนแบบอะตอม
การอัปเดตสองรายการรวมกันเป็นการดำเนินการเชิงตรรกะหนึ่งรายการ นั่นคือหักเงินจากบัญชีหนึ่งและเพิ่มเงินให้อีกบัญชีหนึ่ง ทั้งสองรายการต้องยืนยันพร้อมกัน หรือไม่เช่นนั้นก็ไม่ควรถูกนำไปใช้ทั้งคู่
การจำลองธุรกรรมที่เรียกใช้งานได้
ธุรกรรมจริงจำเป็นต้องใช้ฐานข้อมูล ตัวอย่างที่เรียกใช้งานได้นี้จำลองการเริ่มธุรกรรม การอัปเดตสองรายการ และการยืนยันหรือย้อนกลับธุรกรรมโดยใช้แผนที่ในหน่วยความจำ
package main
import (
"errors"
"fmt"
)
func transfer(bal map[string]int, from, to string, amt int) error {
if bal[from] < amt {
return errors.New("insufficient funds")
}
snapshot := map[string]int{from: bal[from], to: bal[to]}
bal[from] -= amt
bal[to] += amt
if bal[from] < 0 {
bal[from], bal[to] = snapshot[from], snapshot[to]
return errors.New("rolled back")
}
return nil
}
func main() {
bal := map[string]int{"alice": 100, "bob": 20}
if err := transfer(bal, "alice", "bob", 30); err != nil {
fmt.Println("error:", err)
} else {
fmt.Println("committed:", bal)
}
}ระดับการแยกธุรกรรม
db.BeginTx รับตัวเลือกต่าง ๆ รวมถึงระดับการแยกธุรกรรม เช่น sql.LevelSerializable ระดับการแยกที่สูงขึ้นช่วยป้องกันความผิดปกติได้มากขึ้น แต่อาจลดการทำงานพร้อมกัน
tx, err := db.BeginTx(ctx, &sql.TxOptions{Isolation: sql.LevelSerializable})ทำธุรกรรมให้สั้น
ธุรกรรมจะยึดการเชื่อมต่อไว้และอาจยึดล็อกไว้ด้วย ควรดำเนินการคำสั่งฐานข้อมูลทั้งหมดอย่างรวดเร็ว หลีกเลี่ยงการเรียกเครือข่ายหรือรับข้อมูลจากผู้ใช้ภายในธุรกรรม และยืนยันธุรกรรมโดยเร็วเพื่อลดการแย่งใช้ทรัพยากร
ห้ามใช้ db และ tx ปะปนกัน
ภายในธุรกรรม ให้เรียกใช้คำสั่งบน tx เท่านั้น การเรียก db.Exec ที่จุดนั้นจะใช้การเชื่อมต่ออื่นนอกธุรกรรม ดังนั้นการเปลี่ยนแปลงดังกล่าวจึงไม่เป็นส่วนหนึ่งของธุรกรรมและจะไม่ถูกย้อนกลับ
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความรู้เกี่ยวกับธุรกรรม
สรุปทบทวน
คุณได้เรียนรู้เกี่ยวกับธุรกรรมดังนี้:
- Begin ส่งคืน *sql.Tx และให้เรียกใช้คำสั่งบนค่านั้น
- Commit ทำให้การเปลี่ยนแปลงคงอยู่ ส่วน Rollback ยกเลิกการเปลี่ยนแปลงทั้งหมด
- defer tx.Rollback() รับประกันการคืนทรัพยากรเมื่อเกิดข้อผิดพลาด
- BeginTx กำหนดการแยกธุรกรรม และควรทำธุรกรรมให้สั้น
- ห้ามใช้ db และ tx ปะปนกันภายในธุรกรรมเดียว
คำถามที่พบบ่อย
บทเรียน “ธุรกรรม” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ธุรกรรม” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ธุรกรรม”
ยืนยันหรือย้อนกลับธุรกรรม คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “ธุรกรรม” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม
ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ