第五节 Rollback()实现

Rollback()中,主要对不同事务进行不同操作:

  1. 如果当前事务是只读事务,则只需要从db中的txs中找到当前事务,然后移除掉即可。
  2. 如果当前事务是读写事务,则需要将空闲列表中和该事务关联的页释放掉,同时重新从freelist中加载空闲页。
1. // Rollback closes the transaction and ignores all previous updates. Read-only
2. // transactions must be rolled back and not committed.
3. func (tx *Tx) Rollback() error {
4. _assert(!tx.managed, "managed tx rollback not allowed")
5. if tx.db == nil {
6. return ErrTxClosed
7. }
8. tx.rollback()
9. return nil
10. }

12. func (tx *Tx) rollback() {
13. if tx.db == nil {
14. return
15. }
16. if tx.writable {
17. // 移除该事务关联的pages
18. tx.db.freelist.rollback(tx.meta.txid)
19. // 重新从freelist页中读取构建空闲列表
20. tx.db.freelist.reload(tx.db.page(tx.db.meta().freelist))
21. }
22. tx.close()
23. }

25. func (tx *Tx) close() {
26. if tx.db == nil {
27. return
28. }
29. if tx.writable {
30. // Grab freelist stats.
31. var freelistFreeN = tx.db.freelist.free_count()
32. var freelistPendingN = tx.db.freelist.pending_count()
33. var freelistAlloc = tx.db.freelist.size()

35. // Remove transaction ref & writer lock.
36. tx.db.rwtx = nil
37. tx.db.rwlock.Unlock()

39. // Merge statistics.
40. tx.db.statlock.Lock()
41. tx.db.stats.FreePageN = freelistFreeN
42. tx.db.stats.PendingPageN = freelistPendingN
43. tx.db.stats.FreeAlloc = (freelistFreeN + freelistPendingN) * tx.db.pageSize
44. tx.db.stats.FreelistInuse = freelistAlloc
45. tx.db.stats.TxStats.add(&tx.stats)
46. tx.db.statlock.Unlock()
47. } else {
48. // 只读事务
49. tx.db.removeTx(tx)
50. }

52. // Clear all references.
53. tx.db = nil
54. tx.meta = nil
55. tx.root = Bucket{tx: tx}
56. tx.pages = nil
57. }

59. // removeTx removes a transaction from the database.
60. func (db *DB) removeTx(tx *Tx) {
61. // Release the read lock on the mmap.
62. db.mmaplock.RUnlock()

64. // Use the meta lock to restrict access to the DB object.
65. db.metalock.Lock()

67. // Remove the transaction.
68. for i, t := range db.txs {
69. if t == tx {
70. last := len(db.txs) - 1
71. db.txs[i] = db.txs[last]
72. db.txs[last] = nil
73. db.txs = db.txs[:last]
74. break
75. }
76. }
77. n := len(db.txs)

79. // Unlock the meta pages.
80. db.metalock.Unlock()

82. // Merge statistics.
83. db.statlock.Lock()
84. db.stats.OpenTxN = n
85. db.stats.TxStats.add(&tx.stats)
86. db.statlock.Unlock()
87. }