|
|
@@ -48,6 +48,7 @@ type WALWriter struct {
|
|
|
file *File
|
|
|
header *HeaderPage
|
|
|
readPage func(uint32, []byte) error // 用于分配页时读取空闲链表
|
|
|
+ state byte // 当前 WAL 状态 (Mem/Written/Persisted/Committed)
|
|
|
}
|
|
|
|
|
|
type walEntry struct {
|
|
|
@@ -65,11 +66,18 @@ func (db *DB) BeginTxn() *WALWriter {
|
|
|
file: db.file,
|
|
|
header: db.header,
|
|
|
readPage: db.file.readPageDisk, // 必须直接读盘! 走 BufferPool 会被旧缓存干扰空闲链表
|
|
|
+ state: WALStateMem, // 初始状态: Mem (内存中)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// RecordPage 记录一个被修改的页 (同一 pageID 只保留最新镜像)
|
|
|
func (w *WALWriter) RecordPage(pageID uint32, data []byte) {
|
|
|
+ // 确保状态为 Mem (如果已写盘,不应再修改)
|
|
|
+ if w.state != WALStateMem && w.state != WALStateWritten {
|
|
|
+ // 理论上不应发生,因为 Commit 后会清空 entries
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
d := make([]byte, len(data))
|
|
|
copy(d, data)
|
|
|
// 同一 pageID 只保留最新镜像
|
|
|
@@ -85,6 +93,7 @@ func (w *WALWriter) RecordPage(pageID uint32, data []byte) {
|
|
|
// Rollback 回滚: 丢弃所有条目
|
|
|
func (w *WALWriter) Rollback() {
|
|
|
w.entries = nil
|
|
|
+ w.state = WALStateMem // 重置状态
|
|
|
}
|
|
|
|
|
|
// Commit 原子提交流程:
|
|
|
@@ -108,6 +117,8 @@ func (w *WALWriter) Commit() error {
|
|
|
if err := w.file.sync(); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
+ // 状态转换: Written → Persisted (已落盘)
|
|
|
+ w.state = WALStatePersisted
|
|
|
|
|
|
// === 步骤 3: 回写实际页 (直接写盘, 绕过 BufferPool) ===
|
|
|
for _, e := range w.entries {
|
|
|
@@ -148,6 +159,7 @@ func (w *WALWriter) Commit() error {
|
|
|
}
|
|
|
|
|
|
// writeWALPages 将所有 entry 写入 WAL 页链, 返回分配的页 ID 列表
|
|
|
+// 状态转换: Mem → Written
|
|
|
func (w *WALWriter) writeWALPages() ([]uint32, error) {
|
|
|
var pageIDs []uint32
|
|
|
entryIdx := 0
|
|
|
@@ -247,6 +259,9 @@ func (w *WALWriter) writeWALPages() ([]uint32, error) {
|
|
|
_ = w.file.WriteHeader(w.header)
|
|
|
}
|
|
|
|
|
|
+ // 状态转换: Mem → Written (已写盘,未 fsync)
|
|
|
+ w.state = WALStateWritten
|
|
|
+
|
|
|
return pageIDs, nil
|
|
|
}
|
|
|
|
|
|
@@ -257,7 +272,12 @@ func (w *WALWriter) markCommitted(firstPageID uint32) error {
|
|
|
return err
|
|
|
}
|
|
|
buf[walPHDR+12] = WALStateCommitted // State = Committed
|
|
|
- return w.file.WritePageDirect(firstPageID, buf)
|
|
|
+ if err := w.file.WritePageDirect(firstPageID, buf); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ // 状态转换: Persisted → Committed
|
|
|
+ w.state = WALStateCommitted
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
// isFirstWALPage 判断 WAL 页是否为事务首页
|