|
|
@@ -0,0 +1,125 @@
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "TsDB2/DB"
|
|
|
+ "fmt"
|
|
|
+ "os"
|
|
|
+)
|
|
|
+
|
|
|
+type Record struct {
|
|
|
+ DB.BaseModel
|
|
|
+ Name string `tsdb:"32byte"`
|
|
|
+ Age int64 `tsdb:"8byte"`
|
|
|
+}
|
|
|
+
|
|
|
+const dbPath = "txn_test.db"
|
|
|
+
|
|
|
+func main() {
|
|
|
+ os.Remove(dbPath)
|
|
|
+
|
|
|
+ fmt.Println("==============================================")
|
|
|
+ fmt.Println(" TsDB2 事务功能测试")
|
|
|
+ fmt.Println("==============================================\n")
|
|
|
+
|
|
|
+ // 打开数据库
|
|
|
+ db, err := DB.Open(dbPath)
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ defer db.Close()
|
|
|
+
|
|
|
+ // 禁用自动提交,完全手动控制
|
|
|
+ db.SetAutoCommitDelay(0)
|
|
|
+
|
|
|
+ // 创建表
|
|
|
+ tbl, err := DB.UseTable[Record](db, "users")
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========== 测试1: 正常事务提交 ==========
|
|
|
+ fmt.Println("========== 测试1: 正常事务提交 ==========")
|
|
|
+
|
|
|
+ txn1 := db.BeginTransaction()
|
|
|
+
|
|
|
+ for i := 1; i <= 5; i++ {
|
|
|
+ err := tbl.Insert(&Record{
|
|
|
+ Name: fmt.Sprintf("User%03d", i),
|
|
|
+ Age: int64(20 + i),
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := txn1.Commit(); err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ count, _ := tbl.Count()
|
|
|
+ fmt.Printf("✅ 插入 5 行并提交,当前行数: %d\n", count)
|
|
|
+
|
|
|
+ // ========== 测试2: 事务回滚 ==========
|
|
|
+ fmt.Println("\n========== 测试2: 事务回滚 ==========")
|
|
|
+
|
|
|
+ countBefore, _ := tbl.Count()
|
|
|
+ fmt.Printf("回滚前行数: %d\n", countBefore)
|
|
|
+
|
|
|
+ txn2 := db.BeginTransaction()
|
|
|
+
|
|
|
+ for i := 6; i <= 10; i++ {
|
|
|
+ err := tbl.Insert(&Record{
|
|
|
+ Name: fmt.Sprintf("User%03d", i),
|
|
|
+ Age: int64(20 + i),
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ countDuring, _ := tbl.Count()
|
|
|
+ fmt.Printf("插入 5 行后(未提交): %d\n", countDuring)
|
|
|
+
|
|
|
+ // 回滚事务
|
|
|
+ if err := txn2.Rollback(); err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 注意:简化版 Rollback 不立即清除 BufferPool
|
|
|
+ // 需要重启数据库才能看到效果
|
|
|
+ fmt.Println("⚠️ 已调用 Rollback()(简化版不立即清除 BufferPool)")
|
|
|
+ fmt.Println(" 实际回滚依赖 WAL 恢复机制")
|
|
|
+
|
|
|
+ // ========== 测试3: 验证数据持久化 ==========
|
|
|
+ fmt.Println("\n========== 测试3: 验证数据持久化 ==========")
|
|
|
+
|
|
|
+ db.Close()
|
|
|
+
|
|
|
+ // 重新打开数据库
|
|
|
+ db2, err := DB.Open(dbPath)
|
|
|
+ if err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ defer db2.Close()
|
|
|
+
|
|
|
+ tbl2, _ := DB.UseTable[Record](db2, "users")
|
|
|
+ countAfterReopen, _ := tbl2.Count()
|
|
|
+ fmt.Printf("重开后行数: %d(应为 5,回滚的 5 行不应存在)\n", countAfterReopen)
|
|
|
+
|
|
|
+ // 验证具体数据
|
|
|
+ row, err := tbl2.Find(1)
|
|
|
+ if err == nil {
|
|
|
+ fmt.Printf("Row#1: Name=%s, Age=%d\n", row.Name, row.Age)
|
|
|
+ }
|
|
|
+
|
|
|
+ row, err = tbl2.Find(6)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("✅ Row#6 不存在(已回滚)")
|
|
|
+ } else {
|
|
|
+ fmt.Printf("❌ Row#6 存在: Name=%s(回滚失败!)\n", row.Name)
|
|
|
+ }
|
|
|
+
|
|
|
+ fmt.Println("\n==============================================")
|
|
|
+ fmt.Println(" 测试完成!")
|
|
|
+ fmt.Println("==============================================")
|
|
|
+}
|