Skip to main content

Module schema_cache

Module schema_cache 

Source
Expand description

Schema 缓存模块 — 数据表字段元数据缓存(对齐 PHP think\db\Fetch::getFields

本模块提供数据表字段元数据(schema)的缓存能力,对齐 PHP ThinkPHP think\db\Fetch 的字段缓存机制。在 PHP 端,每次查询表字段信息都需要 执行 SHOW COLUMNS FROM <table>(MySQL)或等价 SQL,为避免重复查询, ThinkPHP 将字段元数据缓存到 Cache 中(默认永不过期)。

§PHP 对齐

§核心 API 映射

PHP 方法Rust 方法说明
Fetch::getFields($table)SchemaCache::get_schema从缓存读取字段元数据
Fetch::setFieldCache($table, $data)SchemaCache::set_schema写入字段缓存
Fetch::getFieldCacheKey($table)SchemaCache::cache_key构造缓存 key
Cache::delete($key)SchemaCache::forget_schema清除单表字段缓存
Cache::clear()SchemaCache::clear清除所有字段缓存
Cache::has($key)SchemaCache::has_schema判断字段缓存是否存在
Fetch::getFields 内部回源SchemaCache::remember_schema缓存未命中时回源加载

§PHP getFields 缓存行为

PHP think\db\Fetch::getFields 核心逻辑:

protected function getFields(string $tableName): array
{
    // 1. 从缓存读取
    if ($this->config['fields_cache']) {
        $guid = $tableName . $this->connection->getConfig('fields_cache_flag');
        $content = $this->connection->getCacheHandler()->get($guid);
        if ($content) {
            return $content;  // 缓存命中
        }
    }

    // 2. 缓存未命中,查询数据库
    $fields = $this->connection->getFields($tableName);

    // 3. 写入缓存(永不过期)
    if ($this->config['fields_cache']) {
        $guid = $tableName . $this->connection->getConfig('fields_cache_flag');
        $this->connection->getCacheHandler()->set($guid, $fields);
    }

    return $fields;
}

关键行为对齐

  • 默认 TTL = None(永不过期),对齐 PHP $expire = null
  • 缓存 key 格式:schema_cache:<table_name>(PHP 端为 db_<flag>_<table_name>
  • 缓存未命中时通过 loader 回源加载(对齐 PHP getFields 内部查询)

§PHP 字段元数据结构

PHP getFields 返回的字段元数据结构:

[
    'id' => [
        'name'      => 'id',
        'type'      => 'int(11) unsigned',
        'notnull'   => true,
        'default'   => null,
        'primary'   => true,
        'autoinc'   => true,
    ],
    'name' => [
        'name'      => 'name',
        'type'      => 'varchar(255)',
        'notnull'   => false,
        'default'   => null,
        'primary'   => false,
        'autoinc'   => false,
    ],
]

Rust 端通过 ColumnDefinition 提供等价结构,并扩展 unsignedcomment 字段。

§架构说明

  • 基于 Cache facade:复用 crate::cache::Cache 的驱动管理、序列化、标签系统, 不重新实现底层存储
  • 标签批量清除:所有字段缓存 key 注册到标签(tag),SchemaCache::clear 通过标签一次性清除所有表字段缓存,对齐 PHP Cache::clear() 的批量语义
  • 无锁设计SchemaCache 自身状态在构造后不可变(key_prefixtag_name), 所有并发安全由底层 Cache 保证(RwLock + parking_lot
  • 可配置前缀:通过 SchemaCache::with_prefix 可自定义缓存 key 前缀, 支持多实例隔离(如不同数据库连接使用不同前缀)

§使用示例

use sz_rust_core::cache::{Cache, MemoryCacheDriver};
use sz_rust_core::schema_cache::{SchemaCache, TableSchema, ColumnDefinition};
use std::sync::Arc;

// 创建 Cache facade
let cache = Arc::new(Cache::new());
cache.register_default(MemoryCacheDriver::new());

// 创建 SchemaCache
let schema_cache = SchemaCache::new(cache.clone());

// 构造表字段元数据
let schema = TableSchema::new("users", vec![
    ColumnDefinition::new("id", "int(11) unsigned")
        .nullable(false)
        .primary_key(true)
        .auto_increment(true),
    ColumnDefinition::new("name", "varchar(255)")
        .nullable(false),
]);

// 写入缓存(永不过期)
schema_cache.set_schema("users", &schema, None).unwrap();

// 从缓存读取
let cached = schema_cache.get_schema("users").unwrap().unwrap();
assert_eq!(cached.columns.len(), 2);

// remember_schema:缓存未命中时自动加载
let schema = schema_cache.remember_schema("orders", |_table| {
    Ok(TableSchema::new("orders", vec![
        ColumnDefinition::new("id", "bigint(20)")
            .primary_key(true)
            .auto_increment(true),
    ]))
}).unwrap();

Structs§

ColumnDefinition
单个字段定义(对齐 PHP think\db\Fetch::getFields 返回的单字段元数据)
SchemaCache
数据表字段缓存(对齐 PHP think\db\Fetch 字段缓存机制)
TableSchema
数据表字段元数据(对齐 PHP think\db\Fetch::getFields 返回的完整字段列表)

Enums§

SchemaCacheError
Schema 缓存错误