第一期:遇到 OBServer 中的非预期报错,我应该如何做?
本次课程介绍如何捞取OBServer的日志。
在数据库运维中,SQL 执行报错十分常见,而且可能对业务造成直接影响。SQL 执行报错的原因有很多,比如没能正确连接到数据库、数据库用户权限不足、语法错误或数据不满足查询条件等等。
很多情况下,依靠返回的错误码和报错信息,再加上官网文档对错误码的解释,可能就足够分析问题了。但是还有一些情况,报错信息不够清晰,特别是像 Internal error 这种没有任何有效报错信息的报错,可能就需要去社区论坛发帖向官方技术支持同学寻求帮助了。
但如果只向支持同学提供一个错误码 4016 和对应的报错信息 Internal error,大概率是看不出问题原因的,因此还需要用户协助提供这个错误码对应的日志信息。
实验步骤
1.连接数据库,并登录用户租户
obclient -h127.0.0.1 -P2881 -uroot@mysql_tenant -A -Dtest
2.创建一张测试表
CREATE TABLE t1 (c1 TIMESTAMP CHECK(c1 + UNIX_TIMESTAMP() > '2025-07-30 01:02:03'));
CREATE TABLE t1 (c1 TIMESTAMP CHECK(c1 + UNIX_TIMESTAMP() > '2025-07-30 01:02:03'));
ERROR 3814 (HY000): An expression of a check constraint contains disallowed function.
3.这个报错信息说: check 约束里包含了不允许出现的系统函数。
但 check 约束里有多个系统函数,分别是 ADD(+)、GREATER_THAN(>)和 UNIX_TIMESTAMP。具体是哪个或者哪几个系统函数不被允许出现在 check 约束中,以及为何不允许出现?在这个报错信息里,都是看不出来的。
4.这时候如果希望解决上面提出的这几个问题,就需要获取日志,然后从日志中获得报错的详细信息。获得日志的第一步工作是:在同一个 session 中,紧接着报错的 SQL,去执行 select last_trace_id(),获取这条报错 SQL 的 trace id
select last_trace_id();
YB427F000001-0063A082AF3A88A-0-0
-一
1 row in set(0.001 sec)
通过 last_trace_id() 获取到的 trace id 可能会有差异,请以实际查询结果为准。
5.因为本实验环境是单节点,所以可以直接退出连接串,然后去日志里搜一下上面返回的这个 trace id 即可。
## 退出连接串
quit
## 切换到报错日志所在的目录
cd /home/admin/oceanbase/observer/log
## 搜一下对应 SQL 的 trace id(记得要把下面命令里的 xxxxxxxx-xxxxxxxx-x-x 替换成你自己通过执行 last_trace_id 返回的 trace id
grep YB427F000001-0063A082AF3A88A-0-0 *
可以通过执行 select * from oceanbase.gv$ob_sql_audit where trace_id = ‘xxx’; 获取接收请求的 OBServer 的 ip 和 port,然后到对应 ip 的节点上的日志文件里 grep trace_id。
或者通过 OCP 白屏工具捞日志,这种方式可以一次性返回所有节点上的相关日志。
6.grep 到日志之后,选取最前面的几行看下。
observer.log:[2025-07-16 17:25:31.812779] WDIAG [SOL.RESV] check deterministic sing]e (ob raw expr util.cpp:2054)[2465][T1002 L0 GO][T1002][YB427F000001-00063A082AD3A88A-0-0][1t=18][errcode=-5991] deterministic expr is wrongly specified in CHEck constraint(ret=-5991,expr->get expr type()=542)
observer.log:[2025-07-16 17:25:31.8127981 WDIAG [SOL.RESVl check deterministic single (ob raw expr util.cpp:2058)[2465][T1002 L0 GO][T1002][YB427F000001-00063A082AD3A88A-0-0][lt=19][errcode=-5991] only pure sys function can be indexed(ret=-5991, check status=3, *exopr={item type:"T_FUN_SYS_UNIX_TIMESTAMP", result type: {meta: {type:""collation:"binary", coercibility:"NUMERIC"),accuracy:{length:-1,precision:-1,scale:-1}, flag:0, calc type: {type:"NULL", collation:"invalid type", coercibility:"INVALID"}},expr info:["IS FUNC", "IS CUR TIME", "IS CONST EXPR", "CNT FUNC","CNT CUR TIME"l, rel id:[l, func:"UNIX TIMESTAMP", children:[], enum set values:[], dblink name:"",dblink id:18446744073709551615,local session var:{}, local session var id:-1mview id:18446744073709551615,expr hash:0})
observer.log:[2025-07-16 17:25:31.812868| WDIAG ISOL.RESVl check deterministic (ob raw expr util.cpp:2014)[2465][T1002 L0 GO][T1002][YB427E000001-00063A082AD3A88A-0-01[1t=69|lerrcode=-5991] fail to exec check deterministic single(cur expr, check status)(ret=-5991)
第一行日志里,有一个关键字:deterministic expr。
第二行日志里,有一个关键字:T_FUN_SYS_UNIX_TIMESTAMP。
第三行及后面的日志暂时就先忽略了。一般来说,越后面的日志,和问题本身的关系就越小。
7.这里建议大家先自己去分析一下前两行的日志,看看能不能得到什么结论?
下面是分析过程,供大家参考:
第二行日志明确说了 check 约束里出问题的系统函数是 UNIX_TIMESTAMP,排除了 ADD(+)和 GREATER_THAN(>)有问题的嫌疑。
第一行日志说 UNIX_TIMESTAMP 不允许出现在 check 约束中,原因和deterministic 表达式有关。
大家自行查下关键字 deterministic,可以知道含义是 “确定性的”,而这个 UNIX_TIMESTAMP() 函数在不同时间执行,会返回不同的结果,明显属于 “非确定性(nondeterministic)” 函数。进而可以推测出在 check 约束中,只允许出现确定性函数,不允许出现 now、random 等非确定性函数。
日志里的报错信息如果写成:nondeterministic expr is wrongly specified in CHECK constraint,就更好理解了。这里应该是个笔误,但是并不太影响理解。
除了 check 约束表达式,类似于分区表达式、生成列表达式,也都不允许出现非确定性的函数。
8.至此,靠着日志信息,就已经把这个问题的原因分析出来了。
如果看捞到日志,但还是分析不出来,可以先去 OceanBase 官方文档里搜下日志里的关键字,看看可以获取到什么线索。
如果没有获取到有效的线索,可以把日志发到 OceanBase 社区论坛,让社区值班的技术支持同学(或者论坛 AI 助手)来帮你进行分析。
其他注意事项
上面实验里的方法在使用上,还是有一些限制,需要在在同一个 session 中,紧接着报错的 SQL,去执行 select last_trace_id()。
如果在报错 SQL 之后,已经执行了其他 SQL,或者已经退出对应 session。还可以在日志里通过 grep “keywords”,获取 trace_id。
cd /home/admin/oceanbase/observer/log
grep "CREATE TABLE t1 (" *
然后就拿到 trace_id 。
接下来就回到了之前的方法,通过 trace_id 去 grep 出完整日志即可。
也可以使用 grep “ret=-errno” 获取trace_id,
grep "ret=-3814"
还可以使用OCP白屏及obdiag捞日志。




