当前位置:首页>Linux>Linux 磁盘与文件 I/O 深度笔记

Linux 磁盘与文件 I/O 深度笔记

  • 2026-03-27 00:20:07
Linux 磁盘与文件 I/O 深度笔记

从电子到比特,从应用到 NAND Flash,一次讲透磁盘 I/O 的底层真相。

注:文章中引用了 BookKeeper 的实现案例,部分代码示例为 C 语言。


一、全景图:一次 write() 的奇幻漂流

当你在应用程序里写下 write(fd, buf, 100) 时,这 100 字节要经历一段惊心动魄的旅程:

记住这张图,下面所有内容都是在不同层次上展开的。


二、两条路线:Buffered I/O vs Direct I/O

这是磁盘 I/O 中最核心的分叉路口

2.1 Buffered I/O(默认路线)

int fd = open("data.log", O_WRONLY | O_CREAT, 0644);write(fd, buf, 100);   // 数据去了 Page Cache,还没到磁盘!fsync(fd);  // 现在才真正刷到磁盘

数据路径:

应用缓冲区 ──copy──→ Page Cache (内核内存) ──writeback──→ 磁盘

特点:

  • 数据先写到内核管理的 Page Cache(一块内存区域),write() 就返回了
  • 内核在"合适的时候"把脏页刷到磁盘(或者你主动调 fsync
  • 对应用友好:不需要对齐,不需要管缓冲区大小,内核帮你搞定一切
  • 代价:数据在内存中多了一份拷贝;缓存策略你无法控制

2.2 Direct I/O(硬核路线)

int fd = open("data.log", O_WRONLY | O_CREAT | O_DIRECT, 0644);// ⚠️ 现在你要自己伺候磁盘了

数据路径:

应用缓冲区 ──DMA──→ 磁盘(绕过 Page Cache!)

特点:

  • 数据直接从用户态内存通过 DMA 传输到磁盘控制器
  • 不经过 Page Cache,零内核缓存拷贝
  • 对应用苛刻:必须满足严格的对齐要求(见下文)
  • 优势:应用完全掌控缓存策略,避免"双重缓存"

2.3 对比总结

维度

Buffered I/O

Direct I/O (O_DIRECT)

数据路径

应用 → Page Cache → 磁盘

应用 → 磁盘

内存拷贝

1次(用户态 → 内核态)

0次(DMA 直传)

对齐要求

(内核兜底)

严格(三重对齐)

缓存控制

内核自动管理(你无权干预)

应用自行管理(你说了算)

写入语义

write 返回 ≠ 数据落盘

write 返回 ≈ 数据落盘

编程难度

简单

困难

典型使用者

普通应用、脚本

数据库(MySQL InnoDB)、分布式存储


三、Page Cache:内核的"好意"与"代价"

3.1 Page Cache 是什么?

Page Cache 是 Linux 内核用空闲内存自动维护的一层磁盘数据缓存。它是 Buffered I/O 的核心。

物理内存布局:
┌───────────────────────────────────────────────────────┐
│  内核代码和数据  │  进程内存  │   Page Cache   │  空闲   │
│    (固定)       │  (按需)   │  (自动伸缩)     │        │
└───────────────────────────────────────────────────────┘
                              ↑
                     内核自动用空闲内存做缓存
                     内存紧张时自动回收

3.2 最小管理单位:4KB 的 Page

这是理解所有 I/O 行为的基石。

一个 Page = 4096 字节 = 4KB (在大多数 Linux 系统上)

Page Cache 的索引方式:
  Key   = (inode 编号, 文件内偏移的页号)
  Value = 一个 4KB 的内存页

例如文件 inode=12345:
  (12345, 第0页)  → 对应文件 offset 0~4095
  (12345, 第1页)  → 对应文件 offset 4096~8191
  (12345, 第2页)  → 对应文件 offset 8192~12287
  ...

关键特性:内核不追踪页内哪些字节是脏的。

整个 Page 要么是 clean(和磁盘一致),要么是 dirty(被修改过、需要刷盘)。哪怕你只改了页内 1 个字节,刷盘时也要把整个 4KB 页写出去。

3.3 Page Cache 的文件隔离

不同文件的 Page Cache 页按 inode 严格隔离:

文件 A (inode=111):
  Page Cache: {(111,0) → PageX, (111,1) → PageY}

文件 B (inode=222):
  Page Cache: {(222,0) → PageZ, (222,1) → PageW}

→ 进程写文件 A 的 Page 永远不会影响文件 B 的 Page
→ 即使两个文件在同一目录、同一磁盘上

四、对齐(Alignment):磁盘世界的"交通规则"

4.1 什么是对齐?

对齐就是要求数据的地址/偏移/大小必须是某个值的整数倍

4KB 对齐示例:
  ✅ 合法: 0, 4096, 8192, 12288, ...    (都是 4096 的整数倍)
  ❌ 非法: 100, 1000, 4097, 5000, ...   (不是 4096 的整数倍)

为什么需要对齐?因为硬件的最小读写单元不是 1 字节

4.2 各层的"最小单元"

层次                    最小操作单元         典型大小
──────────────────────────────────────────────────
CPU 内存访问            Cache Line           64 字节
Linux Page Cache       Page                 4KB
文件系统 (ext4/xfs)     Block                4KB
NVMe 逻辑扇区          Logical Block (LBA)   512B 或 4KB
NVMe 物理扇区          Physical Sector       4KB
NAND Flash 写入        Page                  4KB~16KB
NAND Flash 擦除        Block                 256KB~4MB
HDD 扇区              Sector                512B

可以看到,4KB 是一个在多个层次上反复出现的魔法数字

4.3 两种对齐:扇区对齐 vs 页对齐

扇区对齐 (512B)

页对齐 (4KB)

对齐到

512 字节边界

4096 字节边界

目的

保证磁盘原子写入(torn write 保护)

满足 Direct I/O / 匹配物理扇区

谁需要

Journal WAL(保证断电恢复)

Direct I/O 应用(如 DirectEntryLogger)

举例

BookKeeper journalAlignmentSize=512

BookKeeper Buffer.ALIGNMENT=4096

4.4 Direct I/O 的三重对齐要求

使用 O_DIRECT 时,以下三个条件必须同时满足,否则 write()/pwrite() 直接返回 EINVAL(无效参数):

┌─────────────────────────────────────────────────────────┐
│               Direct I/O 的三重对齐铁律                    │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  1. 内存缓冲区地址 必须对齐                                 │
│     ❌ char *buf = malloc(4096);      // 不保证对齐        │
│     ✅ char *buf = aligned_alloc(4096, 4096);  // 对齐!  │
│     ✅ posix_memalign(&buf, 4096, 4096);       // 也行   │
│                                                         │
│  2. 文件偏移量 (offset) 必须对齐                            │
│     ❌ pwrite(fd, buf, 4096, 1000);   // 1000 没对齐!    │
│     ✅ pwrite(fd, buf, 4096, 4096);   // 4096 = 1×4096  │
│                                                         │
│  3. 读写长度 (length) 必须对齐                              │
│     ❌ write(fd, buf, 100);           // 100 没对齐!      │
│     ✅ write(fd, buf, 4096);          // 4096 = 1×4096   │
│                                                         │
│  三条有一条不满足 → errno = EINVAL → 写入失败!              │
└─────────────────────────────────────────────────────────┘

对齐值怎么确定?

# 方法 1: 查看块设备的逻辑/物理扇区大小
cat /sys/block/nvme0n1/queue/logical_block_size    # 通常 512
cat /sys/block/nvme0n1/queue/physical_block_size   # 通常 4096

# 方法 2: 查看文件系统块大小
stat -f /path/to/dir | grep "Block size"
tune2fs -l /dev/nvme0n1p1 | grep "Block size"     # ext4

# 方法 3: 查看 DIO 对齐要求
cat /sys/block/nvme0n1/queue/dma_alignment
cat /sys/block/nvme0n1/queue/minimum_io_size
cat /sys/block/nvme0n1/queue/optimal_io_size

# 方法 4: 查看完整的磁盘拓扑
lsblk -t /dev/nvme0n1

实际规则: 对齐值 = max(逻辑扇区大小, 文件系统要求)。虽然很多情况下 512B 就能通过,但生产环境统一用 4KB 是最安全的选择——因为有些机器 512 行,有些不行,4KB 通吃。

4.5 Buffered I/O 为什么不需要对齐?

因为 Page Cache 帮你兜底了

你的 write(fd, buf, 100):
                          ↓
Page Cache 内部操作:
  1. 找到 offset 0 对应的 Page(如果没有就分配一个 4KB 的 Page)
  2. 把你的 100 字节拷贝到这个 Page 的对应位置
  3. 标记这个 Page 为 dirty
  4. 返回 "写入成功"

刷盘时:
  1. 以 Page (4KB) 为单位写到磁盘
  2. 内核自己做好了对齐
  → 你完全不用操心对齐问题

五、write + fsync 的真实代价:写放大深度剖析

5.1 经典问题:写 100 字节,磁盘写了多少?

应用视角:   write(fd, buf, 100) + fsync(fd)
            "我就写了 100 字节啊"

实际磁盘:   至少 4KB 数据 + 4KB~16KB 元数据
            "你以为你写了 100,其实我写了 8000+"

逐层拆解:

第 1 层: Page Cache → 磁盘 (数据)
─────────────────────────────
你的 100 字节在一个 4KB Page 里:

┌──────────────────────────────────────────────────┐
│ [你的100字节] │         3996 字节的零             │
└──────────────────────────────────────────────────┘
        ↑ 整个 4KB Page 一起写到磁盘

数据写入量: 4KB
写入放大: 4096 / 100 = 40.96 倍


第 2 层: 文件系统日志 (Journaling) — 以 ext4 为例
─────────────────────────────────────────────────
fsync 不光要写数据,还要更新文件系统的元数据:
  - inode (文件大小、修改时间、块指针)
  - 块分配位图 (bitmap)
  - 文件系统日志 (jbd2 journal)

ext4 data=ordered (默认模式) 下的 fsync 流程:
  1. 写数据块到最终位置:        4KB
  2. 写 journal descriptor:     4KB (描述这次事务修改了什么)
  3. 写 journal commit block:   4KB (标记事务完成)
  4. 可能的 inode 更新:          4KB

总计: 数据 4KB + 元数据 4KB~16KB = 8KB~20KB


第 3 层: NVMe SSD 内部 (FTL 写放大)
─────────────────────────────────────
SSD 收到的 4KB 写入在内部可能导致:
  - FTL 映射表更新
  - GC 时的数据搬移
  - 内部写入放大系数通常 1.1x~3x

最终 NAND Flash 上的真实写入量: 可能 10KB~60KB

所以,应用层的 100 字节 write + fsync,最终可能导致 NAND Flash 上写入 10KB~60KB 的数据。这就是"写放大"(Write Amplification)的完整链路。

5.2 连续小写 + fsync:惨烈的写放大现场

操作序列:                           Page Cache 状态         磁盘实际写入
─────────────────────────────────────────────────────────────────────

write(100B) @ offset 0             Page 0 dirty            -
fsync()                            Page 0 clean            4KB + 元数据

write(100B) @ offset 100           Page 0 dirty (同一页!)   -
fsync()                            Page 0 clean            4KB + 元数据 (又写一次!)

write(100B) @ offset 200           Page 0 dirty            -
fsync()                            Page 0 clean            4KB + 元数据 (再写一次!)

...

前 40 次操作都在 Page 0 里 (100×40 = 4000 < 4096)
每次 fsync 都把同一个 4KB Page 完整地重新写到磁盘

═══════════════════════════════════════════════════════
40 次 write(100B) + fsync():
  应用写入总量:      40 × 100 = 4,000 字节
  磁盘数据写入:      40 × 4KB = 160KB         (40 倍放大)
  磁盘元数据写入:    40 × ~12KB = ~480KB       (又是一大笔)
  磁盘总写入:        ~640KB                     (160 倍放大!)
═══════════════════════════════════════════════════════

这就是为什么"每写一点就 fsync"是性能杀手。 正确做法是 batch(批量攒一批再 fsync),也就是所谓的 Group Commit。

5.3 文件大小 vs 磁盘占用

# 写入 100 字节后
$ ls -l test_file
-rw-r--r-- 1 user user 100 ...      ← 文件逻辑大小: 100 字节 (应用看到的)

$ ls -s test_file
4 test_file                          ← 磁盘实际占用: 4KB (至少一个块)

$ stat test_file
  Size: 100           Blocks: 8      ← 8 个 512B 块 = 4KB
                      IO Block: 4096 ← 文件系统块大小

$ du -h test_file
4.0K    test_file                    ← 磁盘占用确认: 4KB

文件的逻辑大小和物理占用是两回事。 哪怕文件只有 1 字节,磁盘上也至少占用一个文件系统块(通常 4KB)。


六、fsync 的真面目:比你想象的更重量级

6.1 fsync 做了什么?

fsync(fd);  // 这一行背后的故事...
fsync(fd) 的完整执行过程:

1. 刷出该文件所有 dirty Page 到磁盘
   └─ 把 Page Cache 中属于该 fd 的所有脏页写到块设备

2. 刷出文件系统元数据
   └─ inode (大小、时间、块指针)
   └─ 间接块 / extent tree

3. 提交文件系统日志事务 (ext4 jbd2)
   └─ 写 journal descriptor block
   └─ 写 journal commit block
   └─ (这些也要写到磁盘)

4. 发送 FLUSH / FUA 命令到磁盘控制器
   └─ 确保数据从磁盘控制器的 DRAM 缓存刷到 NAND/碟片
   └─ NVMe: 发送 Flush 命令
   └─ SATA: 发送 FLUSH CACHE (EXT) 命令

5. 等待磁盘确认完成
   └─ 所有写入都持久化后,fsync 才返回

→ 只有 fsync 返回后,数据才真正"安全"了
→ 这就是为什么 fsync 很慢(通常 50μs~10ms)

6.2 write 返回 ≠ 数据安全

这就是为什么 WAL (Write-Ahead Log) 必须 fsync:
  1. write() 写入 journal → 数据在内存中
  2. fsync() → 数据落盘,此时才向客户端返回 "写入成功"
  3. 如果只 write 不 fsync,断电后 journal 不完整,数据丢失

6.3 fdatasync vs fsync

fsync(fd);      // 刷数据 + 刷元数据 (包括文件大小、修改时间等)
fdatasync(fd);  // 刷数据 + 只刷必要的元数据 (文件大小变了才刷 inode)

fdatasync 在文件大小没变的情况下(比如追加写后又追加写,但中间 prealloc 过)可以少一次 inode 写入,快一点。


七、NVMe SSD 内部:FTL、GC 与写放大

7.1 SSD 的内部架构

┌─────────────────────────────────────────────────────┐
│                    NVMe SSD                          │
│                                                     │
│  ┌─────────────────────────────────────────────┐    │
│  │           NVMe 控制器                        │    │
│  │  ┌──────────┐  ┌──────────┐  ┌───────────┐  │    │
│  │  │ 主机接口  │  │ FTL 固件  │  │ DRAM 缓存 │  │    │
│  │  │ (PCIe)   │  │(核心大脑) │  │ (映射表)  │  │    │
│  │  └──────────┘  └──────────┘  └───────────┘  │    │
│  └──────────────────┬──────────────────────────┘    │
│                     │                               │
│  ┌──────────────────▼──────────────────────────┐    │
│  │              NAND Flash 阵列                  │    │
│  │                                              │    │
│  │  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐           │    │
│  │  │Die 0│ │Die 1│ │Die 2│ │Die 3│  ...       │    │
│  │  │     │ │     │ │     │ │     │            │    │
│  │  │Block│ │Block│ │Block│ │Block│            │    │
│  │  │ Page│ │ Page│ │ Page│ │ Page│            │    │
│  │  └─────┘ └─────┘ └─────┘ └─────┘           │    │
│  └─────────────────────────────────────────────┘    │
│                                                     │
│  可选: 电容 (Power Loss Protection, 断电保护)        │
└─────────────────────────────────────────────────────┘

7.2 NAND Flash 的三个不对称操作

这是 SSD 所有"诡异行为"的根源:

关键约束:
  NAND 的 Page 不能"覆盖写"!
  要写一个已有数据的 Page,必须先把整个 Block 擦除,
  然后重新写入。

  这就像:
  - 纸上写字 (写) 很快
  - 看字 (读) 很快
  - 但修改一个字,要把整页纸揉掉 (擦),换一张新纸重新写

7.3 FTL(Flash Translation Layer)

FTL 是 SSD 控制器里的固件,负责假装自己是一块可以随机覆盖写的磁盘

主机看到的:                         SSD 内部真实情况:
┌──────────────────┐              ┌──────────────────┐
│ LBA 0: [数据A]   │  FTL 映射    │ Die0-Blk3-Page5: [数据A]  │
│ LBA 1: [数据B]   │ ──────────→ │ Die1-Blk7-Page2: [数据B]  │
│ LBA 2: [数据C]   │              │ Die0-Blk1-Page9: [数据C]  │
│ ...              │              │ ...                       │
└──────────────────┘              └──────────────────────────┘

当主机"覆盖写" LBA 0:
  1. FTL 不会去擦旧的 Page
  2. 而是写到一个新的空白 Page
  3. 更新映射表: LBA 0 → 新位置
  4. 旧的 Page 标记为 "invalid"(垃圾)

7.4 GC(Garbage Collection)与写放大

当空白 Page 快用完时,SSD 必须做垃圾回收:

GC 过程:

  Block X (有垃圾):                      Block Y (空白):
  ┌───────────┐                         ┌───────────┐
  │ Page 0: ✓ │ (有效数据)   ──copy──→  │ Page 0: ✓ │
  │ Page 1: ✗ │ (垃圾)                  │ Page 1: ✓ │
  │ Page 2: ✓ │ (有效数据)   ──copy──→  │           │
  │ Page 3: ✗ │ (垃圾)                  │           │
  │ Page 4: ✗ │ (垃圾)                  │           │
  │ Page 5: ✓ │ (有效数据)   ──copy──→  │           │
  └───────────┘                         └───────────┘
       ↓
    擦除 Block X → 变成空白 Block → 可以重新使用

GC 的代价:
  - 要读出有效数据 (读放大)
  - 要写到新 Block (写放大)
  - 要擦除旧 Block (磨损)
  - 在 GC 期间,正常 I/O 可能被阻塞 → 延迟毛刺!

SSD 写放大公式:

SSD Write Amplification Factor (WAF) = 实际 NAND 写入量 / 主机写入量

理想情况: WAF = 1 (写多少就写多少)
实际情况: WAF = 1.1 ~ 3+  (取决于写入模式和 SSD 使用率)

频繁小随机写 → 垃圾多 → GC 频繁 → WAF 高 → SSD 寿命缩短
大块顺序写   → 垃圾少 → GC 少   → WAF 低 → SSD 长寿

八、多进程共享磁盘:隔离与干扰

8.1 数据层面:完全隔离

两个进程在同一块磁盘上写不同文件,数据绝对不会互相污染

隔离机制:

1. 文件系统块分配隔离
   └─ 不同文件的物理块永远不重叠

2. Page Cache 按 inode 隔离  
   └─ (inode_A, offset) 和 (inode_B, offset) 是不同的页

3. VFS 层的 inode 锁
   └─ 同一文件的并发写由内核串行化
   └─ 不同文件之间完全并行

结论: 进程 A 的对齐策略 ≠ 影响进程 B 的数据完整性
      一个进程不对齐,不会让另一个进程的数据出错

8.2 性能层面:会间接影响

虽然数据隔离,但它们共享物理资源

共享资源:
┌──────────────────────────────────────────────────────┐
│                                                      │
│  1. I/O 调度器队列      ← 带宽争用                     │
│  2. 磁盘控制器          ← 命令队列深度有限               │
│  3. Page Cache 内存     ← 互相挤占                     │
│  4. 文件系统日志 (jbd2)  ← 串行化提交                   │
│  5. SSD 内部 FTL/GC    ← 写放大 + GC stall             │
│  6. HDD 磁头           ← 寻道抖动                      │
│                                                      │
└──────────────────────────────────────────────────────┘

各种干扰的严重程度排名:

干扰类型

HDD 严重程度

SSD 严重程度

说明

磁头寻道争用

★★★★★

N/A

HDD 上两个进程写不同位置 = 随机 I/O

SSD GC stall

N/A

★★★★☆

一个进程碎片写导致 GC,影响另一个进程的延迟

I/O 带宽争用

★★★☆☆

★★★☆☆

共享有限带宽

Page Cache 争用

★★★☆☆

★★★☆☆

一方大量写入挤占另一方缓存

文件系统日志争用

★★☆☆☆

★★☆☆☆

频繁 fsync 串行化 jbd2 事务

8.3 HDD 上的灾难场景

HDD 磁盘:

  进程 A 的数据 (外圈)          进程 B 的数据 (内圈)
  ████████                     ████████

  磁头: "我要去外圈写 A... 又要去内圈写 B... 又要回外圈..."

       ←── seek 5~10ms ──→←── seek 5~10ms ──→

  顺序写吞吐: ~150MB/s
  两进程交替写: ~1~5MB/s (暴跌 30~150 倍!)

  原因: 每次 seek 浪费 5~10ms,而传输 4KB 只要 ~0.03ms
        99.7% 的时间在 seek,0.3% 的时间在传数据

8.4 SSD 上的隐蔽杀手:GC Stall

时间线:

t=0s   进程 A: 正常写入,延迟 50μs ✓
       进程 B: 频繁小写+fsync,产生大量碎片

t=30s  SSD 内部: 空闲 Block 减少...
       进程 A: 延迟 50μs ✓ (还没感觉)

t=60s  SSD 内部: 触发 GC!要搬移数据 + 擦除 Block
       进程 A: 延迟突然飙到 5ms~50ms !!!  ← GC stall
       进程 A: "我什么都没改,怎么突然变慢了??"

t=61s  SSD 内部: GC 完成
       进程 A: 延迟恢复 50μs ✓

这种间歇性毛刺在监控上表现为 P99/P999 延迟飙升

九、Torn Write(撕裂写):断电时的数据安全

9.1 什么是 Torn Write?

你要写 8KB 数据 (跨越 2 个扇区):

正常完成:
  ┌─────────────┬─────────────┐
  │  扇区 1 ✓   │  扇区 2 ✓   │  两个扇区都写完 → 数据一致
  └─────────────┴─────────────┘

写到一半断电 (Torn Write):
  ┌─────────────┬─────────────┐
  │  扇区 1 ✓   │  扇区 2 ✗   │  扇区 1 是新数据,扇区 2 是旧数据
  └─────────────┴─────────────┘
  → 数据不一致!半新半旧!

9.2 磁盘的原子写保证

HDD:  原子写单位 = 512 字节 (1 个扇区)
      → 一个扇区要么全写完,要么全没写
      → 跨扇区的写入没有原子性保证

SSD:  原子写单位 = 取决于厂家,通常 4KB (1 个 NAND Page)
      → 一个 4KB Page 要么全写完,要么全没写
      → 有些企业级 SSD 支持 16KB 原子写

NVMe 规范:
      → AWUN (Atomic Write Unit Normal): 保证原子写的最小单元
      → AWUPF (Atomic Write Unit Power Fail): 断电时的原子写单元
      → 可通过 nvme id-ns 查看

9.3 对齐与 Torn Write 的关系

场景: 写 1KB 数据,磁盘原子写单位 = 512B

不对齐的写入:
  ┌──────┬──────┬──────┐
  │Sect 0│Sect 1│Sect 2│
  │  ... │▓▓▓▓▓▓▓▓▓▓▓▓│← 1KB 数据跨越 Sect 1 和 Sect 2
  └──────┴──────┴──────┘
  断电时: Sect 1 写完了但 Sect 2 没写完 → 数据损坏!

对齐的写入 (对齐到 1024B):
  ┌──────┬──────┬──────┬──────┐
  │Sect 0│Sect 1│Sect 2│Sect 3│
  │      │▓▓▓▓▓▓▓▓▓▓▓▓│      │← 1KB 数据完整落在 Sect 1+2
  └──────┴──────┴──────┴──────┘
  这里仍然跨 2 个扇区,仍有 torn write 风险

对齐到 4KB + 数据 < 4KB:
  ┌──────────────────────────┐
  │          4KB Block        │
  │  ▓▓▓▓▓▓▓▓ + padding      │← 数据 + padding 在一个原子写单元内
  └──────────────────────────┘
  如果磁盘保证 4KB 原子写 → 完全安全!

这就是为什么 BookKeeper Journal 的 journalAlignmentSize 设为 512——它确保每次 flush 的数据都对齐到扇区边界,配合 Journal 的 replay 机制保证恢复正确性。


十、综合实战:BookKeeper 的 I/O 设计哲学

把以上所有知识串起来,看看 BookKeeper 是怎么应用的:

10.1 Journal(预写日志)

I/O 方式:     Buffered I/O + fsync (Group Commit)
对齐策略:     journalAlignmentSize=512 (V5 格式, 扇区对齐)
目的:         保证断电后可以正确恢复
为什么不用 DIO: Journal 写入量小但 fsync 频繁,
              Buffered I/O 的 Page Cache 可以合并写入,效率更高

关键优化:
  - Group Commit: 攒一批 entry 再 fsync,减少 fsync 次数
  - Pre-allocation: 预分配文件空间,减少文件系统元数据更新
  - journalRemoveFromPageCache: fsync 后用 POSIX_FADV_DONTNEED
    提示内核释放 Page Cache (因为 journal 写完就不再读了)

10.2 EntryLogger(数据存储)

默认实现 (DefaultEntryLogger):
  I/O 方式:     Buffered I/O
  问题:         数据在 Page Cache 和 BookKeeper 的 Cache 各一份
               → Double Caching,浪费内存

Direct I/O 实现 (DirectEntryLogger):
  I/O 方式:     O_DIRECT + O_DSYNC
  对齐策略:     Buffer.ALIGNMENT = 4096 (4KB 页对齐)
  优势:
    1. 消除 Double Caching → 内存利用率翻倍
    2. 避免 Page Cache 争用 → 把 Page Cache 留给 Journal
    3. 可预测延迟 → 没有内核 writeback 的突然刷盘
    4. 减少 CPU 开销 → 少了一次内存拷贝
  前提:
    - 只支持 Linux
    - 只支持 DbLedgerStorage
    - 需要 JNI (native-io)

10.3 最佳磁盘部署方案

推荐部署:

┌─────────────────────┐     ┌─────────────────────┐
│   NVMe SSD 
#1       │     │   NVMe SSD #2       │
│                     │     │                     │
│   Journal 专用       │     │   EntryLog 专用      │
│   (Buffered I/O)    │     │   (Direct I/O)      │
│                     │     │                     │
│   需求: 低延迟 fsync │     │   需求: 高吞吐顺序写  │
│   大小: 不需要很大    │     │   大小: 尽可能大      │
└─────────────────────┘     └─────────────────────┘

为什么要分开?
  → 避免 Journal 的频繁 fsync 和 EntryLog 的大块写入互相争带宽
  → 避免 EntryLog 的 I/O 导致 SSD GC,影响 Journal 的延迟
  → Journal 盘可以选延迟更低的 Optane SSD
  → EntryLog 盘选容量大的 TLC/QLC SSD

十一、诊断命令速查表

# ═══════════ 磁盘信息 ═══════════# 查看磁盘拓扑 (扇区大小、调度器等)lsblk -t# 查看逻辑/物理扇区大小cat /sys/block/nvme0n1/queue/logical_block_size     # 通常 512cat /sys/block/nvme0n1/queue/physical_block_size    # 通常 4096# NVMe 详细信息 (原子写单元等)sudo nvme id-ns /dev/nvme0n1 -n 1# 文件系统块大小stat -f /data | grep "Block size"sudo tune2fs -l /dev/nvme0n1p1 | grep "Block size"  # ext4sudo xfs_info /dev/nvme0n1p1                         # xfs# ═══════════ I/O 监控 ═══════════# 实时磁盘 I/O 统计iostat -dxz 1# 查看 I/O 调度器cat /sys/block/nvme0n1/queue/scheduler# 查看 Page Cache 使用free -h                          # Buff/Cache 列cat /proc/meminfo | grep -E "Cached|Dirty|Writeback"# ═══════════ 高级追踪 ═══════════# 追踪块设备层真实 I/O (需要 bcc-tools)sudo biosnoop -d nvme0n1         # 每笔 I/O 的大小、延迟sudo biolatency -d nvme0n1       # I/O 延迟分布直方图# 追踪文件级 I/Osudo opensnoop                   # 谁在打开什么文件sudo filetop                     # 哪些文件 I/O 最多# 追踪 fsync 调用sudo strace -e fsync,fdatasync -p <pid>

十二、一句话总结

Buffered I/O 是"内核替你管缓存",Direct I/O 是"我要自己管缓存";对齐是 DIO 的入场券,不对齐连门都进不去;fsync 是确保数据落盘的唯一方式,但它比你以为的要重得多;同一块盘上多个进程数据不会互相污染,但 I/O 性能一定会互相干扰——分盘部署是生产环境的黄金法则。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-03-27 11:43:06 HTTP/2.0 GET : https://f.mffb.com.cn/a/481511.html
  2. 运行时间 : 0.192730s [ 吞吐率:5.19req/s ] 内存消耗:4,725.27kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=9f852a1763989f8588a7bfaef2938b78
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.001006s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001407s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000703s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000617s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001561s ]
  6. SELECT * FROM `set` [ RunTime:0.000633s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001663s ]
  8. SELECT * FROM `article` WHERE `id` = 481511 LIMIT 1 [ RunTime:0.001230s ]
  9. UPDATE `article` SET `lasttime` = 1774582987 WHERE `id` = 481511 [ RunTime:0.020987s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.002474s ]
  11. SELECT * FROM `article` WHERE `id` < 481511 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001012s ]
  12. SELECT * FROM `article` WHERE `id` > 481511 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001072s ]
  13. SELECT * FROM `article` WHERE `id` < 481511 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002415s ]
  14. SELECT * FROM `article` WHERE `id` < 481511 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001946s ]
  15. SELECT * FROM `article` WHERE `id` < 481511 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001361s ]
0.196181s