MoreRSS

site iconAnZhihe | 安志合修改

国学和传统文化爱好者,IT行业从业者,运维和SRE。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

AnZhihe | 安志合的 RSS 预览

大语言模型级别划分及使用场景

2025-11-12 11:45:42

模型参数量的基本概念

我们通常用参数数量来衡量模型的规模。参数是模型在训练过程中学习的变量,这些变量用于根据输入数据做出预测或生成输出。参数数量通常以B(Billion,十亿)为单位。"B"代表"Billion"(十亿),比如常见的大语言模型级别规模:

  • 7B = 70亿参数

  • 32B = 320亿参数

  • 70B = 700亿参数

  • 910B = 9100亿参数

"参数"是什么?

可以把它想象成模型大脑中的 “神经元” 或 “突触连接”是模型通过训练学到的内部知识表示。每个参数都是一个数值,共同构成了模型的"大脑"。

  • 在训练过程中,模型通过海量的文本(或图像)数据学习。

  • 在这个过程中,它会逐步调整和优化其内部数以十亿甚至万亿计的、微小的 “权重” 和 “偏置” ,这些就是参数

  • 每一个参数都负责捕捉数据中某种细微的模式、关联或知识,比如“苹果”和“红色”经常一起出现,或者一个复杂的语法规则。

参数量,直接反映了模型内部结构的复杂程度。模型的大小(参数量)通常与其能力相关:参数量越大,模型通常能够捕捉更复杂的模式,但同时也需要更多的计算资源和内存,并且推理速度可能更慢。


模型级别总览

以下是主流大语言模型的级别划分及其核心特征概览:

1762918070214865.png

各级别模型详解

1. 轻量级模型(7B及以下)

代表模型: Qwen2.5-1.5B/7B, Llama-3-8B, ChatGLM-6B, Gemma-7B

  • 特点

    • 体积小,速度快:可以在CPU或单张消费级GPU(如RTX 4090)上流畅运行,响应延迟极低。

    • 成本极低:非常适合个人开发者、学术研究或大规模部署在边缘设备。

    • 能力聚焦:在通用知识、推理和编程上能力有限,但经过高质量训练或精调后,能在特定任务上表现出色。

  • 典型使用场景

    • 边缘计算与端侧部署:部署在手机、平板、嵌入式设备上,提供本地化的AI助手功能。

    • 高速响应场景:作为智能客服的“第一响应”模块,处理简单、高频的问答。

    • 特定任务工具:通过精调,专门用于文本分类、实体识别、内容过滤、代码补全(小型)等。

    • 研究与教育:学生和研究人员低成本学习模型原理、进行微调实验的理想选择。


2. 主力性能模型(13B - 34B)

代表模型: Qwen2.5-32B, Llama-3-70B(注:虽名为70B,但常被归于此性能级别), Yi-34B

  • 特点

    • 性能与效率的甜蜜点:在保持相对可控的部署成本下,提供了非常强大的通用能力(推理、知识、编程)。

    • 综合能力强:通常在各种公开评测中表现优异,是许多开源应用的“中坚力量”。

    • 需要专业级GPU:通常需要1-2张数据中心级GPU(如A100, H100, H20)进行高效推理。

  • 典型使用场景

    • 企业级私有部署:作为企业内部的通用AI助手,处理文档分析、报告撰写、代码开发等任务。

    • 高质量的聊天机器人:提供流畅、聪明、知识丰富的对话体验。

    • 复杂内容创作:撰写文章、策划方案、编写脚本等。

    • 高级检索增强生成(RAG):能够更好地理解和整合外部知识,给出精准的回答。


3. 高性能模型(~70B)

代表模型: Llama-2/3-70B, Qwen1.5-72B, DeepSeek-67B

  • 特点

    • 逼近顶尖性能:在绝大多数任务上表现出色,非常接近顶级闭源模型(如GPT-3.5)的能力。

    • 资源消耗大:需要多张(通常≥4张)高端GPU进行推理,部署和运维成本高。

    • 强大的推理与思维链:在解决复杂数学问题、逻辑推理和深层代码逻辑时优势明显。

  • 典型使用场景

    • 复杂推理与问题解决:用于高级数学推理、逻辑谜题解答、战略分析。

    • 高质量的代码生成与审查:生成复杂、完整的项目代码,进行深入的代码调试和分析。

    • 作为闭源模型的替代:当企业需要完全的数据控制权,同时又追求顶级模型性能时,会选择此级别模型进行私有化部署。


4. 尖端/前沿模型(百B/千B级)

代表模型: 混元-910B, GPT-4, Claude-3 Opus

  • 特点

    • 追求极致能力:代表了当前大模型技术的最高水平,在需要深度知识和复杂思维链的任务上具有突破性能力。

    • 通才:几乎在所有NLP任务上都有顶级表现,尤其擅长处理模糊、开放性的指令。

    • 极高的成本:训练和推理成本天文数字,通常仅通过API提供服务,或由超大型企业用于内部核心业务。

  • 典型使用场景

    • 前沿科学研究:辅助科学家进行科学发现、文献综述和假设生成。

    • 超高难度内容创作:创作长篇小说、影视剧本、复杂的商业分析报告等。

    • 颠覆性产品应用:作为下一代AI产品的核心大脑,处理前所未有的复杂任务。


场景化选择建议

为了方便选择,这里提供一个直接的指南:

你的身份/需求 推荐级别 理由
个人开发者/学生 轻量级 (7B及以下) 硬件门槛低,学习成本低,足以完成大多数个人项目和学习。
中小企业(追求性价比) 主力性能级 (13B-34B) 能力强大,足以应对大多数企业应用,部署成本相对可控。
大型企业(核心业务) 高性能级 (~70B) 性能卓越,满足核心业务对质量和可靠性的高要求,可私有化部署保障数据安全。
所有企业(通用功能) 尖端模型API 无需管理基础设施,直接获得最强大的能力,按使用量付费,灵活高效。
需要快速响应的场景 轻量级 (7B及以下) 延迟最低,吞吐量高。
处理复杂、开放性问题 尖端模型API 模型具备最强的理解和推理能力。

硬件需求参考表

模型级别 最小GPU配置 内存需求 推理速度 部署成本
7B RTX 4090 (24GB) 16GB ⚡⚡⚡⚡ 💰
32B 2×A100 (80GB) 80GB ⚡⚡⚡ 💰💰
70B 4×H100 (80GB) 160GB ⚡⚡ 💰💰💰
910B GPU集群(32+) 1.8TB+ 💰💰💰💰💰
模型级别 最小GPU配置 内存需求 推理速度 部署成本
7B RTX 4090 (24GB) 16GB ⚡⚡⚡⚡ 💰
32B 2×A100 (80GB) 80GB ⚡⚡⚡ 💰💰
70B 4×H100 (80GB) 160GB ⚡⚡ 💰💰💰
910B GPU集群(32+) 1.8TB+ ⚡ 💰💰💰💰💰


重要提醒:参数量不是唯一标准

虽然参数量很重要,但并不是参数越多,模型就一定越好。模型的最终能力还取决于:

  1. 训练数据的质量与规模:干净、高质量、大规模的数据是训练出优秀模型的基础。

  2. 训练方法和架构:例如,MoE(混合专家)架构可以让模型在拥有庞大参数量的同时,实际计算成本更低(如Mixtral 8x7B模型)。

  3. 对齐优化:通过RLHF(人类反馈强化学习)等技术让模型更符合人类的价值观和使用习惯。

核心思想:没有“最好”的模型,只有“最适合”的模型。择合适的模型级别需要在任务需求、预算限制、技术能力之间找到最佳平衡点。建议从具体场景出发,先试用不同级别的模型,再做出决策。


MySQL迁移至达梦数据库全攻略

2025-11-08 21:57:49

迁移概述

将MySQL数据库迁移至达梦数据库是国产化替代过程中的常见信创改造需求。达梦数据库提供了多种迁移工具和方法,使得迁移过程可以高度自动化。根据数据量和业务复杂度的不同,迁移工作可以在几十分钟到数小时完成。

主要迁移方式对比

迁移方式 适用场景 优点 缺点
SQLark百灵连接 30GB以下数据量,追求效率的场景 图形化操作,几分钟完成,一次成功率90%以上 需下载独立工具
DM数据迁移工具(DTS) 大多数迁移场景,尤其是中小型数据库 官方图形化工具,功能全面,向导式操作 对大表迁移需特殊处理
命令行工具(dmfldr) 超大型数据库,批量数据处理 高性能,适合脚本化自动化迁移 操作复杂,需手动转换格式

迁移流程图

1761118367402-68691337-43b8-4842-b0ff-cc2f518ae879.png

MYSQL移植DM8大致有以下步骤:

1.分析待移植系统,确定移植对象。

2.通过数据迁移工具DTS完成常规数据库对象及数据的迁移。

3.对少数数据库对象进行兼容性改写。

4.移植完成后对移植的结果进行校验,确保移植的完整性和正确性。

5.应用系统进行移植、测试和优化。

详见官方迁移文档:

迁移前准备

1. 环境检查与备份

  • 确认版本信息:记录MySQL数据库版本及实例配置,并安装兼容的达梦数据库(推荐DM8)

  • 检查网络与存储:确保迁移机器能同时访问MySQL和达梦数据库,并有足够存储空间

  • 数据备份:务必对源数据库进行完整备份,防止迁移过程中数据丢失

  • 兼容MySQL配置:

数据库类型版本
参数名 参数值 说明

达梦数据库dm8配置

case_sensitive

N

忽略大小写(需在创建实例时指定)

SELECT CASE_SENSITIVE();

-- 结果为1表示大小写敏感,0表示大小写不敏感

COMPATIBLE_MODE

4

兼容mysql模式(需在创建实例时指定)

ORDER_BY_NULLS_FLAG

2

兼容mysql模式(需在创建实例时指定)

权限

RESOURCE,PUBLIC,SOI,VTI

授予角色

2. 工具准备

  • SQLark:从官网(www.sqlark.com)下载

  • 达梦DTS:达梦数据库安装后自带,可在开始菜单中找到

  • 命令行工具:dmfldr(达梦高速数据加载器)

3. 达梦数据库初始化

  • 初始化数据库时,不勾选"字符串比较大小写",勾选"VARCHAR类型以字符为单位"

  • 创建相应用户和模式并授权(达梦中一个用户对应一个模式,相当于MySQL的数据库)

使用SQLark快速迁移(推荐)

对于追求效率的用户,SQLark是最佳选择,能在几分钟内完成30GB左右数据的迁移。

操作步骤:

  1. 创建迁移任务:在SQLark中点击"数据迁移",选择"仅数据迁移"

  2. 连接数据库:从客户端导入或新建MySQL(源库)和达梦(目标库)连接

  3. 选择迁移范围:支持全量迁移或指定范围迁移,对大表可单独设置只迁结构不迁数据

  4. 环境检查:工具自动检查目标库磁盘空间和参数,按提示解决不通过项

  5. 自动化迁移:工具全自动执行迁移,可实时查看进度

  6. 迁移校验:完成后查看对象数量和表行数是否一致

使用达梦DTS迁移

达梦自带的DTS工具更适合大多数常规迁移场景。

详细步骤:

  1. 打开迁移工具

  • 通过"开始"菜单 → "达梦数据库" → "DM数据迁移工具"

  • 创建迁移工程

    • 右键"迁移管理" → "新建工程",输入工程名称

    • 在工程下右键"新建迁移",自定义迁移名称

  • 配置数据源

    • MySQL源库:选择"MySQL ==> DM"迁移类型

      • 主机名、端口(默认3306)、用户名、密码

      • 指定MySQL驱动包(除DM自带包外需手动提供)

      • 选择要迁移的具体数据库

    • 达梦目标库

      • 主机名、端口(默认5236)、用户名(默认SYSDBA)、密码(默认SYSDBA)

      • 目的模式选择对应的达梦数据库

  • 选择迁移对象

    • 点击"选择"勾选需要迁移的表,支持全选

    • 高级选项中可设置字符集转换(通常UTF8→UTF-8或GB18030)

  • 审阅并执行迁移

    • 确认配置信息无误后点击"完成"开始迁移

    • 监控迁移进度,处理出现的错误

    迁移出错处理

    常见的如字段长度不足错误,可在达梦中修改字段长度后,选择"重新迁移出错的对象"。

    迁移后校验与适配

    1. 数据一致性检查

    • 记录计数比对:在MySQL和达梦中执行SELECT COUNT(*) FROM table_name

    • 抽样数据比对:对关键表抽样查询,对比两边结果是否一致

    2. 应用程序适配修改

    这是迁移成功的关键环节,需要处理以下差异:

    数据库连接配置

    # 原MySQL配置
    spring.datasource.url=jdbc:mysql://localhost:3306/db
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    
    # 达梦配置
    spring.datasource.url=jdbc:dm://localhost:5236/DB?compatible_mode=mysql&clobAsString=true:cite[2]
    spring.datasource.driver-class-name=dm.jdbc.driver.DmDriver:cite[9]

    常见SQL语法差异及解决方案

    MySQL语法 达梦兼容方案 备注
    str_to_date() 使用 date_format() 代替 to_date() 同理
    format() 使用 to_char() 代替 注意格式字符串差异
    group_concat() 使用 wm_concat() 代替
    反引号` 完全去除反引号 达梦不支持此符号
    limit m, n 使用 rownum 或 top
    `column` 使用 "column" 或直接去掉 达梦使用双引号

    达梦数据库参数调整

    在达梦数据库中执行以下SQL,并重启数据库:

    sp_set_para_value(1,'ENABLE_BLOB_CMP_FLAG',1);
    sp_set_para_value(2,'COMPATIBLE_MODE',4);:cite[2]

    COMPATIBLE_MODE=4 表示部分兼容MySQL模式,可解决很多语法兼容性问题

    分页插件配置

    Springboot Pagehelper需指定方言:

    pagehelper:
      helperDialect: oracle:cite[2]
      reasonable: true
      supportMethodsArguments: true
      params: count=countSql

    常见问题与解决方案

    1. 自增列赋值报错

    • 问题:"无法给自增列赋值"

    • 解决:达梦无法直接对自增列赋值,需改为序列值或设置IDENTITY_INSERT为ON

  • GroupBy语法不兼容

    • 问题:"不是GROUP BY表达式"

    • 解决:设置COMPATIBLE_MODE=4并重启数据库

  • 中文乱码问题

    • 解决:确保达梦数据库使用GB18030或UTF-8字符集,在迁移工具中正确设置字符集转换

  • 日期函数不支持

    • 解决:达梦不支持CURRENT_TIMESTAMP作为默认值,迁移后需执行:ALTER TABLE table_name MODIFY column_name DEFAULT sysdate

  • 大表迁移超时

    • 解决:分批迁移数据,使用dmfldr工具直接导入,对大表先禁用索引和约束

  • 索引已存在报错

    1. 解决:达梦schema内不允许索引名重复,如果之前的建表语句中,同一个表对相同的列建了多个索引,则会出现索引已存在报错,删除其中一个索引即可

  • 字符超出长度报错

    1. 解决:达梦默认以字节为长度,实际长度定义并无问题,修改建表语句长度为原先3倍左右即可

    2. 参考:达梦数据库初始化实例参数说明

  • 关键词冲突

    1. 解决:加双引号

    2. 参考:https://eco.dameng.com/community/question/ca8b66b801647c1368485b4a1a1062fd

    3. 不支持的函数/关键词:

      序号

      mysql

      dm

      1

      group_concat

      wm_concat

      2

      date_sub

      INTERVAL必须加单引号

      3

      substring_index

      substr

      4 ignore
      不支持

      5

      is not true  

      不支持

      6

      use index

      不支持

      7

      zerofill

      不支持

      8

      after

      不支持

    参考:

    性能优化建议

    • 迁移前:在达梦数据库中适当增大BUFFER参数

    • 迁移中:对大表禁用索引和约束,迁移后重建

    • 迁移后:执行统计信息收集:CALL SP_TAB_STAT_INIT('SYSDBA', 'TABLE_NAME');

    通过以上系统化的迁移方案,可以顺利完成MySQL到达梦数据库的迁移工作。根据数据量和业务需求选择合适的迁移工具,并特别注意应用程序的适配修改,这样才能确保迁移后系统的稳定运行。


    MySQL迁移达梦数据库方案示例

    1. 需求背景

    xxxx测试环境,需要将已部署产品数据库从mysql迁移至达梦(dm8)数据库,适配信创改造。

    2. 迁移产品及数据库列表

    产品集

    产品中文名

    产品码

    xxxx目前版本

    内部适配达梦版本

    数据库Schema

    迁移进展

    备注

    底座

    xx容器云平台 

    CHEGVA

    2.4.2

    无需数据库




    CNDNS

    CNDNS

    1.19

    1.20

    chegva











    mysql数据库地址及schema

    数据库地址

    数据库Schema

    实例规格

    产品说明

    10.96.110.112

    chegva

    8C16G

    云平台

    cndns





    应用系统情况分析

    序号

    产品类型

    产品型号

    1

    应用后台操作系统

    Red Hat Linux

    2

    数据库后台操作系统

    Red Hat Linux

    3

    后台数据库

    MySQL5.7

    4

    应用开发平台

    JAVA

    5

    应用开发接口

    JDBC

    6

    需要移植的数据库对象

    表(数据量)、分区表视图

    自定义类型触发器、存储过程、函数和其他

    3. 迁移方案

    3.1. 迁移前准备

    • 确认版本信息:记录MySQL数据库版本配置,并使用兼容的达梦数据库(推荐DM8)

    • 检查网络与存储:确保迁移机器能同时访问MySQL和达梦数据库,并有足够存储空间

    3.2. 备份数据

    备份待迁移mysql数据库、备份产品相关配置(如需要)

    # 备份chegva数据库
    mysqldump -h xxx -u root -p'***' --skip-triggers --skip-lock-tables --complete-insert --skip-extended-insert chegva > ./chegva-2025xxxx.sql

    3.3. 迁移数据库至达梦

    准备迁移工具:

    • 数据迁移工具 DTS:提供了异构数据源之间的评估,迁移和对比功能。DM 数据迁移工具采用向导方式引导用户通过简单的图形化进行兼容性评估操作。

    • SQLark 百灵连接:支持对 ORACLE、MySQL、PostgreSQL 等主流数据库迁移到达梦数据库进行在线采集评估和自动转化,一键生成源数据库画像,获取源库对象、不兼容对象、大表、大字段表等迁移重难点情况,评估本次迁移需要投入的工作量。SQLark 会根据源库画像,生成合理的迁移策略,为开发者后续进行的自动/手动迁移提供迁移方案参考。

    SQLark提供15天免费试用,如未购买,请勿提前安装,以免试用过期

    迁移工具使用:

    3.4. 应用发布

    修改产品数据库配置信息,重新部署产品:

    • 修改发布平台应用数据库连接参数为达梦连接配置,关联schema更改为达梦数据库

    • 修改应用k8s集群中deploy、sts、cm、secret中mysql数据库连接配置为达梦数据库

    • 修改应用程序配置文件、连接字符串为达梦数据库配置

    3.5. 验证产品功能

    • 白屏:应用控制台页面各组件标签显示正常

    • 黑屏:应用error.log没有持续打印报错

    • 产品发布自动化测试通过

    • 测试平台平台各个组件测试用例能执行成功

    • 应用链路验证成功

    3.6. 回滚方案

    切换应用达梦数据库连接配置为mysql连接配置,重新发布应用并验证产品功能

    4. 迁移步骤

    产品集迁移顺序:PASS平台(底座) → 中间件 → 应用核心组件 → 应用扩展组件 → 监控系统

    4.1. 底座迁移

    4.2. 中间件迁移

    4.3. xx核心组件迁移

    4.4. xx扩展组件迁移

    4.5. 监控系统迁移

    5. 问题纪录


    达梦数据库角色与权限最佳实践

    2025-10-27 09:09:04

    达梦数据库作为国产数据库的领军产品,其安全机制和权限管理体系达到了B1级安全标准,采用"三权分立"或"四权分立"的安全模型,通过精细化的权限划分和严格的访问控制,将系统权限分散,避免权力过度集中,确保数据库系统的安全性和合规性。

    “三权分立”安全机制

    达梦数据库采用了一种重要的安全设计——“三权分立”(安全版本还有“四权分立”),将数据库管理权限划分为系统管理员、安全管理员和审计管理员三个相互独立又相互制约的角色。这种设计符合国家信息安全等级保护要求,特别适用于政府、金融等对数据安全要求严格的场景。

    • SYSDBA (数据库管理员):负责数据库的创建、备份、还原、性能优化等日常运维工作

    • SYSSSO (数据库安全员):负责制定安全策略、管理用户和权限(在非三权分立模式下SYSDBA也负责)、进行强制访问控制等

    • SYSAUDITOR (数据库审计员):负责设置审计规则、查看和分析审计记录,监督所有操作

    “四权分立“扩展

    在安全版DM8中,可扩展为四权分立,新增数据库对象操作员(SYSDBO)角色,进一步分离对象管理权限 。四权分立下各角色权限变化:

    • SYSDBA 权限缩减:仅保留数据库创建、备份、还原等核心管理权限,去除数据操作权限。

    • SYSSSO 新增:负责数据库对象(表、视图等)的创建与管理,但无数据库维护权限。

    • SYSSSO与SYSAUDITOR :权限范围与三权分立保持一致。

    image.png

    角色与权限管理体系

    角色(Role)是将具有相同权限的用户组织在一起的权限集合。达梦通过角色实现权限的批量管理和分配,主要优势包括:

    • SYSDBA 权限聚合:将多个权限打包为一个角色。

    • 用户分组:相同职能的用户分配相同角色。

    • 动态生效:角色可临时启用/禁用。

    这很像给用户分配不同的“职务”和“工作证”。下面这个表格汇总了核心的内置角色,可以快速了解其权限分工。

    角色名 核心权限/定位 主要应用场景与说明
    DBA 系统管理员角色,拥有除审计和强制访问控制之外的几乎所有权限 数据库的超级管理员,负责全面的管理和维护工作
    RESOURCE 拥有 CREATE TABLECREATE VIEW 等创建数据库对象的权限 适用于开发人员或需要创建数据库对象的普通用户
    PUBLIC 所有用户自动拥有的公共角色,其具体权限取决于管理员授予了PUBLIC角色哪些权限 谨慎授权,因为对其授予的权限会对所有用户生效
    SOI 具有查询系统表(SYS开头的表)的权限 用于需要查询数据字典等系统底层信息的场景。
    VTI 具有查询动态视图(V$开头的视图)的权限 用于数据库性能监控和运行状态诊断。
    SYSAUDITOR 系统审计员角色,负责审计相关功能 在"三权分立"或"四权分立"的安全机制下,负责审计工作
    SYSSSO 系统安全员角色,负责制定安全策略、进行强制访问控制等 在安全版本中存在,负责系统安全。

    详见达梦数据库预设角色权限列表:

    达梦数据库采用 权限 - 角色 - 用户 三级授权模型,权限验证流程如下:

    权限检查顺序:

    1. 直接授予用户的权限

    2. 用户所属角色的权限(需角色处于启用状态)

    3. PUBLIC角色的公共权限

    权限冲突解决:

    • 显式拒绝优先于允许

    • 更细粒度的权限设置优先

    角色与权限管理实战

    了解角色后,关键在于如何将它们赋予用户。这主要通过 GRANT 和 REVOKE 语句实现。

    授予角色与权限

    • 将角色授予用户

    GRANT RESOURCE TO user_developer;

    如果需要该用户能将此角色转授他人,可以加上 WITH ADMIN OPTION

    GRANT RESOURCE TO user_developer WITH ADMIN OPTION;
    • 直接授予系统权限

    如果角色权限不完全匹配需求,可以直接授予精确的系统权限。

    GRANT CREATE TABLE, CREATE VIEW TO user_developer;
    • 授予对象权限

    对于某个特定表(例如 dmhr.employee)的增删改查权限,需要单独授予。

    GRANT SELECT, INSERT, UPDATE, DELETE ON dmhr.employee TO user_developer;

    同样,可以使用 WITH GRANT OPTION 允许该用户转授此对象权限

    回收权限

    当需要撤销权限时,使用 REVOKE 语句。

    • 回收角色

    REVOKE RESOURCE FROM user_developer;
    • 回收系统权限

    REVOKE CREATE VIEW FROM user_developer;
    • 回收对象权限

    回收对象权限时,如果当初授权时使用了 WITH GRANT OPTION,回收时通常需要加上 CASCADE 关键字进行级联回收

    REVOKE SELECT ON dmhr.employee FROM user_developer CASCADE;

    角色管理示例

    1、角色创建与授权

    -- 创建语法:
    CREATE ROLE role_name [WITH IDENTIFIED BY password];
    
    -- 授权示例:
    
    -- 创建角色
    CREATE ROLE finance_role;
    
    -- 为角色授权
    GRANT SELECT ON finance.accounts TO finance_role;
    GRANT INSERT, UPDATE ON finance.transactions TO finance_role;
    GRANT CREATE VIEW TO finance_role;
    
    -- 将角色授予用户
    GRANT finance_role TO fin_user1, fin_user2;

    2、角色启动与禁用

    达梦支持动态启用/禁用角色,实现权限的临时调整:

    -- 禁用角色(即时生效)
    SP_SET_ROLE('finance_role', 0);
    
    -- 启用角色
    SP_SET_ROLE('finance_role', 1);
    
    -- 验证角色状态
    SELECT * FROM SESSION_ROLES;

    3、角色与权限冲突解决

    当用户权限来源多样时,达梦按以下规则处理冲突:

    • 显式拒绝优先:明确的REVOKE优先于GRANT

    • 直接权限优先:直接授予用户的权限优先于角色权限

    • 角色启用状态:仅启用状态的角色权限有效

    冲突解决示例:

    -- 场景设置
    GRANT SELECT ON sales.orders TO user1;
    GRANT sales_role TO user1; -- 该角色有REVOKE SELECT ON sales.orders
    
    -- 权限检查结果:user1无SELECT权限(角色中的REVOKE优先)

    4、查看角色和权限

    -- 查看角色 --
    
    -- 查看角色权限
    SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE='RESOURCE';
    -- 查看用户拥有的角色
    SELECT * FROM DBA_ROLE_PRIVS WHERE GRANTEE='TEST_USER';
    
    
    -- 查看权限 --
    
    -- 查看用户拥有的系统权限
    SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE = 'USER_NAME';
    -- 查看用户拥有的角色
    SELECT * FROM DBA_ROLE_PRIVS WHERE GRANTEE = 'USER_NAME';
    -- 查看用户拥有的对象权限
    SELECT * FROM DBA_TAB_PRIVS WHERE GRANTEE = 'USER_NAME';
    -- 查看当前用户拥有的权限信息
    SELECT * FROM SESSION_PRIVS;

    权限分层模型

    企业级应用建议采用三层权限模型:

    • 基础权限层:通过预定义角色分配基本权限

    • 业务权限层:按业务功能创建自定义角色

    • 特殊权限层:直接为用户分配特定权限

    image.png

    最佳实践建议

    • 最小权限原则:只授予用户完成其任务所必需的最小权限。

    • 使用角色:尽量将权限打包成角色,然后赋予用户,而非直接授予用户权限。

    • 定期审计:定期检查角色和用户的权限分配情况,及时清理不必要的权限。

    • 流程指挥:敏感操作,关键权限需流程审批。

    在实际应用中注意项:

    • 权限规划先行:设计阶段明确权限分层模型。

    • 持续审计监控:建立权限变更审计机制。

    • 安全增强配置:结合国密算法等安全特性。

    • 定期合规检查:确保符合等保要求。


    参考:

    DM达梦数据库登陆方式及日常运维命令

    2025-10-20 05:21:39

    使用SQL客户端连接达梦数据库,主要有命令行工具 DISQL 和图形化工具 DM管理工具 两种方式。具体选择可参考下表:

    工具类型 工具名称 主要特点/适用场景
    命令行工具 DISQL 达梦自带,类似Oracle的SQLPlus,存放于安装路径的/bin//tool/目录,适合习惯命令行操作、需执行特定命令(如DESC查看表结构)或自动化脚本的场景。
    图形化工具 DM管理工具 功能强大、操作简单的图形化客户端,适合日常管理、查询数据、视觉化操作。

    🖥️ 使用DISQL命令行连接

    DISQL工具位于达梦数据库安装路径下的bintool目录

    • 基本连接语法

    ./disql 用户名/密码@主机地址:端口号

    例如,连接本地默认数据库实例(端口通常为5236):

    ./disql SYSDBA/SYSDBA@localhost:5236

    注意:在/bin目录下使用disql时,建议直接在命令中写全连接信息。如果只输入./disql后回车,后续将无法输入端口号(除非使用默认端口5236)

    • 交互式连接
      /tool目录下或直接运行disql后,可以使用LOGINCONNCONNECT)命令连接

    CONN SYSDBA/SYSDBA@localhost:5236

    LOGIN 随后根据提示输入服务器地址、用户名、密码及端口号

    • 简化连接配置(可选)
      为省去每次输入完整地址的麻烦,可配置dm_svc.conf文件(通常在/etc目录)。在文件中按格式添加服务名:

    自定义服务名=(IP地址:端口号)
    
    例如:DMDB=(192.168.1.100:5236)

    配置后,连接时只需使用服务名

    ./disql SYSDBA/SYSDBA@DMDB

    🖱️ 使用图形化客户端连接

    达梦数据库也提供了图形化的DM管理工具(DM Management Studio)

    1. 启动工具:在开始菜单中找到并启动"DM管理工具"

    2. 创建新连接

    • 在工具界面找到"注册连接"图标或选项

    • 在弹出的对话框中,填写主机名(或IP地址)、端口号(默认5236)、用户名(如SYSDBA)和口令

  • 连接:点击"确定"或"连接"按钮即可登录数据库

  • 💡 实用技巧与注意事项

    • 默认连接信息:达梦数据库初始管理员账号常为 SYSDBA,默认密码可能是 SYSDBA,初始端口号一般为 5236

    • 连接问题排查

      • 确保达梦数据库实例已启动

      • 检查主机名端口号是否正确,以及网络是否通畅

      • 注意用户名和密码的大小写,特别是早期版本默认密码可能要求大写

    • 执行SQL脚本:在DISQL中,可以使用 START 或反引号 ` 执行SQL脚本文件

    START /path/to/your_script.sql 或 ` /path/to/your_script.sql
    • 退出DISQL:在DISQL命令行中,输入 QUIT 或 EXIT 即可退出

    🗂️ 关于用户与模式

    在达梦数据库中,创建一个用户时会自动生成一个同名的模式(Schema)作为该用户的默认模式。用户操作自己模式下的对象(如表)时可以不写模式名。查询当前所在模式可以使用:

    SELECT SYS_CONTEXT ('userenv', 'current_schema') FROM DUAL;

    相关文章:


    达梦数据库的SQL命令体系清晰,涵盖了从数据库连接、对象操作到性能分析的各个方面。下面这个表格汇总了最常用的命令,方便快速查阅。

    类别 命令/操作 说明及示例
    连接与基础 启动DISQL ./disql 用户名/密码@主机:端口 ,或使用conn命令
    执行SQL文件 START<文件路径> 或 `` <文件路径> 
    设置环境变量 例如SET PAGESIZESET LINESIZE 
    获取帮助 HELP [命令] 
    数据库对象操作 查看表结构 DESC 表名; 
    创建表 CREATE TABLE 表名 (列定义); 
    修改表名 ALTER TABLE 原表名 RENAME TO 新表名; 
    删除表 DROP TABLE 表名; 
    数据操作 插入数据 INSERT INTO 表名 (列1, 列2) VALUES ('值1', '值2'); 
    查询数据 SELECT 列1, 列2 FROM 表名 [WHERE 条件]; 
    更新数据 UPDATE 表名 SET 列名=新值 [WHERE 条件];
    删除数据 DELETE FROM 表名 [WHERE 条件];
    实用工具命令 屏幕输出到文件 SPOOL 文件路径 ... SPOOL OFF 
    执行操作系统命令 HOST [操作系统命令] 
    查看执行计划 EXPLAIN SQL语句; 

    DM常用操作命令与MySQL对比一览

    操作目的 MySQL 命令 达梦数据库 (DM) 命令 关键差异说明
    查看当前数据库/模式 SELECT DATABASE(); SELECT SF_GET_SCHEMA_NAME_BY_ID(CURRENT_SCHID);

    SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA'); 
    达梦使用模式(Schema) 来逻辑隔离对象。
    查看所有数据库/模式 SHOW DATABASES; SELECT DISTINCT NAME AS SCHEMA_NAME FROM SYSOBJECTS WHERE TYPE$ = 'SCH';  在达梦中,需要查询系统表来获取模式列表。
    切换数据库/模式 USE database_name; SET SCHEMA schema_name;

    ALTER SESSION SET CURRENT_SCHEMA = schema_name; 
    达梦使用 SET SCHEMA 或修改会话的方式来切换当前模式。
    查看当前模式下的所有表 SHOW TABLES; SELECT TABLE_NAME FROM USER_TABLES;  达梦通过查询数据字典视图 USER_TABLES 来获取表列表。
    查看其他模式下的所有表 SHOW TABLES FROM database_name; SELECT TABLE_NAME FROM DBA_TABLES WHERE OWNER = 'schema_name';  需要指定模式的拥有者(OWNER)来查询。
    查看表结构 DESC table_name;

    SHOW CREATE TABLE table_name;
    DESC schema_name.table_name; 

    SELECT DBMS_METADATA.GET_DDL('TABLE', 'table_name', 'schema_name') FROM DUAL; 
    1. 达梦的 DESC 需要指定模式名.表名
    2. 获取完整的建表语句需要使用 DBMS_METADATA 包。

    💡 重要差异与使用技巧

    1. 模式(Schema)与用户(User)的关系
      在达梦数据库中,一个用户可以拥有多个模式,但一个模式只属于一个用户。当创建一个用户时,系统会默认创建一个与用户名同名的模式作为其默认模式。执行SQL时,如果操作的不是当前用户的模式对象,通常需要在表名前加上模式名,格式为 模式名.表名 

    2. 设置默认(当前)模式的方法
      除了在DISQL中手动使用 SET SCHEMA,还可以在应用程序的JDBC连接字符串中直接指定,这可以避免在代码中频繁书写模式名前缀:jdbc:dm://192.168.15.35:5236?schema=TEST2

    3. 标识符和字符串的引用

    • MySQL:表名和字段名可以用反引号(`)引用,字符串可用单引号(')或双引号(")。

    • 达梦表名和字段名只能使用双引号(") 进行引用(如果包含特殊字符或关键字时)。而字符串必须使用单引号(') 表示。

  • 自增列的定义

    • MySQL:使用 AUTO_INCREMENT

    • 达梦:使用 IDENTITY(1,1),例如 id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY 。注意,达梦不支持 AUTO_INCREMENT 关键字,通常使用 GENERATED ALWAYS AS IDENTITY 关键字。

    🛠️ 命令详解与使用技巧

    表格列出了常用命令,下面再补充一些关键细节和使用技巧,能让你更好地使用它们。

    • 连接数据库与DISQL工具
      DISQL是达梦数据库的命令行交互式客户端工具。连接时,如果密码含有特殊字符,建议用'""'包裹密码,例如:./disql SYSDBA/'"#Sjkdzgm0"'@192.168.23.3:5236 
      成功连接后,可以通过 START 或反引号 ` 来执行外部的SQL脚本文件。使用 SPOOL 命令可以将接下来屏幕上显示的所有内容输出到指定文件,这在生成报告或记录操作日志时非常有用。记得操作结束后用 SPOOL OFF 关闭输出

    • 掌握对象管理与数据操作
      建表时需要注意语法细节,例如,达梦数据库中标识符(如表名、列名)若包含特殊字符或与保留字冲突,需要使用双引号包围
      在执行数据操作时,务必注意事务的提交。可以通过 SET AUTO[COMMIT] 设置是否自动提交。在自动提交为OFF时,执行了INSERT、UPDATE、DELETE等修改数据的操作后,需要显式执行 COMMIT; 提交事务,或者执行 ROLLBACK; 回滚事务,才能使数据修改真正生效或撤销。

    • 分析SQL性能
      使用 EXPLAIN 命令是分析SQL语句执行计划、进行性能调优的重要步骤。执行计划采用缩进树形结构展示,读法一般是从内到外,从下到上。需要关注:

      • 高成本操作:执行计划中的高COST值操作通常是优化重点

      • 索引使用:确保适当的查询使用了索引

      • 全表扫描:对大表的全表扫描往往是性能瓶颈

    DM常用SQL命令

    -- 查看实例名
    select instance_name from v$instance;
    -- 查看达梦版本
    select * from v$version; 
    -- 查看达梦有无开启兼容mysql语法
    select para_name,para_value,file_value from v$dm_ini where para_name='COMPATIBLE_MODE';
    -- 查看用户所有库
    SELECT t.name schname, t.id, t.pid, b.name username FROM sysobjects t, sysobjects b WHERE t.pid = b.id AND t.type$='SCH' ;
    -- 查看用户所有角色
    select  grantee,granted_role from dba_role_privs where grantee='chegva';
    -- 查看数据库会话
    select *from v$sessions;
    -- 查看所有索引(当前模式)
    SELECT INDEX_NAME, TABLE_NAME, UNIQUENESS FROM USER_INDEXES;
    -- 查看其他模式的索引
    SELECT * FROM DBA_INDEXES WHERE OWNER = 'schema_name' AND TABLE_NAME = 'table_name';
    -- 查看索引的详细定义
    SELECT DBMS_METADATA.GET_DDL('INDEX', 'index_name', 'schema_name') FROM DUAL;
    -- 查看表的索引
    SELECT * FROM USER_INDEXES WHERE TABLE_NAME = 'table_name';
    或
    SP_TABLEDEF('schema_name', 'table_name');


    相关文章:

    WordPress自动更新缓存功能的归档页面制作

    2025-10-13 23:17:21

    之前使用的归档页面是秋叶博客分享的 → Wordpress带缓存和特效的归档页面制作,使用的是php的缓存机制,每次发布/删除文章后,归档页面缓存不会自动清除和重建,想整一个包含缓存机制和手动刷新功能的归档页面,针对原来的归档页面优化了一下。

    实现方案:将核心功能放在functions.php中,页面模板只负责显示。这种架构使缓存管理和内容生成逻辑集中化,而页面模板只负责显示内容,系统会在文章更新时自动刷新缓存,同时为管理员提供手动刷新选项,确保归档页面始终保持最新状态。更符合WordPress最佳实践,具有更好的性能和可维护性。

    查看效果:https://chegva.com/archive/

    功能设计

    1. functions.php部分

    • 缓存管理机制

    • 文章更新时自动清除缓存

    • 归档内容生成函数

    • 手动清除缓存的工具

  • 页面模板部分

    • 只负责显示归档内容

    • 包含响应式布局和交互功能

    缓存清除场景说明

    场景 旧状态 新状态 说明
      新文章发布 非发布状态 (draftpending 等) publish 归档需要添加新文章
    定时发布 future publish  归档需要添加新文章
      取消发布 publish 非发布状态 (draftprivate 等) 归档需要移除该文章
      移至回收站 任何状态 trash 归档需要移除该文章
      已发布文章更新 publish publish ❌ 不触发缓存清除
      草稿更新 draft draft ❌ 不触发缓存清除

    工作流程图

    1758014815507834.png

    1758014858393353.png

    定时发布文章的工作流程

    1759207128471671.png

    实现代码

    第一步:在functions.php中添加以下代码

    /**
     * 添加归档页面
     **/
    
    // 注册归档缓存选项
    add_action('init', function() {
        add_option('qiuye_archives', '', '', 'no');
    });
    
    // 核心缓存清除函数
    function clear_archive_cache() {
        delete_option('qiuye_archives');
        set_transient('qiuye_cache_cleared', time(), 60); // 设置60秒瞬态标记,避免在清除操作后立即重建
    
        // 增强调试:记录清除操作
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log('清除归档缓存触发 - 文章ID: ' . $post_id);
        }
    }
    
    // 文章状态变更处理 - 只在状态变更时清除缓存
    add_action('save_post', function($post_id, $post, $update) {
        // 跳过自动保存
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
    
        // 只处理文章类型
        if ($post->post_type !== 'post') return;
    
        // 检查权限
        if (!current_user_can('edit_post', $post_id)) return;
    
        // 获取旧状态
        $old_status = get_post_meta($post_id, '_old_status', true);
    
        // 保存当前状态作为下次的旧状态
        update_post_meta($post_id, '_old_status', $post->post_status);
    
        // 检查定时发布
        $is_scheduled = ($post->post_status === 'future');
    
        // 如果是定时发布的文章,设置定时任务
        if ($is_scheduled) {
            $scheduled_time = strtotime($post->post_date);
            $current_time = current_time('timestamp');
    
            // 只有在未来时间才设置定时任务
            if ($scheduled_time > $current_time) {
                wp_schedule_single_event($scheduled_time, 'publish_future_post', array($post_id));
                error_log("定时发布文章设置: $post_id, 发布时间: " . date('Y-m-d H:i:s', $scheduled_time));
            }
        }
    
        // 状态变更检测
        $status_changed = ($old_status && $old_status !== $post->post_status);
    
        // 需要清除缓存的场景
        $clear_cache = false;
    
        if ($status_changed) {
            // 场景1: 从未发布变为发布状态
            if ($old_status !== 'publish' && $post->post_status === 'publish') {
                $clear_cache = true;
            }
            // 场景2: 从发布状态变为非发布状态
            elseif ($old_status === 'publish' && $post->post_status !== 'publish') {
                $clear_cache = true;
            }
            // 场景3: 从任何状态变为删除状态
            elseif ($post->post_status === 'trash') {
                $clear_cache = true;
            }
        }
    
        // 场景4: 新文章直接发布
        if (!$old_status && $post->post_status === 'publish') {
            $clear_cache = true;
        }
    
        if ($clear_cache) {
            clear_archive_cache();
            error_log("文章状态变更触发缓存清除: " . ($old_status ?: 'new') . " => {$post->post_status} (ID: $post_id)");
        }
    }, 10, 3);
    
    // 定时发布文章处理
    add_action('publish_future_post', function($post_id) {
        $post = get_post($post_id);
        if ($post && $post->post_type === 'post') {
            clear_archive_cache();
            error_log("定时发布文章触发缓存清除: $post_id");
    
            // 发送通知(可选)
            if (defined('WP_DEBUG') && WP_DEBUG) {
                $admin_email = get_option('admin_email');
                wp_mail($admin_email, '定时文章已发布', "文章 ID: $post_id 已按计划发布,归档缓存已更新。");
            }
        }
    });
    
    // 文章移至回收站处理
    add_action('trashed_post', function($post_id) {
        $post = get_post($post_id);
        if ($post && $post->post_type === 'post') {
            clear_archive_cache();
            error_log("文章移至回收站触发缓存清除: $post_id");
        }
    });
    
    // 文章从回收站恢复处理
    add_action('untrashed_post', function($post_id) {
        $post = get_post($post_id);
        if ($post && $post->post_type === 'post') {
            // 如果恢复后是发布状态,清除缓存
            if ($post->post_status === 'publish') {
                clear_archive_cache();
                error_log("文章恢复发布触发缓存清除: $post_id");
            }
        }
    });
    
    // 文章永久删除处理
    //add_action('deleted_post', function($post_id) {
    //    // 删除状态跟踪的元数据
    //    delete_post_meta($post_id, '_old_status');
    //
    //    $post = get_post($post_id);
    //    if ($post && $post->post_type === 'post') {
    //        clear_archive_cache();
    //        error_log("文章永久删除触发缓存清除: $post_id");
    //    }
    //});
    
    // 在文章编辑页添加状态跟踪
    add_action('post_submitbox_start', function() {
        global $post;
        if ($post && $post->post_type === 'post') {
            // 保存当前状态作为旧状态
            if (!get_post_meta($post->ID, '_old_status', true)) {
                update_post_meta($post->ID, '_old_status', $post->post_status);
            }
            echo '<input type="hidden" name="old_status" value="'.esc_attr($post->post_status).'">';
        }
    });
    
    // 在文章保存前捕获旧状态
    add_action('pre_post_update', function($post_id) {
        $old_status = get_post_status($post_id);
        update_post_meta($post_id, '_old_status', $old_status);
    });
    
    // 定时清理过期的状态跟踪元数据
    add_action('wp_scheduled_delete', function() {
        global $wpdb;
    
        // 删除30天前的状态跟踪元数据
        $thirty_days_ago = date('Y-m-d H:i:s', strtotime('-30 days'));
    
        $wpdb->query($wpdb->prepare("
            DELETE FROM $wpdb->postmeta
            WHERE meta_key = '_old_status'
            AND post_id IN (
                SELECT ID FROM $wpdb->posts
                WHERE post_modified < %s
            )
        ", $thirty_days_ago));
    
        error_log("清理过期的状态跟踪元数据完成");
    });
    
    // 归档内容生成函数
    function generate_archive_html() {
    	// 生成内容
    	$output = '<div class="archives"><div style="text-align:right;"><img src="https://cdn.chegva.com/static/sorting-answers.png" style="width: 16px;height: 14px;vertical-align:baseline;" ><a id="al_expand_collapse" href="#"> 全部展开/收缩</a> <span style="font-size:11px">(年份/月份也可点击哦!)</span></div>';
    
    	// 使用更可靠的查询方法
    	$args = array(
    		'post_type' => 'post',
    		'post_status' => 'publish',
    		'posts_per_page' => -1,
    		'ignore_sticky_posts' => 1,
    		'no_found_rows' => true,  // 提高性能
    		'update_post_term_cache' => false,  // 提高性能
    		'suppress_filters' => true  // 确保无插件干扰
    	);
    
    	$the_query = new WP_Query($args);
    
    	$year = 0;
    	$mon = 0;
    	while ( $the_query->have_posts() ) : $the_query->the_post();
    	$year_tmp = get_the_time('Y');
    	$mon_tmp = get_the_time('m');
    
    	if ($mon != $mon_tmp && $mon > 0) $output .= '</ul></li>';
    	if ($year != $year_tmp && $year > 0) $output .= '</ul>';
    
    	if ($year != $year_tmp) {
    		$year = $year_tmp;
    		$output .= '<h3 class="al_year">'. $year .'年<span style="padding-left:35px;">( '. get_num_posts_by_year($year) .' 篇文章 )</span></h3><ul class="al_mon_list">';
    	}
    
    	if ($mon != $mon_tmp) {
    		$mon = $mon_tmp;
    		$output .= '<li><span class="al_mon">'. $mon .' 月</span><ul class="al_post_list">';
    	}
    
    	$output .= '<li class="atitle fix"><span class="ttime">'. get_the_time('d日:  ') .'</span><a class="tttile" href="'. get_permalink() .'">'. get_the_title() .'</a><span class="ttview">·'. the_views('0',' ') .'</span></li>';
    	endwhile;
    
    	wp_reset_postdata();
    	$output .= '</ul></li></ul></div>';
    
            // 添加缓存信息 - 使用本地时间
    	$output .= "<!-- Cache generated: ".get_local_time('Y-m-d H:i:s')." -->";
    
        return $output;
    }
    
    // 扩展的获取本地时间函数(带时间戳参数)
    function get_local_time($format = 'Y-m-d H:i:s', $timestamp = null) {
        // 获取WordPress设置的时区
        $timezone_string = get_option('timezone_string');
    
        if ($timezone_string) {
            $timezone = new DateTimeZone($timezone_string);
        } else {
            $offset = get_option('gmt_offset');
            $timezone = timezone_open(sprintf('%+d', $offset));
        }
    
        // 使用当前时间或指定时间戳
        $timestamp = $timestamp ?: time();
        $datetime = new DateTime('@' . $timestamp);
        $datetime->setTimezone($timezone);
    
        return $datetime->format($format);
    }
    
    // 添加手动清除缓存的工具
    add_action('admin_bar_menu', function($admin_bar) {
        if (current_user_can('manage_options')) {
            $admin_bar->add_menu([
                'id'    => 'clear-archive-cache',
                'title' => '清除归档缓存',
                'href'  => wp_nonce_url(add_query_arg('clear_archive_cache', '1'), 'clear_archive_cache')
            ]);
        }
    }, 100);
    
    // 处理手动清除请求
    add_action('init', function($post_id) {
        if (isset($_GET['clear_archive_cache']) && check_admin_referer('clear_archive_cache')) {
    //        delete_option('qiuye_archives');
            clear_archive_cache();
            wp_redirect(remove_query_arg(['clear_archive_cache', '_wpnonce']));
            exit;
        }
    });

    第二步:创建归档页面模板 (page-archives.php)

    <div id="content">
    <?php
    // 归档显示函数
    function qiuye_display_archives() {
    
            // 检查瞬态是否存在
            $cache_cleared_time = get_transient('qiuye_cache_cleared');
    
            if ($cache_cleared_time) {
                    // 如果缓存被清除过,重新生成
                    $output = generate_archive_html();
                    update_option('qiuye_archives', $output);
    
                    // 添加缓存清除时间信息
                    $output .= "<!-- Cache cleared: ".get_local_time('Y-m-d H:i:s', $cache_cleared_time)." -->";
            } else {
                    // 尝试获取现有缓存
                    $output = get_option('qiuye_archives');
    
                    if (empty($output)) {
                            $output = generate_archive_html();
                            update_option('qiuye_archives', $output);
                    }
            }
    
            echo $output;
    }
    ?>
    
    <?php qiuye_display_archives(); ?>

    使用指南

    1. 安装步骤

    • 将functions.php代码添加到主题的functions.php文件

    • 创建page-archives.php模板文件

    • 在WordPress后台创建新页面并选择"归档页面"模板

  • 缓存管理

    • 自动:发布新文章时自动刷新

    • 手动:管理员点击"清除归档缓存"链接

  • 自定义选项

    • 修改缓存名称:'qiuye_archives'

    • 调整样式:编辑CSS代码段

    • 修改查询参数:调整WP_Query数组

    调试步骤:

    1. 将完整代码复制到主题的 functions.php

    2. 发布一篇测试文章

    3. 查看归档页面源代码中的缓存时间标记

    4. 检查debug.log中的清除记录

    5. 使用管理栏按钮测试手动清除功能

    1、检查缓存状态
    在归档页面查看源代码,搜索 <!-- Cache generated: 查看缓存时间

    image.png

    2、检查错误日志
    在 wp-config.php 中添加:

    define('WP_DEBUG', true);
    define('WP_DEBUG_LOG', true);

    发布文章后检查 /wp-content/debug.log

    $ grep "清除归档缓存" debug.log
    [25-Jun-2025 18:36:05 UTC] 清除归档缓存触发 - 文章ID: 6434
    [25-Jun-2025 18:37:27 UTC] 清除归档缓存触发 - 文章ID: 6435
    [25-Jun-2025 18:37:44 UTC] 清除归档缓存触发 - 文章ID: 6436
    [25-Jun-2025 18:37:45 UTC] 清除归档缓存触发 - 文章ID: 6437
    [25-Jun-2025 18:37:54 UTC] 清除归档缓存触发 - 文章ID: 6437
    [25-Jun-2025 18:38:01 UTC] 清除归档缓存触发 - 文章ID: 6437
    [25-Jun-2025 18:38:01 UTC] 清除归档缓存触发 - 文章ID: 6437
    ......
    [25-Jun-2025 19:07:18 UTC] 清除归档缓存触发 - 文章ID: 6442
    [25-Jun-2025 19:07:19 UTC] 清除归档缓存触发 - 文章ID: 6442
    [25-Jun-2025 19:07:27 UTC] 清除归档缓存触发 - 文章ID: 6443
    [25-Jun-2025 19:07:28 UTC] 清除归档缓存触发 - 文章ID: 6444
    [25-Jun-2025 19:08:34 UTC] 清除归档缓存触发 - 文章ID: 6445
    [25-Jun-2025 19:08:51 UTC] 清除归档缓存触发 - 文章ID: 6442

    3、手动清除测试
    使用添加的管理栏按钮手动清除缓存

    image.png

    4、缓存插件排查
    如果使用了缓存插件(W3TC、WP Super Cache等),尝试:

      • 排除归档页面缓存

      • 禁用插件测试

      5、对象缓存检查
      如果使用Redis/Memcached,确保 delete_option 能正确清除持久化存储