StartMVC开发手册

可以快速上手的开发文档

手册目录

数据缓存

数据缓存

cache() 用于把链式查询的结果缓存到文件,下次相同查询直接读缓存,不再打库。

基本用法

// 使用默认缓存时间(取 config/database.php 的 cachetime,默认 3600 秒)
$result = Db::table('users')
 ->where('status', 1)
 ->cache()
 ->get();

// 指定缓存时间 300 秒
$result = Db::table('articles')
 ->where('published', 1)
 ->cache(300)
 ->get();

// 长期缓存 24 小时
$result = Db::table('categories')
 ->orderBy('sort', 'ASC')
 ->cache(86400)
 ->get();

cache($timeout) 只有一个参数:缓存时间(秒);不传时取数据库配置里的 cachetime。缓存目录与默认时长都在 config/database.php 里改:

'cachetime' => 3600, // 缓存时间(秒)
'cachedir' => ROOT_PATH . 'runtime' . DS . 'db' . DS, // 缓存目录(可选)

参数与生效范围

  • cache(0) 的过期时间就是当前秒,等于不缓存——不要用它表示“永久缓存”,要长期缓存就写足够大的秒数。
  • 缓存只作用于返回结果集的查询(select、show、describe、explain 等)。
  • 以类名指定 PDO::FETCH_CLASS 的查询不走缓存,避免把数组还原成对象时出偏差。
  • 缓存目录需可写,不存在时框架会自动创建。

写库后自动失效

不需要等缓存到期,也不需要手工删缓存文件。启用查询缓存后,缓存目录里会生成一个代际文件 db.epoch;每次写库都会更新它,而缓存文件名里带着代际号,旧文件因此整体失联,下次读取会自动重建:

  • insert()、insertGetId()、update()、delete()、inc()、dec()、invert() / toggle()、touch()
  • truncate()、drop()
  • 原生 SQL 写入:Db::query('UPDATE ...')->exec()

代价是每次写库多一次极小的文件写。完全没有使用查询缓存的站点不产生任何额外开销——写库路径只做一次文件存在性探测。

缓存键与多库隔离

缓存键由「连接标识 + 完整 SQL + 绑定参数」组成,连接标识包含驱动、主机、端口、库名与表前缀。因此:

  • 同一条 SQL 换了绑定参数,不会命中原先的缓存;
  • 多个数据库共用一个 cachedir 也不会串味——A 库的结果不会被 B 库读到。

过期与清理

过期条目在下次读到同一个键时被删除。目录里遗留的过期文件、旧代际文件和写入中断留下的 .tmp 会被自动回收(低概率触发,不影响请求结果)。需要立刻清空时,可以显式调用:

use startmvc\core\db\DbCache;

$dir = ROOT_PATH . 'runtime' . DS . 'db' . DS;
$removed = (new DbCache($dir))->collectGarbage(true); // 返回回收的文件数

直接删除 cachedir 下的所有文件也可以,代价是丢掉全部查询缓存(后续访问会按需重建)。

注意事项

  • 结果以 JSON 写入文件;非法 UTF-8(例如 GBK 字符串)的结果不会写入缓存,也不会留下坏文件。
  • 空结果集([])与单行查询无记录(false)同样会被缓存,避免空结果反复打库。
  • 缓存不区分事务状态:不要在事务未提交时缓存“中间态”的查询结果,回滚后它会留在缓存里直到过期。
  • config/cache.php 的 autoFlushTag 是「Cache 标签缓存」的配置,与这里的查询缓存无关。