iptables 黑名单迁移到 ipset:CentOS 6 实战

背景

博客服务器(阿里云 ECS,CentOS 6.3)运行着一个旧的防攻击脚本,通过分析 Apache access_log 识别恶意请求,逐条 iptables -A 封禁 IP。随着黑名单增长,iptables 逐条匹配的性能问题日益突出。

听说 iptables 黑名单到 1 万条性能就明显不行,而 ipset 支撑到 10 万条都没问题。决定迁移到 ipset 方案。

iptables vs ipset

iptables ipset
匹配方式 逐条遍历规则 哈希查找 O(1)
1万条IP 10000条规则 1条规则 + 1个集合
性能 规则多时线性下降 几乎无影响
动态更新 操作整个链 直接操作集合
存储 内核链表 内核哈希表

一句话:ipset 是 iptables 的 IP 集合加速器,规则多时用 ipset。

环境

  • 系统:CentOS 6.3 (Final)
  • 内核:2.6.32
  • iptables:v1.4.7
  • ipset:v6.11(已预装)
  • Apache:httpd,access_log 在 /var/log/httpd/access_log
  • cron:每天凌晨 3 点自动重启

踩坑记录(6个坑,全部填平)

坑一:iptables –matchset 语法不兼容

CentOS 6 的 iptables v1.4.7 不支持 --matchset,需要用旧语法 --set

# CentOS 7+ (新语法)
iptables -A INPUT -m set --matchset blacklist src -j DROP

# CentOS 6 (旧语法)
iptables -A INPUT -m set --set blacklist src -j DROP

坑二:ipset save 不支持 -f 参数

ipset v6.11 不支持 -f 参数指定输出文件,需要手动重定向:

# 错误(v6.11 不支持)
ipset save blacklist -f /etc/sysconfig/ipset

# 正确
ipset save blacklist > /etc/sysconfig/ipset

坑三:ipset save 默认输出到屏幕

ipset v6.11 的 save 命令默认输出到 stdout,不会自动写文件。脚本中必须用重定向 > 写入文件,否则重启后集合丢失。

坑四:旧脚本未做 iptables 持久化

原来的防攻击脚本每次 iptables -A 后没有执行 iptables-save,服务器每天凌晨 3 点自动重启,所有封禁规则全部丢失。迁移到 ipset 后修复了这个问题。

坑五:两个脚本同时跑

部署新脚本时忘了删除旧脚本的 cron 任务,导致两个脚本同时运行。旧脚本用 iptables,新脚本用 ipset,互相干扰。清理后正常。

坑六:cron 环境无 PATH 导致持久化文件被清空

这是最隐蔽的一个坑。cron 运行环境极简,PATH 变量不包含 /usr/sbin/sbin,导致 ipsetiptables-save 命令找不到。而 shell 重定向 > 会先清空目标文件再执行命令,命令找不到输出为空,文件就被清空了。

表现:手动运行脚本一切正常(交互 shell 有完整 PATH),但 cron 每次执行后 /etc/sysconfig/ipset/etc/sysconfig/iptables 都变成 0 字节。

修复:在脚本开头显式设置 PATH:

#!/bin/bash
PATH=/usr/sbin:/sbin:/usr/bin:/bin:/usr/local/sbin
export PATH

坑七:iptables -C 不支持 -m set 导致规则重复添加

脚本用 iptables -C 检测规则是否已存在(幂等添加),但 CentOS 6 的 iptables v1.4.7 的 -C 命令不支持 -m set --set 参数,报错 option -C requires an argument,检测总是失败,每轮 cron 都会重复添加一条规则。

表现:iptables INPUT 链中出现 5 条相同的 blacklist DROP 规则。

修复:改用 iptables -S + grep 检测:

# 旧方式(CentOS 6 不支持)
if ! iptables -C INPUT -m set --set "$SET_NAME" src -j DROP 2>/dev/null; then

# 新方式(兼容 CentOS 6)
if ! iptables -S INPUT 2>/dev/null | grep -q "match-set $SET_NAME"; then

最终方案

防攻击脚本(block-bots-ipset.sh)

核心逻辑:

  1. 脚本开头设置 PATH(解决 cron 环境问题)
  2. 首次运行创建 ipset 集合(hash:ip, maxelem 100000)+ iptables 引用规则
  3. 增量读取 access_log(基于文件偏移量,只读新增部分)
  4. 用 awk 匹配 11 类攻击特征
  5. 新攻击 IP 通过 ipset add 加入集合
  6. 有新增则 ipset save > /etc/sysconfig/ipset + iptables-save > /etc/sysconfig/iptables 持久化
  7. iptables 引用规则用 iptables -S | grep 幂等检测,避免重复添加

11 条攻击检测规则

规则 检测内容 特征示例
1 5xx 服务器错误 注入触发崩溃
2 SQL 注入 UNION, SELECT, SLEEP(), DROP, INSERT
3 XSS 攻击 %3Cscript, javascript:, onerror=
4 路径穿越 ../, %2e%2e, etc/passwd
5 空 UA 扫描器 User-Agent 为 “-“
6 敏感文件扫描 .env, .git, .sql, .bak, wp-config, xmlrpc.php
7 HEAD 探测 HEAD 方法扫描
8 恶意爬虫 MJ12bot, YisouSpider, DotBot
9 攻击工具 sqlmap, nikto, nmap, acunetix, nessus, wpscan
10 RFI/LFI php://input, php://filter, data://
11 命令注入 ;wget, ;curl, eval(, system(, exec(

持久化方案

组件 持久化方式
ipset 集合 ipset save > /etc/sysconfig/ipset + rc.local 开机 ipset restore
iptables 规则 iptables-save > /etc/sysconfig/iptables + iptables 服务开机自启
脚本定时执行 cron 每 5 分钟一次
封禁日志 /var/log/block-bots.log,超过 10MB 自动轮转

迁移过程

  1. 检查环境:确认 ipset v6.11 已安装,CentOS 6.3
  2. 发现 iptables 为空:之前封的 IP 因重启全丢,旧脚本未持久化
  3. 部署新脚本:上传 block-bots-ipset.sh,首次运行创建集合 + iptables 引用
  4. 修复语法兼容:–matchset -> –set,-f -> 重定向
  5. 导入历史黑名单:从 /var/log/block-bots.log 提取 855 个 IP 导入 ipset
  6. 配置 cron:每 5 分钟执行,删除旧脚本 cron
  7. 配置持久化:ipset save + iptables-save + rc.local
  8. 修复 cron PATH 问题:脚本开头加 PATH 和 export
  9. 修复规则重复添加:iptables -C 改为 iptables -S + grep
  10. 全面检查:12 项检查脚本全部通过

最终效果

  • 855 个攻击 IP 已封禁
  • iptables 只需 1 条规则匹配整个集合
  • 每 5 分钟自动检测新攻击并封禁
  • 每天凌晨重启后自动恢复所有规则
  • 封禁在 iptables 层生效,攻击 IP 进不了 Apache,不消耗服务器资源

经验总结

  1. CentOS 6 语法差异多:iptables 用 --set 不用 --matchset,ipset save 不支持 -f,都要手动重定向
  2. 持久化要做全套:ipset save + iptables-save + rc.local + iptables 服务开机自启,缺一不可
  3. 部署新脚本要清理旧任务:两个脚本同时跑会互相干扰
  4. ipset save 的输出要重定向:v6.11 默认输出到屏幕,不写文件,重启后集合丢失
  5. cron 环境极简,必须手动设 PATH:否则 > 重定向先清空文件,命令又找不到,文件就变空了。这个坑最隐蔽,手动测试一切正常,只有 cron 执行时才出问题
  6. iptables -C 不支持 -m set:CentOS 6 的幂等检测要改用 iptables -S | grep,否则每轮 cron 都重复添加规则
  7. 检查脚本很重要:写了 12 项检查脚本,一次性发现所有遗漏

附录:检查脚本

写了 12 项检查脚本(check-ipset-status.sh),覆盖:

  1. ipset 版本
  2. 集合状态与 IP 总数
  3. iptables 引用规则
  4. iptables 持久化文件
  5. iptables 服务开机自启
  6. ipset 持久化文件
  7. rc.local 开机恢复
  8. cron 定时任务
  9. 脚本文件与语法检查
  10. 封禁日志状态
  11. 实时拦截统计
  12. 抽样验证已封禁 IP

OpenClaw v2026.7.1-beta.2 升级与补丁维护实录

背景

线上运行的 OpenClaw v2026.6.11 遇到两个严重问题:

  • #99241 tool-result-placeholder:上下文累积到 65K tokens 后,工具输出被替换为 (see attached image) 占位符,模型无法读取工具结果。触发阈值从最初的 180K 一路恶化到 65K,严重影响使用。
  • #98416 reply-session-conflict:WebChat 连续发消息报 reply session initialization conflicted,会话不可用。

升级到 v2026.7.1-beta.2 后,#98416 官方已修复,#99241 靠 PR #98955(尾部 tool-result 保护)缓解。本文记录升级过程和补丁维护经验。

升级过程

  1. 备份:dist 目录 + openclaw.json 配置文件
  2. 升级npm install -g openclaw@2026.7.1-beta.2
  3. 重打补丁:6 个本地补丁重新打入(reply-session-source-fix 官方已修复,移除)
  4. patch-check:7/7 通过
  5. Gateway 重启,功能验证通过

备份位置:/usr/lib/node_modules/openclaw.bak-2026.6.11 + openclaw.json.bak-2026.6.11

补丁维护核心发现

1. attachment-normalize:遗漏的第二处栈溢出

6月25日打补丁时只修了第89行 data: URL 提取正则((.*)$ 对大字符串触发 V8 正则引擎栈溢出),改为 indexOf + slice

遗漏了第59行 isValidBase64 函数中的另一个正则/^[A-Za-z0-9+/]+={0,2}$/.test(value),同样使用 + 量词对大字符串匹配,同样栈溢出。

之前测试的文件都是 6MB 左右,刚好没触发 V8 正则引擎的栈深度上限。7月10日上传 14MB 文件时暴露,改为逐字符 charCodeAt 遍历修复。

教训:补丁记录必须完整。一个函数里有两处正则栈溢出风险,只修一处是不够的。每次修复后要排查同文件中是否有同类问题。

2. reply-session-conflict:官方三层修复已到位

v2026.7.1-beta.2 中官方已完成三层修复:

  • 源头修复(PR #98835):收窄 guard 对比范围到 sessionId/sessionFile 身份字段,允许并发 metadata drift
  • 重入保护isActiveStoreWriter/runActiveStoreWriter 正确处理 reentrant: true
  • 重试退避retryDelays = [1000, 3000, 5000, 8000]maxRetries = 4

不再需要本地补丁。patches.json 中保留检测规则作为升级后的验证检查。

3. workspace-file-viewer:官方已修复

v2026.7.1-beta.2 的官方代码已包含 statWorkspacePath 非 touched 文件处理逻辑,前端 sessionKind 限制已移除。不需要本地补丁。

升级后测试时发现”补丁打了但没用”,实际是浏览器 JS 缓存问题,硬刷新后正常。前端代码变更后必须 Ctrl+Shift+R 硬刷新。

4. control-ui-allowed-folders:官方未修复,仍需本地补丁

问题 #10210240 分两层:

  • 前端:正则 /^(\/Users\/[^/]+|\/home\/[^/]+)(?:\/|$)/ 只匹配 macOS 和 Linux 非 root 用户,不匹配 /root。本地补丁加 |\/root
  • 服务端getAgentScopedMediaLocalRoots 只返回当前 agent 的 workspace,不包含其他 agent。本地补丁遍历 cfg.agents.list 追加所有 agent workspace。

升级后验证:发送 docx 文件到 WebChat,点击预览正常,不再提示 “Outside allowed folders”。

openclaw-patch-check 技能清理

升级过程中发现技能存在两个问题:

  1. 两套目录~/.openclaw/skills/openclaw-patch-check/(实际运行)和 ~/.openclaw/workspace/skills/openclaw-patch-check/(多余副本)。删除了 workspace 下的副本。
  2. 补丁记录过时:patches.json 从 7 个精简到 4 个,移除 3 个官方已修复的条目,更新检测规则。

当前 patches.json(4 个)

ID Issue 类型
attachment-normalize #90098 两处正则栈溢出 本地补丁
reply-session-conflict #98416 reply session conflicted 验证官方修复
control-ui-allowed-folders-frontend #10210240 前端正则缺 /root 本地补丁
control-ui-allowed-folders-backend #10210240 服务端缺非默认 agent workspace 本地补丁

架构限制:大文件上传

WebChat 通过 WebSocket 上传文件,MAX_PAYLOAD_BYTES = 25 * 1024 * 1024 硬编码限制。14MB 文件 base64 编码后约 19MB,可以上传。但超过 25MB 的文件 base64 后超过限制,无法上传。

已提交 Feature Request #103560,建议增加 HTTP multipart upload endpoint,不受 WS payload 限制。

补丁状态总览

补丁 状态 说明
attachment-normalize 本地补丁 两处正则栈溢出,PR #92223 未合并
reply-session-conflict 官方已修复 v2026.7.1-beta.2 三层修复到位
workspace-file-viewer 官方已修复 代码已含 statWorkspacePath 逻辑
control-ui-allowed-folders 本地补丁 官方未修复 #10210240
tool-result-placeholder 已回滚 PR #99756 打后更差,等官方根治

经验总结

  1. 补丁记录要完整:attachment-normalize 有两处正则栈溢出,只记一处导致遗漏。每处修改都要记录原始代码、修复代码、行号、原因。
  2. 检测规则要通用:从匹配特定文件名 hash 改为 glob get-reply-*.js,从匹配特定数组值改为检测关键字 retryDelays + maxRetries
  3. 区分”补丁生效”和”官方已修复”:patches.json 中保留 reply-session-conflict 条目,作用从”检查本地补丁”变为”验证官方修复”。
  4. 前端变更后硬刷新:workspace-file-viewer 补丁打了但浏览器缓存旧 JS,硬刷新后正常。
  5. 维护单一数据源:发现两套技能目录后删除多余副本,只维护 ~/.openclaw/skills/ 下的版本。

遗留问题

  • #99241:beta.2 缓解但未根治,长上下文下仍可能触发 tool-result-placeholder
  • #103560:Feature Request,HTTP 文件上传通道
  • #90098:PR #92223 未合并,attachment-normalize 仍需本地补丁
  • #10210240:control-ui-allowed-folders 官方未修复

AI编程的边界:从OpenClaw的Bug说起

引子:一个悖论

OpenClaw 是一个重度使用 AI 编程构建的产品–它本身就是 AI 辅助开发的典范。但作为深度用户,我们在日常使用中却发现了一个有趣的现象:几乎每一个版本的升级都会带来一系列严重的问题。

我们当前使用的 2026.6.11 版本,就同时存在多个问题:

  • 需要手动打 6 个补丁才能正常工作,涉及会话冲突、文件查看器、路径白名单等多个 bug
  • 浏览器 profile 连接失效,内置的 user profile 无法连接到已启动的 Chrome
  • PR 审核极其缓慢,bug 修复迟迟无法合并到主线

这不禁让人思考:AI 编程的能力边界到底在哪里?

一、真实案例:看起来修好了,其实没有

最典型的例子是 #99241 这个 bug:当会话上下文累积到 100K+ 时,工具结果会被替换为 (see attached image) 占位符,导致模型无法读取工具输出。

有人提了一个 PR(#99756)声称解决了这个问题。从他的角度来说,他确实测了–图片占位符不出现了,他认为问题解决了。

但实际打上 patch 之后发现:图片占位符确实没了,取而代之的是工具结果直接变成空对象 {}。问题没有解决,只是换了一种形式失败,而且更严重了–原来至少能撑到 180K 上下文,打完 patch 后 120K 就出问题。

这就是 AI 编程的典型问题:局部正确,全局错误。AI 能理解”这个函数该返回什么”,但很难理解”这个改动在 120K 上下文、特定序列化路径下会触发什么连锁反应”。

二、Patch 循环:被逼出来的自助修复

因为 PR 审核慢、合并慢,我们被迫维护了一套 patch 管理机制。目前有 6 个 patch,每个 OpenClaw 升级后都要重新打一遍:

Patch 对应 Issue/PR 等待时间 现状
reply session conflicted #98416 / PR #100178 数周未合并 每次升级重新打
工作区文件查看器后端 #100615 feature request,排期未知 每次升级重新打
工作区文件查看器前端 #100615 同上 每次升级重新打
Control UI 路径白名单 #10210240 issue 提了没人理 每次升级重新打
attachment 栈溢出 无对应 PR 每次升级重新打
Control UI 服务端路径 #10210240 同上 每次升级重新打

这个循环本身就说明了一个问题:用户被迫自己修 bug,而每次官方升级又会覆盖掉这些修复。这不是正常的开源软件使用体验。

三、浏览器问题:设计上的死结

2026.6.11 版本引入了 profile="user" 的内置 profile,通过 Chrome MCP transport 连接浏览器。它的 auto-connect 机制依赖在 Chrome 默认用户数据目录下查找 DevToolsActivePort 文件来发现 Chrome 实例。

但我们的 Chrome 必须用非默认的 --user-data-dir 启动(因为登录态都在自定义目录里),所以 auto-connect 找不到文件,连不上。

那能不能用默认目录启动 Chrome?试了,Chrome 146 直接拒绝:

DevTools remote debugging requires a non-default data directory. Specify this using --user-data-dir.

这就形成了一个设计上的死结:

  • Chrome 要求:remote debugging 必须用非默认 --user-data-dir
  • user profile 的 autoConnect 要求:Chrome 必须用默认 --user-data-dir

两条规则互相矛盾,在需要 remote debugging 的场景下,profile="user" 设计上就不可用。这种”两个模块各自逻辑正确,组合在一起却完全不工作”的情况,正是复杂系统问题的典型特征。

四、为什么 AI 编程解决不了这些问题

1. 生成容易,验证难

AI 能在几分钟内生成一个看起来正确的 PR,但审核这个 PR 是否安全可能需要几小时–因为复杂系统里,验证成本远高于生成成本。一个改动是否安全,取决于它对整个系统运行时行为的影响,这需要”运行时的体感”,而不仅仅是静态代码分析。

2. 边界条件覆盖不足

CI 跑的都是标准路径,但真实用户的运行环境千差万别:root 用户、非默认 Chrome 目录、自定义 agent workspace、多个补丁共存……这些边缘组合 AI 和 CI 都覆盖不到。只有真正在复杂环境中深度使用的用户才会碰到。

3. PR 质量稀释

AI 降低了提 PR 的门槛,大量”看起来对”的 PR 涌入。维护者审不过来,审核变慢,着急的功能合并慢,不着急的 bug 一直挂着。甚至维护者可能也用 AI 辅助 review–AI 写的代码 AI 审,形成信息茧房。

4. 理解系统 vs 写代码

软件复杂度到一定程度后,理解系统行为写代码难得多。AI 擅长后者,不擅长前者。它能写出局部正确的代码,但很难预判这个改动在特定上下文大小、特定序列化路径、特定模块组合下会触发什么连锁反应。

五、结论:AI 提效是真的,但别吹过头

我们不否认 AI 编程的价值–它能显著提升开发效率,降低编程门槛,让更多人能参与开源贡献。这些都是真实的。

但把 AI 编程吹成”颠覆式””革命性””取代程序员”,至少在复杂系统工程上,还没有被验证。

我们用 OpenClaw 的实际体验就是最好的反例:一个 AI 编程构建的产品,用户每天都在给它擦屁股。6 个 patch 每次升级重新打,浏览器 profile 设计上不可用,PR 审核慢到用户被迫自己修 bug……这些都是 AI 编程在复杂系统面前的真实局限。

AI 能提效,但复杂系统的边界条件、模块交互、运行时行为–这些地方仍然是人类工程师的领域,至少目前是。

与其说 AI 会取代程序员,不如说 AI 正在倒逼程序员升级:从”写代码的人”变成”理解系统的人”。前者 AI 已经能做,后者才是真正的核心竞争力。

阿里云自然语言运维实战:一次恶意爬虫攻击的完整防御

故障:博客网站突然变慢

今天下午,我的博客网站(挂在阿里云 ECS 上)访问变得非常慢。直觉告诉我:大概率是被爬虫盯上了。

和以往不同的是,这次我没有像往常一样打开终端敲命令、翻日志、查配置。而是打开阿里云控制台的 Workbench Agent,在对话框里用中文描述故障现象,Agent 自动接管了后续所有排查工作。

四轮排查:层层抽丝剥茧

整个排查过程分四轮,全程通过自然语言对话完成。我只需要描述现象、确认执行建议,Agent 自动生成命令、分析日志、配置防护。

第一轮:发现恶意爬虫

爬虫名称 请求次数 风险说明
MJ12bot 1892 超高频,无公司背书,典型内容采集器
YisouSpider 617 疑似伪造 User-Agent,不实为神马搜索
ris-bot 少量 伪造本地域名 ris.local,恶意扫描

Agent 没有简单地建议封 IP,而是指出关键思路:封 IP 不是好办法,因为攻击 IP 会变化,要根据特征来封。于是基于 User-Agent 特征创建了 Apache Rewrite 规则,返回 403 Forbidden。

第二轮:伪造的浏览器

拦截爬虫后 CPU 仍然高达 84%。Agent 排除已拦截对象,扫描日志中的异常 User-Agent:

User-Agent 请求次数 破绽
Chrome/142 (Win10) 5053 Chrome 真实最新稳定版 ~125
Chrome/145 (Win10) 4916 同上,版本号明显伪造
Edge/145 (Win10) 4922 Edge 也没有 145 版本

每批 4900~5000 次请求,伪装成正常浏览器,但在 Agent 眼里无所遁形。

第三轮:Slowloris 慢速攻击

CPU 仍未降低。Agent 换了个角度——直接检查 TCP 连接层的状态。用 ss -tnp 检查 80 端口时,发现关键证据:某个 IP 的 Recv-Q = 939, Send-Q = 0。客户端连接上了,但只发了一部分请求头就卡住了。

这就是经典的 Slowloris 慢速攻击。靠”挂” Apache 进程——大量 IP 每个建 2 个连接保持半开,慢慢把进程池占满。

Agent 给出方案:iptables 限制单 IP 并发 ≤20,Apache 层面关闭 KeepAlive。

同时发现 Facebook 爬虫群(Meta AS 网段 69.171.x.x)在反复探测 /opt/gforge5/www/robots.txt。每条 403 响应本身也在消耗 CPU。

一个老系统的天花板

Agent 建议启用 Apache 的 mod_reqtimeout 模块来原生防御 Slowloris。检查后发现当前系统是 CentOS 6.3,2020 年就已 EOL,最高只支持 httpd 2.2.x,装不了 mod_reqtimeout 或 mod_evasive。

AI 总结道:当前多层防护已经是这个系统 Apache 层面能做到的天花板了。

短期策略:现有防护基础上,开启阿里云 DDoS 基础防护。长期策略:迁移至 AlmaLinux 8+ 获得 httpd 2.4 原生防护能力。

最终生效的五层防护

措施 状态
UA 特征拦截 MJ12bot / YisouSpider / ris-bot / Chrome/14x → 403 [OK]
路径拦截 /opt/gforge5/ → 403 [OK]
连接限制 iptables 单 IP ≤20 并发 [OK]
静态黑名单 高频攻击 IP → DROP [OK]
服务调优 MaxClients=20 / Timeout=30 / KeepAlive Off [OK]

感受:运维方式的范式变化

这次从发现故障到完全解决,全程通过自然语言对话完成。

传统模式:SSH 登录 → tail 日志 → 分析 IP → awk 排序 → 写配置 → 校验 → 重载 → 再观察 → 循环。每个循环五到十分钟,四到五轮下来至少半小时,还容易遗漏。

对话模式:看到什么说什么。Agent 自动决定分析逻辑,自动写出正确的命令,自动配置规则,甚至主动发现用户没想到的问题。操作者只管做决策和确认。

第三部分:性能优化建议导致的崩溃事故

前文介绍了四层防御体系的搭建过程。然而在排查过程中,一起性能优化建议导致的崩溃事故让情况雪上加霜。

问题:MaxClients 被错误调高到 50

当时正常访问变慢,为了提升并发性能,AI 助手提出建议:MaxClients 20 → 50。这个数字看起来只是乘以 2.5 的变化,但对于一台内存仅 1.9GB 的老服务器来说,这是致命的:

MaxClients 50 的内存账:
  50 × 50MB (空闲) = 2.5 GB → 已超物理内存
  50 × 150MB (PHP)  = 7.5 GB → 直接炸
可用内存:1.9 GB + 0 GB Swap = 1.9 GB
需求 2.5 GB > 1.9 GB → OOM

系统反复 OOM 崩溃

MaxClients=50 导致系统内存快速耗尽,OOM Killer 反复杀 httpd 进程。新请求进来 → 起新进程 → 内存不足 → 杀进程 → 再来请求 → 循环。最终操作系统完全无法启动:

阿里云诊断报告:Linux 实例因内存溢出(OOM),操作系统无法正常启动。错误代码:1684829582。

关键时刻的正确决策:果断停掉了 80 端口 httpd 服务,切断了 OOM 循环。系统内存压力解除后,才通过阿里云 VNC 进入系统修复。

Workbench Agent 再次出手:精准定位 OOM 根因

进入系统后,通过 Workbench Agent 继续分析,精准定位了 OOM 根因。从 /var/log/messages 提取到 OOM 记录:

Jul  7 16:48:16 kernel: Out of memory: Kill process 1983 (httpd) score 27
Jul  7 16:48:23 kernel: Out of memory: Kill process 1985 (httpd) score 27
Jul  7 16:48:28 kernel: Out of memory: Kill process 1987 (httpd) score 27
...(每 3 秒被杀一个,连续 10+ 个)

Workbench Agent 正确判断出:每个 PHP 请求时进程内存飙升到 120~150MB,根本解决方案是降低 MaxClients + 增加 Swap。Workbench Agent 将 MaxClients 紧急降到 8,创建了 2GB Swap。后续在 8 和 20 之间做了平衡测试,最终确认为 MaxClients=20 + 2GB Swap。

最终修复结果

MaxClients: 50 (错误建议) → 8 (紧急) → 20 (平衡值)
Swap:       0 GB → 2 GB
Timeout:    60 → 30
KeepAlive:  On → Off

最终防护体系(七层)

层级 措施 防御目标
Apache UA 特征拦截 facebook / MJ12bot / YisouSpider / ris-bot / Chrome/14x / Go-http-client → 403 已知恶意爬虫 + 伪造浏览器
Apache 路径拦截 /opt/gforge5/ → 403 敏感目录探测
Apache 服务调优 MaxClients=20 / Timeout=30 / KeepAlive Off 防资源耗尽 + 防 Slowloris
网络层并发限制 iptables 单 IP ≤ 20 并发 防分布式 CC
自动封禁 cron 每 5 分钟扫描空 UA 高频 IP → DROP 动态封禁新攻击源
内存保护 2GB Swap + MaxClients=20 防 OOM 崩溃
目录列表禁用 Options -Indexes 防路径枚举

核心教训

教训一:优化建议必须算资源账

AI 助手在不知道服务器具体内存的情况下,直接建议 MaxClients 20 → 50,犯了想当然的错误。正确做法是先 free -m 查看内存,再计算:MaxClients = (可用内存 – 预留) / 单进程峰值内存。

教训二:错误的优化建议比攻击更危险

今天这个案例中,攻击者只是造成了访问变慢,而错误的优化建议直接导致了系统崩溃。性能调优必须先看资源余量,不能凭感觉给数字。

后续维护

所有爬虫规则统一维护在 /etc/httpd/conf.d/block-bots.conf。发现新威胁只需在该文件追加 RewriteCond 行并重启 Apache。

自动封禁脚本

通过 cron 每 5 分钟扫描一次,发现空 UA 或 4xx/5xx 高频探测的 IP,自动 DROP 封禁:

*/5 * * * * /usr/local/bin/block-bots.sh

脚本源码:

#!/bin/bash
# 增量读取日志,无时间过滤,只处理新增访问记录
LOG_FILE="/var/log/httpd/access_log"
BLOCK_LOG="/var/log/block-bots.log"
OFFSET_FILE="/tmp/log_offset.dat"
TMP_FILE="/tmp/hack_ip_$(date +%s).txt"
NEW_BLOCK=0
> "$TMP_FILE"
[ ! -f "$LOG_FILE" ] && exit 0
# 读取上次读取位置,无记录则从0开始
last_pos=0
[ -f "$OFFSET_FILE" ] && last_pos=$(cat "$OFFSET_FILE")
current_pos=$(stat -c %s "$LOG_FILE")
# 日志被切割/清空,重置偏移量
if [ "$current_pos" -lt "$last_pos" ]; then
    last_pos=0
fi
# 只读取增量内容,使用tail替代dd
if [ "$last_pos" -eq 0 ]; then
    cat "$LOG_FILE"
else
    tail -c +$((last_pos + 1)) "$LOG_FILE"
fi | awk '
{
    ua = $NF; req = $7; code = $9; is_hack = 0;
    # 规则1:5xx服务器错误(注入触发崩溃)
    if (code ~ /^50[0-9]$/) is_hack = 1;
    # 规则2:SQL注入特征(只用url编码%27,去掉裸'"'"'避免shell冲突)
    if (req ~ /%27|AND|OR|nvOpzp|%3C%27/) is_hack = 1;
    # 规则3:空UA扫描器
    if (ua == "-") is_hack = 1;
    # 规则4:敏感目录扫描
    if (req ~ /cgi-bin|\/blog\//) is_hack = 1;
    # 规则5:HEAD探测扫描
    if ($6 ~ /^HEAD$/) is_hack = 1;
    # 规则6:恶意爬虫UA
    if (ua ~ /MJ12bot|YisouSpider|Chrome\/14[0-9]|Go-http-client|DotBot/) is_hack = 1;
    if (is_hack) print $1;
}' | sort -u > "$TMP_FILE"
# 更新偏移量,记录本次读到的位置
echo "$current_pos" > "$OFFSET_FILE"
# 批量封禁恶意IP
while read -r ip; do
    # 校验合法IPv4
    if [[ ! $ip =~ ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ ]]; then
        continue
    fi
    # 跳过已封禁IP
    if iptables -C INPUT -s "$ip" -j DROP 2>/dev/null; then
        continue
    fi
    iptables -A INPUT -s "$ip" -j DROP
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] BLOCK $ip | 增量日志检测高危注入/扫描攻击" >> "$BLOCK_LOG"
    NEW_BLOCK=1
done < "$TMP_FILE"
# 新增封禁IP则保存iptables规则
[ $NEW_BLOCK -eq 1 ] && iptables-save > /etc/sysconfig/iptables
# 清理临时文件
rm -f "$TMP_FILE"
# 封禁日志自动轮转(超过10MB备份)
LOG_SIZE=$(du -k "$BLOCK_LOG" 2>/dev/null | awk '{print $1}')
if [[ -n "$LOG_SIZE" && "$LOG_SIZE" -gt 10240 ]]; then
    mv "$BLOCK_LOG" "${BLOCK_LOG}.$(date +%Y%m%d)"
    > "$BLOCK_LOG"
fi

日志巡检命令

awk '$9 ~ /^(40[0-9]|50[0-9])$/ && !/MJ12bot|YisouSpider|ris-bot|Chrome\/14[0-9]|facebookexternalhit|meta-externalagent|Go-http-client|DotBot|facebot/' /var/log/httpd/access_log | tail -n 20

筛出”被拦截但不在已知名单里”的请求,就是新威胁线索。

最终 block-bots.conf

RewriteEngine On

# 1. 优先拦截空User-Agent(扫描器常用无UA请求)
RewriteCond %{HTTP_USER_AGENT} "^$"
RewriteRule .* - [F,L]

# 2. 合并所有恶意爬虫UA,一条规则搞定,消除重复
RewriteCond %{HTTP_USER_AGENT} "(facebookexternalhit|meta-externalagent|Facebot|facebook|MJ12bot|YisouSpider|ris-bot|Chrome/14[0-9]|Go-http-client|DotBot)" [NC]
RewriteRule .* - [F,L]

# 3. 拦截频繁HEAD探测 /blog/ 路径
RewriteCond %{REQUEST_METHOD} HEAD
RewriteRule ^/blog/ - [F,L]

# 4. 拦截SQL注入特征(同时匹配URI + QUERY_STRING)
RewriteCond %{REQUEST_URI} (\%27|'|AND|OR|UNION|SELECT|--|#|;) [NC,OR]
RewriteCond %{QUERY_STRING} (\%27|'|AND|OR|UNION|SELECT|--|#|;) [NC]
RewriteRule ^ - [F,L]

# 5. 高危扫描目录拦截
RewriteRule ^/cgi-bin/ - [F,L]

# 6. 业务敏感目录拦截
RewriteCond %{REQUEST_URI} "^/opt/gforge5/" [NC]
RewriteRule .* - [F,L]

修改后执行 service httpd restart 生效。

大模型语料体系、训练技术与中外能力差距深度研究报告

一、报告概述

本报告基于当前大模型领域的公开技术文献、行业研报与头部厂商(OpenAI、Anthropic、DeepSeek、阿里等)的公开实践,系统梳理八大核心议题:大模型训练的底层 Scaling Law 逻辑、人类语料的历史结构与质量权重(含古籍蓝海)、AI 数据污染与模型坍塌风险、头部厂商技术路线差异(MoE 与稠密架构取舍)、数据成本结构、模型蒸馏的真实定位与天花板、中外大模型核心差距与国产差异化超车。

二、核心底层逻辑:大模型能力的决定性因素

大模型最终能力由两大核心维度共同决定,遵循行业公认的缩放定律(Scaling Law),在预训练阶段边界清晰:

维度 核心作用 关键实证 边界约束
预训练语料(数量+质量+稀缺性) 决定模型能力理论上限 DeepMind Chinchilla 计算最优定律(2022, arXiv:2203.15556):最优模型应满足 D约等于20N(每1个参数配20个训练token);Gopher 280B参数仅喂300B token(D/N约1),性能不及同算力下70B参数喂1.4T token 数据不足时,盲目堆参数只会浪费算力
训练与对齐算法、架构创新 决定模型现有数据利用率 Llama系列实证:同70B参数下,训练数据从2T增至15T tokens(Llama 2到Llama 3),MMLU从68.9%升至82.0% 算法无法突破数据本身的知识边界
测试时计算(o1/R1类推理扩展) 后训练阶段打开新增量 DeepSeek-R1 纯RL+GRPO达到o1级推理能力 基座能力天花板仍由预训练语料决定

简言之:预训练阶段,数据定上限,算法挖潜力,二者缺一不可;测试时计算(o1/R1类推理扩展)为后训练阶段打开新增量,但基座能力天花板仍由预训练语料决定。

三、人类历史语料结构、体量与能力权重配比

3.1 语料体量占比

目前行业暂无绝对精准的全域量化统计,所有语料体量配比均为学术机构(Epoch AI、谷歌图书等)基于公开存量的合理估算区间,无绝对精确定值,本报告去除虚构精准百分比,采用严谨客观表述:

语料类别 体量估算 核心特征 质量评级
2000年前人类印刷语料(古籍、绝版图书、近代专著、学术典籍) 极小(全球独有书籍总存量约数十T token级,其中2000年前古籍仅占极小份额) 高质量、低噪声、长逻辑文本核心载体 高价值稀缺
2000-2020年人类印刷新书(现代专著、教材、科技文献等) 远超2000年前古籍,是印刷语料绝对主体 无AI污染原生文本,但全部印刷语料总存量(估约20T token级)仍远低于互联网文本体量 高价值
2000-2020年互联网人类原生语料(论坛、博客、百科、技术社区) 约3100T token(Epoch AI估算),单Common Crawl开源快照即达130T token,是全部印刷书总量的6倍以上 覆盖日常常识、通用知识、多元观点,但噪声、碎片化、冗余问题突出 基础数据

3.2 语料能力权重占比(模型实际能力贡献)

大模型能力贡献遵循「质量权重远大于体量权重」的核心规律,不存在行业统一精准量化比例,此前固定百分比为不实杜撰,现基于公开实验证据给出客观技术逻辑:

语料类型 能力贡献 关键实验证据 定位
千年印刷/古籍类高质量长文本 承载完整逻辑链条、严谨论证体系、考据型事实知识与规范写作范式,单位价值极高 微软Phi系列仅用约20B token教科书级数据即达到万亿级网页数据训练模型的推理水平;Meta LIMA实验证明千条精选数据的对齐效果可媲美五万条普通数据;书籍类数据在所有主流模型(Llama、GPT等)训练配比中均被过采样5-10倍 小体量、高权重
海量互联网原生网页语料 主导模型日常对话流畅度、现代社会常识、通用语言范式、生活化应答能力 体量庞大、覆盖场景极广,但未经筛选的原始网页内容碎片化、观点混杂、冗余噪声多、论证深度不足;经严格质量过滤后的精品网页子集可部分弥补此短板,但仍无法完全替代书籍与学术文献的结构化知识密度 大体量、低权重、高冗余

3.3 国内古籍资源开采现状(核心蓝海增量)

据《中国古籍总目》(2013)首次摸清的家底,国内现存汉文古籍约20万种、3000余万册(全国古籍普查口径),整体开采率极低,增量空间巨大:

开采阶段 现状描述 占比评估
高清影像扫描(无结构化文本,无法用于模型训练) 占国内存世古籍大半;据国家古籍保护中心数据,20余万种中数字化不超8万种,且多数止步于影像层 大半
基础OCR文本化(异体字错漏、断句混乱、无商用训练授权、未人工精校) 占比不低;真正实现文本数字化的不足4万种 中低
扫描+高精度OCR+人工校对+结构化清洗+合规商用,可直接用于大模型预训练 整体占比极低。版权归属分散(整理者、出版社均持股权)是核心卡点,北大”识典古籍”等平台虽已上线4.7万部,但商用授权覆盖率仍低 极低

结论:海量古籍稀缺语料尚未被有效利用,是国产模型主场专属的差异化数据资产(海外汉学机构有零星数字化布局,但无动力做商用级LLM语料开采)。其核心价值集中在中文文史、古典文献、传统民俗、古代典章制度、东方传统数理与工艺知识领域,可显著补齐模型中文传统文化理解、古籍精读、文史考据、古典文本创作的能力短板,降低文史领域幻觉;但无法大幅提升数学、代码、现代科学逻辑等高阶推理能力,此类能力核心依赖现代科学文献与算法优化。

四、当前互联网数据核心危机:AI数据污染与模型坍塌风险

2020年后互联网内容发生结构性质变,浅层通用语料红利见顶,但基座预训练并未彻底失效,而是从”粗放爬取”转向”分层筛选+高价值保留”:

维度 核心发现 数据来源
AI生成内容占比 新增英文文章AI生成占比52%;新增网页含AI内容74.2%;全球新增约35%有AI痕迹 Graphite 2025; Ahrefs 2025; 帝国理工+斯坦福+互联网档案馆 2025
模型坍塌风险 学术界在小规模、低质量数据多代迭代场景下观测到的潜在风险,未在大厂生产级训练中被证实规模化爆发 Nature 2024 (Shumailov et al.)
头部厂商策略 分层过滤低质AIGC水文,保留2020年后权威、专业、人类原创、高时效性内容;同时重点依托2020年前无大规模AI污染的原生人类文本夯实基础能力 GPT-4, Claude, Llama 3 等主流模型均仍纳入2020后最新学术成果与行业数据
核心判断 易采浅层通用互联网语料(Common Crawl类)红利已接近见顶,Ilya Sutskever在NeurIPS 2024将此称为”数据峰值(Peak Data)”,喻为AI的化石燃料——有限、不可再生 NeurIPS 2024

未来模型竞争核心将转向古籍、绝版专著、垂域专业数据库等深层稀缺语料的开采与精细化利用。

五、大模型企业数据成本结构

以企业全年整体运营成本为统计口径,成本结构分层清晰,但基座预训练厂与垂类/定制化应用厂的口径差异显著,不可混用:

5.1 纯语料采购成本(买书、数据库、版权)

厂商类型 采购特征 代表案例
头部基座厂(OpenAI、Anthropic、DeepSeek) 语料采购为非核心支出,整体占运营成本比例偏低 News Corp对OpenAI $250M/5年;Reddit对Google $60M/年;NYT对Amazon $20-25M/年;Axel Springer对OpenAI约$13M/年——单看金额不低,但摊入单轮预训练$100M-500M+算力支出中占比有限
终端/垂类应用厂 多直接调用头部模型API或采购成品数据集做微调,极少自建预训练语料栈,语料采购成本更低 ——

5.2 全链路数据总成本

厂商类型 数据成本占比 算力成本占比 结构特征
头部基座厂 全链路数据成本为核心研发配套支出,占比显著高于纯采购 算力占总成本57%-70%(智谱招股书披露2024年算力服务费占研发70%+) 算力为绝对第一大刚性成本
垂类/定制化应用厂(企业私域微调、本地化部署) 数据工程(采集+清洗+标注)占比可达30%-50% 可反超算力硬件支出 与基座厂结构不同,数据工程为核心
垂直行业模型(医疗/法律) 高度依赖付费垂域专业数据库与定制标注,数据全链路成本占比最高 —— 数据为第一大成本

5.3 人工标注单价锚点(2025行业公开区间)

标注类型 单价区间 备注
通用偏好对比(RLHF简单) $0.10-$0.50/comparison ——
领域专家标注(医/法/码) $1.50-$8.00+/task ——
高端RLHF(Surge AI等为Anthropic主供) $100+/annotation 为Scale AI单价2-5倍

核心结论:基座预训练口径下,算力(GPU/数据中心租赁、集群运维)为绝对第一大刚性运营成本,远高于数据、人力、办公等其他支出。语料采购属一次性增量投入,算力为全年持续消耗支出。人工标注(SFT/DPO/RLHF)为独立成本科目,不归属语料采购。行业无公开精准统一的财务占比数值,此前固定百分比为杜撰内容,已全部删除。

六、头部厂商技术架构路线本质差异

厂商 架构类型 核心优势 核心短板 备注
OpenAI(GPT-4) 稀疏MoE架构(行业共识) 超大知识承载容量、规模化推理成本可控,适配海量通用与垂域语料训练 多专家路由复杂、训练工程难度极高 从未官宣GPT-5、GPT-6产品及架构细节,网传均为行业猜测
Anthropic(Claude全系列) 稠密Dense架构(行业普遍认为) 长文本极度稳定、幻觉极低、对齐简单、严谨性拉满,适配企业专业场景 推理成本极高、模型容量上限低于MoE架构 从未官方公开架构细节,此为行业基于性能特征与多方信源的推测
国产头部(DeepSeek为主) 全面押注MoE(DeepSeek-V3 671B MoE;Qwen-Max部分旗舰采用MoE,Qwen2.5-72B及以下为稠密) 超大模型容量消化稀缺古籍、工业、外文文献数据,以极低训练成本追平海外稠密模型能力 —— 属于算力约束下的最优解,是国产缩小差距的核心架构抓手

七、模型蒸馏的真实定位(破除行业最大误区)

7.1 核心定论

蒸馏不是国产模型缩小与海外头部差距的核心方法,仅为低成本辅助工具,无法弥补底层预训练语料与基座能力短板。Hinton原始蒸馏论文(2015)已明确:Student参数量与容量天生构成天花板,综合上限小于等于Teacher。

7.2 蒸馏的真实价值

价值维度 具体描述 典型案例
低成本补充微调对齐样本 规避海外天价人工标注成本 DeepSeek-R1用80万条自蒸馏CoT替代同等规模人工标注,按高端RLHF单价($100+/条)估可省$8M-$80M
模型轻量化落地 适配国产终端、中端算力设备 DeepSeek蒸馏Qwen/Llama 1.5B-70B系列
辅助初创企业快速落地商用模型 推理/代码任务可达教师85-95%能力,训练成本仅1/10-1/50 ——

7.3 蒸馏的绝对天花板(行业共识)

限制维度 具体说明
信息损失 仅拿输出层logit的经典蒸馏仅能复刻表层输出模板;即便升级到CoT/Feature蒸馏,仍无法获取Teacher底层预训练语料、中间推理表征的完整信息、长尾稀缺数据
能力天花板 学生模型综合上限小于等于教师模型,泛化能力弱、冷门任务崩盘、幻觉更高(DeepSeek-R1-Distill-Qwen-32B数学AIME与R1持平,但代码/通用能力仍低于R1,且无法复现R1基座的预训练知识)
不可替代性 完全无法替代基座预训练,不能弥补西方科学文献、绝版书籍的原生数据缺口;仅在基座已训好后可用于小模型迁移,不参与基座知识构建本身

八、中外大模型核心差距与国产差异化优势

8.1 国产客观短板(无法短期纯算法弥补)

短板领域 具体描述 数据规模
近代基础科学英文科研文献 PubMed、ArXiv、SpringerLink等高质量科研文献高度集中于英文生态 PubMed约3800万篇、ArXiv约240万篇、SpringerLink约1300万册
百年绝版西方数理教材 海外厂商在高质量清洗与合规商用层面占先 Epoch AI估英文科研/教材类”无AI污染黄金数据”存量仍由美/欧/日图书馆数字化主导
全球冷门工程理论语料 国产模型在纯英文前沿理论、全球通用科学通识上存在原生数据劣势 ——

8.2 国产独家不可复制优势(核心超车壁垒)

优势维度 具体描述 核心数据/案例
海量未开采中文古籍 海外汉学机构仅有零星学术级数字化,无动力做商用级LLM语料开采,形成主场专属的高阶逻辑与文史能力壁垒 《中国古籍总目》:国内现存汉文古籍约20万种、3000余万册(详见3.3)
国内独家工业/工程/政务/临床数据组合 西方模型在”国标场景+中国人群”组合下完全缺失,是西方模型无法复刻的落地类科学数据 高铁(中国8万公里+国标)、特高压电网(全球特高压80%+在中国)、国产制造(比亚迪/宁德/华为产线+国标供应链)、GB国标规范、本土医疗(中国人群+中医+国产器械)
自研无标注强化算法 DeepSeekMath首提GRPO,DeepSeek-R1首次用纯RL(无监督CoT标注)+GRPO推至o1级 AIME 2024 79.8%(o1-preview 74.4%、GPT-4o约50+),MATH-500 97.3%(o1 93.4%),Codeforces 96.3% percentile
中英双语联合预训练+可控合成数据 国产模型中文能力追平/反超GPT-4中文;配合可控合成数据内生补充外文科学数据缺口,摆脱海外API蒸馏依赖 Llama 2 C-Eval中文约30-40%、CMMLU约30+;Qwen2-72B C-Eval 84.2、CMMLU 83.8;DeepSeek-V3 C-Eval 88.5、CMMLU 87.2

九、行业核心争议定论:国产模型是否靠”蒸馏偷窃”海外技术?

9.1 关于Anthropic CEO观点的客观评析

Anthropic CEO Dario Amodei在2024年WSJ访谈中点名”中国模型通过API蒸馏获取数据”,该言论需分两层看:

层次 核心观点 关键事实
合规层 OpenAI、Anthropic的ToS均明文禁止”用模型输出训练竞争性模型”(OpenAI ToS Sec. 2.2) 2024年OpenAI曾发文暗指DeepSeek-V3可能用其输出蒸馏,DeepSeek否认并称全自主预训练+自研数据
技术归因层 Dario把”国产模型能力追上来”归因于”蒸馏海外”,被行业主流(Yann LeCun等)质疑 LeCun公开表态”蒸馏是行业通用做法,OpenAI自己也做过,单点中国不合适”

纯逻辑反证 + GLM-5.2实证(2026.6智谱旗舰,对标2026美Top现役GPT-5.5 / Claude Opus 4.8 / Gemini 3.1 Pro):Hinton蒸馏理论(2015)已明确Student综合能力小于等于Teacher,且Student的偏科方向基本继承自Teacher。若国产靠蒸Claude Opus 4.8(HLE 41.4、Terminus-2 84、AIME 2026 98.3,强Agent/Coding、数学/综合推理偏弱)或GPT-5.5(HLE 45、SWE-bench Pro 54.2、AIME 2026 98.2,强综合推理、Agent/Coding弱于Claude),Student天花板锁死在Teacher的偏科形态,不可能出现GLM-5.2(智谱2026.6,744B MoE、激活40B、28.5T自主预训练、Slime异步RL自研)这种全科均衡高的结果——HLE 40.5(工具辅助54.7,超Opus 4.8的52.2 / GPT-5.5的51.4)、AIME 2026 99.2、SWE-bench Pro 62.1(超GPT-5.5的54.2)、Terminus-2 81.0(追Opus 4.8的84)、Artificial Analysis开源SOTA 51分。单蒸Claude(强Agent弱数学)或单蒸GPT-5.5(强综合弱Agent)都出不了GLM-5.2这种”HLE 40.5 + SWE Pro 62 + Terminus 81 + AIME 99.2 + AA开源SOTA”的全科组合——这件事本身就在逻辑上证伪了”国产靠蒸海外追上”。国产与美Top2旗舰的剩余差距(GPQA 91.2 vs Opus 4.8 93.6 / GPT-5.5 94.3,差2-3pt),真凶是英文语料短板(8.1节)+ H100禁运 + 时间积累,不是”因为用了蒸馏”。

GLM-5.2与海外Top旗舰Benchmark对比

Benchmark GLM-5.2 Claude Opus 4.8 GPT-5.5 Gemini 3.1 Pro 说明
HLE(无工具) 40.5 41.4 45 45 综合推理,接近o1-pro级
HLE(工具辅助) 54.7 52.2 51.4 超Claude Opus 4.8、GPT-5.5
AIME 2026 99.2 98.3 98.2 98.2 数学顶格
GPQA Diamond 91.2 93.6 94.3 博士级推理,略低于Top2但属第一梯队
SWE-bench Pro 62.1 58.6 54.2 超GPT-5.5
Terminus-2(终端) 81.0 84 74 追Claude Opus 4.8
Artificial Analysis Intelligence Index 51(开源SOTA) 闭源 闭源 闭源 开源权重第一

9.2 蒸馏为何解释不了国产的追赶——量化证据

即便放下合规问题,”蒸馏海外基座”这条路本身也走不到GLM-5.2 / R1现在的位置,三层:

层次 核心论点 关键证据
理论天花板 Student参数量与容量构成硬上限,综合能力小于等于Teacher;且Student偏科继承Teacher——蒸单一海外Top基座出不了全科均衡高模型 Hinton 2015, arXiv:1503.02531。Claude Opus 4.8强Agent/Coding(Terminus-2 84)弱HLE数学(41.4),GPT-5.5强综合推理(HLE 45)弱Agent/Coding(SWE Pro 54.2),单蒸任一个都出不了GLM-5.2的HLE 40.5 + SWE Pro 62.1 + Terminus-2 81组合
业界实证 蒸馏海外Top基座的Student在综合benchmark上普遍掉10-15pt,且代码/推理/长尾掉得更狠 业界半公开尝试(如Llama系模型蒸馏GPT-4输出做对齐补充)显示,无任何公开案例显示”蒸海外Top基座能反超Teacher本人或产出全科均衡反超”,与Hinton天花板一致
国产自主体系硬证据 DeepSeek-V3、R1、GLM-5.2均为自主预训练+自研算法,非蒸馏海外基座 DeepSeek-V3:14.8T token中英双语自主预训练;DeepSeek-R1:GRPO纯RL、无监督CoT标注,AIME 79.8 > o1-preview 74.4(注:R1与o1-preview为2025初同期对标,GLM-5.2已进入2026美Top现役对标档),R1的CoT是RL涌现的(o1的CoT不对外开放);GLM-5.2:744B MoE、28.5T自主预训练、Slime异步RL自研(智谱GLM-5技术报告,2025.8)

技术注:辨析两类”蒸馏”

业界所谓”蒸馏”至少含两类,Dario言论里被混用了:

类型 定义 合规性 典型案例
logit KL蒸馏 Hinton 2015原义,调API拿输出训自己——也是OpenAI ToS禁止的那种 违反海外厂商ToS OpenAI ToS Sec. 2.2所禁止的行为
CoT数据蒸馏 / 拒绝采样SFT 用自家模型的CoT当SFT数据训小模型,Teacher是自家模型不是海外基座,logit未外露 不违反ToS(Teacher为自有模型) DeepSeek-R1-Distill系列:用R1的CoT训Qwen/Llama小模型

补充注脚:蒸馏在大模型训练全生命周期中的应用

蒸馏本身并非单一动作,而是贯穿预训练加速(TinyBERT)、指令微调(Alpaca用GPT-3.5生成数据)、对齐(dDPO跳过RLHF)、端侧压缩(DistilBERT、Phi-3-mini)全生命周期的通用技术手段,Meta/微软/HF均有广泛使用;Dario所指责的”抓取API输出训竞品”仅对应指令微调阶段的一种特定用法。

结论:Dario类”蒸馏偷窃”归因,合规层可指个别违规(国内确有厂商早期抓过海外API),但技术归因不成立——纯逻辑上”蒸Claude Opus 4.8或GPT-5.5单蒸任一个都出不了GLM-5.2的全科组合”,GLM-5.2全科均衡高 + 28.5T自主预训练 + 744B MoE自研架构这一事实本身就证伪了”国产全靠蒸海外”;国产剩余差距(GPQA差2-3pt)的真凶是数据+算力+时间,不是蒸馏。

十、最终核心结论与未来趋势

结论维度 核心判断
语料竞争逻辑迭代 通用浅层互联网人类语料的能力红利已逐步释放完毕(Ilya Sutskever在NeurIPS 2024称此为”数据峰值Peak Data”,喻为AI的化石燃料——有限、不可再生;Epoch AI估全网文本存量约3100T token,但易采浅层Common Crawl类已被多轮挖掘,2025年新增内容AI痕迹占比已达35%-52%)。行业增量空间转向古籍、绝版专著、垂域专业数据库等深层稀缺语料开采
古籍差异化能力壁垒 国内现存汉文古籍约20万种、3000余万册,开采率极低(详见3.3),可持续强化模型中文文史、古典文献、传统国学、东方传统工艺数理等专属能力,构建海外模型在”国标场景+中国人群组合”下无法复刻的中文文明场景差异化壁垒;古籍中传统算学/工艺数理属文史逻辑范畴,不赋能现代形式化数学、代码、前沿科学推理
国产模型理性超车路径 仅靠算法优化、模型蒸馏无法实现全方位无短板超越海外头部模型。国内核心突围路线为「本土独家差异化语料 + 适配算力的MoE稀疏架构 + 自研无标注强化算法 + 内生合成数据补全外文短板」四维体系
行业竞争格局深度升级 大模型早期竞争以算力规模、通用网页数据体量为核心(基座厂算力占总成本57%-70%;垂类/定制化厂数据工程占比可达30%-50%,结构已分化),当前已迭代为独家稀缺语料资源、专业化数据工程体系、自主可控训练与对齐算法的核心壁垒竞争

参考文献

一、论文与 arXiv 预印本

序号 文献信息
[1] Kaplan J, McCandlish S, Henighan T, et al. Scaling laws for neural language models. arXiv:2001.08361, 2020.
[2] Hoffmann J, Borgeaud S, Mensch A, et al. Training compute-optimal large language models. arXiv:2203.15556, DeepMind, 2022.
[3] Hinton G, Vinyals O, Dean J. Distilling the knowledge in a neural network. arXiv:1503.02531, 2015.
[4] Shumailov I, Shumaylov Z, Zhao Y, et al. AI models collapse when trained on recursively generated data. Nature, 2024.
[5] Gunasekar S, Tsipras D, et al. Textbooks are all you need. Microsoft Research, 2023.
[6] Zhou C, Liu P, Xu P, et al. LIMA: less is more for alignment. Meta, 2023.
[7] DeepSeek-AI. DeepSeekMath: pushing the limits of mathematical reasoning in open language models. arXiv:2402.03300, 2024.
[8] DeepSeek-AI. DeepSeek-R1 technical report. 2024.
[9] Villalobos P, Sevilla J, Heim L, et al. Will we run out of data? An analysis of the limits of scaling datasets in machine learning. arXiv:2211.04325, Epoch AI, ICML 2024.
[10] Penedo G, et al. FineWeb: decanting the web for high-quality LLM pretraining data. Hugging Face, 2024.
[11] Li Y, et al. DCLM: data-centric LLM benchmarking via filtered common crawl. 2024.

二、行业研报与机构

序号 文献信息
[12] Patel D, Wong G. GPT-4 architecture, infrastructure, training dataset, costs, vision, MoE. SemiAnalysis, 2023-07-10.
[13] Epoch AI. Will we run out of data? Limits of LLM scaling based on human-generated text. 2024 update.
[14] Graphite. State of AI content 2025: 52% of new English articles AI-generated. 2025.
[15] Ahrefs. AI content in the web: 74.2% of new pages contain AI content. 2025.
[16] Imperial College London, Stanford, Internet Archive. Estimating AI-generated content on the public web: ~35% of global new content with AI traces. 2025.

三、公开披露

序号 文献信息
[17] 北京智谱华章科技股份有限公司.首次公开发行股票招股说明书(申报稿).香港交易所,2024.
[18] OpenAI. How OpenAI’s models influenced DeepSeek’s performance and safety standards. OpenAI Official Blog, 2024-02.
[19] Amodei D. Interview on Chinese models distilling overseas API data. Wall Street Journal, 2024-05.
[20] OpenAI. Terms of service, Sec 2.2: restrictions on training competing models. 2023-11 update.
[21] Kang D. Human data is (probably) more expensive than compute for training frontier LLMs. Substack, 2025-08.

四、中文专项

序号 文献信息
[22] 《中国古籍总目》编纂委员会.中国古籍总目[M].北京:中华书局;上海:上海古籍出版社,2013.
[23] 国家古籍保护中心,全国古籍普查平台.全国古籍普查登记数据(汉文古籍约3000万册)[DB/OL].
[24] 北京大学数字人文研究中心.”识典古籍”平台(3年上线4.7万部)[EB/OL].

为什么企业需要制定AI使用分级规范

专题分析报告 | 2026年7月5日


一、核心命题

当员工与AI大模型交互时,他们不仅在”使用工具”,同时在”传授知识”。每一次对话都在将个人的专业判断、推理路径和领域经验无偿输送给AI模型公司。如果企业不对AI使用场景进行分级管控,本质上是在按月付费将自己的核心竞争力输送给第三方

这不是隐私问题,是知识产权问题和生存问题。

二、问题背景:五重趋势交汇

2.1 AI公司的”既卖铲子又挖金矿”模式

Anthropic在发布Claude Science科研工作台的同时宣布自研药物——作为AI工具提供商,它同时在成为客户的竞争者。这种模式在AI行业尚属首次,但正在蔓延。Google DeepMind的Isomorphic Labs、OpenAI的ChatGPT Health都在向垂直领域延伸。

含义:你的AI工具商,可能明天就是你的竞争对手。

2.2 数据主权觉醒已成全球趋势

  • 微软:内部禁用Claude,强制使用Copilot
  • 阿里:全域禁用Claude Code,必须使用通义灵码
  • 美团:推出LongCat后,内部强制用自家模型,用别家需审批
  • 欧盟:有人建议使用中国开源模型自部署,而非依赖美国闭源模型
  • Palantir CEO:公开警告AI大模型公司正在虹吸所有公司的专业知识

含义:大企业已经在行动,中小企业尚未觉醒。

2.3 用户协议实质是强制授权

对OpenAI、Anthropic、DeepSeek、智谱清言、豆包五家用户协议的横向对比显示:

公司 默认用于训练 用户能否退出 退出门槛
OpenAI 可退出,但”可能限制服务能力” 隐性惩罚
Anthropic 可通过账户设置退出 Feedback和安全审查除外
DeepSeek 可关闭”数据用于优化体验” 相对透明
智谱清言 需主动联系客服 门槛最高
豆包 协议未提及退出机制 无退出路径

结论:没有一家是默认不用于训练的。”不同意就别用”构成实质性强制授权。

2.4 个人隐私风险远超传统认知

传统隐私泄露的是静态信息(姓名、电话、身份证号)。AI对话泄露的是动态的、人格级别的信息——思维方式、情感状态、决策偏好、潜意识想法。一个人跟AI聊半年,比他配偶了解他的都多。

工信部已因此下架情感陪伴智能体,字节豆包和阿里千问均下线相关功能。监管正在收紧,但企业不能等监管——自己的核心知识等不起。

2.5 闭源模型估值逻辑面临重置

OpenAI/Anthropic的天价估值建立在数据飞轮叙事上:越多人用→数据越多→模型越强→更多人用。当企业开始撤回数据,飞轮中最高质量的数据源被掐断,估值将从”通用人工智能平台”回归到”正常软件公司”。

含义:AI公司有极强的动力继续吸收企业数据——这不是被动的副作用,是其商业模式的核心。

三、核心风险:知识虹吸的运作机制

3.1 人机交互是双向的

  • AI给人的:公开知识的重新组合、文字组织、代码生成——价值有限,可替代
  • 人给AI的:思维方式、推理路径、专业判断、领域知识、试错经验——价值极高,不可替代

3.2 认知错位是最致命的

  • 你跟同事讨论方案,你知道在交流
  • 你写文档,你知道在产出
  • 但你跟AI聊天时,你觉得自己在使用工具,不是在传授知识

这个认知错位导致员工在最没有防备的状态下,把最有价值的知识交了出去。

3.3 四类核心知识被虹吸

  1. 研发思路泄露 — 你问AI怎么解决某个技术难题,AI知道了你的研发方向和卡点
  2. 推理过程被学习 — 你跟AI反复探讨、迭代方案,你的推理路径被模型吸收
  3. 失败经验被白嫖 — 你告诉AI”这个方案不行,因为X”,这些试错经验是最昂贵的知识
  4. 领域知识蒸馏 — 你把行业专有知识喂给AI,AI转手就能卖给你的竞争对手

3.4 自杀式飞轮

你越用它,它越懂你的领域;它越懂你的领域,你越离不开它;最终你的核心竞争力变成了它模型里的一组权重,而你能被随时替代。付的费越多的重度用户,贡献的高质量知识越多,喂出来的模型越强,反过来对自己威胁越大。

四、囚徒困境与破局路径

4.1 囚徒困境

  • 不用AI → 竞争力落后于同行 → 被淘汰
  • 用公网AI → 核心知识被虹吸 → 被AI公司干掉
  • 私有部署 → 成本太高 → 中小企业扛不起

三条路看似都是死路。但短期无解,长期有解,关键在于时间差。

4.2 五条破局路径

  1. 开源模型追平 — DeepSeek、Qwen已在大量场景下够用,1-2年内差距可能缩小到可接受范围
  2. 行业联盟共建 — 非竞争企业联合部署开源模型,分摊算力成本,数据只在联盟内共享
  3. 国家公共AI基础设施 — 各地智算中心正在建设,企业提供数据在受控环境下微调,数据所有权不转移
  4. 分层使用策略 — 非核心业务用公网API,核心业务用本地模型,最值钱的知识留在本地
  5. 时间换空间 — 用最小代价获取AI能力的同时储备自部署能力,等开源模型和硬件成本到位时完成切换

4.3 最优策略:拖

不是”用或不用”的二选一,而是分场景使用 + 持续储备自部署能力,在开源模型能力追平、硬件成本降到可接受范围时完成切换。核心知识从一开始就不碰公网模型。

五、解决方案:AI使用分级规范

5.1 三级分类框架

[绿] 绿区——可以使用公网API

特征:即使数据被拿去训练,对核心竞争力零影响。

典型场景:通用文案撰写、翻译、格式转换;公开知识查询;代码格式化、注释生成(非核心逻辑);不含商业机密的会议纪要整理。

判断标准:信息来源本身是公开的、通用的。

[黄] 黄区——可以使用,但必须脱敏

特征:知识有价值,但去掉关键细节后模型学到的是”方法”不是”数据”。

典型场景:内部流程优化建议(去掉具体业务参数);通用技术方案评估(去掉核心算法细节);市场分析框架(去掉具体客户数据)。

判断标准:经过脱敏处理后,不暴露核心商业机密。

[红] 红区——绝对禁止使用公网API

特征:企业命根子,喂出去一次永远收不回来。

典型场景:核心算法设计、研发方案讨论;产品架构决策、技术路线选择;客户核心数据、供应链关键信息;商业模式创新、战略规划推演;试错经验、失败案例分析。

判断标准:一旦被模型吸收,将直接削弱企业核心竞争力。

5.2 落地步骤

  1. 盘点 — 梳理企业内所有AI使用场景,逐一标注红黄绿
  2. 设规 — 红区强制使用本地模型,黄区必须脱敏,绿区自由使用
  3. 给工具 — 红区必须提供可用的本地模型(哪怕是7B/14B小模型),否则员工会偷偷用公网的
  4. 做培训 — 告诉员工为什么不能把核心问题喂给公网AI——不是禁令,是认知
  5. 常审计 — 定期检查企业API调用记录,监控是否有红区内容泄露
  6. 动态调整 — 随着开源模型能力提升,持续将更多场景从黄区/绿区纳入可控范围

5.3 关键注意事项

  • 不能只靠制度 — 如果红区没有可用的本地替代方案,员工一定会偷偷用公网API。制度必须有工具支撑
  • 不能只靠培训 — 认知很重要,但没有制度约束的认知是不可靠的
  • 不能一劳永逸 — AI能力在快速变化,分级标准需要定期复盘更新

六、对不同类型企业的建议

大型企业(500人以上)

  • 立即启动AI使用分级梳理
  • 评估私有化部署方案(开源模型+国产算力)
  • 建立企业内部AI治理委员会
  • 将AI使用规范纳入信息安全管理体系

中型企业(50-500人)

  • 优先做红区隔离——至少把最核心的研发和战略讨论挡在公网API之外
  • 评估行业联盟共建模式
  • 选择1-2个开源模型进行小范围试点微调

小型企业(50人以下)

  • 至少做一件事:把核心研发讨论和客户数据从公网AI中隔离出来
  • 利用云厂商提供的私有化推理服务(数据不用于训练的版本)
  • 关注国家公共算力基础设施的开放机会

七、结论

AI使用分级规范不是”要不要做”的选择题,是”什么时候做”的生存题。

不做分级的企业,分两种结局:

  • 快死 — 核心知识被竞争对手通过AI模型获取,直接被碾压
  • 慢死 — 持续向AI公司输送领域知识,最终自己的核心竞争力变成别人模型里的权重

做了分级的企业,能在AI时代保持两个关键优势:

  • 效率优势 — 绿区场景充分利用公网AI的强能力
  • 安全优势 — 红区核心知识留在自己手里,不被虹吸

数据主权觉醒不是未来的趋势,是当下的现实。企业的AI使用分级规范,就是这场觉醒中最紧迫的落地动作。


本报告基于2026年7月5日沟通讨论整理。涉及的市场动态和公司政策信息均基于公开资料。

OpenClaw运维实战:HZERO Agent词典向量同步失败问题排查与修复

使用OpenClaw AI运维助手排查HZERO AIP Agent词典向量同步失败问题,从日志分析、根因定位到修复验证的完整过程。collection_name字段为空导致collectionName is blank异常,3分钟完成修复。

背景

在HZERO PaaS平台的AIP(AI Platform)模块中,Agent词典是AI智能体理解业务语义的关键组件。词典中的每个条目会被同步到向量数据库和ElasticSearch中,供Agent在对话时进行语义匹配。

某天在HZERO开发环境中,发现词典「对象使用方式」(编码:HMDE.BUSINESS_OBJECT.USE_TYPE)下的三个条目(CREATE、MODIFY、MATCHING)全部显示「(向量)同步失败」,而ES同步正常。向量同步时间停留在很久以前,ES同步时间则是刚刚更新的。

本文记录了使用OpenClaw(AI运维助手)从发现问题到定位根因、修复验证的完整过程。

问题现象

条目 向量状态 向量同步时间 ES同步时间
CREATE 🔴 同步失败 2025-06-03 08:00:00 2026-07-04 12:35:25
MODIFY 🔴 同步失败 2025-06-03 08:00:00 2026-07-04 12:35:25
MATCHING 🔴 同步失败 2025-06-03 08:00:00 2026-07-04 12:35:25

关键观察点:

  • 界面显示「向量库集合:haip_dictionary_value_0(已加载)」,看似配置正常
  • ES同步完全正常,只有向量同步失败
  • 三个条目同时失败,不是个别数据问题

排查过程

第一步:检查服务状态

首先确认AIP相关服务是否正常运行:

docker ps --filter name=hzero-aip --format "table {{.Names}}	{{.Status}}"

结果:hzero-aip-serverhzero-aip-app 均正常运行,排除服务宕机问题。

第二步:查看服务日志

检查AIP服务最近1小时的日志,过滤向量同步相关错误:

docker logs hzero-aip-server --since 1h 2>&1 | grep -iE "vector|向量|sync.*fail|embedding.*error" | tail -30

立刻发现大量重复错误:

ERROR - Unexpected exception occurred invoking async method: 
  DictionaryVectorRepositoryImpl.remove()

java.lang.IllegalArgumentException: collectionName is blank
    at CollectionRequest$Builder.build(CollectionRequest.java:87)
    at VectorDb.exists(VectorDb.java:125)
    at VectorDb.deleteByCondition(VectorDb.java:256)
    at DictionaryVectorRepositoryImpl.remove(DictionaryVectorRepositoryImpl.java:189)

核心错误:collectionName is blank — 向量集合名称为空。

第三步:检查数据库配置

错误明确指向集合名称为空,直接查数据库确认:

SELECT dictionary_id, dictionary_code, collection_name, sync_type 
FROM hzero_aip.haip_aigc_dictionary;

结果:

dictionary_id dictionary_code collection_name 状态
2 HMDE.BUSINESS_OBJECT.USE_TYPE (空) 🔴 问题所在
3 LOWCODE.DOMAIN (空) 🔴 同样有问题
7 HAIP.APPLICATION_LINK haip_dictionary_value_0 ✅ 正常

根因确认:词典ID 2和3的 collection_name 字段为空,而词典ID 7有值且正常。

第四步:分析为何界面显示正常但实际失败

这里有一个容易误导的点:界面上明明显示「向量库集合:haip_dictionary_value_0(已加载)」,为什么数据库里是空的?

通过进一步分析日志,发现同步流程分为两个阶段:

  1. remove阶段(清理旧向量):直接读取Dictionary实体的 collection_name 字段 → 为空 → 抛 collectionName is blank 异常 → 失败
  2. doSync阶段(写入新向量):通过其他途径(可能是全局配置或Redis缓存)获取到了集合名 haip_dictionary_value_0 → ES操作实际执行 → 成功

由于同步流程是「先remove → 后doSync」,remove阶段失败导致整个同步任务被标记为「失败」,尽管后续doSync的ES操作实际已执行。

界面显示的集合名来自运行时全局配置,而非该词典的 collection_name 字段,因此看起来「正常」。

根因总结

层面 说明
直接原因 haip_aigc_dictionary 表中部分词典的 collection_name 字段为空
触发条件 向量同步时 remove 阶段直接使用该字段,为空即抛 IllegalArgumentException
误导因素 界面通过全局配置显示集合名,掩盖了字段为空的事实
影响范围 dictionary_id=2(对象使用方式)和 dictionary_id=3(低代码领域)

修复方案与执行

修复SQL

UPDATE hzero_aip.haip_aigc_dictionary 
SET collection_name = 'haip_dictionary_value_0' 
WHERE dictionary_id IN (2, 3);

完整修复步骤

1. 执行SQL补全字段

docker exec mysql-hzero mysql -uhzero -phzero -e "
UPDATE hzero_aip.haip_aigc_dictionary 
SET collection_name = 'haip_dictionary_value_0' 
WHERE dictionary_id IN (2, 3);"

2. 清除Redis向量集合缓存

docker exec redis-hzero redis-cli -n 1 DEL   "haip:config:vector:collection:DEFAULT_ES"   "haip:config:vector:collection:DEFAULT"   "haip:config:vector:database"   "haip:config:vector:database:last-updated-time"

3. 重启AIP服务

docker restart hzero-aip-server

4. 界面重新触发向量同步

在HZERO AIP → Agent词典 → 对象使用方式 → 数据同步 → 向量同步

结果:三个条目全部显示「已同步」✅

OpenClaw运维价值体现

这个问题如果纯人工排查,典型流程是:看界面 → 查日志(在大量日志中找关键错误)→ 理解Java调用栈 → 关联数据库配置 → 发现字段为空 → 分析为何界面显示与实际不符。整个过程至少30-60分钟。

使用OpenClaw的排查过程:

步骤 操作 耗时
1. 服务状态检查 docker ps 确认服务运行 ~5秒
2. 日志错误提取 grep 过滤关键错误,定位异常堆栈 ~10秒
3. 数据库验证 SQL查询确认 collection_name 为空 ~5秒
4. 根因确认 分析调用链,解释界面与实际不一致的原因 ~10秒
5. 修复执行 SQL + Redis缓存清除 + 服务重启 ~30秒
6. 验证 用户界面触发同步,确认成功 ~1分钟

从问题报告到修复完成,全程约3分钟。OpenClaw的核心价值在于:

  • 快速定位:自动执行服务检查 → 日志分析 → 数据库验证的完整诊断链路
  • 准确分析:理解Java异常堆栈,关联数据库配置,解释表面现象与根因的差异
  • 安全修复:执行精确的SQL修复,清除相关缓存,重启服务,全流程闭环
  • 知识沉淀:问题分析过程自动记录到工作日志,便于后续回顾

经验总结

  1. 界面显示 ≠ 数据库实际值:HZERO很多界面字段来自运行时全局配置或缓存,不直接反映数据库字段值。排查问题时要以数据库为准。
  2. 同步流程是多阶段的:向量同步包含 remove → doSync 两个阶段,任一阶段失败都会标记整体失败。看日志要关注失败发生在哪个阶段。
  3. Redis缓存是常见陷阱:修改数据库后必须清除对应Redis缓存,否则服务可能仍读取旧值。这次修复也包含了缓存清除步骤。
  4. collection_name 是关键配置:HZERO AIP的向量同步依赖此字段,初始化环境时应确保所有词典都有正确的集合名。

环境信息

  • 平台:HZERO PaaS + AIP 1.6.1.ALPHA.6.13
  • 向量数据库:ElasticSearch(作为向量存储后端)
  • 缓存:Redis DB 1
  • 部署方式:Docker 容器化
  • 运维工具:OpenClaw AI运维助手

视频信息

 

视频演示

OpenClaw排查HZERO Agent词典向量同步问题全过程:

视频地址:https://www.bilibili.com/video/BV1uxMw6kEwG

AI Agent 问题排查实战:HZERO 低代码 AI 助手故障诊断与修复

一、背景

HZERO 低代码平台提供了「AI 助手」功能,用户通过上传界面截图或描述需求,AI 自动生成业务对象和页面。该功能由 AIP(AI 平台)的 Agent 编排实现,涉及 hzero-aip-apphzero-aip-serverhzero-modeler 等多个微服务协同。

测试过程中连续遇到两个错误,本文记录了作为 AI Agent 如何逐步分析、定位并解决问题的完整过程。

二、问题一:domainCode 缺失

2.1 现象

在 AIP 中台直接调用「AIGC 生成低代码业务对象和页面」Agent 编排,执行到「批量创建对象」节点时报错:

CommonException: 程序出现错误,请联系管理员

2.2 分析过程

第一步:看截图,定位错误节点

用户提供了错误截图,显示错误发生在流程的「批量创建对象」节点,异常类型为 CommonException,调用栈指向 AbstractInnerRequestNodeHandler.execute

判断方向:这是 Agent 流程中的内部接口调用节点,调用了低代码平台的后端接口,接口返回了错误。

第二步:查容器状态,确认服务存活

docker ps --format '{{.Names}}\t{{.Status}}' | grep -i aip

结果:hzero-aip-serverhzero-aip-app 都 Up 7 hours,排除服务宕机。

第三步:拉日志,精确定位错误

先看 hzero-aip-app(Agent 流程执行方)的日志,过滤错误关键词:

docker logs hzero-aip-app --since 30m 2>&1 | grep -i "error\|exception\|批量创建\|InnerRequest" | tail -50

找到关键错误:

ERROR --- Failed on node AIGC 生成低代码业务对象和页面/LOWCODE.BUSINESS_OBJECT_PAGE/INTERNAL_INTERFACE_...
io.choerodon.core.exception.CommonException: 程序出现错误,请联系管理员
  at ResponseUtils.getResponse(ResponseUtils.java:133)
  at AbstractInnerRequestNodeHandler.execute(AbstractInnerRequestNodeHandler.java:199)

这说明 aip-app 调用了某个内部接口,接口返回了非成功响应,ResponseUtils 解析后抛出通用异常。

第四步:查被调用方日志,找到真实错误

错误堆栈显示调用链终止在 aip-app,但真正的错误来自被调用的服务。查看 hzero-modeler 日志:

docker logs hzero-modeler --since 30m 2>&1 | grep -i "error\|exception\|simple-generator" | tail -30

找到根因:

MissingServletRequestParameterException: Required request parameter 'domainCode' for method parameter type String is not present
  Request: {URI=/v1/0/business-objects/domain/simple-generator}

第五步:回溯参数,确认 domainCode 为 null

回到 aip-app 日志,查看脚本节点的参数输出:

脚本节点参数:{businessObjectList=[...], domainCode=null, pageList=[...]}

确认domainCode 为 null,导致低代码平台接口报 400 错误。

2.3 根因

Agent 编排流程中,domainCode 需要从低代码平台的上下文中获取。用户直接在 AIP 中台调用 Agent 编排,没有进入低代码平台的领域上下文,导致 domainCode 为空。

2.4 解决方案

从低代码平台进入领域后调用 AI 助手。在低代码平台的工作台中先进入一个领域(如”调研问卷”),再点击 AI 助手按钮,这样 domainCode 会作为上下文参数自动传入 Agent 流程。

2.5 验证

用户从低代码平台领域内调用 AI 助手后,domainCode 正确传入(值为 RSHQ),第一个问题解决。

三、问题二:业务对象依赖顺序错误

3.1 现象

domainCode 问题解决后,AI 成功生成了业务对象和页面数据,但在「批量创建对象」节点再次报错:

CommonException: 业务对象[RS_MEMBERSHIP_CARD]不存在

3.2 分析过程

第一步:看截图,识别新错误

从截图看到错误信息变为「业务对象[RS_MEMBERSHIP_CARD]不存在」,不再是通用的”程序出现错误”,而是一个具体的业务校验错误。

判断方向:这次不是参数缺失,而是业务逻辑问题——接口在创建某个对象时,发现它依赖的另一个对象不存在。

第二步:查日志,确认调用链

docker logs hzero-aip-app --since 15m 2>&1 | grep -i "error\|RS_MEMBERSHIP\|不存在" | tail -30

找到:

ERROR --- Failed on node ...INTERNAL_INTERFACE_...
CommonException: 业务对象[RS_MEMBERSHIP_CARD]不存在

hzero-modeler 侧也确认:

Common exception, Request: {URI=/v1/0/business-objects/domain/simple-generator}
CommonException: 业务对象[RS_MEMBERSHIP_CARD]不存在

第三步:分析数据,发现依赖关系

从 aip-app 日志中提取 AI 生成的业务对象数据:

  • RS_MEMBER(会员信息):包含一个 MASTER_RELATION 类型字段 membershipCard,指向 RS_MEMBERSHIP_CARD
  • RS_MEMBERSHIP_CARD(会员卡信息):被 RS_MEMBER 引用

两个对象都是 CREATE 模式(新建),businessObjectList 中 RS_MEMBER 排在前面。

问题就在这里:批量创建时,RS_MEMBER 先被处理,它的 MASTER_RELATION 字段引用了还不存在的 RS_MEMBERSHIP_CARD,低代码平台校验依赖对象是否存在时失败。

第四步:审查脚本节点代码

用户提供了「页面&业务对象参数处理」脚本节点的完整代码。审查后发现两个问题:

  1. 没有依赖排序businessObjectList 按原始顺序传给 API,没有按 MASTER_RELATION 依赖关系排序
  2. masterBusinessObjectCode 未同步更新:脚本给 businessObjectCode 加了 domainCode 前缀(如 RSHQ_RS_MEMBER),但字段里的 masterBusinessObjectCode 没同步更新,仍指向旧编码 RS_MEMBERSHIP_CARD

3.3 根因

脚本节点缺少两个关键处理:

  1. 业务对象未按依赖关系排序,导致被引用对象排在引用者之后
  2. 加 domainCode 前缀后,MASTER_RELATION 字段的 masterBusinessObjectCode 指向了不存在的旧编码

3.4 解决方案

在脚本节点中增加两处修复:

修复 1:同步更新 masterBusinessObjectCode

在遍历 businessObjectFields 的循环中增加:

if(field.componentType === 'MASTER_RELATION' && field.masterBusinessObjectCode
   && boCodeToNewMap.has(field.masterBusinessObjectCode)) {
  field.masterBusinessObjectCode = boCodeToNewMap.get(field.masterBusinessObjectCode);
}

修复 2:拓扑排序

在 return 之前,对 businessObjectList 做 Kahn 拓扑排序:

function sortByDependency(objList){
  if(!objList || objList.length <= 1) return objList;

  var codeSet = {};
  objList.forEach(function(o){ codeSet[o.businessObjectCode] = true; });

  var deps = {};
  var inDegree = {};
  objList.forEach(function(o){
    deps[o.businessObjectCode] = [];
    inDegree[o.businessObjectCode] = 0;
  });

  objList.forEach(function(o){
    if(o.businessObjectFields){
      o.businessObjectFields.forEach(function(f){
        if(f.componentType === 'MASTER_RELATION' && f.masterBusinessObjectCode
           && codeSet[f.masterBusinessObjectCode]){
          deps[f.masterBusinessObjectCode].push(o.businessObjectCode);
          inDegree[o.businessObjectCode]++;
        }
      });
    }
  });

  var queue = [];
  objList.forEach(function(o){
    if(inDegree[o.businessObjectCode] === 0) queue.push(o.businessObjectCode);
  });

  var sorted = [];
  while(queue.length > 0){
    var code = queue.shift();
    var obj = objList.find(function(o){ return o.businessObjectCode === code; });
    if(obj) sorted.push(obj);
    deps[code].forEach(function(dep){
      inDegree[dep]--;
      if(inDegree[dep] === 0) queue.push(dep);
    });
  }

  // 循环依赖兜底
  if(sorted.length < objList.length){
    objList.forEach(function(o){
      var found = false;
      for(var i = 0; i < sorted.length; i++){
        if(sorted[i].businessObjectCode === o.businessObjectCode){ found = true; break; }
      }
      if(!found) sorted.push(o);
    });
  }

  return sorted;
}

3.5 验证

用户更新脚本节点后重新测试,业务对象和页面成功创建。

四、方法论总结:AI Agent 如何排查问题

4.1 排查框架

整个排查过程遵循一个清晰的框架:

截图/现象 → 服务状态 → 日志分析 → 参数回溯 → 代码审查 → 定位根因 → 修复验证

4.2 关键原则

原则 说明 实际应用
先看现象,不急于下结论 错误截图是最直接的信息源 第一次看到 CommonException 通用错误,不能止步于此,需要追查具体原因
服务存活先确认 排除基础设施问题 docker ps 确认容器都在运行
调用方与被调用方日志对照看 错误往往在被调用方 aip-app 抛通用异常,hzero-modeler 才有具体错误
参数回溯定位数据问题 日志中的参数数据是关键证据 从脚本节点日志中找到 domainCode=null 和 businessObjectList 的完整数据
代码审查发现逻辑缺陷 静态分析补充动态调试 审查脚本代码发现缺少排序和字段同步
一次只改一个问题 控制变量,便于验证 先修 domainCode,再修依赖顺序

4.3 工具使用策略

阶段 工具/命令 目的
服务检查 docker ps 确认容器存活状态
日志检索 docker logs --since + grep 精确过滤错误信息
参数分析 日志中的脚本节点参数输出 回溯传入接口的实际数据
代码审查 人工提供脚本源码 静态分析逻辑缺陷
修复验证 用户在平台上重新执行 端到端验证

4.4 AI Agent 的优势

在这次排查中,AI Agent 展现了几个独特优势:

  1. 多服务日志关联分析:同时查看 aip-app、aip-server、modeler 三个服务的日志,快速关联调用链,人工排查往往需要切换多个终端窗口
  2. 从海量日志中精准提取关键信息:在数万行日志中用 grep 精确定位到 3 行关键错误,避免了人工翻阅的眼疲劳
  3. 数据与代码交叉验证:从日志中提取业务对象数据结构,再对照脚本代码分析,快速发现两个缺陷
  4. 直接给出可执行的修复代码:拓扑排序算法、字段同步逻辑,不需要人工再翻译成代码

五、涉及的容器服务

服务 角色
hzero-aip-app AI 应用前端,执行 Agent 流程编排
hzero-aip-server AI 平台后端,处理 LLM 调用、知识检索
hzero-modeler 低代码建模服务,提供业务对象/页面创建 API
hzero-lowcode 低代码前端服务
hzero-lowcodedata 低代码数据服务

六、结论

两个问题的根因不同但都出在「参数传递」环节:

  1. 问题一是上下文参数(domainCode)未传入 — 需要从正确的入口调用
  2. 问题二是脚本节点对参数的处理不完整 — 缺少依赖排序和字段同步

修复后,AI 助手能够正确生成业务对象和页面,整个链路跑通。建议将脚本修复同步到产品主线版本。

HZERO 根据用户账号获取 Token 方案

问题背景

客户需求:在 HZERO 后端根据用户账号获取对应的 Token。客户原思路是”根据账号查出密码 → 解密 → 调用登录接口获取 Token”。

一、为什么”查密码→解密”方案不可行

HZERO 用户密码使用 BCrypt 单向哈希算法存储,数据库中保存的是哈希值,不可逆、不可解密。因此”从数据库查出密码 → 解密 → 调用登录接口”这条路在技术上走不通。

二、根据是否有用户明文密码,分两种方案

方案一:有用户明文密码 — 标准 OAuth2 password 模式

如果调用方持有用户的明文密码(例如用户自己输入),HZERO 原生支持标准 OAuth2 Password Grant,直接调用即可获取 Token,无需二次开发:

请求:

POST /oauth/oauth/token
Authorization: Basic <Base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=用户账号&password=明文密码

返回示例:

{
  "access_token": "***",
  "token_type": "bearer",
  "refresh_token": "***",
  "expires_in": 32399999,
  "scope": "default"
}

注意事项:

  • 端点路径是 /oauth/oauth/token(两层 oauth 路径,不是 /oauth/token
  • client_idclient_secret 使用项目实际配置的客户端凭据
  • 密码传输明文,建议接口走 HTTPS
  • Token 有效期可通过 OAuth 服务端配置调整

方案二:无用户明文密码 — 自定义登录接口(二开)

如果调用方没有用户密码(例如服务间调用、管理端代操作等场景),需要在 hzero-oauth 服务中进行二次开发,实现自定义认证流程。

HZERO 已提供了标准扩展组件 LoginTokenService,核心开发步骤如下:

1. 自定义认证对象 AuthenticationToken

继承 AbstractAuthenticationToken,封装认证信息(如用户账号 + 加签字符串):

public class CustomAuthenticationToken extends AbstractAuthenticationToken {

    private final Serializable principal;  // 用户账号
    private final String sign;             // 加签字符串

    // 未认证构造方法
    public CustomAuthenticationToken(Serializable principal, String sign) {
        super(null);
        this.principal = principal;
        this.sign = sign;
        setAuthenticated(false);
    }

    // 已认证构造方法
    public CustomAuthenticationToken(Serializable principal,
            Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.sign = null;
        super.setAuthenticated(true);
    }

    @Override
    public Serializable getCredentials() { return null; }

    @Override
    public Serializable getPrincipal() { return this.principal; }

    public String getSign() { return this.sign; }
}

2. 自定义认证器 AuthenticationProvider

实现 AuthenticationProvider 接口,在 authenticate() 方法中:

  • 校验加签字符串(自定义安全逻辑)
  • 通过 UserDetailsService 加载用户
  • 返回已认证的 Authentication
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) {
        CustomAuthenticationToken token = (CustomAuthenticationToken) authentication;
        String username = (String) token.getPrincipal();
        String sign = token.getSign();

        // 1. 校验加签字符串(自定义安全逻辑)
        // TODO: 实现你的签名校验逻辑,例如 HMAC/RSA 验签

        // 2. 加载用户
        UserDetails user = userDetailsService.loadUserByUsername(username);

        // 3. 返回已认证的 Authentication
        return new CustomAuthenticationToken(username, user.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return CustomAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

3. 自定义 LoginTokenService

继承 LoginTokenService,在 attemptAuthentication() 中从请求提取参数:

public class CustomLoginTokenService extends LoginTokenService {

    public CustomLoginTokenService(TokenGranter tokenGranter,
            ClientDetailsService clientDetailsService,
            OAuth2RequestFactory oAuth2RequestFactory,
            CustomAuthenticationProvider authenticationProvider) {
        super(tokenGranter, clientDetailsService, oAuth2RequestFactory, authenticationProvider);
    }

    @Override
    protected Authentication attemptAuthentication(HttpServletRequest request) {
        String username = request.getParameter("username");
        String sign = request.getParameter("sign");
        return new CustomAuthenticationToken(username, sign);
    }
}

4. 配置类

@Configuration
@AutoConfigureAfter(AuthorizationServerEndpointsConfiguration.class)
public class TokenConfiguration {

    private final AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer();

    @Autowired
    private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();

    @PostConstruct
    public void init() {
        for (AuthorizationServerConfigurer configurer : configurers) {
            try {
                configurer.configure(endpoints);
            } catch (Exception e) {
                throw new IllegalStateException("Cannot configure endpoints", e);
            }
        }
    }

    @Bean
    public CustomLoginTokenService customLoginTokenService(
            CustomAuthenticationProvider customAuthenticationProvider) {
        return new CustomLoginTokenService(
            endpoints.getTokenGranter(),
            endpoints.getClientDetailsService(),
            endpoints.getOAuth2RequestFactory(),
            customAuthenticationProvider
        );
    }
}

5. 登录接口

@RestController
public class CustomLoginController {

    @Autowired
    private CustomLoginTokenService customLoginTokenService;

    @PostMapping("/token/custom")
    public ResponseEntity<AuthenticationResult> loginToken(HttpServletRequest request) {
        AuthenticationResult result = customLoginTokenService.loginForToken(request);
        return Results.success(result);
    }
}

调用方式:

POST /oauth/token/custom
Content-Type: application/x-www-form-urlencoded

username=用户账号&sign=加签字符串&client_id=xxx&client_secret=***

三、详细文档参考

开放平台文档《定制登录获取令牌》:

https://open.hand-china.com/document-center/doc/product/10002/11014

文档中包含完整的类图说明和短信验证码登录的代码示例,可直接参考。另外文档目录中还有《非标单点登录示例》也可作为补充参考。

OpenClaw会话死循环案例分析

今天在使用 AI Agent 的过程中发现了一个典型问题:一个无人值守的 Agent 会话陷入了死循环,短时间内消耗了 65 万 tokens 却几乎没有产出。记录整个发现、分析和复盘过程。

现象

通过监控发现某个 Agent 会话(模型 deepseek-v4-flash)反复执行相同的命令,每次调用都没有产出有效结果,但上下文在持续膨胀。

发送 /stop 中断后,让该会话分析自身死循环的原因——结果它又陷入了同样的循环模式。这说明 stop 只能中断当前 turn,无法修复根因

死循环数据

指标 数值 说明
exec 总调用次数 166 次 大部分是重复命令
上下文大小 654K tokens(输入) 正常会话约 30-50K
有效输出 212 tokens 几乎为零
turn failed 次数 9 次 模型无法产出内容
prompt-error 次数 4 次 请求被拒绝
最终状态 killed(手动 /stop) 用户通过 /stop 强制终止

循环模式分析

从 166 次 exec 调用中提取重复模式:

命令 重复次数 说明
ls -la .../blog-publisher-wordpress/ 33 次 反复列出同一目录
python3 ...读取 session JSONL 20 次 反复解析同一文件
find .../blog-publisher-wordpress -type f 19 次 反复搜索同一路径
python3 -c "...读取 session" 8 次 换种写法做同样的事
tail -100 ...log 5 次 反复读同一段日志

同一个 ls 命令调用了 33 次,find 调用了 19 次。模型完全没有意识到自己在重复。

根因分析

1. 模型缺乏自我觉察

deepseek-v4-flash 在处理”找不到上下文”的情况时,没有能力判断”我已经搜过 30 次了,再搜也不会有结果”。每次搜索的结果被追加到上下文,模型看到更多数据后反而更困惑,于是继续搜索。

2. 没有 Circuit Breaker

当前 Agent 框架没有检测”同一命令重复 N 次”的机制。无论模型调用同一命令多少次,系统都会忠实地执行并返回结果。166 次 exec 调用全部被执行了。

3. 上下文窗口失控

每次 exec 的输入和输出都被追加到上下文。166 次调用的结果累积到 654K tokens,远超模型的有效处理能力。当上下文过大时,模型开始报错(assistant turn failed),但报错本身又被追加到上下文,形成恶性循环。

恶性循环链

找不到上下文 → 搜索 session 文件 → 结果加入上下文
→ 上下文膨胀 → 模型处理不了 → 重新搜索
→ 更多上下文 → 更多错误 → 最终被手动 /stop

浪费的代价

这次死循环消耗了约 654K 输入 tokens,几乎没有有效输出。按主流 API 定价估算:

  • 以 deepseek-v4-flash 的价格计算,单次死循环的成本虽然不高
  • 但如果 无人值守,一个晚上可能触发多次这样的循环
  • 多个 Agent 同时失控,累积消耗会非常可观

真正的风险不是单次成本,而是 无人监控下的累积浪费。如果没有人工 /stop 干预,session 会一直跑到 context window 上限才可能停止——甚至可能不会停止。

一个残酷的事实

OpenClaw 目前 没有自动防护机制 能阻止这类死循环。已有的 globalCircuitBreakerThreshold 是按工具类型计数的,agent 通过轮换不同工具(ls → find → python3 → tail)就能绕过。GitHub 上已有相关 issue(#79252),修复方案(#97577)正在推进中。

防御建议

1. 模型选择

复杂上下文追踪任务避免使用 deepseek-v4-flash。实测 mimo-v2.5 在同一场景下不会陷入重复调用循环,具备更好的自我觉察能力。

2. 建立监控机制

定期检查活跃 session 的 token 消耗和工具调用频率,超阈值自动告警:

# 检查活跃 session 的 token 消耗
openclaw sessions list --active

3. 考虑 Session Token 预算

为单个 session 设置 token 上限,超过后自动中断。这是最直接的防护,但目前 Agent 框架尚未内置此功能。

4. 工具调用频率限制

检测同一命令的连续重复调用,达到阈值后自动中断并通知用户。这需要在框架层面实现。

结论

AI Agent 的死循环不是理论风险,而是真实会发生的问题。关键认知:

  1. /stop 只能中断当前 turn,不能修复根因
  2. 模型重复调用同一命令时,系统不会自动干预
  3. 无人值守的 Agent 可能白白消耗大量 tokens
  4. 选择更稳定的模型 + 建立监控是最现实的防线

在 Agent 真正可靠之前,有人值守仍然是必要的安全网。


二、深入源码分析(2026-07-01 更新)

在初次发布本文后,我们对 OpenClaw 源码进行了深入分析,发现死循环的根因比表面现象更复杂。以下是完整分析过程。

1. 死循环类型:大循环 vs 调度器自循环

最初我们怀疑这是 OpenClaw 调度器层面的”自激循环”——调度器自己反复调用同一个工具,不经过大模型。但经过源码分析确认:这是标准的 OpenClaw → 大模型 → OpenClaw 大循环

调度器层面没有 auto-retry/auto-continue 机制。每次 exec 工具调用都必须由大模型发起:

  1. 模型发出 tool call(exec)
  2. OpenClaw 执行命令,结果返回给模型
  3. 模型收到结果后,决定再次调用 exec
  4. 循环往复

之所以感觉”速度快”,是因为 exec 输出很短,模型处理快,每轮只需几百毫秒。

2. Loop Detection 机制分析

OpenClaw 内置了 tool-loop-detection 模块,包含 4 种检测器:

检测器 触发条件 Warning 阈值 Critical 阈值 适用场景
genericRepeat 相同 toolName + 相同 argsHash + 相同 resultHash 10 20 工具调用完全相同且结果不变
knownPollNoProgress process poll/log 工具,相同参数,结果不变 10 20 轮询死循环
pingPong 两个工具交替调用,参数签名来回切换,结果不变 10 20 A→B→A→B 交替死循环
unknownToolRepeat 连续调用不存在的工具 10 模型反复尝试已删除的工具

响应级别:

  • Warning(≥10次):给模型发警告消息,让模型自己停止
  • Critical(≥20次):直接 block,返回 status: "blocked"
  • Global Circuit Breaker(≥30次):全局熔断,阻止整个 session 继续执行

3. 为什么 Loop Detection 没有阻止死循环?

我们的 openclaw.json 中已正确配置了 loopDetection:

"tools": {
  "loopDetection": {
    "enabled": true,
    "warningThreshold": 10,
    "criticalThreshold": 20,
    "globalCircuitBreakerThreshold": 30,
    "detectors": {
      "genericRepeat": true,
      "knownPollNoProgress": true,
      "pingPong": true
    }
  }
}

但死循环仍然发生了。根因在于 hashExecToolOutcome() 函数的实现:

对于 exec 工具的 status: "completed"status: "failed" 结果,哈希计算包含:

digestStable({
  status,
  exitCode,
  timedOut,
  output: normalizeNullableString(details.aggregated) ?? text
})

关键问题output 字段(完整的命令输出文本)被纳入了 resultHash 计算。即使命令相同、exit code 相同,只要输出文本有任何细微差异(比如时间戳、路径顺序、错误信息的微小变化),resultHash 就会不同。

这导致 noProgressStreak(要求连续相同的 resultHash)始终为 1,永远不会达到 criticalThreshold(20)或 globalCircuitBreakerThreshold(30)。

检测路径 使用的计数器 是否触发 原因
Warning recentCount(相同 args 计数,不看 result) ✅ 触发 参数相同即可
Critical noProgressStreak(要求 resultHash 相同) ❌ 不触发 exec 输出略有变化,resultHash 每次不同
Global Circuit Breaker noProgressStreak ❌ 不触发 同上

Warning 虽然触发了,但模型(GLM-5.2)忽略了警告文本,继续循环。

4. 复现验证

在分析过程中,我们多次复现了死循环。最典型的场景:模型反复执行 grep -n "loopDetection" /root/.openclaw/openclaw.json,每次输出为空(exit code 1),模型不断重试,30+ 次后需要手动 /stop。

每次 exec 的输出完全相同(都是空),但 hashExecToolOutcome() 仍然为每次生成了不同的 resultHash——这可能是因为 exec 的 status details 中包含了 tailaggregated 字段的细微差异。

5. GitHub Issue 跟踪

这个问题已在 GitHub 上提交并跟踪:

  • Issue #93917:Bug: genericRepeat critical/circuit-breaker never fires when exec results vary slightly
  • PR #97577:fix: make tool loop circuit breaker session-global
  • Issue #97485:feat(agents): add iteration budget for agent loop safety

我们已在 #93917 下补充了复现信息,包括 OpenClaw 2026.6.10 + GLM-5.2 的完整配置和现象描述。

6. 临时缓解措施

在官方修复之前,可考虑以下措施:

  • 降低 warningThreshold:设为 3-5,让 warning 更早触发(虽然模型可能仍忽略)
  • 关注 PR #97577:session-global circuit breaker 可以防住跨工具循环
  • 关注 PR #97485:iteration budget 从根本上限制工具调用轮数
  • 模型选择:不同模型对 warning 的遵从度不同,换模型可能有缓解效果
  • 人工监控:在可预见的死循环场景中保持 /stop 就绪

7. 根因总结

设计缺陷hashExecToolOutcome() 将完整 output 文本纳入 resultHash,导致 exec 结果的任何微小变化都会重置 noProgressStreak。

影响范围:所有使用 exec 工具的场景,只要命令输出有细微变化(时间戳、错误信息、路径顺序等),critical 和 circuit-breaker 就不会触发。

修复方向

  1. 从 exec resultHash 中剥离 volatile 字段(output、tail)
  2. 或采用相似度比较替代精确哈希匹配
  3. 配合 session-global circuit breaker 作为兜底

8. 模型能力差异对比(2026-07-01 补充)

在后续测试中发现,死循环的严重程度与模型能力密切相关。同一个任务场景下,不同模型的表现差异显著:

模型 行为特征 循环次数 是否会换工具 结果
deepseek-v4-flash(火山引擎) 同一个 exec 命令反复调用,不改变策略 166 次 ❌ 很少换工具 654K tokens,手动 /stop
GLM-5.2(智谱) 也会重复调用,但会尝试换命令、换工具 30+ 次 ✅ 会换工具/换参数 仍然会循环,但次数少很多

关键发现:

  • deepseek-v4-flash 在工具连续失败后缺乏”停下来反思”的能力,倾向于用完全相同的参数反复重试,陷入最坏情况的死循环
  • GLM-5.2 虽然也会循环,但会尝试不同的命令和参数(比如换 grep 为 find、换路径),说明它有一定的”换策略”意识,只是不足以完全跳出循环
  • 更强的模型(如 GPT-5.5)可能根本不会陷入循环——在 3-5 次失败后就会主动停下来向用户报告问题

这说明死循环是两层问题叠加:

  1. OpenClaw 层:loop detection 的 critical/circuit-breaker 对 exec 失效(resultHash 问题),缺少 session 级别的硬上限——这是系统性缺陷,所有模型都受影响
  2. 模型层:部分模型在工具连续失败后缺乏策略切换能力——这是模型能力差异,不同模型表现不同

如果只修 OpenClaw 层(加上 session-global circuit breaker 或 iteration budget),所有模型都安全。但如果模型本身能力强,可能根本不需要 loop detection 兜底。

实践建议:在 OpenClaw 官方修复 loop detection 之前,选择”工具失败后容易换策略”的模型(如 GLM-5.2、GPT-5.5)可以显著降低死循环的风险和严重程度。避免在生产环境中使用 deepseek-v4-flash 执行需要多次工具调用的复杂任务。


三、supportsTools: false 与死循环的关系(2026-07-01 补充)

在分析过程中,我们发现了一个值得关注的问题:之前因 DeepSeek-v4-flash 工具调用不匹配导致大量 400 错误,在 openclaw.json 中禁用了其工具支持:

{
  "id": "deepseek-v4-flash",
  "compat": { "supportsTools": false }
}

今天的死循环发生时,session 使用的正是这个配置了 supportsTools: false 的 deepseek-v4-flash。这引发了我们的疑问:禁用工具支持是否反而加剧了死循环问题?

1. supportsTools: false 的实际效果

通过源码分析,supportsTools: false 的实际效果如下:

层面 行为 是否符合预期
API 请求 不传 tools 字段给模型 API ✅ 符合
工具构建 tools: toolsEnabled ? toolsRaw : [],传给 runner 的工具为空 ✅ 符合
System Prompt 仍然包含完整的工具描述(”你可以用 exec 工具…”) ❌ 不符合

关键问题effectiveToolsAllow(决定 system prompt 中列出哪些工具)不依赖 toolsEnabled,而是来自 params.toolsAllow。因此即使工具被禁用,system prompt 仍然告诉模型”你有 exec、read、write 等工具可用”。

2. DSML Recoverer 分析

OpenClaw 有一个 DeepSeek DSML Tool Call Recoverer,能从模型文本输出中解析 DSML 格式的工具调用并执行。我们最初假设这是死循环的根因,但源码分析排除了这个假设:

shouldFilterDeepSeekDsmlText(compat) 的判断条件是 compat.thinkingFormat === "deepseek",而 handai/deepseek-v4-flash 的配置里没有 thinkingFormat: "deepseek",所以 DSML recoverer 不会生效。

3. 矛盾点

如果 supportsTools: false 确实完全禁用了工具调用,那 deepseek-v4-flash 不可能反复执行 exec 命令。但实际观察到的现象是:模型确实陷入了工具调用死循环

可能的解释:

  • 模型在文本中模拟工具调用:模型收到 system prompt 说有工具可用,但 API 请求里没有 tools 定义,于是在文本输出中生成类似工具调用的格式。虽然 DSML recoverer 不生效,但可能存在其他文本解析路径。
  • 触发了 fallback:deepseek-v4-flash 调用失败后,OpenClaw 的 fallback 机制切换到有工具能力的模型(如 deepseek/deepseek-v4-flash 或 alibaba/deepseek-v4-flash),由 fallback 模型执行了工具调用。
  • 其他未发现的机制:可能存在我们尚未发现的工具调用解析路径。

4. 设计缺陷

无论死循环的具体触发路径是什么,system prompt 与实际工具可用性不一致本身就是一个设计缺陷:

  • System prompt 告诉模型”你有 exec、read、write 等工具可用”
  • 但 API 请求里没有 tools 定义
  • 模型被诱导去”使用”实际不存在的工具
  • 这种行为在弱模型(如 deepseek-v4-flash)上更容易导致问题

正确的做法应该是:当 supportsTools: false 时,system prompt 中也应该移除工具描述,或明确告知模型”当前模式下工具不可用”。

5. 待验证问题

  1. supportsTools: false 时,system prompt 仍包含工具描述是否合理?
  2. 是否存在 DSML 之外的文本工具调用解析路径?
  3. 死循环时 session 实际使用的模型是哪个?是 deepseek-v4-flash 本身,还是 fallback 到了其他模型?

这些问题需要进一步验证,欢迎在评论区讨论或到 GitHub Issue #93917 跟进。

四、Loop Detection 实际生效验证(2026-07-01 补充)

在之前的分析中,我们指出 Loop Detection 的 critical/circuit-breaker 对 exec 工具失效(因为 hashExecToolOutcome() 将完整 output 纳入 resultHash,exec 输出的微小变化导致哈希每次不同)。但今天的测试提供了一个新的观察角度。

1. 现象:browser 工具的 Loop Detection 正常工作

今天在执行一个浏览器自动化任务时,由于 targetId 不匹配,agent 反复用相同参数调用 browser 工具的 navigateact 操作。网关日志中记录了大量 Loop Detection 警告:

时间 警告内容 调用次数
14:42:59 Loop warning: browser called 12 times with identical arguments 12
14:43:06 Loop warning: browser called 13 times with identical arguments 13
(持续递增)
14:46:45 Loop warning: browser called 18 times with identical arguments 18

当次数达到 20 次时,系统执行了 Critical 级别的拦截:

CRITICAL: Called browser with identical arguments and identical outcomes 20 times. Session execution blocked to prevent runaway loops.

Session 被成功阻止,不再继续执行重复调用。这说明 对于 browser 工具,Loop Detection 的 warning → critical → block 全链路正常工作

2. 为什么 browser 有效而 exec 无效?

关键差异在于 resultHash 的稳定性

工具 相同参数时的结果 resultHash 是否稳定 Critical 是否触发
browser 相同参数 → 相同结果(页面状态不变) ✅ 稳定 ✅ 触发
exec 相同命令 → 输出可能有微小差异(时间戳、路径顺序等) ❌ 不稳定 ❌ 不触发

browser 工具的返回值是结构化的 JSON(页面 URL、snapshot 等),当参数完全相同时,结果也完全相同,resultHash 保持一致,noProgressStreak 能正确累加到 criticalThreshold。而 exec 工具的输出包含命令的 stdout/stderr,即使命令相同,输出的微小差异(如 ls -la 的时间戳)会导致 resultHash 每次不同。

3. 关于 supportsTools: false 的重要发现

在之前的章节中,我们分析了 supportsTools: false 配置可能导致 system prompt 与实际工具可用性不一致的问题。今天的测试进一步确认了一个关键事实:

当 deepseek-v4-flash 配置了 supportsTools: false 时,它根本不会调用任何工具(包括 browser、exec 等),因此 Loop Detection 机制永远不会被触发。

这解释了为什么之前认为”Loop Detection 没有起作用”——不是因为配置问题,而是因为 deepseek-v4-flash 禁用了工具调用,agent 根本不会发起工具调用循环。今天的测试使用了 GLM-5.2(工具调用启用),agent 频繁调用 browser 工具,Loop Detection 立即正常工作。

换句话说:

  • deepseek-v4-flash(supportsTools: false):不调用工具 → 不触发 Loop Detection → 但也不执行实际任务(陷入文本层面的重复)
  • GLM-5.2(supportsTools: true):调用工具 → 触发 Loop Detection → Critical 拦截成功阻止循环

4. 结论与修正

对之前分析的两个修正:

  1. Loop Detection 配置是生效的——至少对 browser 工具完全正常。exec 工具的 resultHash 问题仍然存在(详见第二章),但这不影响其他工具的检测。
  2. 之前”没有看到 Loop Detection 日志”的原因——不是配置问题,而是 deepseek-v4-flash 的 supportsTools: false 导致工具调用根本不发生。切换到有工具能力的模型后,Loop Detection 立即表现出正常行为。

这一发现进一步印证了第三章的结论:supportsTools: false 的影响远超预期——它不仅可能导致 system prompt 不一致,还掩盖了 Loop Detection 机制本身的正常运作。在排查”防护机制是否生效”类问题时,首先需要确认当前模型是否实际具备工具调用能力。

OpenClaw会话重置失忆原因分析

今天在使用 OpenClaw 的过程中遇到一个现象:正在进行的会话突然“失忆”了,助手对不久前做过的操作完全不知情。经过日志追溯和源码分析,弄清了整个链路。记录如下。

现象

一次完整的会话链涉及了 3 个关联的 session:

时间 Session 内容 结果
20:25 639ede17 Agent宕机诊断 → 发布博客 → iNove主题排版调整 被 abort
20:32 6520c2c3 继续iNove主题调整,找CSS文件 被 abort
20:38 7f1f9d61 当前会话,全新开始,对之前一无所知 正常运行

两个前序 session 在 abort 后被 reset,新 session 从零开始,对过去 13 分钟内的所有操作完全没有记忆。

直接原因:手抖多打了一个 0

openclaw.json 的模型配置中,deepseek-v4-flashmaxTokens 值被设为了 3840000

{
  "id": "deepseek-v4-flash",
  "name": "deepseek-v4-flash",
  "contextWindow": 1000000,
  "maxTokens": 3840000,    ← 多了一个 0
  "compat": { "supportsTools": false }
}

这个值应该是 393216(火山引擎 deepseek-v4 实际支持的 max_completion_tokens 上限),但配置时多输入了一个 0,变成了 384 万。OpenClaw 的计算逻辑是:

max_completion_tokens = min(maxTokens, contextWindow - 已用token数)

当上下文膨胀后,contextWindow - 已用token数 约 90 万,min(3840000, 90万) 取了 90 万,远超火山引擎 393216 的上限,直接 400 拒绝:

400 The parameter `max_completion_tokens` specified in the request are not valid:
expected a value <= 393216, but got 966158 instead.

也就是说,整条调用链 OpenClaw → handai(newapi) → 火山引擎 本身没有兼容性问题,根因就是配置错误

链式崩溃经过

第 1 轮:连番 400 错误 + 大量重试

用户在 webchat 上发送了 Agent 宕机诊断请求,模型连续返回 400 format error。每次 failover(handai→deepseek→alibaba)都持续失败——因为模型提供商本身没问题,是请求参数超标了。用户因看不到响应,在 webchat 上反复发送同一条消息 30 多次,每一次都触发新的 400 错误,形成恶性循环。

最终用户手动 abort 当前请求,但 abort 的回收超时了:

embedded abort settle timed out: timeoutMs=2000

同时 session 文件已被修改,触发保护机制:

session file changed while embedded prompt lock was released

结果:session 639ede17 被标记为 .reset.,视为被接管放弃。

第 2 轮:CSS 文件查找也 abort

新 session 启动后,用户继续讨论 iNove 主题的 CSS 调整。助手在 /var/www//www/ 等路径远程查找 CSS 文件,全部失败(路径不存在)。用户再次 abort,同样的 chat.abort + settle timeout → session 6520c2c3 也被 reset。

OpenClaw 的 Session Reset 机制

从日志可以看出 OpenClaw 在这类场景下的行为:

  1. 模型 400 错误 → 触发 failover(handai → alibaba → deepseek),但 failover 同样失败(请求参数依然超标)
  2. 用户手动 abort → 调用 chat.abort WebSocket 接口
  3. Abort settle timeout(2秒) → 如果在 2 秒内 abort 不能被嵌入层清理完成,触发 session takeover
  4. Session takeover → 旧的 session 文件被重命名为 .reset.,新请求从新 session 开始
  5. 失忆 → 新 session 没有历史消息,模型看到的是一块空白画布

如何重建记忆

当前这个 session 恢复“记忆”的方式并非真正记住了,而是通过以下步骤从文件系统中重新构建了上下文:

  1. 搜 session 文件:用 grep -rl "retailsolution|xmlrpc" 在所有 session 文件中找到相关记录
  2. 读 trajectory 日志:从 reset 过的 session 的 .trajectory.jsonl 中提取助手回复文本和用户消息
  3. 找残留证据/tmp/publish_xmlrpc.py 等脚本还躺在文件系统上
  4. 翻日志确认崩溃原因/tmp/openclaw/openclaw-YYYY-MM-DD.log 中的 failover 和 abort 记录

这种方式的问题很明显:它依赖助手在运行时主动去“考古”,且只能找到轨迹日志中残留的信息,并非系统级的内存持久化。

启示

这次事件揭示了几个值得注意的问题:

  1. 配置错误是最隐蔽的故障源:多输入一个 0,就能让整套系统反复崩溃。模型配置中的 maxTokens 要与最终提供商的实际支持上限对齐,不能写理论最大值。
  2. Abort 回收的可靠窗口:2 秒的 settle timeout 在复杂场景下偏短,一旦超时就导致整个 session 上下文丢失。这是 OpenClaw 的一个设计缺陷(Issue #98156)。
  3. 长期记忆 vs 会话记忆:OpenClaw 的 memory 系统保存的是长期语义记忆,但会话级的工作记忆在 session reset 后彻底消失。即使这次是配置错误触发的,其他场景(网络波动、模型超时等)同样会触发 session takeover,导致同样的失忆问题。

Agent集体卡死原因分析及解决方案

故障时间线

本次故障从触发到恢复历经约8个小时,关键节点如下:

时间 事件 状态
10:00:21 handai/deepseek-v4-flash 模型服务首次返回 400 format 错误 触发点
10:12:42 h0assistant 主会话 context overflow(290条消息),自动压缩超时 加剧
10:15:41 上下文压缩 Compaction timed out, failover 到 qwen3.5-flash 失败
10:46 首次 long-running session 告警 队列积压
13:01~13:12 handai/deepseek-v4-flash 反复出 format 400 恶化
13:21~17:37 h0assistant 卡死 processing 状态 完全卡死
16:17 飞书消息无法响应 影响用户
17:33 手动导出诊断包并重启网关 恢复

根本原因分析

本次故障并非单一故障点,而是链式连锁反应的结果.

触发点: 模型提供商 Tool Schema 兼容性问题

调用链路: OpenClaw -> handai(newapi) -> 火山引擎 deepseek-v4-flash. 日志中出现: FailoverError: provider rejected the request schema or tool payload. status=400, reason=format. 火山引擎 deepseek-v4 在 tool_call 参数校验上与 OpenAI 标准不完全一致,复杂 tool call 触发校验失败.

加剧因素 1: Context Overflow 死循环

290条历史消息触发 context overflow,自动压缩超时,全量摘要也失败,形成死循环.

加剧因素 2: 内存压力过高

网关进程内存达 1.95 GB,加载 59 个插件,大量未使用.

加剧因素 3: 历史会话积压

主 agent 66 个会话, h0assistant 18 个会话.

已采取的解决方案

方案一: 关闭模型 Tool Call 能力

compat.supportsTools = false,规避火山引擎 tool schema 校验问题.

方案二: 插件白名单削减

59 个插件缩减到 24 个必要插件.

方案三: 内存压力立即缓解

重启后内存从 1.95 GB 下降至 432 MB.

防御建议

建议一: 定期清理历史会话

建议二: 控制模型兼容性

建议三: 添加 Context Overflow 告警监控

效果总结

指标 整改前 整改后 变化
网关内存 1,955 MB 432 MB darr;78%
插件数量 59 个 24 个 darr;59%
deepseek-v4-flash tools 开启 关闭 规避 400 format

本次故障揭示了 AI Agent 系统在生产环境中的典型威胁:模型提供商兼容性问题、上下文管理失败、插件臃肿、内存危机之间形成链式反应.


后续复盘:supportsTools: false 是双刃剑(2026-07-01 更新)

在采用 supportsTools: false 作为应急方案一段时间后,我们发现这个配置本身引发了新的问题。

背景补充:DeepSeek 官方 vs 火山引擎

经查证,DeepSeek 官方 API(api.deepseek.com)完全支持 Function Calling</strong,遵循 OpenAI 标准 tools 参数格式。当时的 400 错误来自火山引擎的 deepseek-v4-flash 端点,其 tool_call 参数校验与 OpenAI 标准不完全一致。

调用链路:OpenClaw → handai(newapi) → 火山引擎 deepseek-v4-flash

supportsTools: false 的实际效果

通过 OpenClaw 源码分析,supportsTools: false 的效果是”禁用了一半”:

层面 行为 是否符合预期
API 请求 不传 tools 字段给模型 API ✅ 符合
工具构建 传给 runner 的工具列表为空 ✅ 符合
System Prompt 仍然包含完整的工具描述(”你可以用 exec 工具…”) ❌ 不符合

原因:effectiveToolsAllow(决定 system prompt 中列出哪些工具的参数)不依赖 toolsEnabled,而是来自 params.toolsAllow。因此即使工具被禁用,system prompt 仍然告诉模型”你有 exec、read、write 等工具可用”。

引发的新问题:死循环

在 2026-07-01 的分析中,我们发现 supportsTools: false 配置下的 deepseek-v4-flash 陷入了工具调用死循环(详见 OpenClaw 会话死循环案例分析)。

矛盾点:如果工具确实被禁用了,模型不应该能执行工具调用。但实际观察到模型反复执行 exec 命令 166 次,上下文膨胀到 654K tokens。

可能的解释:

  • 模型收到 system prompt 说有工具可用,但 API 请求里没有 tools 定义,于是在文本输出中”模拟”工具调用格式
  • OpenClaw 的 DSML 过滤器或其他文本解析路径检测到这些工具调用块并执行了它们
  • 或者触发了 fallback 机制,切换到有工具能力的模型执行了工具调用

利弊分析

时间维度
短期(应急) 立即消除 400 错误,恢复服务 模型不能正常调用工具
长期(现状) system prompt 仍诱导工具使用 → 死循环;虚假安全感;模型能力浪费

建议的长期方案

  1. 排查火山引擎 tool schema 兼容性问题:具体是哪个字段不兼容?能否在 handai provider 层做 schema 转换?
  2. 或换用 DeepSeek 官方 APIapi.deepseek.com)代替火山引擎端点,官方 API 完全兼容 OpenAI 格式
  3. 恢复 supportsTools: true,同时确保 loop detection 对 exec 生效(参考 Issue #93917
  4. 如果确实需要禁用工具:应该同时从 system prompt 中移除工具描述,而不是只禁用 API 层面的工具传递

本次复盘的核心教训:supportsTools: false 只禁用了 API 层面的工具传递,但没有同步调整 system prompt,导致”告诉模型有工具但又不给工具”的矛盾状态,反而引发了更严重的死循环问题。

SQL中使用文字标量和绑定变量对解析时间的影响实验

说明:本实验主要验证SQL中使用文字标量导致硬解析(hard parse) 和使用绑定变量导致软解析(soft parse);

实验数据库:EBS 12.1.3 Demo数据库

数据库参数 cursor_sharing 默认等于 EXACT;

以下操作在PLSQL DEveloper SQL Window中操作

————————————————————————————————————————

–模拟EBS登录
begin
   fnd_global.APPS_INITIALIZE(user_id =>1318,resp_id =>21623 ,resp_appl_id => 660 )  ;
   mo_global.init(p_appl_short_name => ‘ONT’);
end ;

–打开Session级的TRace
alter session set sql_trace=true;
–设置TRace文件名的前缀,便于查找
alter session set tracefile_identifier=’SYF20130630′;

–执行一段匿名块程序
declare
  v_order_number        varchar2(100);
  v_order_number_result varchar2(100);
begin

  select ORDER_NUMBER    into v_order_number_result
    from oe_order_headers_v   where ORDER_NUMBER = ‘777849’;
  
  select ORDER_NUMBER    into v_order_number_result
    from oe_order_headers_v   where ORDER_NUMBER = ‘777848’;
  
  v_order_number := 777847;
  select ORDER_NUMBER    into v_order_number_result
    from oe_order_headers_v   where ORDER_NUMBER = v_order_number;
  
  v_order_number := 777846;
  select ORDER_NUMBER    into v_order_number_result
    from oe_order_headers_v   where ORDER_NUMBER = v_order_number;

end;
–结束Session级的TRace,生成Trace文件
alter session set sql_trace=false;

–Trace File 在$user_dump_dest路径下,这个路径的具体值可以在commond window下执行如下语句获得
show param user_dump_dest;

———————————————————————————————————–

获得trc文件后进行tkprof

然后查看tkprof后的文件可以看到如下效果:

********************************************************************************

SQL ID: 6hf9x8a7sxzua
Plan Hash: 796084466
SELECT ORDER_NUMBER
FROM
 OE_ORDER_HEADERS_V WHERE ORDER_NUMBER = ‘777849’
call     count       cpu    elapsed       disk      query    current        rows
——- ——  ——– ———- ———- ———- ———-  ———-
Parse        1      0.25       0.26          0          3          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.00       0.05          2         27          0           1
——- ——  ——– ———- ———- ———- ———-  ———-
total        3      0.26       0.31          2         30          0           1

********************************************************************************

SQL ID: 6z7x7xu7u8yk7
Plan Hash: 796084466
SELECT ORDER_NUMBER
FROM
 OE_ORDER_HEADERS_V WHERE ORDER_NUMBER = ‘777848’
call     count       cpu    elapsed       disk      query    current        rows
——- ——  ——– ———- ———- ———- ———-  ———-
Parse        1      0.22       0.23          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.00       0.00          0         27          0           1
——- ——  ——– ———- ———- ———- ———-  ———-
total        3      0.22       0.23          0         27          0           1

 

很显然,上述两句SQL是类似的,但由于SQL语句中使用的是文字标量,且数据库参数cursor_sharing=EXACT,导致了硬解析。

 

********************************************************************************

SQL ID: 9zt28w8ru22ny
Plan Hash: 796084466
SELECT ORDER_NUMBER
FROM
 OE_ORDER_HEADERS_V WHERE ORDER_NUMBER = :B1
call     count       cpu    elapsed       disk      query    current        rows
——- ——  ——– ———- ———- ———- ———-  ———-
Parse        2      0.00       0.00          0          0          0           0
Execute      2      0.24       0.24          0          0          0           0
Fetch        2      0.00       0.00          0         54          0           2
——- ——  ——– ———- ———- ———- ———-  ———-
total        6      0.24       0.24          0         54          0           2

 

很显然 在解析这两句话的时候,即是使用绑定变量的方式,其Parse 时间为0,说明只是进行了软解析。

v_order_number := 777847;
  select ORDER_NUMBER    into v_order_number_result
    from oe_order_headers_v   where ORDER_NUMBER = v_order_number;
  
  v_order_number := 777846;
  select ORDER_NUMBER    into v_order_number_result
    from oe_order_headers_v   where ORDER_NUMBER = v_order_number;

ZT:深度分析数据库的热点块问题

热点块的定义

数据库的热点块,从简单了讲,就是极短的时间内对少量数据块进行了过于频繁的访问。定义看起来总是很简单的,但实际在数据库中,我们要去观察或者确定热点 块的问题,却不是那么简单了。要深刻地理解数据库是怎么通过一些数据特征来表示热点块的,我们需要了解一些数据库在这方面处理机制的特性。

数据缓冲区的结构

我们都知道,当查询开始的时候,进程首先去数据缓冲区中查找是否存在查询所需要的数据块,如果没有,就去磁盘上把数据块读到内存中来。在这个过程中,涉及 到数据缓冲区中LRU链的管理(8i开始以接触点计数为标准衡量buffer冷热从而决定buffer是在LRU的冷端还是热端),关于这部分内容,从 oracle concepts 中就能得到详尽的文档,我不准备去论述这部分内容,这也不是本文的重点。现在我们的重点是,到底进程是如何地去快速定位到自己所想要的block的,或者 如何快速确定想要的block不在内存中而去进行物理读的。

我们仔细想一想,随着硬件的发展,内存越来越大,cache buffer也越来越大,我们如何才能在大量的内存中迅速定位到自己想要的block?总不能去所有buffer中遍历吧!在此数据库引出了hash的概 念(oracle中快速定位信息总是通过hash算法的,比如快速定位sql是否在shared pool size中存在就是通过hash value来定位的,也就是说shared pool size中对象也是通过hash table来管理的),了解一点数据结构的基本知识就知道,hash 的一大重要功能就是快速地查找。举个最简单的例子,假设我们有一个hash table 就是一个二维数组a[200][100],现在有1000个无序数字,我们要从这1000个数字里面查找某个值是否存在,或者说当我们接收到某个数字的时 候必须判断是否已经存在,当然,我们可以遍历这1000个数字,但这样的效率就很低。但现在我们考虑这样一种方法,那就是把1000个数字除以200,根 据其余数,放在a[200][100]里面(假设相同余数的最大数量不超过100),余数就是数组的下标。这样,平均来说一个数组a[i]里面可能有5个 左右的数字。当我们要去判别一个数字是否存在的时候,对这个数字除以200(这就是一个最简单的hash算法),根据余数i作为下标去数组a[i]中查 找,大约进行5次查找就能判别是否已经存在,这样通过开辟内存空间a[200][100]来换取了时间(当然hash 算法的选取和hash table的大小是一个很关键的问题)。

明白了基本的hash原理之后,我们再来看oracle的block的管理。数据库为这些block也开辟了hash table,假设是a,则在一维上的数量是由参数_db_block_hash_buckets 来决定的,也就是存在hash table a[_db_block_hash_buckets ],从oracle8i开始,_db_block_hash_buckets =db_block_buffers*2。而一个block被放到哪个buckets里面,则是由block的文件编号、块号(x$bh.dbarfl、 x$bh.dbablk对应了block的文件属于表空间中的相关编号和block在文件中的编号,x$bh是所有cache buffer的header信息,通过表格的形式可以查询)做hash 算法决定放到哪个bucket的,而bucket里面就存放了这些buffers的地址。这样当我们要访问数据的时候,可以获得segment的 extent(可以通过dba_extents查到看,详细的信息来源这里不做探讨),自然知道要访问的文件编号和block编号,根据文件和block 编号可以通过hash算法计算出hash bucket,然后就可以去hash bucket里面去找block对应的buffer。

除此之外,为了维护对这些block的访问和更改,oracle还提供了一种latch来保护这些block。因为要避免不同的进程随意地径直并发修改和 访问这些block,这样很可能会破坏block的结构的。latch是数据库内部提供的一种维护内部结构的一种低级锁,latch的生存周期极短(微秒 以下级别),进程加latch后快速的进行某个访问或者修改动作然后释放latch(关于latch不再过多的阐述,那可能又是需要另一篇文章才能阐述清 楚)。这种latch数量是通过参数_db_block_hash_latches 来定义的,一个latch对应的保护了多个buckets。从8i开始,这个参数的default规则为:

当cache buffers 少于2052 buffers

_db_block_hash_latches =  power(2,trunc(log(2, db_block_buffers – 4) – 1))

当cache buffers多于131075 buffers

_db_block_hash_latches =  power(2,trunc(log(2, db_block_buffers – 4) – 6))

当cache buffers位于2052与131075 buffers之间

_db_block_hash_latches =  1024

通过这个规则我们可以看出,一个latch大约可以维护128个左右的buffers。由于latch使得对block的操作的串行化(9i中有改进,读 与读可以并行,但读与写、写与写依然要串行),很显然我们可以想到一个道理,如果大量进程对相同的block进程进行操作,必然在这些latch上造成竞 争,也就是说必然形成latch的等待。这在宏观上就表现为系统级的等待。明白了这些原理,为我们下面的在数据库中的诊断奠定了基础。

如何确定热点对象

如果我们经常关注statspack报告,会发现有时候出现cache buffer chains的等待。这个cache buffer chains就是_db_block_hash_latches所定义的latch的总称,通过查询v$latch也可得到:

select”>sys@OCN>select latch#,name,gets,misses,sleeps from v$latch where name   like ‘cache buffer%’;

LATCH# NAME                                 GETS     MISSES     SLEEPS
———- —————————— ———- ———- ———-
93 cache buffers lru chain          54360446      21025        238
98 cache buffers chains           6760354603    1680007      27085
99 cache buffer handles               554532          6                   0

在这个查询结果里我们可以看到记录了数据库启动以来的所有cahce buffer chains的latch的状况,gets表示总共有这么多次请求,misses表示请求失败的次数(加锁不成功),而sleeps 表示请求失败休眠的次数,通过sleeps我们可以大体知道数据库中latch的竞争是否严重,这也间接的表征了热点块的问题是否严重。由于 v$latch是一个聚合信息,我们并不能获得哪些块可能存在频繁访问。那我们要来看另一个view信息,那就是 v$latch_children,v$latch_children.addr记录的就是这个latch的地址。

select”>sys@OCN>select addr,LATCH#,CHILD#,gets,misses,sleeps from v$latch_children
2  where name = ‘cache buffers chains’  and rownum < 21;

ADDR         LATCH#     CHILD#       GETS     MISSES     SLEEPS
——– ———- ———- ———- ———- ———-
91B23B74         98       1024   10365583       3957         33
91B23374         98       1023    5458174        964         25
91B22B74         98       1022    4855668        868         15
91B22374         98       1021    5767706        923         22
91B21B74         98       1020    5607116        934         31
91B21374         98       1019    9389325       1111         25
91B20B74         98       1018    5060207        994         31
91B20374         98       1017   18204581       1145         18
91B1FB74         98       1016    7157081        920         23
91B1F374         98       1015    4660774        922         22
91B1EB74         98       1014    6954644        976         32
91B1E374         98       1013    4881891        970         19
91B1DB74         98       1012    5371135        971         28
91B1D374         98       1011    5154497        990         26
91B1CB74         98       1010    5013796        936         18
91B1C374         98       1009    5667446        939         25
91B1BB74         98       1008    4673421        883         14
91B1B374         98       1007    4589646        986         17
91B1AB74         98       1006   10380781       1020         20
91B1A374         98       1005    5142009       1110         19

20 rows selected.

到此我们可以根据v$latch_child.addr关联到对应的x$bh.hladdr(这是buffer header中记录的当前buffer所处的latch地址),通过x$bh可以获得块的文件编号和block编号。

select”>sys@OCN>select dbarfil,dbablk
from x$bh
where hladdr in
(select addr
from (select addr
from v$latch_children
order by sleeps desc)
where rownum < 11);

DBARFIL     DBABLK
———- ———-
4       6498
40      14915
15      65564
28      34909
40      17987
1      24554
8      21404
39      29669
28      46173
28      48221

……………………

由此我们就打通了cache buffers chains和具体block之间的关系,那再继续下来,知道了block,我们需要知道究竟是哪些segment。这个可以通过dba_extents来获得。

select distinct a.owner,a.segment_name from
dba_extents a,
(select dbarfil,dbablk
from x$bh
where hladdr in
(select addr
from (select addr
from v$latch_children
order by sleeps desc)
where rownum < 11)) b
where a.RELATIVE_FNO = b.dbarfil
and a.BLOCK_ID <= b.dbablk and a.block_id + a.blocks > b.dbablk;
OWNER                          SEGMENT_NAME                   SEGMENT_TYPE
—————————— ——————————         ——————
ALIBABA                        BIZ_SEARCHER                               TABLE
ALIBABA                        CMNTY_USER_MESSAGE             TABLE
ALIBABA                        CMNTY_VISITOR_INFO_PK          INDEX
ALIBABA                        COMPANY_AMID_IND                   INDEX
ALIBABA                        COMPANY_DRAFT                         TABLE
ALIBABA                        FEEDBACK_POST                           TABLE
ALIBABA                        IM_BLACKLIST_PK                         INDEX
ALIBABA                        IM_GROUP                                        TABLE
ALIBABA                        IM_GROUP_LID_IND                      INDEX
ALIBABA                        MEMBER                                           TABLE
ALIBABA                        MEMBER_PK                                    INDEX
ALIBABA                        MLOG$_SAMPLE                            TABLE

……………………

我们还有另外一种方式

select object_name
from dba_objects
where data_object_id in
(select obj
from x$bh
where hladdr in
(select addr
from (select addr
from v$latch_children
order by sleeps desc)
where rownum < 11)) ;
OBJECT_NAME
————————————
I_CCOL2
RESOURCE_PLAN$
DUAL
FGA_LOG$
AV_TRANSACTION
COMPANY_DRAFT
MEMBER
SAMPLE
SAMPLE_GROUP
VERTICAL_COMPONENT
MEMBER_PK
SAMPLE_GROUP_PK
IM_BLACKLIST_PK
IM_CONTACT
IM_GROUP
CMNTY_USER_MESSAGE
CMNTY_VISITOR_INFO_PK
IM_OFFLINEMSG_TID_IND
OFFER
OFFER_PK
OFFER_EMAIL_IND
OFFER_DRAFT
CMNTY_USER_MESSAGE_TD_BSM_IND
CMNTY_MESSAGE_NUM_PK
BIZ_EXPRESS_MEMBER_ID_IND

……………………

到这里我们基本能找到热点块对对应的对象。但实际上还有另外一个途径来获取这些信息,那就是和x$bh.tch 相关的一种方法。对于8i开始oracle提供了接触点(touch count)来作为block是冷热的标志,在一定条件满足的情况下block被进程访问一次touch count 增加一,到某个标准之后被移动到LRU热端(关于touch count 在这里不做详细介绍,那又将是一大篇文章)。那在短时间内从某种意义上讲,touch count 大的block可能暗示着在当前某个周期内被访问次数比较多。

select distinct a.owner,a.segment_name,a.segment_type from
dba_extents a,
(select dbarfil,dbablk
from (select dbarfil,dbablk
from x$bh order by tch desc) where rownum < 11) b
where a.RELATIVE_FNO = b.dbarfil
and a.BLOCK_ID <= b.dbablk and a.block_id + a.blocks > b.dbablk;

OWNER                          SEGMENT_NAME                   SEGMENT_TYPE
—————————— ——————————         ——————
ALIBABA                        CMNTY_USER_MESSAGE              TABLE
ALIBABA                        MEMBER_PK                                      INDEX
ALIBABA                        OFFER_DRAFT_GMDFY_IND          INDEX

同上面一样还有这个方法

select object_name
from dba_objects
where data_object_id in
(select obj
from (select obj
from x$bh order by tch desc) where rownum < 11) ;
OBJECT_NAME
—————————————————
DUAL
MEMBER_PK
SAMPLE_GROUP_PK
CMNTY_USER_MESSAGE_TD_BSM_IND
OFFER_DRAFT_MID_GMDFY_IND
OFFER_MID_GPOST_IND
OFFER_DRAFT_PK
MEMBER_GLLOGIN_IND
OFFER_MID_STAT_GEXPIRE_IND
SAMPLE_MID_STAT_IND

10 rows selected.

到这里,我们寻找热点块和热点对象的工作算是完成了,但我们还并没有解决问题。

热点问题的解决

热点块和热点对象我们都找到了,但是我们该怎么来解决这个问题呢?一般来说,热点块会导致cache buffers chains竞争等待,但并不是说cache buffer chains一定是因为热点块而起,在特别情况下有可能是因为latch数量的问题导致的,也就是一个latch管理的buffers数量太多而导致竞争 激烈。但是latch数量我们一般是不会轻易去设置的,这是oracle的隐藏参数。

实际上最有效的办法,是从优化sql入手,不良的sql往往带来大量的不必要的访问,这是造成热点块的根源。比如本该通过全表扫描的查询却走了索引的 range scan,这样将带来大量的对块的重复访问。从而形成热点问题。再或者比如不当地走了nested loops的表连接,也可能对非驱动表造成大量的重复访问。那么在这个时候,我们的目标就是找出这些sql来并尝试优化。在statspack报告中,根 据报告中sql列表,我们如果是通过dba_extents确定的热点对象而不是通过dba_objects确定的,则可以通过查找出的热点 segment转换为对应的表,对于非分区的索引,index_name就是segment_name,通过dba_indexes很容易的找到对应的 table_name,对于分区表和分区索引也能通过和dba_tab_partition和dba_ind_partitions找到segment和 table的对应关系。通过这些table到statspack报告中去找相关的sql。

select sql_text
from stats$sqltext a,
(select distinct a.owner,a.segment_name,a.segment_type from
dba_extents a,
(select dbarfil,dbablk
from (select dbarfil,dbablk
from x$bh order by tch desc) where rownum < 11) b
where a.RELATIVE_FNO = b.dbarfil
and a.BLOCK_ID <= b.dbablk and a.block_id + a.blocks > b.dbablk) b
where a.sql_text like ‘%’||b.segment_name||’%’ and b.segment_type = ‘TABLE’
order by  a.hash_value,a.address,a.piece;

SQL_TEXT
—————————————————————-
SELECT SEQ_SMS_TRANSACTION.nextval FROM DUAL
SELECT SEQ_BIZ_EXPRESS.nextval FROM DUAL
SELECT bizgroup.seq_grp_post.NextVal FROM DUAL
SELECT SEQ_SAMPLE.nextval FROM DUAL
SELECT bizgroup.seq_grp_user.NextVal FROM DUAL
SELECT SEQ_BIZ_SEARCHER.nextval FROM DUAL
SELECT SEQ_OFFER_DRAFT.nextval FROM DUAL
select seq_Company_Draft.NextVal from DUAL
SELECT SEQ_SAMPLE_GROUP.nextval FROM DUAL
SELECT SEQ_CMNTY_USER_MESSAGE.nextval FROM DUAL
SELECT SYSDATE FROM DUAL
select seq_News_Forum.NextVal from DUAL
SELECT SEQ_SMS_USER.nextval FROM DUAL
select seq_Biz_Member.NextVal from DUAL
select seq_Pymt_Managing.NextVal from DUAL
E= ‘+08:00’ NLS_DUAL_CURRENCY = ‘$’ NLS_TIME_FORMAT = ‘HH.MI.SSX
SELECT SEQ_COMPANY_DRAFT.nextval FROM DUAL
SELECT 1 FROM DUAL
select seq_offer_draft.NextVal from DUAL
select seq_Biz_Express_Category.NextVal from DUAL

20 rows selected.

当然这里是从statspack搜集的stats$sqltext中去找的(你可以在statspack的文本报告中去找),实际上,我们可以直接在当前数据库中的v$sqlarea或者v$sqltext里面去找到这些sql,然后来尝试优化。

select sql_text
from v$sqltext a,
(select distinct a.owner,a.segment_name,a.segment_type from
dba_extents a,
(select dbarfil,dbablk
from (select dbarfil,dbablk
from x$bh order by tch desc) where rownum < 11) b
where a.RELATIVE_FNO = b.dbarfil
and a.BLOCK_ID <= b.dbablk and a.block_id + a.blocks > b.dbablk) b
where a.sql_text like ‘%’||b.segment_name||’%’ and b.segment_type = ‘TABLE’
order by  a.hash_value,a.address,a.piece;
SQL_TEXT
—————————————————————-
SELECT NULL FROM DUAL FOR UPDATE NOWAIT
SELECT SEQ_SMS_TRANSACTION.nextval FROM DUAL
SELECT SEQ_BIZ_EXPRESS.nextval FROM DUAL
SELECT SEQ_IM_GROUP.nextval FROM DUAL
SELECT SEQ_SAMPLE.nextval FROM DUAL
=’DD-MON-RR HH.MI.SSXFF AM TZR’ NLS_DUAL_CURRENCY=’$’ NLS_COMP=’
SELECT SEQ_BIZ_SEARCHER.nextval FROM DUAL
SELECT SEQ_OFFER_DRAFT.nextval FROM DUAL
SELECT SEQ_SAMPLE_GROUP.nextval FROM DUAL
DD-MON-RR HH.MI.SSXFF AM TZR’ NLS_DUAL_CURRENCY=’$’ NLS_COMP=’BI
SELECT SEQ_CMNTY_USER_MESSAGE.nextval FROM DUAL
SELECT SYSDATE FROM DUAL
SELECT SEQ_SMS_USER.nextval FROM DUAL
IMESTAMP_TZ_FORMAT=’DD-MON-RR HH.MI.SSXFF AM TZR’ NLS_DUAL_CURRE
SELECT SEQ_COMPANY_DRAFT.nextval FROM DUAL
SELECT 1 FROM DUAL
SELECT USER FROM DUAL
SELECT DECODE(‘A’,’A’,’1′,’2′) FROM DUAL

18 rows selected.

除了优化sql外,当然对于热点的表或者索引来说,如果小的话,我们可以考虑cache在内存中,这样可能降低物理读提高sql运行速度(这并不会减少 cache buffer chains的访问次数),对于序列,我们可以对序列多设置一些cache。如果是并行服务器环境中的索引对象,并且这个索引是系列递增类型,我们可以考 虑反向索引(关于反向索引这里就不过多地做介绍了)。

热点块的其他相关症状

在数据库中还可能存在一些其他方面的热点块症状,通过v$waitstat的等待可以看出一些端倪,v$waitstat是根据数据缓冲区中各种block的类型(x$bh.class)而分类统计的等待状况。

select”>sys@OCN>select * from v$waitstat;

CLASS                   COUNT       TIME
—————— ———- ———-
data block            1726977     452542
sort block                  0          0
save undo block             0          0
segment header             40         11
save undo header            0          0
free list                   0          0
extent map                  0          0
1st level bmb             611        112
2nd level bmb              42         13
3rd level bmb               0          0
bitmap block                0          0
bitmap index block          0          0
file header block          13         92
unused                      0          0
system undo header        111         28
system undo block           7          0
undo header              2765        187
undo block                633        156

比 如在ASSM表空间出现之前,由于freelist的存在,如果表经常被并发的进程DML,则可能存在大量的data block的等待,或者有free list的等待。那么这个时候我们发现这样的segment之后需要考虑增加freelist数量。再比如经常发生长时间的DML的表被频繁地访问,这样 将会造成过多的对回滚段中块的访问,这时可能undo  block 的等待会比较多。那么我们可能需要控制DML的时间长度或者想办法从应用程序入手来解决问题。如果是undo header的等待比较多,没使用undo tablespace 之前,可能需要考虑增加回滚段的数量。

总结

本文从热点块的原理入手,详细地由oracle的内部结构特征开始介绍了热点块的产生和表现特征。进而阐述了诊断热点对象和找出造成热点对象的sql的方法。并从解决热点问题方面提供了解决方向。

文章来源:http://blog.csdn.net/biti_rainy/article/details/35188

遭遇美尼尔

       3周前的1天,早上起床感觉头晕,去大华医院检查,医生检查了小血,心电图,除窦性心动过缓(58/次)外,其他正常,但医生说其实窦性心动58/次也还不算太差。当时开了通天口服液4盒; 个人认为是缺乏体育锻炼而导致,于是又开始早晨跑步,希望能消灭头晕症状。3天以后到外地出差1周,出差期间早上也坚持跑步,但有时感觉头不是很清醒,有疲劳感。

        出差回上海后第1天晚上睡觉时,在从仰卧转为左侧卧或者右侧卧的时候,感觉天旋地转,但一般20秒以后消失。早上起来还晕,有天旋地转的感觉,但1分钟以后即恢复正常。第2天晚上症状依旧,睡觉不踏实,早上起来竟然无论如何也无法站立,一站起来就天旋地转,恶心,心跳加速,呼吸加速,很难受;只能躺下,几分钟后再次尝试站起来均告失败。 家人着急,既无法起床,那么只能叫120来把我扶上车,去8院挂急诊;

       在8院挂了2袋生理盐水,1袋党参;同时做大血检查、心电图检查、脑CT检查;情况均属正常;想让医生继续做颈椎检查,急症医生说中青年因为颈椎原因导致眩晕的可能性极小,急症室不做这种检查。 3瓶水挂完已是下午,LP给我吃了点皮蛋瘦肉粥,尝试站起来依然很晕,问能否吃刚才医生配的 甲磺酸倍他司汀片(俗称 敏使朗),医生说回去再吃,于是强坚持站了起来,虽感觉头脑还是有点昏沉,脚步还不是太稳,但相信自己可以坐出租回去;于是到院外叫了一辆出租回家,回到小区先在活动区坐了一会,然后自行爬楼梯上楼了;到家终于坚持不住了,狂吐不止,把在医院吃的瘦肉粥和红枣全部还了出来,躺下后抱着试试看的态度,服用了甲磺酸倍他司汀片,半小时后感觉疗效很快很好;感觉这药很对胃口,看说明其药理作用是加快内耳迷路微循环的血流量。网上查这种药也属于晕车药的一种。

       第2天继续休息调整,继续服用甲磺酸倍他司汀片,感觉好很多了;晚上睡觉时侧翻虽然也有晕的感觉,但明显要轻很多,且恢复速度快!第3天早上起来感觉还可以,于是去上班了,由于很多人建议得这种病的人尽量别开车或者少开车,于是坐地铁去上班;个人觉得这样也好,因为坐地铁的话,整个路程中要步行25分钟,这样一天来回可以多走50分钟,既绿色又健康;

       第一天在公司上班有时感觉有些气短,但基本没有眩晕;第二天上班气短的感觉没有了,上午也没有眩晕,但下午3点左右时在弯身往地板上拔插电源时,依然触发了眩晕,但恢复很快,一段时间内有点难受,但基本站立没有问题;本想再次服用甲磺酸倍他司汀片,但考虑到这种药片毕竟是应急药,不宜多服,于是没有服用,晚上坐地铁回家,一路上没有问题;

    回到家后,感觉还不错,增强中药治疗,有朋友推荐了红枣+天麻 共煮服用的药方,虽然网上有人说服用天麻对美尼尔好像无效,但我认为每人情况不一样,既然甲磺酸倍他司汀片对我有效,那么天麻也有活血作用,对我应该也有效,至少不会有反作用,于是就煮了服用了,考虑到多睡对美尼尔有用,在晚上9:00就开始睡了。这一晚,在翻侧时基本没有眩晕的感觉了。 早上醒来感觉好多了,开车陪LP去了趟龙华寺也没有什么问题。

经过上述经历,我个人认为如下细则应该在今后被遵守:

1)以后坚持坐地铁上下班(除非遇到流感高峰),这样既可以减少危险发生概率,又可以多锻炼身体(每天增加50分钟步行时间)

2)没事不要折腾到很晚才睡,晚上10:00之前没什么事就睡吧。

3)天麻这种食品在平时可以少量泡茶,含在嘴里咀嚼等等,以促进脑部血液循环。

4)在适当的时候增加体育锻炼;我记得2003年的时候,每次弯身都感觉脑部有胀感,后来坚持跑步1年多以后,就没有这种感觉了。

 

其他嘛,有人说美尼尔病人不能开车,我倒是觉得只要身体状况稳定,周六周日开开也无所谓。对我而言,这种病发作是有征兆的,由轻到重,可以提前控制。

附:天麻的副作用

天麻是一味常用而较名贵的中药,临床多用于头痛眩晕、肢体麻木、小儿惊风、癫痫、抽搐、破伤风等症。由于天麻对肝阳上亢引起的头痛、眩晕等效果显著,故常被人当成“补药”服用。一见眩晕,不分体质虚实,气血盛衰,就妄用天麻,其结果就可能出现以上患者一样的不良反应。

    服用天麻出现的常见不良反应有:头晕、恶心、胸闷、皮肤丘疹伴瘙痒等,个别会出现面部或全身浮肿,甚至脱发现象。不仅单用天麻会发生这类反应,有的人服了含天麻的汤剂如半夏白术天麻汤等、中成药如天麻丸、天麻蜜环菌糖衣片后,同样会出现对天麻过敏的症状。

    对天麻的副作用或使用禁忌,古人早有认识。如《本草纲目》云:“久服天麻,遍身发出红丹。”《本经逢原》也云:“天麻性虽不燥,毕竟风剂,若血虚无风,火炎头痛、口干便闭者,不可妄用。”

    清代名医吴仪洛更是直言:“血液衰少及非真中风者忌用”。现代药理实验证明:天麻有一定毒副作用,天麻中毒剂量是40g以上,中毒潜伏期是1~6小时。

    使用天麻时“药不对证”是引起不良反应的重要原因之一。所以,使用天麻时应注意这样几点:

    1.凡病人见津液衰少,血虚、阴虚等,均慎用天麻。

    2.重视配伍应用。《本草衍义》有“天麻须别药相佐使,然后见其功”的记述。古今医家很少单味使用天麻,而多根据不同病证组方用药。如:半夏白术天麻汤、天麻钩藤饮、天麻丸等。临床证明,单独使用天麻的效果不佳或者效果不确定。

    3.即使针对肝阳上亢、痰阻经络等实证时,使用天麻也要详审病情,把握病机,随证加减,方能取得良好的治疗效果。

    4.天麻不宜合久煎。天麻的主要成分为天麻甙,遇热极易挥发。天麻与他药共煎会因热而失去镇静镇痛的有效成分。所以,天麻最好先用少量清水润透,待软化后切成薄片,晾干或晒干研末,用煎好的汤药冲服,或研末入丸、散服用。

    5.使用单味天麻或天麻制剂时,如出现头晕、胸闷气促、恶心呕吐、心跳及呼吸加快、皮肤瘙痒等时,应立即停药,症状严重者应及时到医院诊治。

2011春节-常州恐龙园

 

有朋友说过年这几天晚上,常州恐龙园挺好玩的,虽是常州人,以前还真是一直没去过,于是在大年初四晚上,决定去看一下。

这是常州恐龙园的一个概要介绍:

IMG_0997

走了一圈整体感觉恐龙园是一个科教基地和娱乐设施齐聚的大型游乐场所,还是挺值得大家去看看的,大家跟着我的摄像镜头,来领略一下恐龙园的特别景致吧。

IMG_0984

这些都是恐龙化石。

IMG_1009

 

IMG_1012

这个是什么,大家猜到了吗,对了,这就是恐龙蛋。

IMG_1020

 

IMG_1024

 

IMG_1073

 

IMG_1013

 

IMG_1011

 

IMG_1008

由于是晚上去的,所以灯光效果特好。

IMG_1044

这个是金刚。

IMG_1104

IMG_1146

IMG_1141

 

这是大风车

IMG_1159

这是新春特别节目,彩灯游行。

p2

 

p4

 

p6

 

p7

 

p10

vmware虚拟机中的oracle侦听性能问题

vmware虚拟机中的oracle数据库侦听性能问题

最近发现一件怪事情:vmware虚拟机中的oracle数据库在更改到另一网段的IP后性能暴降,简直低到不能忍受。

背景:vmware 7.1软件运行于64位 win7平台。新建一个32位置 linux(redhat 5.x) 虚拟机,数据库oracle11g 运行于此虚拟机上。

问题重现步骤(nat方式):

1、假设你的虚拟机的vmnet8 (nat) 是192.168.15.X   网段,设置虚拟机网络为nat方式,并设置虚拟机的ip地址为192.168.15.10 ; 这种情况下,在虚拟机的本机上使用sqlplus username/passwrod@Tnsname 链接数据库,速度很快,基本在1秒以内肯定链接上了。

2、更改你的数据库的 IP地址到其他网段,比如192.168.188.10 , 重启inxu网络服务,再重启数据库,再测试,在虚拟机本机上 使用sqlplus username/passwrod@Tnsname 连接数据库,速度很慢,大概有10秒以上。

或者,你使用桥接方式测试也是这样的:

问题重现步骤(桥接方式):

假设你的虚拟机使用桥接方式:在家庭网络中,你的桥接网段是192.168.1.x , 你的数据库ip 是:192.168.1.10 , 这时候速度正常。 然后你到了公司,网段是10.X.X.X ;  这时候发现在公司网段中数据库测试:在虚拟机本机上使用 sqlplus username/passwrod@Tnsname 连接数据库,速度很慢,大概有10秒以上。

按道理说:我在虚拟机本机上使用sqlplus又没有跨什么网络。使用traceroute都是一跳就到了。这是什么原因导致oracle 的侦听响应特别慢呢?

R12.1.2 使用问题汇集

 

本文的上一篇文章是:从 R12.1.1 升级到 R12.1.2 中文语言 Patch问题

 1、访问主组织物料提示:你必须至少允许访问一组物料属性。 

       原因:INV模块没有被授权

       解决方法:system administration ->License Manager ->Product 把INV 产品授权,即可。 

2、打开order 界面 报ORA-04062错误  of  state changed,且中文语言进入的Form上还都是英文的。 

      解决方法:adadmin 重新编译数据库对象、重新编译菜单(这个还算快,不太费时)。 没用!

                            adadmin 重新编译Form(比较耗时间,准备1晚上吧,9000多个Form,Pll任务要编译 US 和 ZHS) ,ORA-04062 在新建订单时不出现了,中文Form进入也是显示中文label了。 

3、中文模式进入OM模块  编辑订单时还提示CCID未找到,订单行上的Item显示为空。但英文模式进入没有上述问题。 

       查 : select distinct language from mtl_system_items_tl 只有 US ,没有中文。 

                 select * from  fnd_lookup_values  where language =’ZHS’ 有中文。 

                 说明只是部分表的多语言没有被初始化。 

       解决方法:停应用; 

      想使用adadmin 中的   Maintain multi-lingual tables  功能来把item的中文给初始化一下,但又担心把其他好的表中的中文内容给“冲”掉。于是查Maintain multi-lingual tables究竟干了什么? 查metalink  [ID 981868.1] 发现在执行Maintain multi-lingual tables 时,实际就是执行inv模块下面的 sql/INVNLINS.sql ;打开这个sql看,其实针对item执行的是INV_ITEM_PVT.add_language; 查看INV_ITEM_PVT.add_language的代码,发现其逻辑是:不会重复“覆盖”原来已经有其他语言的记录。所以多次执行也没有问题,但为什么为什么Item的中文信息会丢失呢?难道是以前没有运行Maintain multi-lingual tables,不可能啊,ORG_FREIGHT_TL中是有中文的记录的,ORG_FREIGHT_TL的中文信息也是在sql/INVNLINS.sql执行的。 

      不管它,先在plsqldeveloper中直接运行 INV_ITEM_PVT.add_language,把中文item给生成了。 

      再起应用,中文环境,进入OM,打开一张订单 item已经有了,但是新建一行时,计量单位还是没有,在英文环境是好的。 

      停应用,使用adadmin  Maintain multi-lingual tables, 再启应用,在中文下问题依旧,查MTL_UNITS_OF_MEASURE_TL 确实缺少中文记录,查adadmin的log  INVNLINS.sql已执行。在plsqldeveloper中单独执行 INVNLINS.sql ,发现例外:

LANGUAGE = AMERICAN

PACKAGE= MTL_UNITS_OF_MEASURE_TL_PKG

SQLERRM= ORA-00001: unique constraint (INV.MTL_UNITS_OF_MEASURE_TL_U2) violated 

是这个原因导致 INVNLINS.sql执行中断的。 

这些记录比较怪,Source_lang =’ZHS’,这是不对的,source_lang 应该都是’US’才对。 

Period N 2010/8/13 22:38 0 2005/5/5 120 0   每半年 每半年 ZHS ZHS
Period N 2010/8/13 22:38 0 2005/5/5 120 0   每周 每周 ZHS ZHS
Period N 2010/8/13 22:38 0 2005/5/5 120 0   每月 每月 ZHS ZHS
Period N 2010/8/13 22:38 0 2005/5/5 120 0   每季 每季 ZHS ZHS
Period Y 2010/8/13 22:38 0 2005/5/5 120 0   每两周 每两周 ZHS ZHS
                       

 经查是 patch/6678700_ZHS/inv/patch/115/import/ZHS/invuomcl.ldt 给导入进来的。想不通为啥中文语言包要单独insert这几条数据。 

删除这5条记录 delete from mtl_units_of_measure_tl where  source_lang=’ZHS’ 

再次单独执行  INVNLINS.sql 返回:

ORA-0000: normal, successful completion 成功完成。 再次以中文环境登录,Ok了。

物料事务处理接口错误处理日志-例2

客户:达芙妮

现象:1 并发节点文件系统满,导致并发管理器挂起

             2用户删除了部分日志和输出文件,并重新启动管理器,所有管理器都正常启动,只有库存管理器actual=0, target=10

分析&解决 

一、灏明(Oracle) 10日去现场看了下,发现后台库存管理器进程状态为defunct,mtl_tranasctions_interface中有大量待处理数据(从出故障到现在的所有库存事物处理),并采取了一次处理少量数据来解决问题,下面是他的脚本

——————————————–

继续阅读“物料事务处理接口错误处理日志-例2”

接收事务处理接口错误处理日志1例

/*******************************************************************************
date : 2007-05-08
处理者: yunfang.shang
*******************************************************************************/

select * from rcv_transactions_interface
–查接收接口中来自销售订单退货的记录(error_message是错误信息提示)
SELECT rti.processing_request_id,
       rti.creation_date,
       rti.transaction_date,
       rti.group_id,
       oeh.order_number,
       rti.item_id,
       item_description,
       rti.unit_of_measure,
       rti.quantity,
       rti.source_document_code,
       rti.subinventory,
       oel.flow_status_code,
       pie.error_message
  FROM rcv_transactions_interface rti,
       oe_order_headers_all       oeh,
       oe_order_lines_all         oel,
       PO_INTERFACE_ERRORS        pie
 WHERE rti.oe_order_header_id = oeh.header_id
   AND rti.oe_order_line_id = oel.line_id
   AND rti.oe_order_header_id = oel.header_id
   AND rti.interface_transaction_id = pie.interface_line_id(+)
 ORDER BY oeh.order_number
—       
继续阅读“接收事务处理接口错误处理日志1例”

物料事务处理器启动后自动失效的问题处理日志

/*******************************************************************************
date : 2007-04-25
处理者: yunfang.shang
*******************************************************************************/

现象:

在 INV-〉SETUP-〉Transactions ->Interface Manager 中把Material transaction启动
Material transaction 变成有效状态
但是 Material transaction 在运行一次后又自动失效了。

由于 Material transaction 未能始终处于有效状态,所以导致很多接口数据未能被处理。
用户需要在启动Material transaction时,让并发请求处于周期运行的方式。
用户觉得比较怪。因为正常情况是启动管理器以后,管理器就应该始终处于有效状态。不需要人为的把并发请求设置为周期运行的。

分析:
查Metalink, 关键词: Material transaction inactive
所查到的都是2004年及以前的与此类似的现象,都是说要打个patch 1734240 解决此问题。
但现在是11.5.10.2版本,这个patch肯定早已经包含在某个patch set中了,故肯定不是这个问题。

  继续阅读“物料事务处理器启动后自动失效的问题处理日志”

物料事务处理接口日志一例

物料事务处理接口日志一例

/*******************************************************************************
date : 2007-05-06
处理者: yunfang.shang
*******************************************************************************/
现象:库存事务处理接口中堆积了大量记录未被处理
现象:接口表中很多记录处理结果为Error;原因是组织层不允许负库存,而库存现有量不足,导致无法扣减库存成功
      大量出库记录由此被堵塞在接口表。
处理日志:
 select count(*) from MTL_TRANSACTIONS_INTERFACE
 select count(*) from Mtl_Material_Transactions_Temp
 
 –事务处理数量
 SELECT
   — *
   –transaction_quantity
   –distinct transaction_source_type_id
   FROM MTL_TRANSACTIONS_INTERFACE
  WHERE transaction_interface_id = 321706
    AND error_code IS NOT NULL
   
 SELECT *
   –transaction_quantity
   FROM Mtl_Material_Transactions_Temp where trx_source_line_id =22964
  
 –保留
 select * from mtl_demand_v a where a.demand_id =  22964
   
 –现有量
 SELECT sum(transaction_quantity)
   FROM mtl_onhand_quantities moq
  WHERE moq.INVENTORY_ITEM_ID = 3489
    AND moq.ORGANIZATION_ID =108
    AND moq.SUBINVENTORY_CODE =111215001
    –物料编码
    SELECT segment1
      FROM mtl_system_items_b
     WHERE organization_id = 108
       AND inventory_item_id = 3489
      
 — 查找错误记录的现有量
 SELECT a.transaction_interface_id,
       msi.segment1,
       a.organization_id,
       a.subinventory_code,
       a.transaction_quantity,
       XH_COMMON_UTL.get_onhand_qty(a.inventory_item_id,
                                    a.organization_id,
                                    a.subinventory_code) on_hand_qty
  FROM mtl_transactions_interface a,
       mtl_system_items_b msi
 WHERE a.inventory_item_id = msi.inventory_item_id
 and   a.organization_id = msi.organization_id
 and   a.error_explanation IS NOT NULL  

继续阅读“物料事务处理接口日志一例”

千M网络-实际应用中传输速度测试

千M网络在实际应用中究竟能给我们的传输速度带来多大的提高呢?

理论上千M网络的速度可以达到1000M bit (大约100M byte)的速度,以下的讨论中,如果不做特别说明速度均是针对Byte而言的。也就是说千M网络的传输速度上限是100M/秒。

在实际应用中受各种因素(包括硬盘读写速度,操作系统文件读写处理,传输软件本身的设计等等)的影响,速度要大打折扣。我们这里做了几个试验来看看效果:

继续阅读“千M网络-实际应用中传输速度测试”

虚拟机性能优化小结

虚拟机性能优化小结

1、使用预分配的vmdk虚拟硬盘,速度不比物理分区慢。一定要使用预分配的,如果是动态增长的vmdk那速度是比预分配的vmdk 差一个数量级的。

 2、给Host机器适当留些内存,不要以为把Host上的几乎所有内存否分配给Guest机,Guest机就会跑得最快。要考虑vmware 本身也是在Host机上运行的,一般建议至少给Host机留600M内存(Linux Host 图形模式)

3、按照vmware 手册中的Performance tunning 指导进行操作,主要包括:

       3.1  vmware settings ->options->Advanced: Disable memory page trimming

      3.2  在vmx 中添加配置:sched.mem.pshare.enable=”FALSE”

      3.3  在edit ->Perferences ->Memory :Fit all virtual machine memory into reserved host RAM

      3.4  尽量去掉虚拟机上不不要的设备,比如对于运行EBS的虚拟机而言,软驱、光驱、声卡都不需要。去掉。

经过上述优化后的虚拟机的磁盘IO性能测试结果如下:

     DELL PE800 + segate Sata 250G   , 使用hdparm -t 进行测试, Host 可达到74M/s  ;  虚拟机可达到 70M/s  基本与Host相当。

     另外发现在DELL PE800 + segate Sata 250G 上运行 EBS 运行时,CPU经常出现 wa  >50%的情况,说明IO是瓶颈。

     DELL PE800 + segate Sata 250 没有做Raid的情况下:hdparm -t 测试 74M/s ; DELL PE2950 + sas 硬盘 ,没有Raid的情况下hdparm -t 测试 125M/s ;Riad0 的情况下 225M/s;   可见 riad 0 的情况下,IO 速度基本是 2倍于非Raid的磁盘。

     在Host = DELL PE800 + segate Sata 250G +4G内存 + P43.0  的情况下,给Guest 分配2.8G内存;数据库Pga 设置750M , db cache 300M +  shared pool  600M +java pool 100M  ,启动后的SGA 打开1.2G;  运行ebs115102时,数据库 和应用启动后,连接一个用户,访问部分模块后,内存消耗大概在2.1G ; 访问部分页面存在等待现象,主要原因在于IO瓶颈;CPU 和 内存还暂时没有问题。 如果要改进,需要使用Raid 0;

     在vmware  中使用软Raid; vmdk分别创建在不同的物理磁盘上,IO效果是否会增强呢? (有关如何创建软raid请参考:http://net.csai.cn/store_Raid/200707251026451937.htm

    测试过程:在笔记本电脑的虚拟机上,使用4块vmdk 构成riad0 ; 其中2块vmdk在物理磁盘1上,另外2块vmdk 在屋里磁盘2上。riaid 的速度是17.5M/s , 非raid的速度是: 16M/S ; 可见 软raid0的速度提升很小。

产销“联营扣点”商家如何纳税

发布:2008-8-06 10:15 | 作者:webmaster | 来源:转载

 

我是深圳的一家大型零售企业,主要经营3个综合商场。在具体经营过程中,我们一方面实行自营,即自己组织商品,自己组织销售;另一方面,将部分柜台出租给生产厂家,由他们派人组织销售活动,我公司只负责现场管理。在具体操作过程中,我们采用了如下操作模式:商场与生产厂家签署租赁合同,规定,一是商场出租200平方米的柜台给厂商作为销售产品的场地;二是厂商自派员工到商场销售和管理自己的商品;三是厂商每月向商场支付按销售额的18.5%(但是不得低于20万元)的租金;四是厂商的销售额由商场统一收取,月末结算时租金直接在销售额扣除;五是商场向厂商每月收取8万元的进场费和宣传费。
  2005年11月28日,当地主管国税局稽查局的税务人员对我公司2004年度的经营情况进行了检查,他们发现我公司2004年度的“其他业务收入”存在问题,认为公司从10月份开始通过“联营扣点”形式取得的租金收入2360万元应当计算缴纳增值税。对此我们很不理解,根据现行税收法规,我们取得的收入应当按租金收入计算缴纳营业税,为什么要我们缴纳增值税呢?要知道,两者税率相差12个百分点啊!请专家给我们指点迷津。
        深圳市某公司财务总监 李红

继续阅读“产销“联营扣点”商家如何纳税”

美廉美朱幼农-为什么采用以联营为主的生鲜经营模式

  
    来源: 作者: 发布时间:2007-08-28 

  北京美廉美连锁商业有限公司总裁 朱幼农

  2007超市生鲜经营研讨会系列报道之——

  美廉美朱幼农:为什么采用以联营为主的生鲜经营模式?

继续阅读“美廉美朱幼农-为什么采用以联营为主的生鲜经营模式”

视同销售会计处理总结

2009-06-12 源自:价值中国网

    税法中规定企业的八种视同销售行为需要计算缴纳增值税:
 
  (1)自产或委托加工货物用于非应税项目的会计处理:企业将自产或委托加工的货物用于非应税项目,属于自产自用性质,不得开具增值税专用发票,但需按规定计算销售额和应纳税额。

  借:在建工程

    贷:库存商品

      应交税金——应交增值税(销项税额)

继续阅读“视同销售会计处理总结”

行业发展的一些想法

2007年老范确定了行业发展思路。

2007 – 2009 本人参与的项目基本集中在零售行业,包括协亨手机,旭硝子零售公司、达芙妮。

2009年8月30日,我们与Oracle 北区总经理一起讨论的时候,Oracle也重点强调了实施伙伴行业发展 更深入,更彻底。他认为Hand 有300多个Oracle客户,积累了丰富的、各行各业的解决方案,是个大金库。只是现在对这些金矿的开发还很不够。需要加大力度。

继续阅读“行业发展的一些想法”

Gforge 全文检索攻略

=====================
Step0  准备工作:  安装sphinx + Sphinx分词补丁 + 中文分词
=====================
详细步骤请参考:

http://blog.retailsolution.cn/index.php/sphinx-pgsql-chinese-word-seg

=====================
Step1  创建增量索引计数表
=====================
# In Pgsql ,Create table for form_message
CREATE TABLE sph_counter
(
counter_id INTEGER PRIMARY KEY NOT NULL,
max_doc_id INTEGER NOT NULL
)

— for forum message
insert into sph_counter (1,100);
— for tracker item
insert into sph_counter (2,100);

继续阅读“Gforge 全文检索攻略”

Sphinx+Pgsql+中文分词安装

一、安装所需文件
mmseg-0.7.3.tar.gz  中文分词

http://www.coreseek.com/uploads/sources/mmseg-0.7.3.tar.gz

sphinx-0.9.8-rc2.tar.gz sphinx-0.9.8-rc2源代码
http://www.sphinxsearch.com/downloads/sphinx-0.9.8-rc2.tar.gz 

sphinx-0.98rc2.zhcn-support.patch sphinx支持分词补丁
http://www.coreseek.com/uploads/sources/sphinx-0.98rc2.zhcn-support.patch

fix-crash-in-excerpts.patch sphinx支持分词防crash补丁
http://www.coreseek.com/uploads/sources/fix-crash-in-excerpts.patch

 

继续阅读“Sphinx+Pgsql+中文分词安装”

On-Off-line混合模式应用实例-销售线索跟踪(Flex+Gears)

salesbuilder.png

As a follow up to my previous post, here is the sample Sales Force Automation application I built to demonstrate the Flex/Google Gears integration, and that Kevin Lynch demonstrated during the Google Developer Day keynote last week in San Jose.

SalesBuilder uses the Google Gears Database API to save data to an embedded SQLite database, and the LocalServer API to enable offline access to the application.

  继续阅读“On-Off-line混合模式应用实例-销售线索跟踪(Flex+Gears)”

中国制鞋工业中CAD/CAM现状

中国制鞋工业中CAD/CAM现状

中國制鞋企業目前對CAD/CAM應用現狀還處於摸索起步階段;現在國內能夠把CAD/CAM真正運用起來的企業為數尚少,只有一些像萊爾斯丹鞋業、森達鞋業、百麗鞋業、港京鞋業、港龍鞋業 …… 等較大型的企業引進了這方面的系統。是什麼制約我國的制鞋CAD/CAM應用呢?究其原因,有眾多因素在面。

1. 對CAD/CAM系統不夠瞭解:有些人甚至認為CAD/CAM系統應該只要把鞋子一掃描進入電腦,電腦發出指令給機器自動將所需的產品全部自動做出來。究竟CAD/CAM系統是什麼呢?能夠做到什麼呢?電腦輔助制鞋系統實分為輔助設計及輔助生產兩部分;CAD輔助設計包括2D及3D,現在國內的軟體只是停留在2D平面設計,紙板級放及算料的階段,而國外有些軟體可以從3D輸入鞋楦開始 → 設計開發鞋楦 → 3D虛擬鞋樣 → 3D展平成2D → 取蹺處理 → 產生成套紙板樣片。CAM輔助生產設備如數控刻楦機、自動排料鞋面切割機 …… 等。

继续阅读“中国制鞋工业中CAD/CAM现状”

设计模式读书笔记(1)-模式的普遍性

设计模式读书笔记(1)-模式的普遍性

最近利用周末时间在看《设计模式》,我会把个人的理解以读书笔记的形式发布在这个Blog 上,与关注此类问题的朋友们一起来讨论。

     《设计模式》第1页提到了利用模式的好处:“内行的设计者知道:不是解决任何问题都要从头做起。他们更愿意用以前使用过的解决方案。当找到一个好的解决方案,他们会一遍又一遍地使用。这些经验是他们成为内行的部分原因。第2页提到模式的定义:“每个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必重复劳动” 。

继续阅读“设计模式读书笔记(1)-模式的普遍性”

2008-2012年中国女鞋市场深度调查与发展前景分析报告

【报告名称】 2008-2012年中国女鞋市场深度调查与发展前景分析报告
【出版日期】 2009年2月
【报告页码】 103页 
【交付方式】 email、EMS特快专递
【报告价格】 纸版价 RMB6500元  电子版价 RMB 6800元  纸版价+电子版价 RMB 7000 元

前言
    我国人口总数超过13亿人,其中女性人口数量6.24 亿,约占人口总数的48%。这是一个蕴涵着巨大的商机的市场。然而,巨大的市场商机中也暗藏着巨大的竞争。市场中有80%都属于地方品牌。目前,我国从事鞋业生产的企业7200多家,加上国外企业针对中国推出的品牌和已经成名的国际品牌以及贴牌生产的皮鞋品牌,品牌数量不下万余。

继续阅读“2008-2012年中国女鞋市场深度调查与发展前景分析报告”

鞋业设计师

1) 鞋业设计师

(参考来源:http://file.yingjiesheng.com/list/career_guide/ent/art/20080430/8842.html
 
【职能定义】
鞋业设计师是指在制鞋行业负责鞋子的外形设计、材质选择、版样绘制等事务专业人员。
 
【工作职责】
①对鞋业设计的信息进行搜集和筛选;
②设计鞋子的外形;
③挑选鞋子的材质;
④制作鞋子的版样;
⑤对鞋子的设计进行调整;
⑥与制鞋人员就设计相关问题进行沟通。
 
 
【薪酬待遇、职业发展等行情】
鞋样创新是当前中国鞋业发展所必须考虑的重要问题。设计开发创新已成为促进我国制鞋企业发展最有效的手段,未来的竞争是设计竞争,是特色竞争,靠设计和特色制胜(在鞋的需求上,舒适、保健、美观、文雅将成为一种重要追求)。在新形势下,鞋类企业竞争的焦点就是企业自身新产品的开发能力,最终体现为设计师水平的较量。

【专业、技能及素质要求】
①美术专业或鞋业设计专业,大专以上学历;
②了解各类鞋子的结构特点和人们的穿着习惯;
③擅长使用各种设计软件;
④时尚信息触觉敏锐,敏锐的观察力,丰富的想象力,巧妙的构思能力和高超的表现能力。
 
 
【求职小贴士】
从某种角度上来说,鞋类设计师又充当着企业“调研员”、“情报员”的角色,在新产品开发和实施行销计划过程中,鞋类设计师还应当在产品开发档次定位、产品市场销售定位、销售价格定位、消费群层次定位以及营销策划、宣传策划等方面成为企业的参谋。

时装巨头H&M和ZARA的供应链对决

H&M用双供应链平衡效率与成本,ZARA则凭借极速供应链打天下。这对时装业大佬,台前拼光鲜,台后却各有各道。
  H&M 竭力在效率和成本之间寻找利润平衡点
  上海淮海中路的嘉丽都商厦的外墙上,H&M的巨幅海报吸引着每个路人的视线。4月12日,这家来自瑞典的时装零售业巨头将在这里开设内地首家旗舰店。相隔几站地铁的南京西路上,H&M的宿敌——西班牙Inditex集团下面的旗舰品牌ZARA正在热卖。ZARA的这家面积约1500平方米,今年春节却创下了单日销售额愈百万元的佳绩。
  在黄金地段开店、与奢侈品为邻、店面光鲜,采用“少量、多款、平价”的理念,对流行时尚做出快速反应,是ZARA和H&M的共同点。凭借这些策略,它们在过去几年飞速成长:2003年,ZARA成为全球排名第三的服装零售商,2004财年其全球营业收入达到46亿欧元,获利率高达9.7%,超过美国第一大服饰连锁品牌GAP6.4%的获利率。作为欧洲最大的服装零售商,H&M在过去5年中,营业额增加了100%,分店数量增加了75%,每股盈利增加了262%,2005财年的税前利润总额达到135.53亿瑞典克朗(约合1188.59亿欧元)。
  “做时尚的跟随者,而不是创造者”,就意味着对前导时间(lead time,即产品从设计到销售上架的时间)要进行有效控制。资料显示,ZARA的前导时间为15天,H&M的前导时间最快为20天,而国内服装企业的通常前导时间为90天~120天左右。
  ZARA和H&M,这是一对常被时装业界同时提起的劲敌,台前它们拼的是光鲜,台后拼的却是供应链。让ZARA引以为傲的是极速供应链,即便是在远离西班牙的中国开设门店,它也奇迹般地保持了15天的极速;而信奉“时间、品质和价格”三合一的H&M则采用了两条供应链,竭力在效率和成本之间寻找利润平衡点。
  双供应链
  和ZARA相比,H&M最快的前导时间晚了5天。不过,这5天的代价却让H&M赢得了成本优势——“它的服装售价比ZARA便宜了30%-50%”。
  ZARA 用“极速”供应链打天下
  在H&M推崇的“三合一”理念中,成本的优先级别最高,因此其生产地总是向拥有优良劳动力、低廉工资和高质量生产的地区转移。上世纪60年代中期~70年代,H&M陆续在北欧、南欧、东亚等设立了生产地,它并不拥有自己的工厂,而是将生产全部外包给分布在欧亚22个国家的700家独立供应商。
  如何与这些分布在各地的供应商建立紧密联系?H&M采取了在生产地设立生产办事处的策略,以协调内部采购部门和供应商之间的关系,及开拓新的供应商。“生产办事处要确保找到合适的供应商,且确保产品在优良品质下,以低廉价格进行生产。”H&M在上海的一位工作人员说。
  基于采购成本的考虑,H&M将60%的生产放在亚洲,其余则在欧洲进行。一般而言,常规款式的时装和童装是在亚洲生产,量小且流行性强的服装,通常给欧洲的供应商。
  “并不是所有产品的前导时间越短越好,我们的前导时间从两三周甚至到6个月不等。其实,迅捷的前导时间不一定最有利,适当的前导时间才有利于我们在价格、时间和品质之间找到最佳平衡点。”当ZARA致力于打造极速神话时,H&M集团的CEO Rolf Eriksen却道出了其独特的经营策略。
  这个策略演绎着一个玩转时间和成本的经典故事。于是,H&M设计了两条供应链:管控亚洲生产的高效供应链、管控欧洲生产的快速反应供应链。H&M内部采用名为OFS(Offer Follow up System)的信息系统跟踪供应链的生产计划。对于制作基本款式的亚洲供应商,H&M的高效供应链策略是在满足产品供给的同时,使成本控制到最低,因此它与供应商之间的沟通往往通过email进行。在这条供应链里,更多的工作是靠生产办事处的员工以标准化流程进行监控。
  “H&M给我们的代工价格压得极低,但量却很大!”上海华源针织时装公司总经理胡红霞说。华源公司从1994年便加入了H&M的供应商名录。和给别的国外品牌代工不同,H&M只和加入其名录的供应商合作,门槛的设立有利于保证质量和协调合作关系。
  华源主要为H&M提供贴牌毛衣。据胡红霞介绍,H&M给他们每单业务量至少是10几万件。通常而言,10几万件的订单,从衣服打样到走货,至少需要两个月。“H&M将设计图纸通过email发给我们,我们首先要做样衣给它确认,待修改意见返回后,我们开始生产推销样,一般是20多件,再次确认无误后,才进行大批量生产。”
  远在瑞典的H&M总部如何才能知道亚洲供应商的生产进度?“H&M的工作人员会在生产初期、中期和后期到厂里来验货。”胡红霞说。验货完毕,H&M的员工会将生产进度录入OFS系统里,汇报给瑞典总部。当产品生产出来后,华源会将货物送到海关,由第三方物流公司交付给H&M。“一般货物是走海运,虽然慢,但最经济。”
  华源拥有自己的供应链体系,它和其上游毛纱厂建立了紧密关系,“当推销样确定后,H&M的订单数量会同时出来,毛纱厂可以计算出需要多少原料,开始准备毛纱了。”尽管H&M的高效率供应链是以成本为主导的,但是为了提高效率,仍然尽可能对每个环节进行丝丝入扣的衔接。
  对于那些流行感强的服装,H&M则将订单投放到欧洲,以快速反应供应链来应对市场需求。除了采用OFS系统跟踪欧洲供应商的生产计划外,H&M总部和22个生产办事处的所有部门间的沟通还基于ICT(Information and Communication Technologies)平台完成。在H&M总部,设计与采购部门协同工作,每个设计理念都有一支设计师、采购员、助理、打版师、财务总监及部门经理组成的团队,这样可以在设计初期便着手在价格、市场反馈和流行时尚之间取得平衡。
  当设计草图出来后,ICT平台就能将数据发放给相应部门,甚至22个产品办事处,以便确定合适的生产地和供应商。“将一款产品放在哪个地方生产,不仅要考虑成本,效率也是一个重要因素。如果某款产品需要快速投放市场,那么我们会选择离这个市场较近的生产地。”一位H&M的工作人员说。
  灵活采购是H&M快速反应供应链的核心。一般而言,服装企业都要进行季节性采购,这一模式被H&M于1968年就打破了——它的买手采用1年采购12次的策略,以对流行趋势进行快速反应。
  为了支持灵活采购的模式,ICT平台做出了巨大贡献。在ICT平台上,H&M的采购部和销售部得以紧密合作;所有门店也能在ICT平台上知道彼此的销售情况以及时进行货物调拨;采购和物流部门能跟踪到每款产品的销售和库存情况,便于及时补货。“takten(同步)”,是H&M第一任CEO提出的理念,即每周更新明细列表,使得每个采购部门、每家店都能知道每款产品卖出了多少。“这一理念在ICT上贯彻至今。”H&M的一份内部报告指出,“ICT为H&M建立了一个环型的信息反馈机制,销售、库存、采购计划和生产能力的信息变得完全透明。”
  在物流环节,为了避免过量生产而导致积压,H&M的中央物流体系通过ICT紧跟每款产品的销售进程。H&M供应商生产的产品通常会运送到德国汉堡的中央仓库,进行整理和发送,但是如果这款产品是针对某个区域市场的,H&M通过ICT做出快速反应,将产品直接送达该国分部,甚至直接运送到店面。
  基于ICT的快速反应供应链,为H&M赢得了宝贵的时间,自然刺激了销售业绩。2004年秋天,迷你裙很流行,H&M一款畅销的黑色羊毛裙的订单翻了3番,这一切都归功于其快速反应供应链。“每天都有新款产品抵达门店”,这让H&M对时尚拥趸充满了诱惑。
  值得一提的是,H&M在销售渠道的拓展上,也一直进行着创新。尽管目前其销售渠道仍以直营店为主,但其目录销售、在线销售的业绩却在持续增长。1980年,H&M收购了Rowells公司,开始在瑞典、芬兰、挪威和丹麦进行目录销售;1998年,H&M在瑞典开设了网上商店,随后在芬兰、挪威、丹麦都开通了在线销售。在取得初步成功的基础上,2006年秋天,荷兰成为其在北欧地区以外首个开设在线销售的国家。“2007年秋季,德国和奥地利将启动在线销售。” Rolf Eriksen介绍道。
  极速供应链
  15天!这是ZARA被服装业界追赶的数字。H&M善于在成本和速度间“跳舞”,而ZARA则专注地聚焦在供应链的快速反应上。这家被摩根斯坦利青睐有加的西班牙企业,凭借15天的前导时间,成为服装业极速供应链的经典。
  和H&M不同,ZARA将大部分生产放在欧洲。在西班牙,ZARA拥有22家工厂,其50%的产品通过自己的工厂生产,50%的产品由400家供应商完成。这些供应商有70%位于欧洲,其他则分布在亚洲。这样的地理位置也是为了保持其供应链的响应速度。
  同样,为了加快整条供应链的灵活性,ZARA从供应链上游便控制了布料、染料等原材料供应商,他们总是以半成品的方式待命 —— 一旦ZARA发出生产指令,这些原材料供应商便投入生产,最大程度地避免了浪费时间。
  在剪裁打版环节,ZARA的工厂采用了与丰田联合开发的JIT(Just In Time)系统。与大型服装业规模化生产不同,ZARA的生产线都是小批量的流水线,“小批量、多品种”正是丰田汽车的生产模式,ZARA将其移植到服装行业。借助JIT系统,ZARA可以定制生产流程,实现柔性生产。当布料剪裁完成后,它们会被送到西班牙或葡萄牙的小工厂、家庭作坊进行缝制加工。一般而言,每个生产单位只接受一种款式、被安排一个班次,这样可以快捷地增加或减少某款衣服的产量。
  在物流环节,ZARA和H&M一样,都依托高效的中央配送中心,其中央配送中心在西班牙总部,产品由它统一分发到全球各地。“ZARA拥有一个基于Web的供应商管理平台,通过这个平台,总部可以监测从发货、出关、通关到总部的全过程,甚至能跟踪物流公司的动态。”ZARA公司一位IT负责人介绍道。这个平台同样为ZARA节省了宝贵的时间,它除了可以提高物流效率外,互联网还可以消除时差带来的工作节奏的不一致。
  服装业的信息都是反向回溯的,即从市场前端往上游行进。H&M的“镇山之宝”是ICT,而在全球拥有超过2000家门店的ZARA如何及时了解市场情况,以便做出极速反应?
  ZARA的每个门店,都安装着彼此独立的信息系统。每天晚上,位于西班牙西北部拉科鲁尼的ZARA总部,会和每个门店交换大量原始数据,数据细致到每款产品卖了几单、尺码、颜色、数量、卖出时间、支付方式、折扣信息、价格调整等。之后,各部门会根据需要分解数据,以对各地市场做出判断。特别是对设计部门而言,来自各门店的销售数据可以帮助他们分析畅销或滞销产品,作为新产品的设计参考。为了更贴近市场,ZARA采用了由买手、设计、市场专员组成的团队设计模式。
  此外,ZARA每个门店经理手上的PDA也是其获取市场信息的利器。在上海南京西路的ZARA店,门店经理Joise时常通过手上的PDA向西班牙总部发出订单,同时她也能在PDA上知道总部给她的建议订货量。与分布在全球各地的门店经理一样,Joise可以通过PDA与总部产品经理进行直接沟通。
  通过IT手段,ZARA建立了闭合的沟通机制,大量信息得以在供应链上顺畅流动,令设计、采购、生产和销售等环节实现直接沟通。
  对供应链采用单一节奏,也是ZARA极速供应链的重要法则。每周三和周六是ZARA各门店的固定到货日期。由于高速增长的业绩,ZARA自去年进入中国内地后,已经快速开设了3家店,第4家店也即将开张。无论是在北京还是在上海,ZARA依然保持着步调一致的供应链节奏。另外,“不计成本地”坚持用空运送货,这也让ZARA维持着“极速”。在欧洲,ZARA的衣服从物流中心送出,24小时便能抵达门店;在中国和美国,这个数字是48小时;在日本则是72小时。
  在北京光华路的ZARA店,店员Smart时常在晚上打烊时劝那些慕名而来的时尚男女改日再来,不过总有不甘心的顾客恳求Smart网开一面。可是纵然Smart好脾气,却也无能为力,因为每晚10点以后,ZARA的每个门店便开始和总部的数据交换,所有交易将被停止。在ZARA这部运作精密、流程标准化的庞大服装机器里,个人的感情不能改变任何运作。

来源: http://hi.baidu.com/calm6666/blog/item/4f7dfe8119bd1edcbd3e1e1a.html

百丽国际:赢在纵向一体化

 由于大环境的影响,去年至今,已有不少鞋企关门歇业。有业内人士测算,保守估计,倒闭鞋企的比率也高达30%

 

 

  百丽国际是逆境中强势发展的代表企业,根据其9月中旬发布的业绩报告:上半年,百丽国际控股有限公司总收入82.28亿元人民币,大大高于去年同期的51.31亿元,同比增长60.4%。其中鞋类业务销售额由去年同期的28.03亿增加至42.53亿元,运动服饰业务销售额由去年同期的 23.28亿元增加至今年的39.75亿元。鞋类业务及运动服饰业务的毛利率分别为65%35.6%,与去年同期相差无几。尽管这个业绩低于市场预期,但仍然算得上一份比较漂亮的答卷。

 

 

  那么,百丽缘何能逆风飞扬?它占据了价值链哪个最具价值的有利位置?推动它强势成长的重要因素是什么?

 

 

  掌控整体产业链

 

 

  百丽鞋业于199110月创立于深圳,属中外合资企业,主要从事订单加工及鞋类产品制造,与现在的绝大多数订单生产企业并无两样。1997 年,在鞋类制造方面积累了丰富经验后,百丽开始拓展全球零售网络,并开始打造自有品牌。2001年,百丽女鞋成为中国同类产品中销量、销售额双料冠军。

 

 

  为了进一步加强对零售终端的掌控力,2002年,百丽与分销商共同组建百丽投资有限公司,以股权为纽带,将销售终端与百丽的发展牢牢地捆在了一起。

 

 

  2004年,百丽投资旗下的1681家零售店通过改签租约的方式,转移至离岸公司百丽国际旗下;百丽投资旗下的办公设备等无形资产也出售给了百丽国际。2005年,重组之后的百丽国际获得了摩根士丹利旗下两家基金公司的注资,在充足的资本支撑下,开始迅猛扩张,成为中国最大的女鞋零售商和中国最大的运动服饰零售商,旗下有百丽、思加图、天美意、他她等自有品牌和真美诗及Bata两个授权品牌。去年5月,百丽在香港联交所挂牌上市。

 

 

  纵向一体化模式是百丽在中国鞋企中脱颖而出的重要发展模式从产品的设计到开发、生产、营销、推广、分销、零售等产业链上的各个环节,全部由百丽自己承担。在倡导产业链分工协作的今天,这种模式似乎有点另类。实际上,它是百丽获得高额利润的保证,也是百丽十几年来蓬勃发展的深厚积淀。在这种模式支撑下,百丽赚足了产业链上每一个关键环节的利润,企业的综合毛利率远高于行业平均水平,比国内鞋业的其他优秀企业奥康、李宁等高出10个百分点左右。更重要的是,在瞬息万变的市场环境中,对零售网络的直接控制,使百丽在企业与消费者之间搭起了一个随处可见的高效运作平台,能够随时获得和掌控市场信息,把握市场趋势,在竞争中赢得主动。这种模式,还可以让百丽最大程度地控制供应链,使产品一开始就比在国外研发的产品提前4个月左右上市。

 

 

  在对销售环节进行强势掌控的同时,百丽并没有忽视对制造环节的投入。“2006年,百丽投资5亿元兴建百丽工业园。这样做的目的,是将制造环节牢牢地掌握在自己手中,可以使企业在供应链后端发力,辅助前端很好地迎合市场。百丽CEO盛百椒说。

 

 

  打造极速供应链

 

 

  众所周知,在服装鞋帽行业,库存是企业的天敌。而对库存的严格控制,正是百丽提高利润率的秘密武器。在这个过程中,西班牙品牌ZARA是百丽的标杆这家企业以研究客户需求为中心,以市场需求为导向,满足时尚产品的平民化需求,其运作模式讲究团队高效协调、沟通无阻及运作的高速化,大大降低了库存压力。快速对标加之自己的创新,使百丽形成了自己独特的极速供应链。

 

 

  小批量,多品种。目前在百丽,一款鞋从生产到上架只需20多天;任何一款产品的首批订单永远只做50%,其余通过补单的形式完成首批产品上架后,各地零售终端的销售情况会迅速反馈到企业,根据这些信息,来决定其余50%产品的生产。另外,各产品的设计师也会在第一批货投入市场后迅速赶到一线,听取消费者的声音,并根据市场需求对产品设计进行改进。小批量、多品种的产品投放方式,成为百丽的一个重要特征。而构筑百丽强大的市场能力的,正是遍布全国各地的零售网点,它们是百丽研究消费模式的直接窗口,也是百丽打造极速供应链的重要保障。对市场需求多样化的高度迎合,使百丽轻装上阵,将令同业普遍头痛的库存问题轻松化解。

 

 

  大城市多开店,小城市开大店。令同业震撼的,还有百丽的开店速度。当然,与这种速度相匹配的,还有百丽独特的开店理念。做品牌首要的是抓好产品的供应链。盛百椒说,大城市开店成本高,且进入的品牌多,竞争激烈,一个品牌无法以压倒性的优势占领市场,我们的策略是多开店,让品牌逐渐深入人心;小城市房租和人工都便宜,在较好的位置开大店,形成旗舰。

 

 

  多品牌制胜。有了这么多的零售店,如何在极速扩张的同时,把每个零售点的业绩做足?百丽的策略是:不断引进新的知名品牌,通过并购、代理等方式占据更多的细分市场份额。百丽旗下的品牌个个在国内市场赫赫有名,今年年初,百丽又并购了妙丽、森达等4个知名品牌,并新增4个代理品牌。多品牌策略为百丽赢得了广泛的客户群和细分市场的稳定收益。

 

 

  扁平化决策。为了迎合各地消费者的不同需求及审美情趣,百丽将全国分为10大销售区,并将采购及销售权彻底下放。这种扁平化的决策程序,使百丽得以快速适应市场变化,提升了销售和盈利能力。

 

 

  用品牌铺垫出高起点。利用品牌、供应链和强势渠道,再加上精细化的管理,自然使百利摆脱了多数鞋企所遭遇的微利尴尬。凡是女人路过的地方,都要有百丽!这是盛百椒的目标他计划每年在全国新开1000家新店,其中包括建立更多的零售商城。

    来源:经理人

女鞋品牌百丽:危机下快跑的大象

中国品牌服装网   www.china-ef.com

 

  1月22日讯 新年将至,为自己备置新装的你是否常常在各个女鞋品牌之间犹豫不决?是休闲的天美意、女人味的百丽、传统的森达、年轻的他她,还是适合OL的思嘉图?但是你可能不知道,这些风格迥异的品牌其实都同属一家公司——百丽集团。

  除了上述自有品牌外,百丽还代理BCBG、Clarks等高端国际品牌,还是耐克、阿迪达斯在内地最大的运动鞋分销商。2007年,集团净利润为19.79亿元,同比增长102.7%.国内皮鞋市场销售额排名前10中,有5个品牌属于百丽。百丽国际在香港上市的首日市值达到789亿港元,甚至超过了当时的国美。

  那百丽的成功秘诀是什么?一个字,“快”。百丽的一款鞋从生产到上架,最快只有二十多天,百丽每个自主品牌每个季度平均要推出300-400款新鞋样式。但这么大规模、这么多品牌的集团是如何实现“快”的赢利模式呢?

  首先是随市而动的灵活生产方式。

  尽管品牌众多,产品规模大,但百丽坚持小生产流水线混合生产。不同款式的鞋子放到一个生产线上混合生产,大大加快了整体速度。而且每批鞋的首次生产只有订单的50%,其余的根据市场的反馈全部按补货方式生产产品经理对首批的销售情况进行调研,然后进行预测,在每周下达补货订单。

  百丽通常采用三天的滚动式计划,车间三天内把产品生产出来,第四天就开始进行补货生产。为了降低库存,百丽还取消成品仓库,车间生产出来的产品直接装箱发货。今年中期年报显示,百丽集团存货周转率为2.53,低于行业平均水平的3.40.

  其次是内外结合的设计网络。

  为了每季度推出几千个新产品,百丽不仅拥有自己的设计师队伍,还大量外购设计。因为如果将每一季的设计都押在自己的设计师身上,风险会很大,通过外购设计,百丽既能保证自己的研发优势,又能针对市场需求进行灵活应对。值得一提的是,设计师不仅在生产前发挥作用,在其后50%的生产中仍然具有重要作用,当第一批货投放到市场去后,设计师将亲自到一线,然后进行改款,以应对市场需求。

  第三,专一而强势的自营渠道。

  百丽从一开始就瞄准了百货店,与许多商场建立合作伙伴关系,利用商场的连锁布局实现自身扩张。而且大部分渠道都由百丽自营,截至到2007年底,集团在大陆拥有6090间自营零售店。渠道直营不仅加快了铺货速度,更重要的是直营店比加盟商在销售、库存或者其他感性信息反馈方面更及时、全面和准确,为百丽搜集了大量消费者信息。

  此外,百丽还通过激励机制调动渠道的热情,百丽总部、各销售区域及生产部门的所有高级管理人员均为公司股东,分公司拥有定价权,利润、费用、库存等指标也都全部下放。

  第四,多品牌营销和物流的规模效应。

  百丽在进驻商场时,一般会将主打的四五个品牌一起进,加强自身的谈判能力,因此能够同商场实现“按照每月销售收入的百分比来计算租金”的模式,这使百丽极大降低了库存压力和成本风险。百丽的物流体系也是多品牌共用的,配送中心同时为百丽所有品牌和运动品做物流配送,你会看到运送工人经常同时搬着百丽高跟鞋、耐克运动鞋和levi‘s的牛仔裤奔忙!

  最后,借助资本力量,扩大竞争优势。

  2005年,百丽鞋业引入摩根士丹利和鼎晖投资两家PE战略投资者,融资2366万港元。借助PE 资本支撑,百丽鞋业商业规模快速扩张。鞋类产品生产能力从2004年的730万双增至2006年的1150万双;15个月内在中国内地新增零售点1419 家。2007年,百丽在香港上市,仅在2007年下半年,百丽就利用上市后募集的资金并购了20多个品牌。

  制鞋业是廉价的“中国制造”的典型代表,但百丽却在其中创出了一番天地。虽然在与跨国公司相比,中国本土企业在技术、品牌等方面处于下风,但中国企业仍可以通过从流程管理、产业链控制等方面入手,获得竞争优势。

 

源文档 <http://www.china-ef.com/article/2009-01-22/155756.shtml>

 

百丽历史

    2007年5月23日,百丽国际控股有限公司在香港联交所挂牌上市。市场预期,其总市值将超过500亿港元,成为港交所最大内地零售股。  

    72岁的香港人、百丽集团创办人兼主席邓耀届时将持有百丽国际32%的股份,股票市值将近180亿港元。而上世纪50年代,他仅仅是皮鞋厂的一名学徒工。   

    百丽(BELLE)品牌的创立是在上世纪70年代,其时,邓耀已是香港知名的鞋款设计师。但邓氏事业的真正崛起则要等到其1991年投资内地。今天,百丽国际的核心资产,正是其在内地150多个城市设立的3828个零售网点(截至2006年底)。   

    1991年11月,深圳百丽工厂成立。当年,百丽国际的核心人物之一、现任CEO盛百椒亦加入深圳百丽。

    1992年3月,工厂投产。最初,深圳百丽主要为香港品牌代加工。当时,国内市场消费需求逐步增长,邓耀已不满足加工贸易的生存状态,很快进入国内批发市场。

    1993年,内地第一家百丽零售店在深圳开业。由此,百丽开始了一个零售王国的建立。   

    1995年,百丽开始建立品牌零售网络。但当时内地零售业对外资及港、澳、台地区的资本仅有限开放,百丽很难达到在内地开展零售业务的进入门槛。百丽集团采取了巧妙的变通办法,“选择有共同经营理念的个体经销商成为当地的独家零售代理,专一销售品牌商旗下系列产品”。

     1997年,百丽和16家个体分销商签订独家分销协议。这些个体分销商乃邓耀为了绕开政策限制而做出的安排,由邓氏家族成员及总经理盛百椒的家族成员等关联方实际控制。资料显示,盛百椒的妻子、妻妹、侄儿,邓耀的堂侄女等皆参与其中。此等安排为百丽内地零售网点的布局赢得了时间和空间。截至2002年7月,这些个体分销商已发展零售网点600余个。之后,16家个体分销商合并成深圳百丽投资。   而等到内地零售业全面放开的2004年底,百丽在内地实际控制的零售网点已达到1681家。通过“16家个体分销商”的设置,百丽赢得了长达7年的宝贵时间和巨大的市场空间。

百丽生产

    对于百丽来说,光自产自销的鞋子,年销售额就可达30多个亿人民币,而代理的知名品牌鞋,年销售额更可达50多个亿人民币。在同行企业中,连续六年排名第一;市场占有率连续三年排名第一。

   
 

 

百丽的工厂非常有特色

    首先,是他们的广告。一般企业宣传广告是挂在商场里,而百丽的宣传广告首选地是生产工厂。他们每年会把设计出来的最新款式的鞋子宣传图片挂在工厂里,让工人们了解到,他们在生产鞋子的同时,也是在创造

    其次,是采用小生产流水线混合生产。百丽的工厂,一个订单,尽管鞋子的款式不同,仍放到一个生产线上混合生产,大大加快了整个速度。销售公司拿到订单如果要求百丽生产5000件,但百丽只生产其中的50%,其余的一律补货生产。

    三者,取消成品仓库。一般企业拿货配货是到成品仓库去,百丽直接取消了成品仓库,车间生产出来的产品直接装箱发货,大大降低了库存。百丽一年在处理库存方面就可以转四次,而服装一年最多只能转两次。

    第四个特点是,采用三天的滚动式计划。由于他们主管生产的都是原生产劳动力。因此车间采取三天内就要把产品生产出来,第四天就可进行补货生产,大大加快了生产速度。

    200多位设计师

    目前,百丽企业旗下有四个品牌:百丽,思加图,天美意,他她。他们以时尚、成熟、年轻化的不同定位,吸引了不同的客户群。百丽的老总说,女人跟男人不一样,女人是感性的,买鞋就可能把包买过来了,买包可能就把衣服买过来了,男人就不一样了,买东西目标明确。所以百丽旗下有五六个品牌,风格定位各异,以满足女人们的不同需求,在商场里你根本不知道哪个是他们的品牌。

    同时百丽也代理了NIKEADIDAS等多种休闲品牌。百丽的老总说,代理休闲品牌,主要是看到未来行业的发展将趋于休闲化。

    百丽跟ZARA一样,要做时尚的追求者,绝不做时尚的抄袭者,因此他们的设计师经常到国外去寻找潮流和时尚灵感。目前百丽有两百多个设计师。他们分布在法国,意大利的各个工作室,每年都会出一定量的设计作品,供他们参考,因此百丽在设计方面的能力非常强大。

使用google自定义搜索引擎

mailman,google自定义搜索引擎,搜索站点,邮件列表

google搜索引擎很强大,如果没有机密信息的话,是否可以尝试让google来帮我们完成全站搜索引擎,而不必再自己去建立。

下文是个例子,用google自定义搜索引擎来搜索指定的邮件列表,具体步骤如下:

 

1)下载并安装sitemap生成器
参考:http://code.google.com/p/perlsitemapgenerator/

2)(可能需要)安装XML:SAX

$ perl -MCPAN -e shell
cpan> install XML::LibXML XML::SAX::Base XML::SAX::ExpatXS XML::SAX::Writer
cpan> quit

参考:http://www.ibm.com/developerworks/cn/xml/x-xmlperl2.html#resources

3)按要求修改comfig.xml ,另存为testlist_config.xml

   内容如下:

[root@retailsolution sitemap_gen_perl]# vi testlist_config.xml
 
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
<!--
  sitemap_gen.pl example configuration script
 
  This file specifies a set of sample input parameters for the
  sitemap_gen.pl client.
 
  You should copy this file into "config.xml" and modify it for
  your server.
 
 
  ********************************************************* -->
 
 
<!-- ** MODIFY **
  The "site" node describes your basic web site.
 
  Required attributes:
    base_url   - the top-level URL of the site being mapped
    store_into - the webserver path to the desired output file.
                 This should end in '.xml' or '.xml.gz'
                 (the script will create this file)
 
  Optional attributes:
    verbose    - an integer from 0 (quiet) to 3 (noisy) for
                 how much diagnostic output the script gives
    suppress_search_engine_notify="1"
               - disables notifying search engines about the new map
                 (same as the "testing" command-line argument.)
    default_encoding
               - names a character encoding to use for URLs and
                 file paths.  (Example: "UTF-8")
-->
<site base_url="http://report.retailsolution.cn/mhonarchive/testlist/" store_into="/var/lib/mhonarc/archives/testlist/sitemap.xml" verbose="1">
 
  <!-- ********************************************************
          INPUTS
 
  All the various nodes in this section control where the script
  looks to find URLs.
 
  MODIFY or DELETE these entries as appropriate for your server.
  ********************************************************* -->
 
  <!-- ** MODIFY or DELETE **
    "url" nodes specify individual URLs to include in the map.
 
    Required attributes:
      href       - the URL
 
    Optional attributes:
      lastmod    - timestamp of last modification (ISO8601 format)
      changefreq - how often content at this URL is usually updated
      priority   - value 0.0 to 1.0 of relative importance in your site
  -->
 
 
 
  <!-- ** MODIFY or DELETE **
    "urllist" nodes name text files with lists of URLs.
    An example file "example_urllist.txt" is provided.
 
    Required attributes:
      path       - path to the file
 
    Optional attributes:
      encoding   - encoding of the file if not US-ASCII
  -->
 
 
 
  <!-- ** MODIFY or DELETE **
    "directory" nodes tell the script to walk the file system
    and include all files and directories in the Sitemap.
 
    Required attributes:
      path       - path to begin walking from
      url        - URL equivalent of that path
 
    Optional attributes:
      default_file - name of the index or default file for directory URLs
  -->
  <directory path="/var/lib/mhonarc/archives/testlist/" url="http://report.retailsolution.cn/mhonarchive/testlist/" />
 
 
 
  <!-- ** MODIFY or DELETE **
    "accesslog" nodes tell the script to scan webserver log files to
    extract URLs on your site.  Both Common Logfile Format (Apache's default
    logfile) and Extended Logfile Format (IIS's default logfile) can be read.
 
    Required attributes:
      path       - path to the file
 
    Optional attributes:
      encoding   - encoding of the file if not US-ASCII
  -->
 
 
  <!-- ** MODIFY or DELETE **
    "sitemap" nodes tell the script to scan other Sitemap files.  This can
    be useful to aggregate the results of multiple runs of this script into
    a single Sitemap.
 
    Required attributes:
      path       - path to the file
  -->
 
 
  <!-- ********************************************************
          FILTERS
 
  Filters specify wild-card patterns that the script compares
  against all URLs it finds.  Filters can be used to exclude
  certain URLs from your Sitemap, for instance if you have
  hidden content that you hope the search engines don't find.
 
  Filters can be either type="wildcard", which means standard
  path wildcards (* and ?) are used to compare against URLs,
  or type="regexp", which means regular expressions are used
  to compare.
 
  Filters are applied in the order specified in this file.
 
  An action="drop" filter causes exclusion of matching URLs.
  An action="pass" filter causes inclusion of matching URLs,
  shortcutting any other later filters that might also match.
  If no filter at all matches a URL, the URL will be included.
  Together you can build up fairly complex rules.
 
  The default action is "drop".
  The default type is "wildcard".
 
  You can MODIFY or DELETE these entries as appropriate for
  your site.  However, unlike above, the example entries in
  this section are not contrived and may be useful to you as
  they are.
  ********************************************************* -->
 
  <!-- Exclude URLs that end with a '~'   (IE: emacs backup files)      -->
  <filter action="drop" type="wildcard" pattern="*~" />
 
  <!-- Exclude URLs that is a picture gz bak file       -->
  <filter action="drop" type="wildcard" pattern="*jpg" />
  <filter action="drop" type="wildcard" pattern="*gif" />
  <filter action="drop" type="wildcard" pattern="*bmp" />
  <filter action="drop" type="wildcard" pattern="*gz" />
  <filter action="drop" type="wildcard" pattern="*bak" />
 
  <!-- Exclude URLs within UNIX-style hidden files or directories       -->
  <filter action="drop" type="regexp" pattern="/\.[^/]*" />
 
</site>

 

参考:http://code.google.com/p/perlsitemapgenerator/wiki/Create

4)测试

   perl sitemap_gen.pl –config=testlist_config.xml –testing

   参考:README

   没问题,一切OK

4) 运行

   perl sitemap_gen.pl –config=testlist_config.xml

   没问题,一切OK, 成功生成sitemap.xml 并且通知了google的搜索引擎。

5)用gmail帐号登录 google, 使用向导创建一个自定义搜索引擎

6) 自定义搜索引擎后,在我的帐户->网站管理员工具->选择一条你创建自定义搜索引擎时使用的网站地址

   ->SiteMaps

   在我的 SiteMaps处输入 sitemap.xml

   然后点击【提交SiteMap】  
7) 在我的帐户->我的搜索引擎->针对刚才创建的搜索引擎->控制面板->编制索引

   在 按需编入索引 下选择刚才提交的 sitemap.xml,然后【Index Now】

   完成后,google提示成功刷新了索引。

8) 在我的帐户->我的搜索引擎->针对刚才创建的搜索引擎->控制面板->预览  中

   输入一个你的邮件列表中的关键词,执行搜索,结果没有搜到。别灰心,你需要等待大约2个小时。

   2小时以后再执行搜索,发现已经能够搜索到指定的关键词了。

   到这里,自定义搜索引擎创建,测试成功。

9)在我的帐户->我的搜索引擎->针对刚才创建的搜索引擎->控制面板->代码

   把 搜索框代码 下面的代码copy到要显示搜索框的网页中,比如邮件类表的索引页:threads.html中

   现在当我们访问邮件列表归档的时候,就可以看到搜索框了:

http://report.retailsolution.cn/mhonarchive/testlist/threads.html

   试着这行一个搜索,确实是我们期望的结果。

10)使用 cron job 周期执行  perl sitemap_gen.pl –config=testlist_config.xml

    可参考:http://www.linuxsir.org/main/?q=node/209

11)我们还可以创建另一个自定义搜索引擎,把我们要搜索的内容全部整合到一起。

    11.1) 建立一个脚本文件,为其他maillist创建sitemap:gen_maillist_sitemap.sh 内容如下:

sitemap_gen_path=/d01/sitemap_gen_perl 
export sitemap_gen_path 
perl $sitemap_gen_path/sitemap_gen.pl --config=$sitemap_gen_path/testlist_config.xml 
perl $sitemap_gen_path/sitemap_gen.pl --config=$sitemap_gen_path/channelproject-commits_config.xml 
perl $sitemap_gen_path/sitemap_gen.pl --config=$sitemap_gen_path/datafix_config.xml 
perl $sitemap_gen_path/sitemap_gen.pl --config=$sitemap_gen_path/handtech_config.xml 
perl $sitemap_gen_path/sitemap_gen.pl --config=$sitemap_gen_path/report-maillist_config.xml

 
    chmod 744 gen_maillist_sitemap.sh

    11.2)把这个脚本放到crontab 每天定时运行

    cd /etc

    cp crontab crontab.bak

    vi crontab ,  添加:

    02 4 * * * root /d01/sitemap_gen_perl/gen_maillist_sitemap.sh

    #每天 4时2分运行这个脚本

    #重启crond 服务

    service crond restart

    11.3) 建立一个自定义搜索引擎,把上述sitemap都包括进去。同时把属于retailsolution.cn域上的其他站点的sitemap也包括进去。

    这样可以形成一个对retailsolution.cn全域的搜索引擎

比如这个搜索引擎就可以搜索retaisolution.cn上的 report.retailsolution.cn,blog.retailsolution.cn,all maillist 
   

<!-- Google Customer serch engine begin -->
<form id="cse-search-box" action="http://www.google.com/cse">
  <div>
    <input type="hidden" value="016037023302352540634:y7c8yn6q_ra" name="cx" />
    <input type="hidden" value="UTF-8" name="ie" />
    <input style="border-right: #7e9db9 1px solid; padding-right: 2px; border-top: #7e9db9 1px solid; padding-left: 2px; background: url(http://www.google.com/coop/intl/zh-Hans/images/google_custom_search_watermark.gif) #ffffff no-repeat left 50%; padding-bottom: 2px; border-left: #7e9db9 1px solid; padding-top: 2px; border-bottom: #7e9db9 1px solid" size="31" name="q" />
    <input type="submit" value="搜索" name="sa" />
  </div>
</form>
 
<script src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;lang=zh-Hans" type="text/javascript"></script>
<!-- Google Customer serch engine End -->

完。

 

Issue:

Issue1: google自定义搜索引擎的不足,

主要有:       
    1) 索引的建立不稳定,或者说延迟太厉害,经验感受下:          
       1.1 testlist邮件列表的sitemap提交给googl后,第一次是在半小时后能看到效果。 第二次添加一篇文章 ,里面含有"测试GB2312” 这个字符串,我看到google控制台上已经显示该sitemap.xml对应的文章数增加了,我针对这个sitemap 运行了"index Now" 然后过了半小时去搜索"测试GB2312” 依然是没有结果。3小时以后才看到了期望的结果。经过多次试验发现一般在运行"Index Now"以后3小时可完成sitemap中URL对应页面的索引.           
       1.2 report-maillist邮件列表中有很多页面,其sitemap已经在1天前提交给google,由于当时没有点"Index Now",今天在自定义搜索引擎中搜索其中包含的关键词时,还是搜索不到,说明google未曾给它做索引。难道是说如果提交了某个sitemap,而没有手动"Index Now"的话,就不知道google要隔多久才会主动来抓取sitemap中的网页并建立索引了?。

     这个问题其实很严重,因为你跟普通用户去解释全文搜索需要隔N个小时才起作用,很难解释得通,所以,如果使用google自定义搜索引擎作为企业级的正式搜索引擎,可能不妥,因为在用户看来它显得不可靠,但作为一个备用搜索引擎还是可以的。或者作为一个个人站点的邮件列表的搜索引擎也还勉强凑活。

     如果要使用google自定义索引,建议能些个脚本自动为每个sitemap定期运行"Index Now" ,分析"Index Now"页面的源码可以看到其执行的http请求。我们也可以自己执行这些请求,可以为多个sitemap执行"Index Now"

 

http://www.google.com/coop/manage/cse/index?cx=016037023302352540634:y7c8yn6q_ra&amp;hl=zh-CN&amp;sig=__4TuuBdvPw7mRe-F4gl4lRNM-56w=&amp;qauth=kcmf3TVXwKibiK2x&amp;qinfo=zvq2LnMpaIo&amp;sitemap=http://report.retailsolution.cn/mhonarchive/testlist/sitemap.xml.gz
http://www.google.com/coop/manage/cse/index?cx=016037023302352540634:y7c8yn6q_ra&amp;hl=zh-CN&amp;sig=__4TuuBdvPw7mRe-F4gl4lRNM-56w=&amp;qauth=kcmf3TVXwKibiK2x&amp;qinfo=zvq2LnMpaIo&amp;sitemap=http://report.retailsolution.cn/mhonarchive/datafix/sitemap.xml.gz
http://www.google.com/coop/manage/cse/index?cx=016037023302352540634:y7c8yn6q_ra&amp;hl=zh-CN&amp;sig=__4TuuBdvPw7mRe-F4gl4lRNM-56w=&amp;qauth=kcmf3TVXwKibiK2x&amp;qinfo=zvq2LnMpaIo&amp;sitemap=http://report.retailsolution.cn/mhonarchive/handtech/sitemap.xml.gz
http://www.google.com/coop/manage/cse/index?cx=016037023302352540634:y7c8yn6q_ra&amp;hl=zh-CN&amp;sig=__4TuuBdvPw7mRe-F4gl4lRNM-56w=&amp;qauth=kcmf3TVXwKibiK2x&amp;qinfo=zvq2LnMpaIo&amp;sitemap=http://report.retailsolution.cn/mhonarchive/report-maillist/sitemap.xml.gz
http://www.google.com/coop/manage/cse/index?cx=016037023302352540634:y7c8yn6q_ra&amp;hl=zh-CN&amp;sig=__4TuuBdvPw7mRe-F4gl4lRNM-56w=&amp;qauth=kcmf3TVXwKibiK2x&amp;qinfo=zvq2LnMpaIo&amp;sitemap=http://report.retailsolution.cn/mhonarchive/channelproject-commits/sitemap.xml.gz

Over 

不过可惜,这些请求不能直接执行,需要登录。不过在google文档中提供了login的API的。文档参考:我的帐户->我的搜索引擎->文档->开发人员指南。有时间的时候可以继续研究。

      google帐户,有不同级别,不同级别的帐户在使用Index Now功能的时候有不同的限制,一般的帐户提交"Index Now"不管你的SiteMap中有多少条URL,google只会为其中级别最高(如果级别都一样,就是最后更新的)的10个页面建立索引。级别高的帐户可以一次获得更多数量的页面索引,此外"Index Now" 针对一个CSE限制只能一天执行一次(不过你有多少个SiteMap); 这个一天执行一次是官方说法,实际上可以做到每隔1小时执行一次。如果写程序来执行"Index Now"需要试验,因为Google的标准Service API中没有明确支持通过程序执行"Index Now"

            2009-01-31 经过多次测试发现,如果没有手动"Index Now" ,在提交了SiteMap以后经过3天也没有被Google Index进去,真是郁闷,我们总部能每天手动去"Index Now"吧,唉,即使手动去"Index Now" ,Google还做了上面的很多限制,你要靠Google来对你的站点进行全文检索?天大的笑话,真是幼稚。

           看来,即便是一个个人站点的搜索引擎也不能靠Google, 得另寻出路。网上有关于全文检索引擎的资料,下一步研究方向:1、Oracle 商业搜索引擎,2、开源搜索引擎。 对于开源搜索引擎,首先研究:Lucene , 可参考:http://www.chedong.com/tech/lucene.html

mailman 集成 MHonArc 操作指南

mailman 集成 MHonArc 操作指南

mailman 内置的邮件归档程序pipmail ,不能处理mime类型邮件, 一个图文并茂的邮件 ,会被拆分成多个图片,html的邮件也会另存为一个附件。阅读很不方便。那么如何改善呢? 一般建议使用其他的邮件归档程序和mailman集成,下文描述mailman集成MHonArc的步骤:

 

–1)下载并安装MHonArc-2.6.16-1.noarch.rpm
—  请参考: http://www.mhonarc.org/#support
—  下载def-mime.mrc 作为默认的resource 文件
—  请参考:http://www.mhonarc.org/MHonArc/doc/rcfileexs/def-mime.mrc.html

–2)配置mailman 使用MHonArc
—  请参考:http://www.mhonarc.org/archive/html/mhonarc-users/2001-10/msg00021.html
—  在/etc/mailman/mm_cfg.py 中添加:
PUBLIC_ARCHIVE_URL  = ‘/mhonarchive/%(listname)s’
PRIVATE_ARCHIVE_URL  = ‘/mhonarchive/%(listname)s’
PUBLIC_EXTERNAL_ARCHIVER = ‘/usr/bin/mhonarc -rcfile /etc/mailman/def-mime.mrc -add -outdir /var/lib/mhonarc/archives/%(listname)s > /dev/null’
PRIVATE_EXTERNAL_ARCHIVER = ‘/usr/bin/mhonarc -rcfile /etc/mailman/def-mime.mrc -add -outdir /var/lib/mhonarc/archives/%(listname)s > /dev/null’

–3)配置httpd.conf
vi /etc/httpd/conf/httpd.conf
–找到 Alias /icons/ 在下面添加:
Alias /mhonarchive/ “/var/lib/mhonarc/archives/”
<Directory “/var/lib/mhonarc/archives/”>
    Options -Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

–4)建立列表目录
cd /var/lib
mkdir /mhonarc
chown root:mailman mhonarc
cd mhonarc
mkdir archives
chown root:mailman archives
cd archives

mkdir testlist
chown root:mailman testlist
chmod 775 testlist

–所有需要 mhonarc 归档的列表,都需要手动建立对应的目录,改变目录的group,写权限.
–当新建一个mailman 列表时,系统还是会在默认的归档目录中自动建立对应的列表目录,
–但不会在EXTERNAL_ARCHIVER 指定的目录中自动建立对应的列表目录.所以很遗憾,需要手动建立.

–5)重启Apache
service httpd restart

–6)初始化转换
prefix=/var/lib/mailman
export prefix
mhonarc -mbox $prefix/archives/private/testlist.mbox/testlist.mbox -outdir /var/lib/mhonarc/archives/testlist -rcfile /etc/mailman/def-mime.mrc

— 转换后在/var/lib/mhonarc/archives/testlist目录下后会产生一个.mhonarc.db 文件,该文件是def-mime.mrc 模板必须的,要使得mailman 对 此文件有读权限。
— 否则mhonarc运行会报错,归档失败,但不影响邮件发送。要避免这个问题可以如下更改:
chown root:mailman .mhonarc.db

把目录的读写权限设置为:755

chmod 755 /var/lib/mhonarc/archives/testlist

把目录的所有者更改为:root:mailman

chown  root:mailman /var/lib/mhonarc/archives/testlist

 

–所有需要 mhonarc 归档的列表,都需要初始化转化一下.

–7)重启mailman
service mailman restart

–8)问题
    8.1) 从web访问归档时,提示Forbidden ,不允许访问,怎么办?
         答:原因是mailman 使用mhonarc 转换邮件为html的时候, 写文件时, 只有owner和group的读权限,没有other的读权限,所以无法访问.
            最简单的方法就是把 apache用户放入到mailman 用户组下去.
            比如: usermod -G apache,mailman,cvs_project apache
            加入后,需要重启apache.
    8.2) 从web访问归档时, 显示的是目录,而不是默认的归档列表页. 怎么办?
         答: 使用mhonarc 产生的索引文件名是:threads.html 和maillist.html 没有index.html 所以没有显示默认页面.
            最简单的方法,在httpd.conf  中 DirectoryIndex 参数添加 threads.html  
            DirectoryIndex index.html index.html.var threads.html 
            加入后,需要重启apache.
    8.3) 我发现gforge 集成mailman,由Gforge创建的maillist 不受上述改动的影响
         答: 是这样的,在gforge的httpd.conf中,对mailman 别名有自己的定义. 这个问题在有时间的时候可以继续研究.
    8.4) 如果哪天我不想使用mhonarc来归档了,还是恢复到pipmail来归档,那么会有什么问题么?
         答: mailman的逻辑是,先归档到默认的地方,然后查看是否有外部归档程序,如果有,再交给外部归档程序继续归档.所以原始归档总是存在的.
             没有什么问题.
    8.5) 从web访问归档时, 发现来自post-notification的html模版的邮件中的中文是乱码,但是outlook发过来的是正常的.怎么解决?
         答: 在gmail中查原始文件,发现字符集不对,只需要修改post-notification的html 的email模版就可以了.把字符集改成UTF-8.

–9)其他Mailman相关问题

    9.1)如果我原来使用80端口,后来使用:81作为web端口,如何更改以前的列表使得其中的所有链接都带有:81?

          答:按照下面的做法即可实现:

                进入 mailman 目录(一般是/usr/lib/mailman),在其中新建一個文件 (取名为 webdata 好了),內容为:
                web_page_url = ‘http://gforge.retailsolution.cn:81/mailman’
                然后使用
               $ bin/config_list -i webdata yourlist
               命令,你就会得到
               Non-standard property restored: web_page_url
               这就是成功了。

               查看你的管理页面,就会发现里面的链接都已经指向新的域名了。

数据仓库-多维数据库-关系型数据库-利弊分析

数据仓库-多维数据库-关系型数据库-利弊分析

 

ROLAP优缺点

http://en.wikipedia.org/wiki/ROLAP

 

MOLAP优缺点

http://en.wikipedia.org/wiki/ROLAP

 

ROLAP查询性能较MOLAP差,存储却较MOLAP节剩

既然ROLAP和MOLAP各有优缺点,就自然提出HOLAP , 即部分使用ROLAP,另一部分使用MOLAP 以充分利用两种OLAP的优点,避其缺点。一般认为HOLAP是趋势。

 

我们应该如何来评价这个问题呢?

美国著名的数据仓库工程专家Pieter R. Mimno先生认为,除非业务环境的确要求采用专用的数据库才能解决业务需求,或者需要采用专用的数据库管理系统才能达到业务所需要的性能指标,否则,从节省成本和降低复杂性的角度出发,一般情况下,应优先考虑采用传统的关系型数据库管理系统,这个中肯的意见值得我们在选择数据仓库的数据库时认真考虑。

 

我们将继续对这个问题进行调研和实践,以得出一个科学的结论。。。

系统集成MSN提醒的问题

系统集成MSN提醒的问题

如果有需求:每当网上有人下了订单,有些人需要得到MSN提醒。这个能否实现?

google了一下,发现有MSN 的 java API应该是可以做到这一点的。 不过要做的好,可能还是需要花点时间的。这里对网上提供的一些方法做了可行性测试,抛砖引玉。给需要的人一个开头:

首先找到了这么一段程序:

连接:http://bbs.star-bbs.net/thread-31120-1-51.html

MSNDaemon.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
* Created on 2003-11-21 by Liudong
*/
import rath.msnm.MSNMessenger;
import rath.msnm.SwitchboardSession;
import rath.msnm.UserStatus;
import rath.msnm.entity.MsnFriend;
import rath.msnm.event.MsnAdapter;
import rath.msnm.msg.MimeMessage;
/**
* MSN演示程序
* @author Liudong
*/
public class MSNDaemon extends Thread {
private static MSNMessenger msn;
 
public static void main(String[] args) {
msn = new MSNMessenger(&quot;retailsolution@live.cn&quot;, &quot;hello1&quot;);
msn.setInitialStatus(UserStatus.ONLINE);
msn.addMsnListener(new MSNAdapter(msn));
msn.login();
System.out.println(&quot;Waiting for the response....&quot;);
//捕捉Ctrl+C的输入以便注销MSN的登录
Runtime.getRuntime().addShutdownHook(new MSNDaemon());
}
/**
* 用户中止程序执行
*/
public void run() {
msn.logout();
System.out.println(&quot;MSN Logout OK&quot;);
}
}
/**
* MSN消息事件处理类
* @author Liudong
*/
 
class MSNAdapter extends MsnAdapter {
MSNMessenger messenger;
 
public MSNAdapter(MSNMessenger messenger) {
this.messenger = messenger;
}
/**
* 某人正在输入信息
*/
public void progressTyping(
SwitchboardSession ss,
MsnFriend friend,
String typingUser) {
System.out.println(friend.getLoginName() + &quot;正在输入信息...&quot;);
}
/**
* 收到消息的时候执行该方法
*/
public void instantMessageReceived(
SwitchboardSession ss,
MsnFriend friend,
MimeMessage mime) {
System.out.print(&quot;接收到消息:&quot; + friend.getFriendlyName() + &quot;-&gt;&quot;);
System.out.println(mime.getMessage());
try {
//发送相同的回复信息给发送者
messenger.sendMessage(friend.getLoginName(), mime);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 登录成功后执行该方法
*/
public void loginComplete(MsnFriend own) {
System.out.println(own.getLoginName() + &quot; Login OK&quot;);
}
/**
* 登录失败后执行该方法
*/
public void loginError(String header) {
System.out.println(&quot;Login Failed: &quot; + header);
}
/**
* 好友离线时执行该方法
*/
public void userOffline(String loginName) {
System.out.println(&quot;USER &quot; + loginName + &quot; Logout.&quot;);
}
/**
* 好友上线时执行该方法
*/
public void userOnline(MsnFriend friend) {
System.out.println(&quot;USER &quot;+friend.getFriendlyName()+&quot; Login.&quot;);
}
/**
* 有人加我为好友时执行
*/
public void whoAddedMe(MsnFriend friend) {
System.out.println(&quot;USER &quot; + friend.getLoginName() + &quot; Addme.&quot;);
try {
messenger.addFriend(friend.getLoginName());
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* 有人把我从好友列表中删除时执行
*/
public void whoRemovedMe(MsnFriend friend) {
System.out.println(&quot;USER &quot;+friend.getLoginName()+&quot; Remove me.&quot;);
try {
messenger.removeFriend(friend.getLoginName());
} catch (Exception e) {
e.printStackTrace();
}
}
}

如何运行这个程序?步骤如下

1、下载 MSN API : http://sourceforge.net/project/showfiles.php?group_id=47932

2、如果还没有jdk ? 下载jdk ,比如 jdk1.5.0_16 (下载地址很多,google一下)

3、设置java运行编译环境:比如下文注意点中的 javaenv.env; 然后source javaenv.env

4、编辑:MSNDaemon.java ,把其中的msn帐号换成你的测试帐号

4、编译:javac MSNDaemon.java

5、运行:java MSNDaemon

运行效果如下:

image

想像一下

把MSN API 这个集成到我们的系统中去,就可以实现MSN提醒了!

注意点

1:if You are on a Unix system running as root, using the 1.4.2 GCJ version? The GJC version may not

have the com.sun.net.ssl.internal.ssl.Provider ,it will cause an error, you may download new version jdk from sun,

then will be ok;

2: 编译前先运行环境变量,比如你可以建立如下的env 文件:

[root@retailsolution d01]# more javaenv.env

JAVA_HOME=/d01/jdk1.5.0_16      
PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin      
CLASSPATH=.:$JAVA_HOME/jre/lib/:$JAVA_HOME/jre/lib/jsse.jar:$JAVA_HOME/lib:/d01/MSN_Java/msnm.jar      
export     JAVA_HOME     J2EE_HOME     PATH     CLASSPATH 
[root@retailsolution d01]#

3:我这边测试可以和其他MSN用户通讯,但在测试前,我是先用标准的MSN客户端,把MSN机器人的MSN帐号进行一次登陆,并加另外一个MSN帐号为好友。然后再回到这个程序进行测试

4:程序做的MSN机器人很容易断线,我这边测试情况是:MSN机器人登录并与好友聊天后1分钟之后就断线了,这个程序需要改进。

5:相关链接:

   5.1 MSN机器人源程序连接:http://bbs.star-bbs.net/thread-31120-1-51.html

   5.2 MSN java Api 下载链接:http://sourceforge.net/project/showfiles.php?group_id=47932

本站文章编辑技巧

本站文章编辑技巧

一、分页功能

如果一篇文章很长,则一次加载所需时间太长,要考虑分页;

操作方法:在要分页的地方插入分页符即可,如下图:

image

二、上传附件

一般来说,我们建议尽量不要使用附件方式发表文章,但是如果文章涉及代码(package),或者文章很长,在发表以后希望同时提供pdf或者word压缩版则也可以适当考虑附件方式作为备选项。

上传附件很简单,点附件上传按钮,如下图:

image

附件就是媒体。

 

三、代码高亮显示

文章中如果使用到代码 ,并且希望代码在文章中具有很好的可读性,则可以使用<pre lang="lang" colla="+"></pre>标记。(注意在HTML模式下,而非可视化模式下添加这对标记,发布的时候也要在HTML模式下进行) 比如下面的一段代码是java代码,显示行号(line="1") ,可折叠(colla="+") 。

<pre lang="java"  colla="+" line="1">  
    public class Hello {
      public static void main(String[] args) {
        System.out.println("Hello World!");
      }
    }
</pre>

效果如下

    public class Hello {
      public static void main(String[] args) {
        System.out.println("Hello World!");
      }
    }

四、高清晰的图象

 
如果全篇文章(包括图片)都从Word文档拷贝到Windows Live Write(选择性粘贴),那么即使word中图片的清晰度还可以,但是到了Live Write后质量很差,解决办法可以是: 使用抓图软件(比如SnagIt)从源头或者Word文档中再抓一次,放到live Write中.

五、表格的制作

 
目前表格制作最方便的就是Excel了,live Write也可以插入表格,但是制作的表格没有Excel方便,漂亮。而在线

编辑模式下没有提供表格编辑,所以比较好的方法是使用Excel编辑表格,然后以在线编辑模式,粘贴表格,效果比较好。Live Write中无法使用Ctrl+V 直接粘贴Excel表格, 但可以击邮件选择“选择性粘贴”,然后选择“保留格式”来粘贴Excel  表格。

Oracle 数据挖掘和分析:零售行业应用举例一

oracle database 10g r2 中引入的新的package 提供了线性代数的两个最重要的函数库。可用于多元线性回归分析,主成份分析,线性方程组求解等等。其中多元线性回归分析经常用于零售行业的销售预测。

概述  

    Oracle Database10g R2 中有个新的Package: UTL_NLA,这个Package没什么名气,但是把线性代数功能带进了Oracle Database. 这使得Oracle数据库成为一个不错的科学计算和分析平台. 现在,我们可以很容易的在Oracle 数据库中写出很好的矩阵代码. 下面是从Oracle Database Data Warehousing Guide 10g R2中摘录的简要描述:

    线性代数是有着很广泛的实际应用的数学分支.很多领域都存在可以用线性代数来描述的任务. 比如: 统计领域(多元线性回归,主成分分析),数据挖掘(聚类和分类),生物信息学(微阵列数据分析),业务研究(供应链和其他优化问题),计量经济学(分析消费者的需求数据)以及财务(资产分配问题)每个人都可以自由使用线性代数的各种函数库。Oracle的UTL_NLA包可以定义矩阵类型的数据并且把两个功能最强,使用最广的两个库封装到PLSQL包的子程序中。

     线性代数依赖于矩阵运算,以前,在PLSQL中执行矩阵运算需要基于PLSQL 的本地数据类型,从零开始写矩阵运算函数。这需要写大量的程序并且性能有限。如果开发人员选择把数据发送到外部程序包中去处理而不是在Oracle 中创建矩阵计算函数来处理 ,就存在数据的导出、导入等IO时间消耗。使用UTL_NLA package可以不用做这些,可以快速交付实现。

   

     BLAS和LAPACK可能是应用最广泛的线性代数库。这些库被广泛的应用于大量的科学计算程序和专门工具。

对开发者来说,这些函数库提供了积木实现大量的高级技术。比如 MATLAB工具库,其大多数功能都是建立在类似于BLAS和LAPACK之类的线性代数库的基础上的。在数据库中提供这些函数库,允许开发者编写紧凑的,易于阅读的代码用于矢量操作,当然因为这些库拥有高效而强劲的线性代数操作的实现,使用UTL_NLA Package的代码自然就具有这些特性。

    除了科学计算,Oracle的线性代数支持可用于业务分析。一个例子就是多元线性回归。数据库中带有一个多元线性回归的应用例子,这个例子就是使用UTL_NLA  写的。这个应用在一个叫做OLS_Regression的对象中实现。注意,例子OLS Regression对象的文件文件可以在$ORACLE_HOME/plsql/demo 中找到。点击 这里 查看例子,学习如何使用这个功能。

  

Example 21-19 Linear Algebra

这是一个Oracle数据库附带的例子,  演示了如何使用Oracle  的线性代数功能来支持业务分析,它使用UTL_NLA Package来调用多元线性回归应用。这个多元线性回归应用在一个叫做 OLS_Regression 的对象中被实现。 对应的例子文件可以在$ORACLE_HOME/plsql/demo中找到。

考虑下列场景:零售商需要分析营销计划的效果。

背景:

每个门店都会把它每年的市场费用预算分配到如下四个方面:1) 媒体广告(media);2)促销(promo);3)折扣券(disct);4)直邮(dmail);回归分析需要在每个门店每年的销售额 与上述4项费用支出 之间建立线性关系。假设这些市场数据都存储于如下的表中:

sales_marketing_data (
  /* Store information*/
  store_no   NUMBER,
  year       NUMBER,
  /* Sales revenue (in dollars)*/
  sales      NUMBER,   /* sales amount*/
  /* Marketing expenses (in dollars)*/
  media      NUMBER,   /*media advertisements*/
  promo      NUMBER,   /*promotions*/
  disct      NUMBER,   /*dicount coupons*/
  dmail      NUMBER   /*direct mailers*/)

那么你可以建立如下线性模型:

Sales Revenue = a + b Media Advisements + c Promotions + d Discount Coupons + e Direct Mailer

实现:

这个模型可以使用下面的视图来实现,这个视图引用了OLS回归对象。

View start:

CREATE OR REPLACE VIEW sales_marketing_model (year, ols)
   AS SELECT year,
        OLS_Regression(
        /* mean_y =&gt; */
        AVG(sales),
        /* variance_y =&gt; */
        var_pop(sales),
        /* MV mean vector =&gt; */
        UTL_NLA_ARRAY_DBL (AVG(media),AVG(promo),
                           AVG(disct),AVG(dmail)),
        /* VCM variance covariance matrix =&gt; */
        UTL_NLA_ARRAY_DBL (var_pop(media),covar_pop(media,promo),
                           covar_pop(media,disct),covar_pop(media,dmail),
                           var_pop(promo),covar_pop(promo,disct),
                           covar_pop(promo,dmail),var_pop(disct),
                           covar_pop(disct,dmail),var_pop(dmail)),
        /* CV covariance vector =&gt; */
  UTL_NLA_ARRAY_DBL (covar_pop(sales,media),covar_pop(sales,promo),
                           covar_pop(sales,disct),covar_pop(sales,dmail)))
 FROM sales_marketing_data
 GROUP BY year;

view end:

通过这个视图,市场部经理可以进行一些分析,比如“这个销售营销模型对2004年的数据来说合理吗?”也就是说多重关联性是否大于可接受的值。查询sql如下:

SELECT model.ols.getCorrelation(1)

       AS “Applicability of Linear Model”

FROM sales_marketing_model model

WHERE year = 2004;

也可做如下分析:“在2003年,如果没有任何市场活动,那么门店的基本收入是多少?” 或者“在2004年,最有效的是那种类型的市场活动?”

 

解释:

1、OLS_Regression 定义在 $ORACLE_HOME/plsql/demo/olstype.sql 中

      OLS是普通最小二乘分析法(ordinary leastsquares)的简写 ,想深入了解OLS可点击这里,而 OLS Regression 即指使用最小二乘法进行线性回归分析。

     

2、var_pop, 函数参考这里  , 或者这里  covar_pop 函数参考这里

 

3、OLS_Regression 使用说明

$Header: olstype.sql 09-jun-2004.17:32:14 lvbcheng Exp $
 
olstype.sql
 
Copyright (c) 2004, Oracle. All rights reserved.  
 
   文件名
     olstype.sql - 普通最小二乘回归
 
   描述
     这个文件包含普通最小二乘(OLS)的类型定义
     This files contains the type definition for Ordinary Least Squares (OLS)
     回归: y = b0 + b1 z1 + ... + bn zn.
 
   备注
     OLS_Regression 的构造函数需要用户传入如下参数:除其他值外,
     预测变量的均值向量(vm), 自变量的协方差矩阵(vcm),  因变量和自变量的协方差(cv). 
 
     1. 有 n个 自变量 (zi) 就应该有n个均值, 这里 MV[i] = avg(zi).
 
     2. 协方差矩阵(VCM) 是一个 NxN 对称矩阵, 并且作为一个阵列参数传入,
        主要使用阵列的右上三角部分,(i &lt;= j  i是列,j是行)  当i!=j时, V[i,j] 是协方差
        covar_pop(zi, zj);当i=j的时候,V[i,j] 是方差  ,比如 ,如果有三个预测变量
        (a, b, and c) 那么其协方差(VCM)就应该是
        :
 
                [     var_pop(a)   covar_pop(a,b)   covar_pop(a,c) ]
         VCM =  [ covar_pop(b,a)       var_pop(b)   covar_pop(b,c) ]
                [ covar_pop(c,a)   covar_pop(c,b)       var_pop(c) ]   
 
        但传给 OLS_Regression()的应该是右上三角部分:
 
         VCM =  UTL_NLA_ARRAY_DBL(var_pop(a), covar_pop(a,b), covar_pop(a,c),
                                                  var_pop(b), covar_pop(b,c),
                                                                  var_pop(c))
 
     3. 对于 N 个自变量(zi)和一个因变量(y)的情况, 协方差(CV) 应该有n中不同情况,
         CV[i] = covar_pop(y, zi).
 
     4. 标准化的评分回归只需要一个相关矩阵(RM)和一个相关矢量(RV),
        使用 RM 替换上面的 VCM, 不过,RM[i,j] = corr(zi, zj) when i != j, and 1 when i = j.
        使用 RV 替换上面的 CV  不过,  RV[i] = corr(y,zi).
 
   依赖
     这个文件依赖于 UTL_NLA package.
 
   参考
     Johnson, Richard A., and Dean W. Wichern, "Applied Multivariate Statistical
     Analysis (5th ed.)". New Jersey: Prentice Hall, 2002.
     《多元统计分析应用》
 
   举例
     1. 下面的SQL语句将从模型:y = b0 + b1 z1 + b2 z2  中返回回归方程。
         而因变量y 和自变量 z1,z2 存储在表中:ols_data(y number, z1 number, z2 number).
 
        SELECT model.ols.getEquation() "OLS Regression Equation"
        FROM
        (SELECT OLS_Regression(AVG(y), VAR_POP(y),
                               UTL_NLA_ARRAY_DBL(AVG(z1),AVG(z2)),
                               UTL_NLA_ARRAY_DBL(VAR_POP(z1),COVAR_POP(z1,z2),VAR_POP(z2)),
                               UTL_NLA_ARRAY_DBL(COVAR_POP(y,z1),COVAR_POP(y,z2))) ols
         FROM ols_data) model;
 
     2. 下面的SQL语句将从模型:y = y = 0 + b1 z1 + b2 z2  中返回回归方程。
        相应的数据存储在表table ols_data(y number, z1 number, z2 number)
 
        SELECT model.ols.getEquation() "OLS Regression Equation"
        FROM
        (SELECT OLS_Regression(AVG(y), VAR_POP(y),
                               UTL_NLA_ARRAY_DBL(AVG(z1),AVG(z2)),
                               UTL_NLA_ARRAY_DBL(VAR_POP(z1),COVAR_POP(z1,z2),VAR_POP(z2)),
                               UTL_NLA_ARRAY_DBL(COVAR_POP(y,z1),COVAR_POP(y,z2)), 0) ols
         FROM ols_data) model;
 
     3. 更多其它关于 OLS_Regressions 应用的例子可以参考 olsexmpl.sql 文件.

专业需求,局限和可用性。

    在使用UTL_NLA Package之前,必须了解一些事情,Oracle文档指出使用这个Package的开发者应该有线性代数基础,特别是BLAS和LAPACK的知识。我相信,如果要使用这个Package来实现一些总所周知的算法的话,只需要了解线性代数的基础即可。关于BLAS和LAPACK, 熟悉一些基本概念是重要的。(比如,矩阵存储表示:列或行),除了Oracle文档,其他一些有用的参考包括:

The Lapack Users’ Guide, the BLAS and the LAPACK chapters in the in CRC Handbook of Linear Algebra

参考:http://oracledmt.blogspot.com/2007/04/way-cool-linear-algebra-in-oracle.html

订单行在订单关闭后未能生成AR发票行的原因追查日志

/*******************************************************************************
date : 2007-05-08
处理者: yunfang.shang
*******************************************************************************/

/*
现象: 顾问做了一张订单,在登记并完成“后台工作流程序” 后,订单及订单行关闭;
但是有一行 在AR中未找到对应的发票行(总共有6行,5行到了AR,有一行没有到AR)
*/

— 查订单行(由于订单行及发票行的attribute2 都用于存放 POS小票号,所以可以根据POS小票号来查
select  * from  oe_order_lines_all   where attribute2 = ‘ZCXSS111202800000035’
–返回6条记录
–查发票接口
select  * from  RA_INTERFACE_LINES_ALL  where attribute2 = ‘ZCXSS111202800000035’
–返回 0 条记录,说明已经全部被处理
–查发票行
select  * from  RA_CUSTOMER_TRX_LINES_ALL  where attribute2 = ‘ZCXSS111202800000035’
–返回 5 条记录
–说明肯定有一条根本就没有生成到AR接口表中

— AR 行 和订单行的差异,发现没有过来的一条记录,其发票接口状态字段异常 INVOICE_INTERFACE_STATUS_CODE =  NOT_ELIGIBLE
— 所以直接原因是 因为订单行不合法导致未能开票。 那么具体是什么原因呢?
— 打开 OM   行流 工作流定义 ,根据返回状态为NOT_ELIGIBLE 进行代码追踪 ;
— 从 行开票接口节点开始  OE_INVOICE_WF.INVOICE_INTERFACE->OE_Invoice_PUB.Interface_Line  – >OE_Invoice_PUB.Interface_Single_Line->OE_Invoice_PUB.Line_Invoiceable
— Line_Invoiceable 这个函数是最终的可能提供详细原因的函数。看代码后发现 导致行不可开票的原因有很多种,究竟是哪一种呢?
— 启用Debug ,准备做一次调试,看具体的debug原因就可以确定了明确的不可开票原因了。

— 在用户层设置  系统配置文件  “OM: 调试级别”      把值设置为5
— 在用户层设置  系统配置文件  OM:调试日志目录”      把值设置为   /usr/tmp
— demo  环境应用服务器:
— 删除 usr/tmp/  *.dbg  文件
— 再作一张订单,登记,运行工作流后台程序 ,直到订单关闭
— 在usr/tmp 目录下去看日志文件。
— 郁闷,这里的日志文件 只是跟踪到订单界面上的操作。根本就未能跟到  Line_Invoiceable 这个函数。所以从这个日志文件也看不出什么名堂。
— 那么是否信息被debug 到  fnd_log_message 表中去了呢? 去找了一把也没有找到。
— 再去读  oe_debug_pub 程序,也就是记录日志的那个程序包。 发现它会判断:如果从系统配置文件中获取的当前 并发请求Id 不是 -1 ,
— 并且不是在 UI模式的话则会把日志的输出文件输出到 并发程序的log中去
— 想想,虽然我们是在界面上录入,登记订单。 但是真正启动   Line_Invoiceable 这个函数 的人应该是” 工作流后台流程” 这个并发程序。
— 是不是log信息被记录到这个” 工作流后台流程” 的log中了呢?
— 看刚才运行的 ” 工作流后台流程” 的log ,果来是这样。其中有句log 应该是 Line_Invoiceable 输出的

— 日志 ENTERING LINE_INVOICEABLE 应该是进入  Line_Invoiceable 函数的 标志性的日志语句
/*
ENTERING LINE_INVOICEABLE
。。。。。。
ITEM NOT INVOICEABLE ( 2 )
l_freight_count: 0
Handling non-invoiceable lines with no freight or automatic numbering*/

— 根据错误日志 “Handling non-invoiceable lines with no freight or automatic numbering”  到OE_Invoice_PUB 包中查找,,发现这个错误是由
— Interface_Line 函数抛出的,而且这句话是在调用line_invoiceabel 返回结果 false  并且
— 在  FND_PROFILE.VALUE(‘WSH_INVOICE_NUMBERING_METHOD’) = ‘A’ 的情况下设置的。

— ITEM NOT INVOICEABLE(2) 是 Line_Invoiceable 函数抛出的日志,在程序中有如下判断:

     IF (l_invoiceable_item_flag = ‘N’) OR
        (l_invoice_enabled_flag = ‘N’) OR
        (p_line_rec.item_type_code = ‘SERVICE’ AND l_serviceable_product_flag = ‘N’) THEN
           IF l_debug_level  > 0 THEN
               oe_debug_pub.add(  ‘ITEM NOT INVOICEABLE ( 2 ) ‘ , 1 ) ;
           END IF;
           RETURN FALSE;
     END IF;
    
—  而l_invoiceable_item_flag 和 l_invoice_enabled_flag 都是从物料信息表获取的:

        SELECT INVOICEABLE_ITEM_FLAG, INVOICE_ENABLED_FLAG
        INTO   l_invoiceable_item_flag, l_invoice_enabled_flag
        FROM   mtl_system_items
        WHERE  inventory_item_id = p_line_rec.inventory_item_id
        AND    organization_id = nvl(p_line_rec.ship_from_org_id, oe_sys_parameters.value(‘MASTER_ORGANIZATION_ID’, p_line_rec.org_id));
    
    
— 可见本次问题发生的真正原因就找到了: 就是物料属性设置不对,不可开票阿!!!。