main.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package main
  2. import (
  3. "TsDB2/DB"
  4. "fmt"
  5. "os"
  6. "sync"
  7. "time"
  8. )
  9. type Record struct {
  10. DB.BaseModel
  11. Name string `tsdb:"32byte"`
  12. }
  13. const dbPath = "lock_table_test.db"
  14. func main() {
  15. fmt.Println("==============================================")
  16. fmt.Println(" 锁表机制测试")
  17. fmt.Println("==============================================\n")
  18. os.Remove(dbPath)
  19. db, err := DB.Open(dbPath)
  20. if err != nil {
  21. panic(err)
  22. }
  23. defer db.Close()
  24. tbl, err := DB.UseTable[Record](db, "test")
  25. if err != nil {
  26. panic(err)
  27. }
  28. // ========== 测试1: 手动锁表 ==========
  29. fmt.Println("测试1: 手动 LockWrites/UnlockWrites")
  30. db.LockWrites()
  31. fmt.Println(" ✅ 已锁定写入")
  32. // 尝试在另一个 goroutine 中插入(应该阻塞)
  33. var wg sync.WaitGroup
  34. insertSuccess := false
  35. wg.Add(1)
  36. go func() {
  37. defer wg.Done()
  38. err := tbl.Insert(&Record{Name: "Emp0000001"})
  39. if err == nil {
  40. insertSuccess = true
  41. fmt.Println(" ❌ 锁定期不应允许插入")
  42. } else {
  43. fmt.Printf(" ✅ 插入被阻止: %v\n", err)
  44. }
  45. }()
  46. // 等待 100ms,确认 goroutine 已阻塞
  47. time.Sleep(100 * time.Millisecond)
  48. fmt.Println(" ⏳ 插入操作正在等待解锁...")
  49. // 解锁
  50. time.Sleep(200 * time.Millisecond)
  51. db.UnlockWrites()
  52. fmt.Println(" ✅ 已解锁写入")
  53. wg.Wait()
  54. if insertSuccess {
  55. fmt.Println(" ❌ 测试失败: 锁定期插入了数据")
  56. } else {
  57. fmt.Println(" ✅ 测试通过: 锁定期成功阻止写入")
  58. }
  59. // ========== 测试2: Commit 期间自动锁表 ==========
  60. fmt.Println("\n测试2: Commit 期间自动锁表")
  61. // 插入一些数据
  62. for i := 1; i <= 100; i++ {
  63. tbl.Insert(&Record{Name: fmt.Sprintf("Emp%07d", i)})
  64. }
  65. fmt.Println(" 已插入 100 行")
  66. // 在另一个 goroutine 中尝试插入
  67. wg.Add(1)
  68. commitBlocked := false
  69. go func() {
  70. defer wg.Done()
  71. start := time.Now()
  72. err := tbl.Insert(&Record{Name: "Emp0000101"})
  73. elapsed := time.Since(start)
  74. if elapsed > 10*time.Millisecond {
  75. commitBlocked = true
  76. fmt.Printf(" ✅ 插入被 Commit 阻塞 (%v)\n", elapsed)
  77. }
  78. _ = err
  79. }()
  80. // 等待 goroutine 启动
  81. time.Sleep(50 * time.Millisecond)
  82. // 执行 Commit(会自动锁表)
  83. fmt.Println(" 执行 Commit...")
  84. db.Commit()
  85. fmt.Println(" ✅ Commit 完成")
  86. wg.Wait()
  87. if commitBlocked {
  88. fmt.Println(" ✅ 测试通过: Commit 期间成功阻止写入")
  89. } else {
  90. fmt.Println(" ⚠️ 未检测到阻塞(可能 Commit 太快)")
  91. }
  92. // ========== 测试3: BufferPool 满时阻塞等待 ==========
  93. fmt.Println("\n测试3: BufferPool 满时阻塞等待")
  94. // 设置很小的容量 (10页)
  95. db2, _ := DB.Open("lock_test2.db")
  96. defer db2.Close()
  97. os.Remove("lock_test2.db")
  98. db2.SetBufferPoolCapacity(10) // 只允许10页
  99. tbl2, _ := DB.UseTable[Record](db2, "test")
  100. // 插入10行(填满 BufferPool)
  101. for i := 1; i <= 10; i++ {
  102. tbl2.Insert(&Record{Name: fmt.Sprintf("Emp%07d", i)})
  103. }
  104. fmt.Println(" 已插入 10 行(BufferPool 已满)")
  105. // 在另一个 goroutine 中尝试插入第11行(应该阻塞)
  106. var insertBlocked bool
  107. wg.Add(1)
  108. go func() {
  109. defer wg.Done()
  110. start := time.Now()
  111. tbl2.Insert(&Record{Name: "Emp0000011"})
  112. elapsed := time.Since(start)
  113. if elapsed > 50*time.Millisecond {
  114. insertBlocked = true
  115. fmt.Printf(" ✅ 插入被阻塞 (%v),等待空间释放\n", elapsed)
  116. }
  117. }()
  118. // 等待 goroutine 启动并阻塞
  119. time.Sleep(100 * time.Millisecond)
  120. // 执行 Commit,释放空间
  121. fmt.Println(" 执行 Commit 释放空间...")
  122. db2.Commit()
  123. fmt.Println(" ✅ Commit 完成,空间已释放")
  124. wg.Wait()
  125. if insertBlocked {
  126. fmt.Println(" ✅ 测试通过: BufferPool 满时正确阻塞等待")
  127. } else {
  128. fmt.Println(" ⚠️ 未检测到阻塞(可能 Commit 太快)")
  129. }
  130. fmt.Println("\n==============================================")
  131. fmt.Println(" 所有测试完成!")
  132. fmt.Println("==============================================")
  133. }