package main import ( "TsDB2/DB" "fmt" "os" "sync" "time" ) type Record struct { DB.BaseModel Name string `tsdb:"32byte"` } const dbPath = "lock_table_test.db" func main() { fmt.Println("==============================================") fmt.Println(" 锁表机制测试") fmt.Println("==============================================\n") os.Remove(dbPath) db, err := DB.Open(dbPath) if err != nil { panic(err) } defer db.Close() tbl, err := DB.UseTable[Record](db, "test") if err != nil { panic(err) } // ========== 测试1: 手动锁表 ========== fmt.Println("测试1: 手动 LockWrites/UnlockWrites") db.LockWrites() fmt.Println(" ✅ 已锁定写入") // 尝试在另一个 goroutine 中插入(应该阻塞) var wg sync.WaitGroup insertSuccess := false wg.Add(1) go func() { defer wg.Done() err := tbl.Insert(&Record{Name: "Emp0000001"}) if err == nil { insertSuccess = true fmt.Println(" ❌ 锁定期不应允许插入") } else { fmt.Printf(" ✅ 插入被阻止: %v\n", err) } }() // 等待 100ms,确认 goroutine 已阻塞 time.Sleep(100 * time.Millisecond) fmt.Println(" ⏳ 插入操作正在等待解锁...") // 解锁 time.Sleep(200 * time.Millisecond) db.UnlockWrites() fmt.Println(" ✅ 已解锁写入") wg.Wait() if insertSuccess { fmt.Println(" ❌ 测试失败: 锁定期插入了数据") } else { fmt.Println(" ✅ 测试通过: 锁定期成功阻止写入") } // ========== 测试2: Commit 期间自动锁表 ========== fmt.Println("\n测试2: Commit 期间自动锁表") // 插入一些数据 for i := 1; i <= 100; i++ { tbl.Insert(&Record{Name: fmt.Sprintf("Emp%07d", i)}) } fmt.Println(" 已插入 100 行") // 在另一个 goroutine 中尝试插入 wg.Add(1) commitBlocked := false go func() { defer wg.Done() start := time.Now() err := tbl.Insert(&Record{Name: "Emp0000101"}) elapsed := time.Since(start) if elapsed > 10*time.Millisecond { commitBlocked = true fmt.Printf(" ✅ 插入被 Commit 阻塞 (%v)\n", elapsed) } _ = err }() // 等待 goroutine 启动 time.Sleep(50 * time.Millisecond) // 执行 Commit(会自动锁表) fmt.Println(" 执行 Commit...") db.Commit() fmt.Println(" ✅ Commit 完成") wg.Wait() if commitBlocked { fmt.Println(" ✅ 测试通过: Commit 期间成功阻止写入") } else { fmt.Println(" ⚠️ 未检测到阻塞(可能 Commit 太快)") } // ========== 测试3: BufferPool 满时阻塞等待 ========== fmt.Println("\n测试3: BufferPool 满时阻塞等待") // 设置很小的容量 (10页) db2, _ := DB.Open("lock_test2.db") defer db2.Close() os.Remove("lock_test2.db") db2.SetBufferPoolCapacity(10) // 只允许10页 tbl2, _ := DB.UseTable[Record](db2, "test") // 插入10行(填满 BufferPool) for i := 1; i <= 10; i++ { tbl2.Insert(&Record{Name: fmt.Sprintf("Emp%07d", i)}) } fmt.Println(" 已插入 10 行(BufferPool 已满)") // 在另一个 goroutine 中尝试插入第11行(应该阻塞) var insertBlocked bool wg.Add(1) go func() { defer wg.Done() start := time.Now() tbl2.Insert(&Record{Name: "Emp0000011"}) elapsed := time.Since(start) if elapsed > 50*time.Millisecond { insertBlocked = true fmt.Printf(" ✅ 插入被阻塞 (%v),等待空间释放\n", elapsed) } }() // 等待 goroutine 启动并阻塞 time.Sleep(100 * time.Millisecond) // 执行 Commit,释放空间 fmt.Println(" 执行 Commit 释放空间...") db2.Commit() fmt.Println(" ✅ Commit 完成,空间已释放") wg.Wait() if insertBlocked { fmt.Println(" ✅ 测试通过: BufferPool 满时正确阻塞等待") } else { fmt.Println(" ⚠️ 未检测到阻塞(可能 Commit 太快)") } fmt.Println("\n==============================================") fmt.Println(" 所有测试完成!") fmt.Println("==============================================") }