KingbaseES常见问题手册.pdf
KingbaseES 常见问题手册 金仓数据库管理系统 KingbaseES 文档版本:V9(V009R001C001B0024) 发布日期:2023 年 10 月 12 日 北京人大金仓信息技术股份有限公司 目 目 录 录 第 1 章 前言 1 1.1 适用读者 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 相关文档 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3 手册约定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 第 2 章 SQL 类 2.1 2.2 2.3 2.4 2.5 空值问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.1.1 ‘’与 null 兼容性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.1.2 判断值是否为空,要用 is null . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.1.3 PG 模式下‘’值问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.4 Ora_input_emptystr_isnull 对于字符类型空值的影响 . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.5 Ora_input_emptystr_isnull 对于数值类型空值的影响 . . . . . . . . . . . . . . . . . . . . . . . 8 Core 分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.2.1 多线程 core 分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.2.2 如何生成 core 文件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.2.3 如何查看 core 文件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 关键字问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3.1 如何确认是否系统关键字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3.2 遇到关键字无法使用作为表名或列名 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 字符和字符集 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.4.1 乱码或无效字符编码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.4.2 全角字符支持 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 分区表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 如何创建一个间隔分区 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 MySQL 兼容 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.5.1 2.6 2.7 3 2.6.1 group by 操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.6.2 MySQL date_format 改写 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 数据库对象 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.7.1 视图源定义信息为啥和创建的语句不一样 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.7.2 共有同义词和私有同义词有什么区别 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.7.3 同义词查找规则 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 I 2.8 目 录 2.7.4 Nextval 在同一条语句中的值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.7.5 序列的 cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 数据库版本 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 查询版本 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.8.1 2.9 用户管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.9.1 能为模式指定表空间吗? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.9.2 丢失了数据库密码,如何恢复? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.9.3 指定表空间 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.10 OID 与 CTID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.10.1 OID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.10.2 CTID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.11 数据库管理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.11.1 数据库大小限制 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.11.2 KES 数据页结构 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.12 COPY 命令 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.12.1 如何将数据从客户端通过 copy 命令导入数据库 . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.13 其他错误 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.13.1 命令报参数错误问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.13.2 Failed to find conversion function from UNKNOWN to TEXT . . . . . . . . . . . . . . . . . . 24 2.14 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.14.1 To_date 函数问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.14.2 如何改变 sys_guid() 返回值类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.14.3 时间函数问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.15 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.15.1 字符串类型长度怎么获取 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.15.2 Pg_relation_size 问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.16 系统包 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.16.1 dbms_metadata 包获取对象的定义信息 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.17 系统视图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.17.1 sys_class 里显示的 RELTABLESPACE 值为 0? . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.17.2 KES 有什么办法,默认不读取 sys_catalog 下的系统视图? . . . . . . . . . . . . . . . . . . . . 28 2.18 SQL 优化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.18.1 全表 update 非常慢 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.19 索引 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.19.1 索引问题导致数据访问问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 第 3 章 PLSQL 类 3.1 3.2 31 PLSQL 存储过程 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.1.1 KES 创建过程,报错:PL/SQL block not end correctly . . . . . . . . . . . . . . . . . . . . . . 31 3.1.2 如何调用含 out 参数的存储过程 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 PLSQL 函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 函数变量不能超过 512 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.2.1 II 3.3 3.4 控制语句 目 录 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.3.1 Savepoint 使用问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.3.2 For 循环变量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 PLSQL 数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Create operator(bool 与整型比较) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.4.1 第 4 章 参数相关 35 4.1 Kingbase.conf 与 kingbase.auto.conf 参数文件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 4.2 不同参数如何生效 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 4.3 error_user_connect_times and max_error_user_connect_times . . . . . . . . . . . . . . . . . . . . . 36 4.4 Exclude_reserved_words 排除关键字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 4.5 max_locks_per_transaction 设置过大引发数据库启动问题 . . . . . . . . . . . . . . . . . . . . . . . . 37 4.6 max_identifier_length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.7 数据库启动失败,报“内存段超过可用内存” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 第 5 章 License 相关 39 5.1 查询 license 有效时间 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 5.2 查询 V8R3 license 完整信息 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 5.3 查询 V8R3 license 单项信息 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 5.4 替换 license 步骤 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 5.5 替换 license 是否要重启数据库 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 5.6 如何判断 license 有效 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 5.7 V8R3 License 与网卡 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 5.8 Bond 网卡切换 license 支持问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 第 6 章 扩展组件 45 6.1 查看系统是否支持某组件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 6.2 create extension oracle_fdw 报.so 找不到加载失败 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 6.3 Sys_pathman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 6.4 Separate_power . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 6.5 Sysaudit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 第 7 章 空间组件 47 7.1 Create extension postgris 报错“GLIBC_2.18 not defined in file libc.so.6” . . . . . . . . . . . . . . . 47 7.2 acgis 版本备份还原 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 7.3 V9 是否支持超图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 第 8 章 数据库运行管理 49 8.1 网线拔插后,IP 丢失问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 8.2 [KESV8R2/3] 客服端服务器编码原理说明 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 8.3 Bulkload 并行加载报错 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 8.4 Windows 版本安装未注册服务 50 第 9 章 工具类 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 III 9.1 9.2 9.3 9.4 目 录 KSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 9.1.1 客户端连接找 .s.PGSQL.5432 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 9.1.2 undefined symbol: PqgssEncInUse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 管理工具 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 9.2.1 客户端管理工具无法加载 ER 图问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 9.2.2 如何修改管理工具 client_encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 迁移工具 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 9.3.1 迁移工具对于同名对象处理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 9.3.2 数据迁移报“invalid byte sequence for encoding ”UTF8”: 0x00 ” . . . . . . . . . . . . . . . . . 53 其他问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 9.4.1 开始菜单没有数据库快捷工具图标 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 9.4.2 缺少操作系统 GUI 组件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 第 10 章 数据安全 55 10.1 SSL 认证 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 10.1.1 证书生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 10.1.2 证书配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 10.1.3 证书有效期 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 10.2 Windows 配置免密登录 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 第 11 章 TPCC 测试类 58 11.1 autovacuum 参数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 11.2 index_cursor_id 参数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 11.3 unixdomain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 11.4 集群环境下测试 tpcc 连接参数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 第 12 章 接口 60 12.1 JDBC 接口 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 12.1.1 JDBC 打开日志方式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 12.1.2 没有 VIP 情况下 JDBC 连接配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 12.1.3 V9 JDBC 使用 VIP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 12.1.4 LOB 对象 update 机制 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 12.1.5 KBBlob 迁移至 Oracle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 12.1.6 JDBC jar 包版本 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 12.1.7 JDBC 的连接参数填写 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 12.1.8 JDBC 配置文件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 12.1.9 JDBC 读写分离的打开和关闭 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 12.1.10 JDBC 读写分离配置参数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 12.1.11 JDBC 读写分离一主两备的 URL 和配置文件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 12.1.12 JDBC 连接池功能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 12.1.13 JDBC 读写分离配置参数依赖关系 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 12.1.14 JDBC 读写分离重发不成功的情况 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 12.1.15 JDBC 读写分离分发策略 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 IV 目 录 12.1.16 JDBC 读写分离相关参数默认值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 12.1.17 sockettimeout 导致 jdbc 重建连接 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 12.1.18 主备切换后备机的连接数持续上升问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 12.1.19 主机切机后,应用登陆 WEB 慢 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 12.1.20 JDBC 打开日志方式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 12.1.21 JDBC 报错:无效的”UTF8” 编码字节顺序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 12.1.22 系统 JVM 和应用和 JDBC 和数据库编码之间的关系 . . . . . . . . . . . . . . . . . . . . . . . 70 12.1.23 V7 V9 JDBC 混用问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 12.1.24 JDBC 读写分离模式混淆找不到表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 12.1.25 JDBC 读写分离日志分析办法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 12.1.26 JDBC 使用 SSL 加密 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 12.1.27 JDBC 常见异常 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 12.1.28 JDBC 读取 BLOB 乱码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 12.1.29 读写分离分发现象分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 12.1.30 com.kingbase8.util.KSQLException: ERROR: type ”q” does not exist(R6) . . . . . . . . . . 81 12.1.31 fetchsize 功能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 12.1.32 同时使用 R3 和 R6,jar 包 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 12.1.33 jar 包的版本号 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 12.1.34 R3 客户端无法使用 scram-sha-256 认证 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 12.2 Spring-JDBC 常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 12.2.1 大字段的设置--lobHandler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 12.2.2 Cannot determine a dialect for org.springframework.jdbc.core . . . . . . . . . . . . . . . . . . . 83 12.3 Hibernate 使用常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 12.3.1 Hibernate 配置方言包 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 12.3.2 V9 Hibernate 非法 long 值问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 12.3.3 Hibernate 无法确定参数类型 $1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 12.3.4 TEXT 与 BYTEA 的转换错误 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 12.3.5 Hibernate 控制输出真实 SQL 日志 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 12.3.6 Springboot JPA 配置方言包问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 12.3.7 hibernate-spatial 方言包配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 12.3.8 hibernate 使用 numeric 或 char(1) 映射 java 的 boolean . . . . . . . . . . . . . . . . . . . . . . 88 12.3.9 The column name sequence_catalog was not found in this ResultSet. . . . . . . . . . . . . . . . 88 12.3.10 主键自增策略 hilo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 12.3.11 Method com.kingbase8.jdbc.KbPreparedStatement.setCharacterStream(int, Reader, long) is not yet implemented. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 12.3.12 Hibernate 的 hql 不支持部分数据库函数的使用 . . . . . . . . . . . . . . . . . . . . . . . . . . 89 12.3.13 Hibernate 设置为 update 已经建好表,仍旧去建表 . . . . . . . . . . . . . . . . . . . . . . . . 90 12.3.14 java.lang.NoSuchMethodError: javax.persistence.Table.indexes()[Ljavax/persistence/Index; . . 90 12.3.15 表取名 user 的规避 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 12.3.16 其它模式下有同名表的处理机制 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 12.4 Mybatis 常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 12.4.1 Mybatis 设置 SQL 超时时间 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 V 目 录 12.4.2 Mybatis 非法 long 值问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 12.4.3 TEXT 与 BYTEA 的转换问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 12.4.4 Mybatis 控制 JDBC 底层不走预编译 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 12.4.5 Mybatis 控制 Bind 参数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 12.4.6 Mybatis 使用 pagehelper 插件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 12.4.7 Mybatis 使用自动返回主键功能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 12.4.8 Mybatis 配置 databaseId . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 12.4.9 Mybatis 使用匿名块插入语句报错 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 12.4.10 Mybatis 使用 ScriptRunner 执行含 plsql 的 sql 脚本报错 . . . . . . . . . . . . . . . . . . . . . 95 12.4.11 Mybatis 使用游标的注册方式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 12.4.12 Mybatis 写 json 类型示例 12.5 Mybatis-plus 常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 12.5.1 Mybatis-plus 使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 12.6 Activiti 使用常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 12.6.1 Activiti 使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 12.7 Maven 仓库使用常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 12.7.1 Maven 本地仓库使用 KingbaseES 的 JDBC 驱动 . . . . . . . . . . . . . . . . . . . . . . . . . . 105 12.7.2 Maven 本地仓库使用 KingbaseES 的 dialect 方言包 . . . . . . . . . . . . . . . . . . . . . . . . 106 12.8 连接池配置问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 12.8.1 Druid 数据库连接池配置问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 12.8.1.1 Druid 配置国产金仓数据库 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 12.8.1.2 Druid 配置例子 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 12.8.1.3 Druid 的连接强制回收 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 12.8.2 常用 C3p0 配置金仓 V9 数据库 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 12.8.3 常用 dbcp 配置金仓 V9 数据库 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 12.9 Apache James 适配 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 12.10 PHP-PDP 接口常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 12.10.1 导入驱动失败 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 12.10.2 加载 PDO_KDB 报错 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 12.10.3 PHP 的线程安全和非线程安全 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 12.10.4 使用的 PDO 驱动与 PHP 版本不匹配 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 12.10.5 Windows 下使用 PDO 驱动的方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 12.10.6 thinkphp 使用过程中报函数不存在的问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 12.10.7 通过金蝶等中间件查看驱动加载信息时,看不到 pdo_kdb 或者 pdo_pgsql 的信息 . . . . . . . 114 12.10.8 如何在搭建 Thinkphp+apache+kdb 环境 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 12.10.8.1 apache 环境搭建 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 12.10.8.1.1 源码编译 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 12.10.8.1.2 配置 httpd.conf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 12.10.8.2 php 环境搭建 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 12.10.8.2.1 配置驱动 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 12.10.8.3 thinkphp 在 httpd 中使用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 12.10.8.3.1 配置数据库连接 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 VI 目 录 12.10.8.3.2 配置数据库连接 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 12.10.8.3.3 修改控制文件 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 12.11 Perl 常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 12.11.1 驱动 pdi 无法加载问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 12.11.2 perl 中配置金仓 perl 驱动 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 12.11.3 排查 perl 驱动加载失败 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 12.12 ODBC 常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 12.12.1 环境依赖 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 12.12.2 unixodbc 连接串参数配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 12.12.3 开启 odbc 驱动的日志 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 12.12.4 linux 下 odbc 驱动接口连接数据库 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 12.12.5 linux 下 odbc 驱动开启日志 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 12.12.6 SQLFreeStmt() 函数与 SQLCloseCursor() 函数的不同 . . . . . . . . . . . . . . . . . . . . . . . 123 12.12.7 通过驱动名连接数据库 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 12.13 C# 常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 12.13.1 NDP 的连接数问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 12.13.2 NDP 驱动版本 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 12.14 Python 常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 12.14.1 Python 通过 PyODBC 连接 Kingbase 的说明 . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 12.14.1.1 环境配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 12.14.1.2 KingbaseV7 驱动配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 12.14.1.3 KingbaseV9 驱动配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 12.14.1.4 连接测试 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 12.15 Ruby 常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 12.15.1 ruby-pg 驱动连接 kingbaseES V8R3 数据库 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 12.16 QT 常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 12.16.1 windows 加载 QT 驱动 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 12.16.2 编译器版本 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 12.17 V7 接口常见问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 12.17.1 KCI 操作大对象写入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 12.17.2 JDBC 读写分离配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 12.17.3 JDBC 日志分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 12.17.4 JDBC 读写分离分发策略 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 12.17.5 JDBC 非法大对象操作符异常 FastPath call returned invalid large object descriptor:0. . . . . 133 12.17.6 fetchsize 功能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 12.17.7 mybatis 一次执行多条语句时报错 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 12.17.8 OCI 读写分离配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 12.17.9 OCI 日志分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 12.17.10 OCI 日志配置说明 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 12.17.11 OCI 配置文件如何配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 12.17.12 OCI 和 DCI 的头文件可以混用吗? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 VII 目 第 13 章 Docker 环境相关问题 13.1 【exit code 137】错误信息 录 136 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 13.2 Docker 环境的 license 机制 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 第 14 章 高可用集群 14.1 启动异常 137 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14.1.1 libssl 问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14.1.2 if_up_cmd faild . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 14.1.3 arping 问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 14.1.4 arping_path 版本不正确 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 14.1.5 kingbasecluster 服务启动失败 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 14.1.6 R3 集群启动 esHAmodel.sh 失败问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 14.1.7 kingbaseES R3 集群启动后“无 standby”问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 14.1.8 V8R3 备库 kingbasecluster 服务通过 kingbase_monitor.sh 启动失败,手工启动 kingbasecluster 服务解决 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 14.1.9 KES V8R3 集群通过 kingbase_monitor.sh 启动失败,提示“pam_nologin(8)” 错误 . . . . . . 143 14.2 集群部署问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 14.2.1 V8R3 esHAmodel.sh 脚本错误 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 14.2.2 V8R3 集群名称不能使用 cluster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 14.2.3 未配置 root 用户 ssh 互信,部署集群时,添加节点“auth fail” . . . . . . . . . . . . . . . . . 146 14.2.4 V8R3 集群部署工具“auth fail”错误 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 14.2.5 R3 集群部署工具部署时,出现 sys_md5 的错误 . . . . . . . . . . . . . . . . . . . . . . . . . . 148 14.2.6 kingbaseES R6 集群部署“open files”问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 14.3 运行异常 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 14.3.1 网络问题导致备机无法加入集群 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 14.3.2 集群 sys_md5 生成错误密码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 14.3.3 两节点读写分离集群,集群无法创建主备,两个 node 都是主 . . . . . . . . . . . . . . . . . . . 150 14.3.4 集群无法修改 max_connections 参数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 14.3.5 No Space left on device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 14.3.6 防火墙导致集群 show pool_nodes 信息错误 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 14.3.7 KES V8R2 集群 kingbasecluster 服务 9999 端口无法连接 . . . . . . . . . . . . . . . . . . . . . 151 14.3.8 R3 集群切换后 es_client 无法和 es_server 通讯问题 . . . . . . . . . . . . . . . . . . . . . . . . 152 14.3.9 kingbaseES R3 集群 kingbasecluster 无法正确识别备库状态 . . . . . . . . . . . . . . . . . . . . 153 14.3.10 kingbaseES R3 集群无法加载 db VIP 和 cluster VIP 案例 . . . . . . . . . . . . . . . . . . . . 153 14.3.11 网关无法连通,导致集群 down,手工启动数据库服务 . . . . . . . . . . . . . . . . . . . . . . . 155 14.3.12 conflict with recovery 问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 14.4 读写分离 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 14.4.1 读写分离分发机制 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 14.4.2 如何测试一下现场的备机失败,转发主机的场景? . . . . . . . . . . . . . . . . . . . . . . . . . 157 14.4.3 失败重发机制 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 14.4.4 ssh 引发的相关问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 14.4.5 读写分离备机备份报错 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 VIII 目 录 14.4.6 读写分离集群 Hash 索引老是出问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 第 15 章 备份与恢复 159 15.1 sys_dump . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 15.1.1 sys_dump 备份成 sql 格式报错 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 15.1.2 如何导出一致时间点的数据 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 15.2 sys_restore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 15.2.1 sys_restore 报错 too many Command-line arguments . . . . . . . . . . . . . . . . . . . . . . . 160 15.3 sys_rman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 15.3.1 sys_rman 备份报“current time may be rewound” . . . . . . . . . . . . . . . . . . . . . . . . 160 15.3.2 sys_rman OPENSSL 问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 版权声明 162 服务周期承诺 163 IX 第 1 章 前言 1 第 章 前言 本文档汇总了 KingbaseES 数据库的常见问题。 前言部分包含以下主题: • 适用读者 • 相关文档 • 手册约定 1.1 适用读者 KingbaseES 常见问题精简手册面向所有使用金仓数据库的用户,主要是数据库管理员和应用程序开发人员。 1.2 相关文档 有关 KingbaseES 数据库的更多信息,请参阅以下资源: • 《基于 Linux 系统的数据库软件安装指南》 • 《基于 Windows 系统的数据库软件安装指南》 • 《KingbaseES 数据库概念》 • 《数据库管理员指南》 • 《KingbaseES 运维工具参考手册》 • 《KingbaseES 数据库安全指南》 • 《KingbaseES 数据库性能调优指南》 • 《KingbaseES 数据库 SQL 调优指南》 1 第 1 章 前言 1.3 手册约定 本文档中可能出现“注意、提示、警告、另请参阅”等标志,它们所代表的含义如下: 注意: 用于突出重要/关键信息、最佳实践等。 提示: 用于突出小窍门、捷径等。 警告: 用于传递设备或环境安全警示信息,若不避免,可能会导致设备损坏、数据丢失、设备性能降低或其 它不可预知的结果。 另请参阅: 用于突出参考、参阅等。 以下程序代码书写约定适用于本文档: 符号 说明 [] 表示包含一个或多个可选项。不需要输入中括号本身。 {} 表示包含两个以上(含两个)的候选,必须在其中选取一个。不需要输入花括号本身。 | 分割中括号或者花括号中的两个或两个以上选项。不需要输入“|”本身。 ... 表示其之前的元素可以被重复。 斜体 表示占位符或者需要提供特定值的变量。 大写 表示系统提供的元素,以便与用户定义的元素相互区分。除出现在方括号中的元素外,应当按 照顺序逐字输入。当然,部分元素在系统中是大小写不敏感的,因此用户可以根据系统说明以 小写形式输入。 小写 表示由用户提供的元素。 2 第 2 章 SQL 类 2 第 章 2.1 空值问题 2.1.1 ‘’与 null 兼容性 SQL 类 问题描述: 数据库是 oracle 模式时,参数 ora_input_emptystr_isnull=on 是为了兼容 oracle 对于‘’作为 null 处理。 分析与解决方法: 以下是 oracle 环境下,’’比较结果: SQL> create table t1 (id integer, name char (9) ) ; Table created. SQL> insert into t1 values(1,'') ; 1 row created. SQL> select * from t1 where name='' ; no rows selected SQL> select * from t1 where name is null; ID NAME 同样,开启 ora_input_emptystr_isnull 参数后,KES 结果如下: test-# create table t1 (id integer,name char(9)) ; CREATE TABLE test=# insert into t1 values(1, '') ; INSERT 0 1 test=# select * from t1 where name=' ' ; id | name ---+------(10 rows ) test=# select * from t1 where name is null; id | namc 3 第 2 章 SQL 类 ---+-------1 | (1 row) test=# show database_mode; database_mode ---------------oracle (1 row) 2.1.2 判断值是否为空,要用 is null 问题描述: 对于空值使用 =‘’返回结果与 is null 返回结果不同 test=# show ora_input_emptystr_isnull; ora_input_emptystr_isnull ---------------------------on (1 row) test=# create table t1 (id1 integer ,id2 integer) ; CREATE TABLE test=# insert into t1 values (1, nul1) ; INSERT 0 1 test=# insert into t1 values(2, ''); INSERT 0 1 test=# select * from t1 where id2 is null; id1 | id2 ----+-----1 | 2 | (2 rows) test=# select * from t1 where id2=''; id1 | id2 -----+----(0 rows) 分析与解决方法: 当参数 ora_input_emptystr_isnull=on 时,’’会转换为 null,而 null 表示不确定的值,因此,NULL 值比较 只能是 IS NULL 或 IS NOT NULL,不可以是 = NULL 或 <> NULL 的的形式判断,无论 = NULL 或 <> NULL,都是不成立的。 4 第 2 章 SQL 类 2.1.3 PG 模式下‘’值问题 问题描述: PG 模式下,需要设置 ora_input_emptystr_isnull=off,否则会有很多问题(因为这个参数本身就是为兼容 oracle 设置的,必须在 oracle 模式下使用)。 分析与解决方法: PG 模式,‘’行为如下: test=# show ora_input_emptystr_isnull; ora_input_emptystr_isnull -------------------------off (1 rows) test=# select * from t1 where name=''; id | name ---+----1 | (1 rows) test=# select * from t1 where name is null; id | name ---+----(0 rows) test=# set ora_input_emptystr_isnull=on; SET test=# select * from t1 where name=''; id | name ---+----1 | (1 rows) test=# select * from t1 where name is null; id | name ---+-----(0 rows) 2.1.4 Ora_input_emptystr_isnull 对于字符类型空值的影响 问题描述: 当 insert 数据时,对于空值可以是 ‘’(中间没有空格)或 null,不同参数值结果是不同的,会影响后续的 5 第 2 章 SQL 类 select 访问结果。 分析与解决方法: 1) ora_input_emptystr_isnull=on 插入的数据,‘’和 null 都会转为 null,之后的 select 操作不管 ora_input_emptystr_isnull 为何值,返回结果都相同: test=# show ora_input_emptystr_isull; --在参数开启的情况下 insert 数据 ora_input_emptystr_isull ------------------------on (1 row) test=# create table t1(id integer,name varchar(9)); CREATE TABLE test=# insert into tl values(1,''); --没有空格 INSERT 0 1 test=# insert into 1 values(2,null); INSERT 0 1 test=# select * from tl where name is nu11; id |name ---+-----1 | 2 | (2 rows) test=# select * from t1 where name=''; id | name ---+-----(0 rows) test=# set ora_input_emptystr_isull=off; --参数改为 off, 不影响 select 结果 SET test=# select * from t1 where name is null; id | name ----+-----1 | 2 | (2 rows) test=# select * from t1 where name=''; id | name ---+------ 6 第 2 章 SQL 类 (0 rows) 2) 在 ora_input_emptystr_isnull=off 时插入的数据,ora_input_emptystr_isnull 值不同,返回的结果 也不同: test=# show ora_input_emptystr_isnull; ora_input_emptystr_isnull ------------------------off (1 row) test=# create table t1 (id integer,name varchar(9)); CREATE TABLE test=# insert intc t1 value(1,''); INSERT 0 1 test=# insert inte tl values(2,null); INSERT 0 1 test=# select * from t1 where name is null; id | name ---+------2 | (1 row) test=# select * trom tl where name='; --与 null 不同 id | name ---+------2 | (1 row) test=# set ora_input_emptystr_isnull=on; SET test=# select * from t1 where name is null; id | name ---+-----2 | (1 row) test=# select * from t1 where name ''; --虽然开启 set ora_input_emptystr_isnull,对先前插入的数据无 效 id | name ---+------ 7 第 2 章 SQL 类 (0 rows) test=# select length(name) from t1 where id=1; length -------0 (1 row) test=# select * from ti where name is not null; id | name ---+-----1 | (1 row) 测试结论:数据内部对于 ‘’与 null 值的存储是不同的,当 ora_input_emptystr_isnull=on 时,不管的 insert ‘’, 还是 where col=’’,’’都会转为 null , 2.1.5 Ora_input_emptystr_isnull 对于数值类型空值的影响 问题描述: 对于 integer 类型数据,当 ora_input_emptystr_isnull=off 时,’’对于 insert 或 select 都会因为类型转换问 题报错。 分析与解决方法: 当 ora_input_emptystr_isnull=off 时,’’当做字符串,无法转换成整型。当 ora_input_emptystr_isnull=on 时,’’被转成 null,而 null 没有类型约束,所以转换没有问题。 1) 当 ora_input_emptystr_isnull=on ,insert 与 select 对于 ‘’都没问题 test=# show ora_input_emptystr_isnull; ora_input_emptystr_isnull ------------------------on (1 row) test=# create table t1 (id1 integer,id2 integer); CREATE TABLE test=# insert intc t1 value(1,null); INSERT 0 1 test=# insert inte tl values(2,'');--可以 insert '' INSERT 0 1 8 第 2 章 SQL 类 test=# select * from t1 where id2 is null; id1 | id2 ----+------1 | 2 | (2 rows) test=# select * trom tl where id2=''; id1 | id2 ----+------(0 row) 2) 当 ora_input_emptystr_isnull=off ,insert 与 select 对于 ‘’都有问题 test=# show ora_input_emptystr_isnull; ora_input_emptystr_isnull ------------------------off (1 row) test=# select * from t1 where id2 is null; id1 | id2 ----+------1 | 2 | (2 rows) test=# select * from t1 where id2='';--对于条件转换有问题 ERROR: invalid input syntax for type integer:"" LINE 1:select * from tl where id2=''; test=# create table t1 (id1 integer,id2 integer); CREATE TABLE test=# insert intc t1 value(1,null); INSERT 0 1 test=# insert into tl values(2,'');--不可以 insert '' ERROR: invalid input synlax for type integer:"" LINE 1: insert into t1 values(2,''); 9 第 2 章 SQL 类 2.2 Core 分析 2.2.1 多线程 core 分析 问题描述: 如果现场的数据库 core 了,利用 gdb 进行分析时有多个 thread,没法确定哪个 thread 才是真正 core 的? 分析与解决方法: kingbase 提供了 HandleCrash 函数,该函数被注册为一个信号处理函数,用来处理:SIGILL,SIGBUS, SIGSEGV 等信号,其子函数:StandardHandlerForSigillSigsegvSigbus_OnMainThread 用来收集堆栈信息,进程信 息,并且将他们写入管道中。如果现场中需要 gdb 重定向,需要以下方法: set logging file set logging on info threads thread n info functions set logging off 然后将对应的 filename 拷贝回来。 2.2.2 如何生成 core 文件 **问题描述:**为什么没有生成 core 文件?core 文件创建在什么位置? 问题解析: 没生成 core 文件,可能是目录权限或 limit 设置太小。Redhat7 采取 abrtd 服务,core 文件在/var/spool/ abrt 目录。Core 文件通常在进程当前工作目录的下创建,或与程序在相同的路径下。但如果程序中调用 了 chdir 函数,则有可能改变了当前工作目录。这时 core 文件创建在 chdir 指定的路径下。Redhat7 使用 abrtd (automatically bug report daemon )服务,core 文件会在/var/spool/abrt/ccpp* 目录下。 以 Centos7 为例: 1、 确认针对用户的 core 文件大小没有限制。 $ulimit -c unlimited 2、 修改/etc/abrt/abrt-action-save-package-data.conf 文件,并重启 abrtd 服务(如果不行,重启服务 器)。 OpenGPGCheck = no ProcessUnpackaged = yes 10 第 2 章 SQL 类 3、 确认/var/spool/abrt 目录下有生成 ccpp* 之类的文件。 2.2.3 如何查看 core 文件 问题描述: 如何分析 core 文件 分析与解决方法: 1、 确认 core 文件是哪个程序生成的 2、 使用 gdb 分析 core 文件。 11 第 2 章 SQL 类 2.3 关键字问题 2.3.1 如何确认是否系统关键字 问题描述: 如何确认是否系统关键字 分析与解决方法: 可以通过函数 pg_get_keywords 取得系统的所有关键字列表。 Keyword 分类解释: 1、unreserved,不保留,可以用于任何 identity(视图、表、函数、类型、索引、字段、类型等名称)。 2、reserved,保留,不可用于任何 identity。 3、reserved (can be function or type name),保留,但是可用于函数、类型名。 4、unreserved (cannot be function or type name),不保留,但是不可用于函数、类型名。 注意: 虽然 unreserved 的关键字可以用于字段名等,但不能用于列别名。 test=# create table t3(id integer,result integer); CREATE TABLE test=# select id result,id a from t3; ERROR: syntax error at or near "result" LINE 1: select id result id a from t3; ^ test=# select id "result",id a from t3; result | a -------+------(0 row) 2.3.2 遇到关键字无法使用作为表名或列名 问题描述: 遇到关键字无法使用作为表名或列名 分析与解决方法: 一般出现无法使用作为表名或列名的关键字,我们都采取将表或列名用双引号将其引用。使用双引号 (标识符) 时,表名和列名区分大小写,这意味着被标识符包起来的对象,写到数据库的原信息就是区分大小写的。 例子如下: 12 第 2 章 SQL 类 不使用标识符“”时候: TEST=# create table tb2(create int); ERROR: syntax error at or near "create" LINE 1: create table tb2(create int); ^ TEST=# create table tb3(col int); CREATE TABLE TEST=# \d+ tb3; Table "PUBLIC.TB3" Column | Type | Modifiers | Storage | Stats target | Description --------+---------+-----------+---------+--------------+------------COL | INTEGER | | plain | | 使用标识符时候: TEST=# create table "tb4"("col" int); CREATE TABLE TEST=# \d+ tb4; Did not find any relation named "tb4". TEST=# \d+ "tb4"; Table "PUBLIC.tb4" Column | Type | Modifiers | Storage | Stats target | Description --------+---------+-----------+---------+--------------+------------col | INTEGER | | plain | | TEST=# create table tb5("create" int); CREATE TABLE TEST=# \d+ tb5; Table "PUBLIC.TB5" Column | Type | Modifiers | Storage | Stats target | Description --------+---------+-----------+---------+--------------+------------create | INTEGER | | plain | 2.4 字符和字符集 2.4.1 乱码或无效字符编码 | 问题描述: • 问题 1:为什么界面有时会显示中文乱码? • 问题 2:终端查询类似“invalid byte sequence for encoding “utf8”: 0xd0 ” 报错 • 问题 3:应用报错“com.kingbase8.util.KSQLException: 错误: 无效的”GBK” 编码字节顺序: 0xe8” 13 第 2 章 SQL 类 分析与解决方法: 1. client_encoding 与 server_encoding 之间不一致,在存储或读取数据时,会自动进行转换,不会有乱码问 题。 2. 问题 1、2 主要是显示问题,比如客户端的字符集 client_encoding 与工具的字符集(如 SecureCRT)不一 致。这种情况影响的只是显示,而不影响数据存储。 3. 对于问题 3, 可以“看下驱动是否支持连接参数 bytestype,指定 bytestype=bytea”,或者在插入数据时 强制类型转换。 几种字符编码: 1. 查看操作系统的编码 env | grep LANG 2. show server_encoding 查看数据库编码,一般与环境变量 LANG 相同,除非手动设置。 3. show client_encoding 查看客户端编码 2.4.2 全角字符支持 问题描述: 用户应用开发不规范,SQL 中间掺杂全角字符,比如“,”。 分析与解决方法: V9 对于中文符号进行部分兼容,其中包括全角逗号、空格等。如: 2.5 分区表 2.5.1 如何创建一个间隔分区 问题描述: 如何使用 SYS_PATHMAN 创建间隔分区 分析与解决方法: 尤其特别注意红色部分参数设置 CREATE TABLE range_rel ( id SERIAL PRIMARY KEY, dt TIMESTAMP, 14 第 2 章 SQL 类 txt TEXT); INSERT INTO range_rel (dt, txt) SELECT g, md5(g::TEXT) FROM generate_series('2015-01-01', '2015-04-30', '1 day'::interval) as g; set ora_func_style = false; SELECT create_range_partitions('RANGE_REL', 'DT', '2015-01-01'::DATE, '1 month'::INTERVAL); CREATE_RANGE_PARTITIONS ------------------------4 (1 row) TEST=# \d+ RANGE_REL; Table "PUBLIC.RANGE_REL" Column | Type | Modifiers | Storage | Stats target | Description --------+-----------------------------+--------------------------------------------------------+----------+-------------+-----------ID | INTEGER | not null default NEXTVAL('RANGE_REL_ID_SEQ'::REGCLASS) | plain | | DT | TIMESTAMP WITHOUT TIME ZONE | | plain | | TXT | TEXT | | extended | | Indexes: "RANGE_REL_PKEY" PRIMARY KEY, BTREE (ID) Child tables: RANGE_REL_1, RANGE_REL_2, RANGE_REL_3, RANGE_REL_4 2.6 MySQL 兼容 2.6.1 group by 操作 问题描述: KES 数据库 group by 操作与 mysql 结果不同 分析与解决方法: MySQL 的 group by : MySQL 支持 selectlist 中非聚集列可以不出现在 group by 中。sql 标准是必须出现在 group by 中, 如:select col1, col2 from tab group by col1; kingbase 为兼容 mysql,设置了个参数 ql_mode 参数,目前 只支持 ONLY_FULL_GROUP_BY 选项。如果 sql_mode 中不包含 ONLY_FULL_GROUP_BY,group by 语句 15 第 2 章 SQL 类 可以不符合 sql 标准。 也就是与 mysql 结果相同。 2.6.2 MySQL date_format 改写 问题描述: KES 是否有类似 MySQL 的 date_format 日期格式函数 分析与解决方法: • Mysql:select date_format(CURRENT_TIMSTAMP,‘%Y-%m-%d %H:%i:%s’) • KES:select to_char (CURRENT_TIMSTAMP,‘yyyy-mm-dd hh24:mi:ss’) 2.7 数据库对象 2.7.1 视图源定义信息为啥和创建的语句不一样 问题描述: 视图源定义信息是存在 pg_description.description 列中,这里有的和创建语句一致,有的不一致。 分析与解决方法: 这个和视图的状态有关。下面是获取视图定义的信息规则: • 有效视图:通过 Sys_rewrite 规则 query 查询树,反解析 query 查询获得视图的定义信息。 • 无效视图:直接通过 pg_description.description,得到定义信息 16 第 2 章 SQL 类 获取视图定义:查询 sys_get_viewdef(reloid),如下例子 TEST=# create force view vtest as select * from test; WARNING: View created with compilation errors CREATE VIEW TEST =# select sys_get_viewdef('VTEST'::regclass); PG_GET_VIEWDEF --------------------select * from test; 2.7.2 共有同义词和私有同义词有什么区别 问题描述: 创建同义词,报错如下:ERROR: missing or invalid synonym identifier,the current default schema is public 分析与解决方法: KES 同义词分为两类:公有同义词,在 public 模式下;私有同义词,在其他模式下。当创建同义词时,如果是 建在 public 模式下,则必须加 public 关键字,否则报错。 test=# select current_user; current_user -------------system (1 row) test=# show search_path; search_path ----------------"$user", public (1 row) test=# create synonym ps_t2 for t2; ERROR: missing or invalid synonym identifier,the current default schema is public test=# create public synonym ps_t2 for t2; CREATE SYNONYM test=# drop synonym ps_t2; ERROR: synonym "ps_t2" does not exist test=# drop public synonym ps_t2; DROP SYNONYM 注意: 这里是参照 oracle 模式来的,oracle 用户即模式,所以私有同义词在用户名模式下。 17 第 2 章 SQL 类 2.7.3 同义词查找规则 问题描述: 用户查找同义词的先后规则 分析与解决方法: KES 实际根据 Search_path 的先后顺序查找用户模式,可以通过设置 search_path,影响搜索的先后顺序。 Oracle:—> 私有同义词—> 共有同义词 Kes:—>search_path 这里为了和 oracle 查询一致,可以将 search_path 改成用户模式,PUBLIC(用户模式在前,PUBLIC 在后,一 般兼容 oracle 情况,也是采取的先用户模式再 public 模式) 2.7.4 Nextval 在同一条语句中的值 问题描述: oracle 序列 nextval 在同一条语句中是一样的值,KES 却是增长的值 分析与解决方法: 这个和 ora_func_style 参数有关,ora_func_style 为 true 的时候兼容 oracle 序列风格,如下验证: TEST=# show ora_func_style ; ora_func_style ---------------on (1 row) TEST=# select serial.nextval, serial.nextval; NEXTVAL | NEXTVAL ---------+--------116 | 116 (1 row) TEST=# set ora_func_style = false; SET TEST=# select serial.nextval, serial.nextval; NEXTVAL | NEXTVAL ---------+--------118 | 119 (1 row) 18 第 2 章 SQL 类 注意: 对于 R6 版本,没有 ora_func_style 参数,如果 database_mode=oracle,表示兼容 oracle 模式,在一条 SQL 内,nextval 值也是相同的。 2.7.5 序列的 cache 问题描述: 为什么我的序列 SERIAL 列的编号存在间隙?为什么在事务异常终止时我的序列号没有被重用?为什么不同会 话不同会话间 nextval 差距很大? 分析与解决方法: 为了提高并发性,每个会话会按照序列的 cache 参数大小,在用户的私有内存空间缓存一定数量的序列值。在服 务器关闭(stop fast)或会话退出时,会丢弃会话缓存的序列值,因此,序列值会出现跳跃。 注意: 如果要保证序列的取值不出现跳跃,保证不同会话间的取值完全按时间顺序的,可以设置 cache 0。但无论如 何事务 rollback,序列值是不能重用的。 2.8 数据库版本 2.8.1 查询版本 问题描述: 如何查询版本的提交号 分析与解决方法: Select build_version(); 注意: build_version 函数实际是 kingbase_version 插件生成的 19 第 2 章 SQL 类 2.9 用户管理 2.9.1 能为模式指定表空间吗? 问题描述: 能为模式指定表空间吗? 分析与解决方法: 创建用户或 schema 时,都不支持指定表空间,一般只有数据库和表能够指定表空间。 2.9.2 丢失了数据库密码,如何恢复? 问题描述: 丢失了数据库密码,如何恢复? 分析与解决方法: 无法恢复密码,但是,你可以将其重置为其他密码。为此,你可以用如下方式重置密码 1. 编辑 sys_hba.conf 以暂时允许信任授权 (trust) 2. 重新加载配置文件(重新加载 sys_ctl) 3. 连接并通过 ALTER ROLE PASSWORD 设置新密码 4. 再次编辑 sys_hba.conf 并恢复之前的设置 5. 再次重新加载配置文件 2.9.3 指定表空间 问题描述: 表在指定表空间,为何显示为默认表空间? 分析与解决方法: 1. 创建表空间 create tablespace testtb location ’/home/kingbase/KingbaseES/tb_dir’; 2. 创建数据库指定表空间 create database testtb tablespace ’TESTTB’; 3. 在数据库里创建表,且已存储到创建的表空间里 create table test2 (A int); 4. 查询物理存储 select sys_relation_filepath(’test2’); SYS_RELATION_FILEPATH ----------------------------------------------------sys_tblspc/32785/SYS_V008R002_201608131/32786/32793 20 第 2 章 SQL 类 5. 使用工具查看表空间显示错误,显示为默认表空间 6. 工具使用 select TABLESPACE from sys_tables where tablename = 'TEST2'; TABLESPACE -----------(1 row) 解答: 表的表空间显示 0 或空表示其表空间为所在库的表空间,也就是 TEST2 表默认为的表空间和 TESTTB 库 一致,表空间为 TESTTB。 可以通过以下方式看到表的真实表空间: TESTTB=# select TABLESPACE_NAME from user_tables where table_name = 'TEST2'; TABLESPACE_NAME ----------------------------database default tablespace (1 row) 2.10 OID 与 CTID 2.10.1 OID 问题描述: 什么是 OID? 分析与解决方法: • 如果使用 WITHOIDS 创建表,则每一行都包含一个 OID 伪列,该列将在 INSERT 期间自动填充。OID 被顺 序分配 4 字节整数。最初,它们在整个安装过程中都是唯一的。但是,OID 计数器大约为 40 亿个,此后可能 会重复 OID。 • 通过在 OID 列上创建唯一索引,可以防止单个表中的 OID 重复(但请注意,WITH OIDS 子句本身不会创建 此类索引)。系统检查索引以查看是否已经存在新生成的 OID,如果存在,则生成新的 OID。重复该操作,直 至满足唯一约束。因此,如果表内的数据已经很多,整个过程是非常低效的。 • 要对用户表中的行进行唯一编号,最好使用 SERIAL 而不是 OID 列,如果期望该表在其整个生命周期中拥有 超过 20 亿个条目,则最好使用 bigserial。 21 第 2 章 SQL 类 2.10.2 CTID 问题描述: 什么是 CTID? 分析与解决方法: • CTID 通过表中的块和偏移位置来标识特定的物理行。 • 索引条目使用它们来指向物理行。 • 行的 CTID 在更新时会更改,因此 CTID 不能用作长期行标识符。 • 格式 (blockid,itemid):拿其中 (0,1) 来说;0 表示块 id;1 表示在这块第一条记录。 2.11 数据库管理 2.11.1 数据库大小限制 问题描述: 行,表和数据库的最大大小是多少? 分析与解决方法: 以下这些是限制: • 数据库的最大大小?无限(存在 32 TB 数据库) • 表的最大尺寸?32 TB • 一行的最大大小?400 GB • 字段的最大大小?1 GB • 表中的最大行数?无限 • 表中的最大列数?250-1600,取决于列类型 • 一个表上的最大索引数?无限 当然,这些实际上并不是无限的,而是限于可用的磁盘空间和内存/交换空间。当这些值变得异常大时,性能可 能会受到影响。 最大表大小为 32 TB,不需要操作系统提供大文件支持。大表存储为多个 1GB 文件,因此文件系统大小限制并 不重要。通过将默认块大小增加到 32k,最大表大小,行大小和最大列数可以增加三倍。也可以使用表分区来增加最 大表大小。 一个限制是不能在长度超过 2,000 个字符的列上创建索引。最好通过长列的 MD5 哈希的函数索引来保证唯一 性,并且全文索引允许在列中搜索单词。 22 第 2 章 SQL 类 注意: 如果存储的表中的行大小超过 2KB(每行中数据的总大小),则“表中的最大行数”可能限制为 40 亿或更 少。 2.11.2 KES 数据页结构 问题描述: 数据行存储需要哪些额外的空间? 分析与解决方法: 例如,考虑一个 100,000 行的文件,每行有一个整数和文本描述。假设文本字符串的平均长度为二十个字节。文 件大约为 2.8MB。包含此数据的 kingbase 数据库文件的大小估计为 5.2 MB 每行 52 个字节: • 24 字节:每行头(大约) • 24 个字节:1 个 int 字段和 1 个文本字段 • – 4 个字节:页面上指向元组的指针 kingbase 中的数据页大小为 8192 字节(8KB),因此:每个数据库页面 8192/52=158 行(四舍五入)。注意, 这里假设 fillfactor 是 100%。 大约需要 633 个数据库页面(向上舍入) 633 个数据库页面 * 每页 8192 字节 = 5,185,536 字节(5.2 MB) 索引不需要那么多的开销,但是确实包含要建立索引的数据,因此它们也可能很大。 NULL 存储为位图,因此它们使用的空间很小。 注意: 大字段可能会透明压缩 2.12 COPY 命令 2.12.1 如何将数据从客户端通过 copy 命令导入数据库 适用版本:所有 问题描述: 如何将数据从客户端通过 copy 命令导入数据库 23 第 2 章 SQL 类 分析与解决方法: 通过 copy 导入数据,要求数据在数据库服务器上,如果数据在客户端机器上,需要用 \copy 2.13 其他错误 2.13.1 命令报参数错误问题 问题描述: 命令正确,却报奇怪的错误 分析与解决方法: 用户命令格式报错,但实际命令是正确的。如下: $sys_restore -U system -d test test.dmp sys_restore:error:toomanycommand-line arguments ("first is system") 原因分析:命令内部包含非法字符。这种问题原因很难排查,需要使用时注意。 2.13.2 Failed to find conversion function from UNKNOWN to TEXT 问题描述: 分析与解决方法: 升级到 190 之后或 160 之前的版本。 24 第 2 章 SQL 类 2.14 函数 2.14.1 To_date 函数问题 问题描述: to_date 函数显示结果与 oracle 不一致 分析与解决方法: 系统除 pg_catalog 下有 to_date 函数外,组件 kdb_oracle_datatype 也会在 sys 用户下创建 to_date 函数,二 者返回值是有区别的。默认调用的是 sys 用户下的。 具体例子如下: 2.14.2 如何改变 sys_guid() 返回值类型 问题描述: sys_guid 函数默认返回的是 16 进制的串的 ascii 编码,通过修改参数 guid_default_return_type=name,可以 返回 16 进制字符串,但修改参数时,会发现参数实际已修改,但没效果。 分析与解决方法: 以上问题是由于修改过程没有运行 alter_sys_guid() 函数导致的。修改过程如下: • 修改参数 guid_default_return_type; • 重启数据库; 25 第 2 章 SQL 类 • 执行 select alter_sys_guid()。这个实际是重建 sys_guid() 函数,根据参数 guid_default_return_type 决定是 调用 sys_guid_bytea,还是调用 sys_guid_name。 Alter_sys_guid 函数的内容: begin select setting into return_type from sys_catalog.sys_settings where name = 'guid_default_return_type'; if lower(return_type) = 'bytea' then stmt = 'DROP FUNCTION IF EXISTS sys_catalog.sys_guid(); CREATE OR REPLACE INTERNAL FUNCTION sys_catalog.sys_guid() RETURNS BYTEA AS $$SELECT sys_catalog.sys_guid_bytea()$$ LANGUAGE sql;'; else stmt = 'DROP FUNCTION IF EXISTS sys_catalog.sys_guid(); CREATE OR REPLACE INTERNAL FUNCTION sys_catalog.sys_guid() RETURNS NAME AS $$SELECT sys_catalog.sys_guid_name()$$ LANGUAGE sql;'; end if; end; 注意: 对于 R6 版本,没有 alter_sys_guid,需要手动修改创建脚本。 2.14.3 时间函数问题 问题描述: 为什么有的时间函数在同一事务内返回的都是同一值? 分析与解决方法: KES 的认为返回事务开始时间点的时间有利于保证同一事务的多个修改保持同样的时间戳。这点与 oracle 机制 不同,oracle 默认返回命令执行时间点的时间戳。实际上 KES 同时提供了两类函数: • 以下函数返回事务开始的时间戳: transaction_timestamp() now() • 以下返回语句执行时的时间戳 statement_timestamp() clock_timestamp() timeofday 26 第 2 章 SQL 类 2.15 数据类型 2.15.1 字符串类型长度怎么获取 问题描述: 字符串类型长度怎么获取。 分析与解决方法: 对于字符类型数据,pg_attribute.attlen 值为 -1。字符串类型长度是 abs(atttypmod) –4。 2.15.2 Pg_relation_size 问题 问题描述: pg_relation_size 是否包含 clob 等大字段大小 分析与解决方法: 不包含行外存储的数据段大小。pg_relation_size 是根据 schema.relname 取得表的 relfilenode,从而确认表大 小。不包括 reltoastrelid。 系统包 2.16 2.16.1 dbms_metadata 包获取对象的定义信息 问题描述: 获取对象的定义信息。 分析与解决方法: V9 提供了类似 oracle dbms_metadata 的包,用于获取对象的定义信息。 test=# select dbms_metadata.GET_DDL('table','t1'); get_ddl -------------------------CREATE TABLE PUBLIC.T1( + ID INTEGER + ) + test=# select dbms_metadata.get_index_ddl('ind_t1','public'); get_index_ddl 27 第 2 章 SQL 类 --------------------------------------------------CREATE INDEX ind_t1 ON public.t1 USING btree (id)+ 2.17 系统视图 2.17.1 sys_class 里显示的 RELTABLESPACE 值为 0? 问题描述: 为什么 sys_class 里显示的很多表的 RELTABLESPACE 值为 0? 分析与解决方法: 数据库创建时,可以指定表空间,如果没有指定数据库表空间,数据库默认表空间是 SYS_DEFAULT 用户创建表时,如果没有指定表空间,则默认放在数据库所在的表空间,此时 RELTABLESPACE 显示为 0。 也就是说 RELTABLESPACE = 0 表示 relation 所在的表空间是 sys_database.DATTABLESPACE . 2.17.2 KES 有什么办法,默认不读取 sys_catalog 下的系统视图? 问题描述: 客户业务表 sys_user 和咋们系统视图 sys_user 重名,客户反馈 SQL 中不能加模式名,URL 加上 currentSchema 本地也试了不行。开发不愿意改代码只接受 select * from sys_user 这么直接查 分析与解决方法: 当 Search_path 参数不含“sys_catalog”时,在查询时,会自动将“sys_catalog”加在 search_path 最前面, 这样,在有同名对象情况下,默认优先访问“sys_catalog”下的对象。 修改 kingbase.conf 中的 search_path=’”$USER”,PUBLIC,SYS_CATALOG’,修改以后重启数据库就可以了 (并 java 配置:嗯,URL 中不加 currentSchema 测试可以了) 2.18 SQL 优化 2.18.1 全表 update 非常慢 问题描述: 全表关联 update 时,效率非常低 分析与解决方法: 28 第 2 章 SQL 类 请看以下两种 update 方法。方法一采用 loop 方式,效率非常低。而方法二采用 hash 方式进行连接,效率高。 2.19 索引 2.19.1 索引问题导致数据访问问题 问题描述: 系统在进行压力测试,同时系统主备切换。主备间采取异步方式 问题现象: 可以看到,根据条件返回的记录数据与 where 条件不匹配。这 3 个条件是主键。 29 第 2 章 SQL 类 分析与解决方法: 解决方案:rebuild index 原因分析: 1. 这条 SQL 采取的是索引访问; 2. 根据索引取得两个 ctid,再根据 ctid 取得数据; 3. 通过访问表记录的 xmax ,确定记录是有效的(未被删除); 4. 问题 1:为什么索引 entry 的值(4,3,2521)与 table tuple(7,5,998)值不一致?索引通过 ctid 与 table tuple 关联,当索引异常时,就可能出现该问题。 5. 问题 2:既然是主键,索引 entry 为什么会出现两个 entry?索引是没有有效性判断的,需要访问表进 行判断,也就是说就算索引存在两个相同 entry,理论上通过 tuple 有效判断后最多只能留 1 条。 30 第 3 章 PLSQL 类 3 第 章 PLSQL 类 3.1 PLSQL 存储过程 3.1.1 KES 创建过程,报错:PL/SQL block not end correctly 问题描述: KES 创建过程,报错:PL/SQL block not end correctly 分析与解决方法: 在使用 ORACLE 方法创建 PLSQL 函数时候,需要先设置好 SQLTERM 结束符。如: CREATE OR REPLACE PROCEDURE proc1() AS BEGIN raise notice 'call proc1'; END; 报错:PL/SQL block not end correctly 正确执行方式: \set SQLTERM / --设置结束符 CREATE OR REPLACE PROCEDURE proc1() AS BEGIN raise notice 'call proc1'; END; / 3.1.2 如何调用含 out 参数的存储过程 问题描述: 如何调用含 out 参数的存储过程 31 第 3 章 PLSQL 类 分析与解决方法: 对于 out 参数的过程,只能在 block 里调用,而且必须传入参数。 declare v_retcode text; v_id integer; begin CALL proc1(v_id, v_retcode); end; / 3.2 PLSQL 函数 3.2.1 函数变量不能超过 512 问题描述: 使用 block,function, procedure 时,可能会遇到如下错误: ERROR:ANONYMOUS BLOCK has more than 512 arguments。 分析与解决方法: 这是由于参数个数超过了 512,需要修改代码。参数 max_function_args 默认是 512,无法修改。 3.3 控制语句 3.3.1 Savepoint 使用问题 问题描述: Savepoint 使用问题 分析与解决方法: V9 不支持在 PLSQL 块使用,以下不行: begin insert into t1 values(1); savepoint sv1; insert into t1 values(1,'a'); exception 32 第 3 章 PLSQL 类 when others then rollback to sv1; end; 只能在事务块内使用: begin; insert into t2 values(1); savepoint sv1; insert into t2 values(2); rollback to sv1; insert into t2 values(3); commit; 3.3.2 For 循环变量 问题描述: 在创建 procedure 时,会有如下错误: reate or replace procedure plpgsql_proc() as $$ begin for i in select regexp_split_to_table('ab,bc,cd',',') loop raise notice '%',i; end loop; end; $$ language plpgsql; ERROR: LINE 4: loop variable of loop over rows must be a record variable or list of scalar variables for i in select regexp_split_to_table('ab,bc,cd',',') loop 分析与解决方法: 以上的写法实际是 plsql 的语法,对于 R6 版本的 database_mode=pg,R3 版本大小写不敏感的环境,执行块时 默认是 plpgsql 编译器。因此,以上写法是报错的。 必须先定义循环变量。 create or replace procedure plpgsql_proc() as $$ declare v_text text; begin for v_text in select regexp_split_to_table('ab,bc,cd',',') loop 33 第 3 章 PLSQL 类 raise notice '%',v_text; end loop; end; $$ language plpgsql; 3.4 PLSQL 数据类型 3.4.1 Create operator(bool 与整型比较) 问题描述: 对于整数类型数据与 bool 类型进行比较时,要么转换报错,要么结果错误。具体问题如下例: 分析与解决方法: 创建 operator ,具体脚本如下: create or replace internal function sys_catalog.bool_eq_numeric(bool,numeric) returns bool as $$ select $1:: numeric = $2; $$ language sql; create operator sys_catalog.= (procedure = bool_eq_numeric,leftarg = bool,rightarg = numeric,commutator = =); create or replace internal function sys_catalog.numeric_eq_bool(numeric, bool) returns bool as $$ select $1 = $2::numeric; $$ language sql; create operator sys_catalog.= (procedure = numeric_eq_bool,leftarg = numeric,rightarg = bool,commutator = =); 34 第4章 参数相关 4 第 章 参数相关 4.1 Kingbase.conf 与 kingbase.auto.conf 参数文件 问题描述: Kingbase.conf 与 kingbase.auto.conf 这两个参数文件的读取先后、优先级 分析与解决方法: 1) 对于 kingbase.conf 与 kingbase.auto.conf 文件,如果有相同条目,则以 kingbase.auto.conf 文件参数值为准(忽 略 kingbase.conf 相同条目)。 2) 读取先后顺序:数据库启动时先读取 kingbase.conf,再读取 kingbase.auto.conf,如果二者相同条目,会忽略 kingbase.conf 文件的相同条目。 3) 所有文件读取完成后,才 apply 参数,由于 kingbase.conf 参数读取在前,kingbase.auto.conf 读取在后,对于 有先后顺序要求的参数必须注意。 举例如下: kingbase.conf 文件有 error_user_connect_times and max_error_user_connect_times 这两个参数,但 是用户又运行了 alter system setmax_error_user_connect_times,相当于在 kingbase.auto.conf 文件增加了 max_error_user_connect_times 条目。当系统启动时,先读取 kingbase.conf 文件,再读取 kingbase.auto.conf 文 件,由于 kingbase.auto.conf 文件也有 max_error_user_connect_times 条目,就会忽略 kingbase.conf 文件中的同 样条目。而 apply 的顺序是按读取先后进行的,当 apply error_user_connect_times (假设 100)参数时,由于还没 apply max_error_user_connect_times(在 kingbase.auto.conf)参数 ,认为 max_error_user_connect_times 值为 默认的 5 ,导致报错。 4.2 不同参数如何生效 问题描述: 为什么有些参数 reload 就可以生效,而有些参数必须重启数据库? 分析与解决方法: 35 第4章 参数相关 修改参数后,如何生效是由 pg_settings.context 值决定的。具体如下: • internal:这些参数是在编译或 initdb 时设定的,不能修改。如:block_size, database_mode • kingbase: 修改这些参数要求重启数据库。如:archive_mode • sighup: 不需要重启数据库,只需 reload 就可生效。Kingbase 会把 sighup 传递给子进程,通知子进程重新读取 配置。如:archive_command • backend: 不需要重启数据库,只需 reload 就可生效,但只影响后续启动的会话。如:log_connections • user: 表示可以在会话中用 set 命令设置。如:bytea_output 4.3 error_user_connect_times and max_error_user_connect_times 问题描述: 为什么数据库启动报错:100000 is outsize the max valid range for parameter ”max_error_user_connect_times” 5,而实际的 max_error_user_connect_times 参数值并不是 5 分析与解决方法: 这两个参数要求先后顺序,max_error_user_connect_times 参数必须放于 error_user_connect_times 前面,否 则会默认为 max_error_user_connect_times 是 5 ,报错。 4.4 Exclude_reserved_words 排除关键字 问题描述: 客户设置 Exclude_reserved_words=’level’,导致 show transaction isolation level 语法错误。 分析与解决方法: 关键字可配置功能实际实现:将原来的关键字配置为非关键字,词法解析到该字符串时,不再将其识别为关键 字,而认为是一个普通的字符串。该功能风险点:排除该关键字,那么语法规则中涉及到该关键字的语法规则都将失 效,甚至出现莫名的错误(以为是关键字,结果识别为字符串,导致语法对应错误,识别为其他语义)。本例中配置 了 level,导致涉及 level 的语法失效。 36 第4章 参数相关 4.5 max_locks_per_transaction 设置过大引发数据库 启动问题 问题描述: 数据库无法启动,报无法分配内存 分析与解决方法: • max_locks_per_transaction: 这 个 参 数 控 制 每 个 事 务 能 够 得 到 的 平 均 的 对 象 锁 的 个 数, 默 认 值 是 64。 数据库在启动以后创建的共享锁表最大可以保存 max_locks_per_transaction * (max_connections + max_prepared_transactions) 个对象锁。每个锁空间需预留 270 个字节的共享内存。单个事务可以同时获 得的对象锁的数目可以超过 max_locks_per_transaction 的值,只要共享锁表中还有剩余空间。 • max_connections(integer):这个参数只有在启动数据库时,才能被设置。它决定数据库可以同时建立的最大的 客户端连接的数目。默认值是 100。每个连接占用 400 字节共享内存。 注意: Increasing max_connections costs ~400 bytes of shared memory per connection slot, plus lock space (see max_locks_per_transaction). • 用户将 max_locks_per_transaction 值设置 为 215927809,导致系统启动时要求分配 215927809 * 270 * 1000(max_connections)= 54TB 的内存空间,数据库启动失败 4.6 max_identifier_length 问题描述: 对象名称能否超过 63 字符? 分析与解决方法: 参数 max_identifier_length 决定最大的对象名称长度,该参数只能在编译时指定,不能修改。默认是 63。对 于汉字表名,根据编码的不同,一个汉字占 2-3 字符。 4.7 数据库启动失败,报“内存段超过可用内存” 问题描述: 数据库启动报内存不足,错误信息如下: 37 第4章 参数相关 分析与解决方法: • 原因 1:实际物理内存不够 • 原因 2:swap 与 shared_buffers 相差过大,如以上例子,Swap 才配置 2G,而 Shared_buffers 16G • 原因 3:系统参数设置过小 • 原因 4:启用了大页,但是大页内存却不够。数据库参数 huge_pages = on,表示数据库启动时只能用大页。如 果操作系统大页内存设置过小,数据库就无法启动 • 原因 5:数据库参数设置不合理。除了内存相关的参数,如 shared_buffers 外,还有其他参数也会要求内存段: max_connections, max_prepared_transactions 都会影响内存段的分配。还有 max_locks_per_transaction 参 数,每个需要 270 字节的内存。 38 第 5 章 LICENSE 相关 5 第 章 License 相关 5.1 查询 license 有效时间 问题描述: 如何查询 license 有效时间 分析与解决方法: TEST=# select get_license_validdays (); GET_LICENSE_VALIDDAYS ----------------------24 (1 row) SELECT get_license_validdays(); 5.2 如果返回值为 -2 ,表示永久 license 查询 V8R3 license 完整信息 问题描述: 如何查询 license 完整信息 分析与解决方法: TEST=# select get_license_info(); GET_LICENSE_INFO ----------------------------------------------------------------License 序列号 --- 启用 --- 6AB57220-864E-11EA-AA4F-000C2937A8A8 生产日期 --- 启用 --- 2020-04-25 39 第 5 章 LICENSE 相关 产品名称 --- 启用 --- KingbaseES V9 细分版本模板名 --- 启用 --- TEST 人大金仓内部测试 产品版本号 --- 启用 --- V008R003 浮动基准日期 ------ 启用 有效期间 --- 启用 --- 30 CPU 检查 --- 启用 --- 0 MAC 地址 --- 启用 --- 00:00:00:00:00:00 最大连接数 --- 启用 --- 0 数据同步 --- 启用 --- 0 物理同步 --- 启用 --- 0 增量备份恢复 --- 启用 --- 0 集群对网络故障的容错 --- 启用 --- 0 集群配置工具 --- 启用 --- 0 读写分离模块 --- 启用 --- 0 保密通讯协议 --- 启用 --- 0 审计 --- 启用 --- 0 三权分立 --- 启用 --- 0 密码复杂度 --- 启用 --- 0 用户锁定 --- 启用 --- 0 运行状态分析 --- 启用 --- 0 滚动升级 --- 启用 --- 0 恢复到指定时间点 --- 启用 --- 0 快速加载 --- 启用 --- 0 40 第 5 章 LICENSE 相关 日志压缩 --- 启用 --- 0 全文检索 --- 启用 --- 0 健康检查 --- 启用 --- 0 并行查询 --- 启用 --- 0 并行备份还原 --- 启用 --- 0 日志解析 --- 启用 --- 0 异构数据源 --- 启用 --- 0 透明加密 --- 启用 --- 0 强制访问控制 --- 启用 --- 0 (1 row) 注意: V9 没有该函数 5.3 查询 V8R3 license 单项信息 问题描述: 如何查询 V8R3 license 单项信息 分析与解决方法: TEST=# select \* from substring(get_license_info() , instr(get_license_info(), 'MAC 地址'), instr(get_license_info(), '最大连接') - instr(get_license_info(), 'MAC 地址') - 1); SUBSTRING ---------------------------------------MAC 地址 --- 启用 --- 00:00:00:00:00:00 41 第 5 章 LICENSE 相关 (1 row) 5.4 替换 license 步骤 适用版本:V8R3 ,V9 替换过程: 第一步,登录服务器,执行:find -name license.dat,看 license.dat 在哪些路径。 第二步:把上一步找到的路径记录下来。 第三步,根据上一步的路径把原有 license.dat 重命名为 license.dat_old 或者其他名字 第四步:把新的 license.dat 传到服务器,重命名为 license.dat,并且执行 chown -R kingabse:kingbase license.dat(用什么用户安装的用户权限给到哪个用户) 第五步,执行 su -kingbase 切换到 kingbase 用户,把最新的 license 拷贝到第二步记录下来的路径。 最后一步:重启数据库:sys_ctl restart -D /home/kingbase/KingbaseES/V9/data(备注:每个地方 data 路径可能不一样,通过 ps -ef 查找出带-D 的进程,确定准确的 data 路径) 5.5 替换 license 是否要重启数据库 问题描述: 替换 license 是否要重启数据库 分析与解决方法: 可以不必重启数据库,可以在任一 system 用户连接上执行 select sys_reload_conf(),退出重登录后就可以看到 变更生效。或者 kill -1 kingbase 主进程号的方式,也可以重新加载 license 信息。 5.6 如何判断 license 有效 问题描述: 替换了 license 后还是显示授权过期,更换另一个 license 就正常。 分析与解决方法: 更换的 license 需要比较以下几点: 42 第 5 章 LICENSE 相关 1、 版本是否相同,包括:产品版本号、细分版本模板名。不同版本 license 不通用。 2、 数据库 key 值。如果换了 license,但 key 值还是与原来相同,实际是同一个 license 文件,也就是实 际没换。 3、 如果“浮动基准日期”是禁用的状态,到期日是“生产日期”+“有效期间”。如果“浮动基准日 期”是启用的,到期日是 license 更换日期 +“有效期间”。 4、 License 例子如下: 5.7 V8R3 License 与网卡 问题描述: 为什么部分 R3 版本无法识别 bond 开始的网卡? 分析与解决方法: 43 第 5 章 LICENSE 相关 V8R3 B0261 版本解决了网卡问题,可以识别所有网卡,而之前的版本只能识别 e 开头(不仅是 eth 开头的)的 网卡。 5.8 Bond 网卡切换 license 支持问题 问题描述: Bond 网卡切换 license 是否支持 分析与解决方法: 早期的 license 只提供一个 license,如果网卡切换或者网卡更换 44 第6章 扩展组件 6 第 章 扩展组件 6.1 查看系统是否支持某组件 问题描述: 如何查看系统是否支持某组件 分析与解决方法: KES 与原生 PG 不同,许多开源的组件不能直接在 KES 上使用,需要研发针对特定平台重新编译。如果用户想 知道当前的版本自带或支持哪些组件,只需查询 sys_available_extensions 6.2 create extension oracle_fdw 报.so 找不到加载失败 问题描述: create extension oracle_fdw 报.so 找不到加载失败 分析与解决方法: 依赖 oracle 官方 instantclient-basic-linux.x64-11.2.0.4.0.zip,目前推荐使用 11.2 版本,其他版本可能跟操作系统 存在兼容问题,解决方法根据现场选择以下之一。 方法 1(当机器上安装了 >11.2 的 instantclient 时推荐使用): 解压后将 so 拷贝到 kingbase 安装后的 lib 目录下 方法 2(当机器上没有安装过 instantclient 时选用): 解压到/usr/lib/路径下后执行 ldconfig 6.3 Sys_pathman 问题描述: 45 第6章 扩展组件 pathman_config、pathman_config_params 删除后,如何重建? 分析与解决方法: pathman_config、pathman_config_params 这两个表是 sys_pathman 插件的表,想找回来可以 drop extension 之后再 create extension; extension。 6.4 Separate_power 问题描述: 需要开启审计日志,没有 SYSSAO 和 SYSSSO 用户,有什么解决办法吗 分析与解决方法: create extension Separate_power 6.5 Sysaudit 问题描述: 如何删除语句审计日志? 分析与解决方法: 语句审计日志可以通过视图 sysaudit.sysaudit_records 查询。如果要删除语句审计记录,只需将移除 $KINGBASE_DATA/aud 目录下的文件。 46 第7章 空间组件 7 第 章 空间组件 7.1 Create extension postgris 报错“GLIBC_2.18 not defined in file libc.so.6” 问题描述: create extension postgis,报错如下:无法加载库“postgis-2.5.si”: Server/ lib/ libstdc+ +.si.6: symbol __cxa_thread_atexit_impl, version GLIBC_2.18 not defined in file libc.so.6 with link time reference 分析与解决方法: 1) lddServer/lib/libstdc++.si.6 ,确认动态链接操作系统的 libc.so.6 2) strings libc.so.6 | grep GLIBC | more , 看到最高只到 GLIBC_2.17,也就是说操作系统自带的 gcc 版本不支持 postgis-2.5。经验证,操作系统的 gcc 版本是 4.8.5,而我们的编译环境的 gcc 版本是 5.3.1,需要升级操作系统 的 gcc 版本或根据底版本的 gcc 重新编译。 7.2 acgis 版本备份还原 问题描述: acgis 备份还原因权限问题报错 分析与解决方法: acgis 备份还原不可将用户权限忽略,否则可能发生 acgis 空间信息错乱,导致备份还原后 acgis 无法连接数据 库。 注意: sys_restore 时候,千万不可带-x 参数。 47 第7章 空间组件 7.3 V9 是否支持超图 问题描述: V9 是否支持超图 分析与解决方法: R6 支持超图 10.1.1 连接,但前提是必须要有 postgis 组件。 48 第 8 章 数据库运行管理 8 第 章 数据库运行管理 网线拔插后,IP 丢失问题 8.1 问题描述: 手动拔掉网线,发现 IP 丢失,重新插入网线后,虽然网卡处于 UP 状态,但任然无法获得 IP,需要手动运行 ifupeth0 分析与解决方法: 如果禁用 NetworkManager 服务,发现网线拔插后,网卡 IP 自动恢复。 注意: 由于部分系统只有 NetworkManager 服务,而没有 Network 服务,如果禁用 NetworkManager 服务,将导致 网络问题。 8.2 [KESV8R2/3] 客服端服务器编码原理说明 服务器存储数据:客户端检查输入的字串是否符合 client_encoding,若符合则发给服务器,否则抛出错误--> 服 务器接受到客户端发过来的字符串及 client_encoding,字符串通过 client_encoding 转 server_encoding,转换成服 务器编码风格--> 以服务器编码风格存入字符串。 客户端取数据数据:数据通过 server_encoding 转 client_encoding,最后发给客户端。 注意: 上面已经说到存是数据通过 client_encoding 转 server_encoding,转换成服务器编码风格并写入系统字典,客 户端取数据是通过 server_encoding 转 client_encoding。然而数据库中存在数据库公有数据字典,这可能导致存取的 服务器 server_encoding 编码不一致,从而数据出错。所以建议用户不要创建中文名用户、中文名数据库以及中文名 的过程语言 (如 plsql)。数据库登录时 server_encoding 并未生效,所以登录时采用的是 Unicode 编码进行数据库名 验证。 49 第 8 章 数据库运行管理 8.3 Bulkload 并行加载报错 问题描述: Bulkload 并行加载报错,ERROR: parallel threads initilization failed 分析与解决方法: bulkload 并行导入数据,需要在数据库的配置文件 kingbase.conf 中修改参数 max_work_threads. 如果没有,添 加到配置文件。 例如:max_work_threads=16 8.4 Windows 版本安装未注册服务 问题描述: windows 版本安装未注册服务 分析与解决方法: 先检查是否安装好了 vcredist _2013(vc 2013 的最小化运行环境)。vcredist 2013 x64 是 windows 系统中非常重要 的运行库文件,这个文件是保证电脑系统正常运行的必备软件,一般用 Visual C++ 开发的 Windows 应用程序需要 这个运行时库的支持才能在没有安装 Visual C++ 的计算机上正常运行 50 第9章 工具类 9 第 章 工具类 9.1 KSQL 9.1.1 客户端连接找 .s.PGSQL.5432 问题描述: 客户端连接报错如下 分析与解决方法: • ksql 连接时,正常会去寻找 .s.KINGBASE.54321 文件,这里却去找 PGSQL 文件,说明了可能相关 lib 干扰 了。 • ldd ksql,确认 libpq.so 是否没有正确指向/opt/kb86/ES/V9/Server/lib 目录,而是指向链接到其他目录。 • 确认 LD_LIBRARY_PATH 环境变量,确实包含第二步所指的“其他目录”。 • 修改 LD_LIBRARY_PATH 环境变量,去除“其他目录”,或者将/ opt/ kb86/ ES/ V9/ Server/ lib 放于 LD_LIBRARY_PATH 最前面 KES 在编译时,会设置 runpath,可以不设置 LD_LIBRARY_PATH 就能找到 lib 目录。但如果设置了 LD_LIBRARY_PATH,LD_LIBRARY_PATH 环境变量所指的路径优先级更高,这时可就会影响到数据库正常运 行。 9.1.2 undefined symbol: PqgssEncInUse 问题描述: 运行 ksql 报错: 51 第9章 工具类 $ ksql -Usystem -dtest -p36521 -h172.16.24.240 ksql (V008R006C002B0016) ksql: symbol lookup error: ksql: undefined symbol: PqgssEncInUse 分析与解决方法: 通常是 LD_LIBRARY_PATH 环境变量设置问题。 9.2 管理工具 9.2.1 客户端管理工具无法加载 ER 图问题 问题描述: 客户端管理工具无法加载 ER 图 分析与解决方法: 以下文件内容取自 ManagerTools/configuration/*/bundles.info 标注的这行,然后删掉 configuration 下,除了 config.ini 和 bundles.info 所在的目录以外的其他目录,再删掉安 装目录下的.kingbase,重启工具。 原因分析: plugin 下每一个 com.kingbase 开头的 jar 包对应着一个插件,加载插件的配置文件就是 bundles.info,现场的环 境没有加载 erd 那个插件,导致 er 图打开失败。 9.2.2 如何修改管理工具 client_encoding 问题描述: 如何修改管理工具 client_encoding 分析与解决方法: manager 连接数据库所使用的 client_encoding 是通过 ManagerTools/manager.ini 设置的。 52 第9章 9.3 迁移工具 9.3.1 迁移工具对于同名对象处理 工具类 问题描述: DTS 从 oracle 迁移数据时,报错同名问题。 分析与解决方法: 对于 oracle,同一 schema 下索引与表可以同名,但 kingbase 不允许。迁移工具在遇到同名时,会报错,需要用 户手动处理。 9.3.2 数据迁移报“invalid byte sequence for encoding ”UTF8”: 0x00 ” 问题描述: 数据迁移报“invalid byte sequence for encoding ”UTF8”: 0x00 ” 分析与解决方法: 0x00 是 ascii 的 0 值,表示 null,通过设置添加参数 ignore_char_null_check=on , 避免空值检查。 9.4 其他问题 9.4.1 开始菜单没有数据库快捷工具图标 问题描述: 正确安装数据库后,切换到 kingbase 用户,开始菜单没有数据库快捷工具图标。/home/kingbase/.local/share/ applications/下也没有快捷方式 分析与解决方法: • 把安装路径下/home/kingbase/ES/V9/desktop 下的文件拷贝到/home/kingbase/.local/share/applications/ 53 第9章 工具类 • 有的版本的操作系统,在安装完数据库软件后,需要注销,重新登录,才能看到开始菜单。 9.4.2 缺少操作系统 GUI 组件 问题描述: KES 以 console 安装报错,unable to load and prepare the installer in console 分析与解决方法: 可能的原因是操作系统图形组件的缺失,需要安装相关组件。 yum install gui yum install gnome yum install xorg 54 第 10 章 数据安全 10章 数据安全 第 10.1 SSL 认证 10.1.1 证书生成 服务器: 1. 确保安装 openssl 2. 在数据库 data 目录下,创建自签名的证书 为服务器创建一个快速的自签名的证书,填充那些 openssl 要求的信息。确保把本地主机名当做” Common Name” 输入;挑战密码可以留空。该程序将生成一个用口令保护的密钥,它不会接受小于四字符的口令。 openssl req -new -text -out server.req 要移去密钥(如果你想自动启动服务器就必须这样),运行下面的命令: openssl rsa -in privkey.pem -out server.key rm privkey.pem 将一个证书变成自签名的证书并复制密钥和证书到服务器将要查找它们的地方 openssl req -x509 -days 3650 -in server.req -text -key server.key -out server.crt 修改文件权限,如果文件的权限比这个更自由,服务器将拒绝该文件。 chmod og-rwx server.key 生成根证书 cp server.crt root.crt 3. 配置 kingbase.conf 文件 打开文件找到如下属性放开注释并修改值 55 第 10 章 ssl = on 数据安全 # (change requires restart) ssl_ca_file = ' root.crt ' # (change requires restart) 4. 配置 sys_hba.conf 文件 打开文件,修改 ipv4 连接 host->hostssl, METHOD 一栏增加 clientcert=1,原有密码认证方式不变,如下所示 # IPv4 local connections: hostssl all all 0.0.0.0/0 md5 clientcert=1 5. 重启数据库服务器 6. 为客户端创建所需证书 生成 kingbase8.key openssl genrsa -des3 -out kingbase8.key 1024 openssl rsa -in kingbase8.key -out kingbase8.key chmod 400 kingbase8.key 生成 kingbase8.csr,CN 需要指定为要连接数据库的用户名,如需匹配不同的用户,可指定为 * openssl req -new -key kingbase8.key -out kingbase8.csr -subj '/C=GB/ST=Berkshire/L=Newbury/ O=Kingbase/CN=SYSTEM' 生成 kingbase8.crt openssl x509 -req -days 3650 -in kingbase8.csr -CA root.crt -CAkey server.key -out kingbase8.crt -CAcreateserial JDBC 额外步骤其他请省略此步骤私钥转 pkcs 格式 生成 kingbase8.pk8 openssl pkcs8 -topk8 -outform DER -in kingbase8.key -out kingbase8.pk8 -nocrypt 10.1.2 证书配置 拷贝出客户端证书文件 kingbase8.crt/kingbase8.key 及 root.crt 放到客户端相应目录。通过参数 sslmode 配置证 书验证方式,该参数支持四个值:disable(禁用 SSL)、require、verify-ca、verify-full。使用 verify-ca 和 verify-full 时,需配置证书位置,支持如下三种方式。 1. 默认路径。windows 默认路径位置为%APPDATA%kingbase,linux 下为 ~/.kingbase/,将客户端证书文件放 入,系统会自动查找。只需指定”sslmode=verify-ca”; 2. 环境变量。通过设置环境变量 PGSSLROOTCERT、PGSSLCERT 、PGSSLKEY 指定证书位置。连接参数同 默认路径。 56 第 10 章 数据安全 3. 绝对路径。通过设置 sslrootcert、sslcert、sslkey 参数指定。使用 verify-ca 常常就可以提供足够的保护。只有 verify-full 模式会对主机名进行验证。 4. 绝对路径连接参数示例 gorm: dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=verify-ca sslrootcert=C:\\Users\\ GBJ-0256\\AppData\\Roaming\\kingbase8\\root.crt sslcert=C:\\Users\\GBJ-0256\\AppData\\Roaming\\kingbase8\\ kingbase8.crt sslkey=C:\\Users\\GBJ-0256\\AppData\\Roaming\\kingbase8\\kingbase8.key",host, port, user, password, dbname) QT: QString connOption="sslmode=verify-ca;sslrootcert=/home/wli/cert/root.crt;sslcert=/home/wli/cert/kingbase8. crt;sslkey=/home/wli/cert/kingbase8.key"; conn.setConnectOptions(connOption); 10.1.3 证书有效期 openssl 默认生成的证书有效期为 30 天,通过-days 参数指定证书有效时间,单位为天。查看证书文件有效期 openssl x509 -in server.crt -noout -dates 10.2 Windows 配置免密登录 问题描述: Windows 如何配置免密登录 分析与解决方法: Linux 通过配置 .kbpass, 用 户 可 以 免 密 登 录 数 据 库。Windows 下, 对 应 文 件 是%APPDATA%kingbasekbpass.conf。文件内容格式: hostname:port:database:username:password 57 第 11 章 TPCC 测试类 第 11章 TPCC 测试类 11.1 autovacuum 参数 问题描述: tpcc 测试中是否需要开启 autovacuum 分析与解决方法: 在 tpcc 运行时间小于 30 分钟的时候禁用该参数,tpcc 测试大于 30 分钟的时候需要开启。 11.2 index_cursor_id 参数 问题描述: index_cursor_id 参数的数值是固定的么? 分析与解决方法: 不是固定的,在 tpcc 测试中需要每次到数据库中查询到该参数的数值,然后配置到参数文件中,查询语句是 select oid from sys_class where relname like' bmsql_new_order_pkey'; 11.3 unixdomain 问题描述: 在 tpcc 测试中 unixdomain 作用是? 分析与解决方法: Unix domain socket 或者 IPC socket 是一种终端,可以使同一台操作系统上的两个或多个进程进行数据通信。与 管道相比,Unix domain socket 既可以使用字节流,又可以使用数据队列,而管道通信则只能使用字节流。 58 第 11 章 TPCC 测试类 Unix domain socket 的接口和 Internet socket 很像,但它不使用网络底层协议来通信。Unix domain socket 的功 能是 POSIX 操作系统里的一种组件。Unix domain socket 使用系统文件的地址来作为自己的身份。它可以被系统进 程引用。所以两个进程可以同时打开一个 Unix domain sockets 来进行通信。不过这种通信方式是发生在系统内核里 而不会在网络里传播。 11.4 集群环境下测试 tpcc 连接参数 问题描述: 集群环境下测试 tpcc 连接参数怎样配置? 分析与解决方法: 集群环境下连接参数和非集群环境一样。 driver=com.kingbase8.Driver conn=jdbc:kingbase8://127.0.0.1:54888/BENCHMARKSQL user=BENCHMARKSQL password=123456 59 第 12 章 接口 12章 接口 第 12.1 JDBC 接口 12.1.1 JDBC 打开日志方式 问题描述: KES 中,JDBC 如何打开日志 分析与解决方法: JDBC 驱动支持控制日志打印级别和日志输出到文件或者控制台。 日志级别:loggerLevel = 日志级别指定日志记录级别。例如:”OFF”, ”INFO”, ”DEBUG”, ”TRACE”,默认值 是 null 即不输出日志。 日志输出:loggerFile = 日志文件名字 指定日志信息保存文件或者 console 输出: 1:如果没有指定 loggerFile,表示不生成 JDBC 日志文件, 日志信息全部打印到当前 console 输出。 2:如果 loggerFile 有指定路径,则只打印到文件。例如:LogFile=e:\logFile.txt,默认值是 null。这个路 径可以是相对路径,也可以是绝对路径。 12.1.2 没有 VIP 情况下 JDBC 连接配置 问题描述: 没有 VIP 情况下,JDBC 连接如何配置? 分析与解决方法: JDBC 驱动通过 IP,端口,数据库名,用户名,密码来连接数据库,没有 VIP 情况下,就配置数据库的集群所 有主机实际的地址。 配置文件的内容在开始配置后不会变更,连接成功后,驱动会给数据库发送查询语句来判断当前配置的主机是否 是主机,不是的话回去更新主备机的记录,但这个是记录在驱动的内部的,不会去写配置文件。 60 第 12 章 接口 jdbc 不支持自带连接池,客户可以使用第三方连接池,如 druid,c3p0,dbcp 等 12.1.3 V9 JDBC 使用 VIP 问题描述: V9 JDBC 能否使用 VIP? 分析与解决方法: 不能使用 vip。 jdbc.conf 文件有 host 和 slave_add 项,表示主、备节点。比如,初始配置 host=VIP,而 VIP 是飘移的, 如果 VIP 飘移到备机,那相当于集群少了一台主机(原主机“不见”了) 12.1.4 LOB 对象 update 机制 问题描述: 应用 SQL:1 条语句,update GA_MSGS set ”MSG_BODY”=$1 where MSG_ID =’$2’。 数据库日志捕获 SQL 为: 大约 50 条,update GA_MSGS set ”MSG_BODY”=$1 where ”CTID”=$2 and ” XMIN”= $3 returning CTID,XMIN; 尝试 ksql 执行 update GA_MSGS set ”MSG_BODY”=$1 where MSG_ID = ’$2’,数据库日志捕获为 1 条 update GA_MSGS set ”MSG_BODY”=$1 where MSG_ID = ’$2’,未发生变化。 是 java 驱动转化了 SQL 语句吗,另外 50 条 update 语句中的 blob 字段参数值,是一个不断增长的过程,每自 动更新下一次,参数值会补充一断新的值。 分析与解决方法: 日志分析: 1、应用没有这种 SQL,是 JDBC 接口自动转换的。 2、每次 update 操作 ”CTID”=$2 and ”XMIN”= $3 参数值 ctid 每次增加 1,xmin 都是相同的。 3、库日志中的 update 语句 blob 参数 $1,目前看着符合规律,继承之前的参数变得越来越长,比如第一 次 a,第二次 ac,第三次 acb,第四次 acbd… 结论: 用 select ... for update,查询大对象,然后用大对象的 set 方法(如 blob.setBytes)设置大对象的值时, 驱动实际执行了一条 update 语句,这条 update 语句是驱动构造的。 因为 R3 的大对象实际是 bytea 和 text,数据都是写在用户表里的,内容都是一次写过去的。 如果应用本身是 update 语句,驱动不会去修改语句,只有通过大对象的方法去写大对象才会生成该语 句。 61 第 12 章 接口 这个 write 方法每次调用一次就会调用 update 语句写一次,Blob 实际是 bytea,没法分片写,所以实际 blob 内容是缓存在本地的,每次添加内容,都会在原来的内容上加上新的内容更新一次。 12.1.5 KBBlob 迁移至 Oracle 问题描述: 用户将 BLOB 从 Kingbase 迁移至 Oracle,报错如下:“kblob cannot be cast to oracle.sql.blob” 分析与解决方法: KBBlob 不支持迁移至 Oracle Blob,只能是 Oracle Blob 迁移至 KBBlob。 12.1.6 JDBC jar 包版本 问题描述: JDBC 的 jar 包需要区分 JDK 版本,需要区分 OS 和 CPU 平台吗? 分析与解决方法: JDBC 目前编译时,是根据 JDK 环境编译的 jar 包。所以请使用时检查应用的 JDK 环境。V92 的 JDBC 驱动 支持 Oracle 1.6,1.7,1.8 和 OpenJDK 1.6,1.7,1.8 兼容度:低版本 JDK 环境编译的 jar 包可以运行在高版本的 JDK 环境下,反之则不行。JAVA 程序编译出来都 是 class 文件的中间码 (运行在 JVM 虚拟机上),不是机器码所以不区分 OS 和 CPU,只区分 JDK 环境。所以正常 来说只需要保证 JDK 的版本匹配即可。 12.1.7 JDBC 的连接参数填写 问题描述: JDBC 的连接参数只能通过 URL 串来填写吗? 分析与解决方法: 不是,除了 ConfigurePath 外,其它也可用配置文件方式。JDBC 的可选的连接串参数是比较多的,当你需要的 参数较多时都写在连接串上显得比较笨拙,为了方便现场人员运维管理,新提供了 JDBC 配置文件的方式来配置参 数。 12.1.8 JDBC 配置文件 问题描述: 如何使用 JDBC 配置文件方式? 分析与解决方法: 62 第 12 章 接口 JDBC 是否使用配置文件,是通过连接串参数 ConfigurePath 控制。当你 ConfigurePath=jdbc.conf 时,会优先 使用配置文件里的参数。如果没有 ConfigurePath 参数,就只使用 URL 连接串中的参数。 12.1.9 JDBC 读写分离的打开和关闭 问题描述: JDBC 读写分离怎么打开关闭? 分析与解决方法: JDBC 是否使用读写分离功能, 通过 USEDISPATCH 控制。USEDISPATCH=true 时就会使用读写分离功能进行 分发。USEDISPATCH=false,或者不写这个参数时,就使用原 JDBC 单机方式。 12.1.10 JDBC 读写分离配置参数 问题描述: JDBC 读写分离都需要配置哪些参数? 分析与解决方法: 一般情况下,只需额外 5 个参数来控制。 # 打开读写分离功能, USEDISPATCH=true # 备机地址 SLAVE_ADD=192.168.8.223,192.168.8.130 # 备机端口 SLAVE_PORT=54321,54321 # 主机读负载率,备机之间轮询平分,取值范围 0-100, 例如 0 表示读语句全部分发备机,100 表示读语句全部发送主机 HOSTLOADRATE=33 # 底层 socket receive 的超时时间 socketTimeout=10 # 是否使用连接池缓存连接 USECONNECT_POOL=false 12.1.11 JDBC 读写分离一主两备的 URL 和配置文件 问题描述: JDBC 读写分离一主两备的 URL 和配置文件的样例 分析与解决方法: 1:只用连接串, 开启 JDBC 读写分离一主两备: 63 第 12 章 接口 URL jdbc:kingbase8://192.168.8.128:54321/TEST?USEDISPATCH=true&SLAVE_ADD=192.168.8.223,192.168.8.130&SLAVE_ PORT=54321,54321&HOSTLOADRATE=33&USECONNECT_POOL=false 2:连接串 + 配置文件, 开启 JDBC 读写分离一主两备: URL jdbc:kingbase8://192.168.8.128:54321/TEST?ConfigurePath=jdbc.conf 配置文件 USEDISPATCH=true SLAVE_ADD=192.168.8.223,192.168.8.130 SLAVE_PORT=54321,54321 HOSTLOADRATE=33 socketTimeout=10 USECONNECT_POOL=false 3:目前读写分离实际项目中用到的配置文件参数样例: # 主机地址 HOST=121.1.20.3 PORT=54321 DBNAME=NPC user=RDWWpom password=RDWW123456 #loggerLevel can be OFF, INFO, DEBUG, TRACE loggerLevel=OFF loggerFile=jdbc_test.log preferQueryMode=extendedForPrepared # 是否使用读写分离功能 USEDISPATCH=true HOSTLOADRATE=33 # 备机地址 SLAVE_ADD=192.168.8.220,192.168.8.221 SLAVE_PORT=54321,54321 # 是否使用连接池缓存连接 USECONNECT_POOL=false CONNECT_POOLSIZE=1 # 在新建连接时检查当前连接 DB 是不是 Master, 如果不是回去 slave 检查有没有 Master, 如果还是找不到 Master 就会向 上报错 MASTER_CHECK=true # 失败重发的最高次数 RETRYTIMES=10 64 第 12 章 接口 # 失败重发每次的间隔时间(单位:秒) RETRYINTERVAL=5 # 开启集群备机监测线程定时监测集群备机状态 CLUSTER_MONITOR=true # 监测线程每次监测的间隔时间(单位:秒) MONITORINTERVAL=5 # 指定底层 socket receive 的超时时间,值可以为任意正整数,“0”表示没有超时,一直等,直到返回,默认取值 为:“0”(单位:秒) #socketTimeout=10 # 指定 Socket 做 connect 时的超时时间,默认取值为:“10”(单位:秒) #connectTimeout=10 12.1.12 JDBC 连接池功能 问题描述: 是否开启连接池,开启后的功能及性能 分析与解决方法: 如果应用已经有了连接池,就不开启 JDBC 连接池,因为连接池需要锁来管理全局队列,高并发建连接会有性 能损耗。 如果应用没有连接池,可以开启 JDBC 连接池,因为频繁建连接时很耗时的行为。开启连接池可以降低应用频 繁建连接的损耗。 JDBC 连接池功能限制:JDBC 连接池只是为了读写分离测试性能时使用,只支持相同用户的连接。如果是不同 用户的连接,不要使用,会有模式混乱问题。 12.1.13 JDBC 读写分离配置参数依赖关系 问题描述: JDBC 读写分离配置参数是如何互相依赖的? 分析与解决方法: 关于 JDBC 读写分离配置项的依赖关系: USEDISPATCH=false # 是否使用读写分离功能, 此配置项关闭 JDBC 就变成单机 JDBC,无读写分离功能。 MASTER_CHECK=true # 在新建连接时检查当前连接 DB 是不是 Master, 如果不是会去 slave 节点中检查有没有 新升级的 Master, 如果还是找不到 Master 节点就会向上报错。(此功能开启需要同时开启读写分离功能)。 USECONNECT_POOL=false # 是否使用连接池缓存连接,此功能开启需要同时开启读写分离功能。(此功能开启 需要同时开启读写分离功能)。 65 第 12 章 接口 MASTER_CHECK=true # 在新建连接时检查当前连接 DB 是不是 Master, 如果不是回去 slave 检查有没有 Master, 如果还是找不到 Master 就会向上报错。(此功能开启需要同时开启读写分离功能)。 RETRYTIMES=10 # 连接异常问题造成的语句执行失败情况下,重建连接并重发的最高重试次数(0~100)。(此 功能开启需要同时开启读写分离功能) RETRYINTERVAL=10 # 失败时重建连接并重发的每次的间隔时间(单位:秒)。(此功能开启需要重试次数大于 0) CLUSTER_MONITOR=true # 开启集群备机监测线程定时监测集群备机状态,更新全局备机信息(无锁)。(此 功能开启需要同时开启读写分离功能)。 MONITORINTERVAL=5 # 备机监测线程每次查询备机信息的间隔时间(单位:秒)。(此功能开启需要同时开启 读写分离功能)。 TransactionDispatchStrategy=2 # 事务中语句的分法策略,1 表示事务中的所有语句都不分发,默认是 2 表示事务 中遇到写语句之前的读语句可以分发。(此功能开启需要同时开启读写分离功能)。 12.1.14 JDBC 读写分离重发不成功的情况 问题描述: JDBC 读写分离在哪些情况下重发也不会成功 分析与解决方法: JDBC 支持切机本意就是指尽量让应用的语句不因为切机造成执行失败,让应用对切机无感知。对于单事务语句 基本都可以重发成功。 但是并不是所有的语句都可以重发成功。 • 涉及连接会话上下文的情况。 • 游标:cursor,refcursor 切机后全部丢失,重发不能成功。 • 事务:切机后连接全部都断掉了,事务回退失败,不能重发。 • 结果集遍历:和游标类似,重发不能成功。 • 批量执行。 12.1.15 JDBC 读写分离分发策略 问题描述: JDBC 读写分离分发策略是怎么样的? 分析与解决方法: JDBC 读写分离分发策略是读语句分发,分两种情况: 1. 单语句事务,这种情况下每条语句都是一个独立的事务,所以读语句分发备机没有问题 66 第 12 章 接口 2. 多语句事务,这种情况下,读语句处于事务内,分发需要考虑事务隔离级别,V92 支持的三种隔离级别:可重 复读,读提交,序列化。严格意义上这三种都不允许读语句分发,因为可能出现不可重复读或者读不到已提交 的内容。 但是如果事务内的语句就不分发的话,读写分离就失去大半意义了,因为无论是应用还是框架基本上都是用事务 控制的,所以 JDBC 提供一个分发策略参数控制, TransactionDispatchStrategy 可以选择分发策略:(性能优先,默认是 2) 1. 事务内的所有语句都只发主机,完全不分发备机。 2. 事务内遇到写语句之前的读语句,可以分发备机,遇到写语句之后就只发主机。 12.1.16 JDBC 读写分离相关参数默认值 问题描述: JDBC 读写分离相关参数默认值 分析与解决方法: loggerLevel=OFF # 默认 OFF,可用参数 OFF, DEBUG, TRACE loggerFile=jdbc_test.log # 默认 null,日志文件名,可以是相对路径,也可以是绝对路径,如果默认 null 就是不生 成日志文件 preferQueryMode=extendedForPrepared # 默认 extend,可用参数 simple,extend,extendedForPrepared socketTimeout=10 # 默认 0(没有超时,一直等,直到返回),单位是秒,可选值为任意正整数,控制底层 socket receive 的超时时间。次参数设置取决于应用的超时控制机制,如果应用有自己的超时控制比较好,能够自己控 制对端不在线而造成的 socket receive 一直等待的时间,这个值可以设 0 完全让应用去控制超时时间。但是如果 应有没有超时控制或者控制的不好,只要 JDBC 不返回,应用不能自己根据超时返回,一直阻塞,那就需要设 置这个超时时间,一般设置为该应用查询语句正常返回的最长返回时间。 USEDISPATCH=true # 默认 false,用来控制是否使用读写分离功能 HOSTLOADRATE=33 # 默认 0,用来控制主机读负载率 SLAVE_ADD=192.168.8.228,192.168.8.229 # 备机地址 # 默认 null SLAVE_PORT=54321,54321 # 默认 null USECONNECT_POOL=false # 是否使用连接池缓存连接 # 默认 false,开启连接池 CONNECT_POOLSIZE=100 # 默认 10 个连接 MASTER_CHECK=true # 在新建连接时检查当前连接 DB 是不是 Master, 如果不是回去 slave 检查有没有 Master, 如果还是找不到 Master 就会向上报错 # 默认 true RETRYTIMES=10 # 失败重发的最高次数 # 默认 10 次 RETRYINTERVAL=5 # 失败重发每次的间隔时间(单位:秒)# 默认 5 秒 CLUSTER_MONITOR=true # 开启集群备机监测线程定时监测集群备机状态 # 默认开启 67 第 12 章 接口 MONITORINTERVAL=5 # 监测线程每次监测的间隔时间(单位:秒)# 默认 50 秒 TransactionDispatchStrategy =2 默认是 2 # 事务内语句分发策略,提供两种策略选择 #1:事务内语句全都不分 发,只发给主机。2:事务内遇到写语句之前读语句可以分发 12.1.17 sockettimeout 导致 jdbc 重建连接 问题描述: 集群状态正常,sockettimeout 设置大于 0 时,为什么执行时间超长的事物会失败并导致 jdbc 重建连接? 分析与解决方法: sockettimeout 是控制底层 socket 超时返回的最长时间,默认是 0,即没有超时。如果指定大于 0 的值,意思就是 最多等待 sockettimeout 的时间 socket 的 receive 操作就会返回,这主要是用来防止当 server 掉线时,client 端 socket 的 receive 操作会一直等待。但是这会带来副作用,就是如果一条语句真的执行很长时间超过了 sockettimeout 的值 时,会被认为是超时而中断 receive 返回超时错误,如果是在读写分离状态下,超时会造成重建连连接重发语句。一 条语句如果是因为大于设置的 socketTimeout 而超时退出,那么应用需等待(socketTimeout * (RETRYTIMES + 1)+ RETRYINTERVAL * RETRYTIMES)才会收到异常。此时需要根据用户的语句最长执行时间来设置 sockettimeout 或者设置为 0 一直等待。 如果应用自己有防这种 JDBC 操作一直不返回的机制,JDBC 调用不返回,应用会有自己的超时控制,那就不 需要 JDBC 设置 soc kettimeout,让应用自己控制超时时间就好。 如果应用没有这种防呆机制,一个 JDBC 操作不返回就会造成应用完全卡死,那就需要设置 JDBC 的 sockettimeout 值,让 JDBC 来控制超时时间。 12.1.18 主备切换后备机的连接数持续上升问题 问题描述: 主备切换后,备机 rewind,或者备机故障后,备机恢复时为什么备机的连接数是持续上升,而不是一次性全部 建好? 分析与解决方法: 主备切换后,连接不是马上就全部建立起来的,而是应用确实调用到 JDBC 时,JDBC 才会去判断集群是否切 换了,重建连接,重发语句执行。所以连接数是恢复速度和应用的操作 JDBC 负荷有关,通常是慢慢建立起来的, 备机的连接会稍滞后于主机连接恢复速度,因为切机重发时,都是只要能找到新的主机就可以重发成功了,不会等到 所有备机重启完成。只有等到下一次发送语句触发备机时,JDBC 才会去检测备机是否已经起来了,如果是才会重建 备机连接。 12.1.19 主机切机后,应用登陆 WEB 慢 问题描述: 68 第 12 章 接口 主机切机后,应用第一次登陆 WEB 慢,JDBC 等待时间分析 分析与解决方法: 1. 局域网内测试拔网线切机 1) 集群的新主机起来可连接后-> 2) 应用用户登录 WEB-> 3) 使用连接池中已经有的 JDBC 连接 (主机的连接都已经失效,备机的连接在 rewind 之前都还有效) -> 4) 发送 SQL -> 5) (I/O Error 20 秒) 收到错误返回 -> 6) 重建 JDBC 连接(sleep 5 秒)-> 7) (在线 0.1 秒返回)+(不在线的需要 10 秒返回) -> 8) 重建连接完成开始执行登陆 SQL 返回,总计 35 秒左右。 2. 其中 (不在线的需要 10 秒返回) 这个可以通过 connectTimeout 参数控制 connect 超时时间,默认是 10 秒。 其中 (sleep 5 秒) 这个可以通过 RETRYINTERVAL 参数控制重建连接的间隔时间,默认是 5 秒。 其中 (I/O Error 20 秒) 这个可以通过 socketTimeout 参数控制 receive 的超时时间,默认是 0 无限等待。 3. 备机的连接不是马上断掉,而是在一段时间内都还可以使用,等到 rewind 时连接才会全部断掉。 12.1.20 JDBC 打开日志方式 问题描述: JDBC 驱动支持控制日志打印级别和日志输出到文件或者控制台。 分析与解决方法: 日志级别: loggerLevel = 日志级别 指定日志记录级别。例如:”OFF”, ”INFO”, ”DEBUG”, ”TRACE”,默认值是 null 即不输 出日志。通常读写分离将日志开启到 INFO,单机将日志开到 TRACE。 日志输出: loggerFile = 日志文件名字 指定日志信息保存文件或者 console 输出: • 如果没有指定 loggerFile,表示不生成 JDBC 日志文件, 日志信息全部打印到当前 console 输出。 • 如果 loggerFile 有指定路径,则只打印到文件。例如:loggerFile=e:\logFile.txt,默认值是 null。这个路径 可以是相对路径,也可以是绝对路径。 69 第 12 章 接口 12.1.21 JDBC 报错:无效的”UTF8” 编码字节顺序 问题描述: JDBC 报错:无效的”UTF8” 编码字节顺序 分析与解决方法: V92 早期版本的 JDBC 默认都是 UTF8 编码的,需要设置 client_Encoding=GBK 来指定客户端编码。这个参 数现在已经变更为 clientEncoding V92 目前版本的 JDBC 默认都是获取系统默认编码,自动设置为系统的 clientEncoding,绝大多数情况下是不需 要用户再自己指定这个参数的。 系统 JVM 和应用和 JDBC 和数据库编码之间的关系 12.1.22 问题描述: 乱码的问题通常都是编码不一致导致。 分析与解决方法: 第一落实应用的编码是什么。需要询问应用的开发人员。 第二落实 JVM 的 file.encoding 是什么?一般 Windows 环境是 GBK,linux 是 UTF8。 第三如果应用的编码和 JVM 的 file.encoding 一致,JDBC 默认使用 JVM 的编码,不需要额外指定 clientEncoding 参数。否则需要指定 JVM 的-Dfile.encoding=GBK 或者 JDBC 的 clientEncoding 参数。 第四如果还是报无效编码错误,就把 JDBC 日志打开到 INFO 或者 TRACE,确认连接串信息对不对,再去看 日志里是否有乱码数据。 编码解释 1. 系 统 JVM 的 默 认 编 码:file.encoding 数-Dfile.encoding=UTF8 通 常 和 操 作 系 统 默 认 编 码 一 样。 当 然 用 户 可 以 同 过 来 手 动 指 定 期 望 的 编 码 格 式。JDK1.7 及以上的可以通过命令 jvm 参 java - XshowSettings:properties –version 产看 jvm 参数值。 2. 应用的编码:应用开发的时候自己指定的编码格式。通常应用的编码是要和运行环境的 jvm 的 file.encoding 保 持一致。 3. JDBC 的编码:JDBC 通过参数 clientEncoding 指定编码格式,包括 JDBC 发给数据库的内容和返回给应用的 内容都是按 clientEncoding 编码。通常需要和应用的编码保持一致。 4. 数据库的编码: • client_encoding 就是客户端编码,JDBC 通过 clientEncoding 指定。 • server_encoding 就是服务端编码,这个是数据库自身存储时的编码。 70 第 12 章 接口 12.1.23 V7 V9 JDBC 混用问题 问题描述: V7 V9 JDBC 混用出现报错 分析与解决方法: V9 的 JDBC 连接 V7 的数据库出现的错误: com.kingbase8.util.KSQLException: FATAL: 3 在参数”extra_float_digits” (-15 .. 2) 的有效范围之外 V7 的 JDBC 连接 V9 的数据库出现的错误: [KingbaseES JDBC Driver] 不能与数据库建立连接: 不支持的前端协议 3.3: 服务端支持 1.0 到 3.0。 12.1.24 JDBC 读写分离模式混淆找不到表 问题描述: JDBC 读写分离模式混淆导致找不到表 分析与解决方法: 如果是开启读写分离的,可能是开启了 JDBC 连接池,目前 JDBC 连接池只支持相同的 URL 相同用户的连接, 不支持多用户名。 解决办法关闭 JDBC 连接池指定连接参数 USECONNECT_POOL=false 即可 12.1.25 JDBC 读写分离日志分析办法 问题描述: 如何分析 JDBC 读写分离日志 分析与解决方法: 常用的 JDBC 日志的命令: 1. 比如我要看一个线程的日志,假如 131 是线程 ID, grep "\[131\]" ./jdbc_new.log > 131.log 这样就能看到 131 线程的完整 JDBC 日志,这样就能看到这个线程都干了什么事情,反推应用的业务逻辑。 2. 比如我要看 131 这个线程里的所有执行语句 grep "consume time" ./131.log > 131_consume.log 这个日志就是这个线程里执行的全部的 SQL 是什么和 SQL 执行的时间。 例子: 71 第 12 章 接口 [2019-08-08 11:17:29] [114] [com.kingbase8.dispatcher.executor.DispatchAbstractStatement-->executeTemplet] DispatchPreparedStatementV2.executeQuery(select pk_value ,CTID,XMIN from ecms_gen_pk where pk_name = 'pk_ web_url_access_log' for update;) consume time:::17(ms) 3. 比如我要看 monitor 线程的日志 从全日志里搜 monitor 找到对应的线程 ID 比如是 [32] grep "\[32\]" ./jdbc_new.log > 32.log 这样就能看到 monitor 不停的刷在线的主备机的 IP,这样基本就能看到集群的历史和现在的状态,主备机都是 谁。 4. 比如我要看是哪条 SQL 把事务设置为写事务了,从而不再分发备机。 从日志里搜”Enter transactional state from sql”,后面的 SQL 就是被识别为写语句的 SQL。 例子: [2019-08-08 11:17:29] [114] [com.kingbase8.dispatcher.sqlParser.sql.SqlParser-->parse] Enter transactional state from sql[select pk_value from ecms_gen_pk where pk_name = 'pk_web_url_access_log' for update]. 5. 比如我要看应用建一个新的 JDBC 连接的时间消耗 从日志里搜“this connect consume time”,这个会显示建一个连接的时间消耗。 例子: [2019-08-08 11:25:16] [302] [com.kingbase8.Driver-->makeConnection] this connect consume time:::135(ms) 6. 比如我要看看都发生了什么错误 从日志里搜“Exception”,就能看到所有的异常信息。 例子: [2019-08-08 11:21:29] [302] [com.kingbase8.Driver-->connect] Unexpected connection error: java.sql. SQLException: JDBC can't find a vaild master database in cluster... 12.1.26 JDBC 使用 SSL 加密 问题描述: JDBC 如何使用 SSL 加密 分析与解决方法: 1. 使用 LibPQFactory 服务器: 72 第 12 章 接口 1) 确保安装 openssl 2) 在 data 目录下,创建自签名的证书 为服务器创建一个快速的自签名的证书,填充那些 openssl 要求的信息。确保把本地主机名当 做”Common Name” 输入;挑战密码可以留空。该程序将生成一个用口令保护的密钥,它不会 接受小于四字符的口令。 openssl req -new -text -out server.req 要移去密钥(如果你想自动启动服务器就必须这样),运行下面的命令: openssl rsa -in privkey.pem -out server.key rm privkey.pem 将一个证书变成自签名的证书并复制密钥和证书到服务器将要查找它们的地方 openssl req -x509 -days 3650 -in server.req -text -key server.key -out server.crt 修改文件权限,如果文件的权限比这个更自由,服务器将拒绝该文件。 chmod og-rwx server.key 生成根证书 cp server.crt root.crt 3) 配置 kingbase.conf 文件 ssl = on # (change requires restart) #ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers # (change requires restart) #ssl_prefer_server_ciphers = on # (change requires restart) #ssl_ecdh_curve = 'prime256v1' # (change requires restart) #ssl_cert_file = 'server.crt' # (change requires restart) #ssl_key_file = 'server.key' # (change requires restart) ssl_ca_file = ' root.crt ' # (change requires restart) #ssl_crl_file = '' # (change requires restart) 4) 配置 sys_hba.conf 文件 hostssl all all 0.0.0.0/0 md5 clientcert=1 5) 重启数据库服务器 6) 为客户端创建所需证书 生成 kingbase8.key 73 第 12 章 接口 openssl genrsa -des3 -out kingbase8.key 1024 openssl rsa -in kingbase8.key -out kingbase8.key chmod 400 kingbase8.key 生成 kingbase8.csr,CN 需要指定为要连接数据库的用户名,如需匹配不同的用户,可指定为 * openssl req -new -key kingbase8.key -out kingbase8.csr -subj '/C=GB/ST=Berkshire/ L=Newbury/O=Kingbase/CN=SYSTEM' 生成 kingbase8.crt openssl x509 -req -days 3650 -in kingbase8.csr -CA root.crt -CAkey server.key -out kingbase8.crt -CAcreateserial 生成 kingbase8.pk8 openssl pkcs8 -topk8 -outform DER -in kingbase8.key -out kingbase8.pk8 -nocrypt jdbc: 通过参数 sslmode 配 置 证 书 验 证 方 式, 该 参 数 支 持 四 个 值:disable(禁 用 SSL)、require、 verify-ca、verify-full。使用 verify-ca 和 verify-full 时,需通过连接参数 sslrootcert 指定根证书 文 件 的 位 置, 如 不 指 定,Linux 默认路径为 $HOME/.kingbase8/ root.crt,Windows 默认路径 为%APPDATA%kingbase8root.crt,将服务器 data 目录下的 root.crt 放到对应目录下即可。只有 verify-full 模式会对主机名进行验证。 通过参数 sslcert 配置客户端证书位置,如不指定,Linux 默认路径为 $HOME/.kingbase8/kingbase8.crt, Windows 默认路径为%APPDATA%kingbase8kingbase8.crt,将服务器 data 目录下的 kingbase8.crt 放到 对应目录下即可。 通过参数 sslkey 配置秘钥文件位置,如不指定,Linux 默认路径为 $HOME/.kingbase8/kingbase8.pk8, Windows 默认路径为%APPDATA%kingbase8kingbase8.pk8,将服务器 data 目录下的 kingbase8.pk8 放 到对应目录下即可。 举例: jdbc:kingbase8://192.168.222.128:54321/TEST?sslmode=verify-ca&sslrootcert=root.crt& sslcert=kingbase8.crt&sslkey=kingbase8.pk8 2. 使用默认的 SSLSocketFactory 服务器: 1)、2)、3)、4)、5) 见上 6) 创建 truststore,用于认证服务器端证书 把服务器证书转化为 der 格式 74 第 12 章 接口 openssl x509 -in server.crt -out server.crt.der -outform der 创建 truststore,装入服务器证书 keytool -keystore ./truststore -alias kingbase8server -import -file ./server.crt.der 7) 创建 keystore,保存客户端证书 生成客户端的 keyPair keytool -genkeypair -dname "cn=kingbase8client, ou=basesoft, o=basesoft, c=CN" -alias kingbase8client -keystore ./keystore -validity 180 生成证书请求 keytool -certreq -alias kingbase8client -file ./kingbase8client.csr -keystore ./keystore 用 root.crt 签发客户端证书 openssl x509 -sha1 -req -in ./kingbase8client.csr -CA ./root.crt -CAkey ./server.key CAcreateserial -out ./kingbase8client.crt.der -outform DER -days 365 -passin pass:123456 -extfile /etc/pki/tls/openssl.cnf -extensions v3_req 把证书添加到 keystore 中 keytool -keystore ./keystore -alias kingbase8server -import -file ./server.crt.der keytool -keystore ./keystore -alias kingbase8client -import -file ./kingbase8client.crt. der jdbc: 1) 只需配置连接参数 ssl=true; 2) 将 truststore 和 keystore 拷贝到客户端; 3) 执行程序时指定 java 运行参数 -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=123456 -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=123456 注意: 1. 生成 keystore 时,签发客户端证书命令,可能会对 openssl 的版本有一定的要求,自测使用版本为 OpenSSL 1.0.1e-fips,可以通过命令 openssl version 查看 openssl 版本。 2. 如果需要不与主机名和用户名绑定,使用 LibPQFactory 方式,需要配置 jdbc 连接参数 sslmode 为 verify-ca,指定该参数不会验证主机名,生成 kingbase8.csr 时,CN 指定为 *,可匹配不同的用户。 使用 SSLSocketFactory 不验证主机名和用户名。 75 第 12 章 接口 3. 使用 java 命令执行应用程序时,可以通过-cp 或-Djava.ext.dirs 指定 jar 包路径。但通过后者指定 时,会覆盖 Java 本身的 ext 设置,如果未指定该系统属性的原加载路径,将失去一些功能,如 java 自带的加解密算法实现,会报 NOSuchAlgorithmException 的错误。故需同时在该设置下指定路径 $JAVA_HOME/jre/lib/ext,如-Djava.ext.dirs=./plugin: $JAVA_HOME/jre/lib/ex。 4) 如果 openssl 版本太高,使用其生成的证书服务器可能会报”unknown message digest algorithm” 错误, 此时需将 openssl.cnf 配置加密算法改为 sha1,并且通过环境变量 OPENSSL_CONF 指定该文件的位置。 openssl version 查看 openssl 的版本 openssl version -d 查看 openssl.cnf 所在目录 12.1.27 JDBC 常见异常 问题描述: JDBC 常见异常 分析与解决方法: 1. com.kingbase8.util.KSQLException:The column index is out of range: 1, number of columns: 0. 该异常报错原因是 sql 无需绑定参数(如空 sql:””),然后进行了参数绑定,请客户自己排查原因。 2. Bad version number in .class file(unable to load class com.kingbase8.Driver) 异常原因为 jdk 的版本小于 jdbc 驱动包编译的版本,提升 jdk 版本或使用与 jdk 版本对应的 jar 包。 3. java.lang.NoClassDefFoundError 或 java.lang.ClassNotFoundException 这两个异常都是找不到类,通常是缺少 jar 包,百度下该类在什么包里,导入对应 jar 包即可。 查看是否导入 jar 包: 工具 idea: 1)点击 File –> Project Structure; 2)找到 Modules,选中项目,点击 Dependencies; 3)如果缺少,点击右侧 + 号即可导入。 76 第 12 章 接口 工具 eclipse: 1)点击项目,右键,选中 Build Path,Configure Build Path,在 Libraries 中查看所有导入的包。缺少 可通过 Add JARs 导入。 77 第 12 章 接口 2)直接展开项目,也可以查看,如未导入,直接选中未导入的 jar 包,右键,Build Path,Add to Build Path。 78 第 12 章 接口 4. This connection has been closed. 该异常是因为使用了已关闭的连接,该连接可能由客户端关闭,也可能是 jdbc 遇到了 I/O 异常时,关闭 当前连接。应用程序未处理 I/O 异常,直接使用该连接,就会导致该异常。 5. I/O 异常 ( An I/O e rror occurred while sending to the backend.) 通常是由网络原因导致的,也有可能是超时导致或者磁盘满了。如果是单条语句报 I/O 异常,通常是语句 超时导致,语句超时指的就是语句执行时间超过了 socketTimeout 设置的时间。如果多条语句报错,那就 是其他两个原因。 也有可能是绑定的从参数个数超过了 SQL 的参数限制(Short.MAX_VALUE:32767)。(java.io.IOException:Tried to send an out-of-range integer as a 2-byte value:) 如果是在流写入的过程中遇到该异常,也可能是创建临时文件失败。写入的流如果大于 50k,就会在默认 临时文件目录(java.io.tmpdir 的值) 中创建一个文件来缓存内容,中间出现 IO 异常,也会抛出该错误信 息。 以上错误可以通过错误堆栈来区分。 6. 替换 jar 包未生效问题 原因是之前的 jar 包未删除。排查方法:可以删除新导入的 jar 包,看项目是否可以正常运行,如果可以 正常运行,说明还存在其他 jar 包,删掉之前的 jar 包,再导入新的 jar 包。找不到其他的 jar 包可能原因 是用户修改了驱动包名称或者驱动包被打在了其他 jar 包里。 7. 连接错误分析 1)java.net.SocketTimeoutException:connect time out 79 第 12 章 接口 该错误表示底层的 socket 连接在 10s 内(connectTimeout 默认值为 10s)建立失败,此时客户端与服务 器之间网络不通。 2)com.kingbase8.util.KSQLException: Connection to 192.168.19.128:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/ IP connections. Caused by: java.net.ConnectException: Connection refused: connect 该错误表示设置的端口无法连接,可能是数据库未开启或者端口填写错误。 3)The authentication type 10 is not supported. Check that you have configured the sys_hba.conf file to include the client’s IP address or subnet, and that it is using an authentication scheme supported by the driver. 该错误是 R3 的驱动连接了 R6 的数据库。原因是 R3 的驱动不支持 sha256 验证,R6 数据库默认就是 sha256 验证方式。 4)SCRAM authentication is not supported by this driver. You need JDK >= 8 and pgjdbc >= 42.2.0 (not ”.jre” versions) R6 jdk1.6 版本的驱动不支持 sha256 验证,需要使用 md5 验证方式。首先需要修改 sys_hba.conf 中的 验证方式为 md5,然后需要创建一个 md5 加密的用户。show password_encryption 查看密码加密方式, 不是 md5 的话需要修改加密方式为 md5 再创建用户。创建好后可以使用 SELECT rolname,rolpassword FROM pg_authid; 查看用户名和密码。 5)FATAL:invalid value for parameter ”client_encoding”:XXX 该错误是指服务器不支持 XXX 客户端编码。JDBC 驱动连接数据库时默认设置的客户端编码是 JVM 的 编码,如果该编码服务器不支持就会报上述错误。可以通过修改 JVM 编码或者通过设置 JDBC 连接参数 clientEncoding 来解决。 8. 无法确定参数 $1 的类型 使用 $1::type 或 cast 函数对参数进行类型强转。使用 Hibernate 通常用 cast 函数,否则无法通过 hibernate 的语句解析。 12.1.28 JDBC 读取 BLOB 乱码 问题描述: 如何处理 JDBC 读取 BLOB 乱码问题 分析与解决方法: BLOB 存储的内容为二进制,不会出现乱码。 1. 如果打印内容为 com.kingbase8.jdbc.KbBlob@14ae5a5,这个是 Blob 的对象名称,需要调用 Blob 的 getBytes 等方法,把 Blob 的存储内容拿出来,具体的参考手册示例。 2. 如果打印内容为 x 开头的十六进制字符串,和 ksql 查询出的内容一样,或者转字符串的时候使用了其他编 码,打印出来的也可能是乱码,此时可以直接比较 byte 数组的大小,如果取出来的结果的数组是写之前的 2 倍加 2 80 第 12 章 接口 的大小,那么需要更换新驱动或者在连接串指定连接参数 prepareThreshold=-1。如果不是以上两种情况,那就是写 之前就已经转成了乱码,直接把待写入的 byte 数组转成字符串看是否是乱码。 12.1.29 读写分离分发现象分析 问题描述 1: 集群状态正常,主机负载率也不是 100,但是查询语句全部分发主机。 分析与解决方法: 原因可能为连接数据库的用户的权限小于流复制的权限,导致 JDBC 检测线程查不到在线备机,所有语句全 部分发主机。是否该原因可通过工具或者 ksql 使用相同用户连接相同数据库,执行 select CLIENT_ADDR from sys_stat_replication; 看是否可以查询到备机。 解决办法:使用超级用户 问题描述 1: 读语句发往同一台备机 分析与解决方法: 使用同一个 Statement 执行的读语句都会发往同一台备机,原因是 Statement 的底层实际是有一个主 Statement 和一个备 Statement,如果备 Statement 不为空时,不会去重新获取新的 Statement,会一直使用同一个。如果想将 语句进行分发,就建立新的 Statement 来执行语句。使用 PreparedStatement/CallableStatement 定义语句后,反复 使用 execute 执行,多次执行都是发往同一台机器。 12.1.30 com.kingbase8.util.KSQLException: ERROR: type ”q” does not exist (R6) 问题描述: 报错:com.kingbase8.util.KSQLException: ERROR: type ”q” does not exist(R6) 分析与解决方法: 该问题是由于服务器开启了空串转为 null 参数(ora_input_emptystr_isnull=true),开启该参数后,原先为空 串可以用 q’<>’ 表示,但是有些版本驱动已经修改,服务器未修改,所以会有该问题。 通过升级服务器版本或者关闭空串转为 null 参数(ora_input_emptystr_isnull=false)来解决。 12.1.31 fetchsize 功能 问题描述: 如何使用 fetchsize 功能 81 第 12 章 接口 分析与解决方法: V8R3:使用参数 defaultRowFetchSize 指定返回行数即可。 V9:自动提交模式下,使用参数 defaultRowFetchSize 指定返回行数即可。 非自动提交模式下,使用参数 defaultRowFetchSize 指定返回行数,同时指定连接参数 useFetchSizeInAutoCommit=true。同时还需将服务器的 GUC 参数 enable_autocommit_crossquery 和 enable_autocommit_fetch 置为 true。 12.1.32 同时使用 R3 和 R6,jar 包 问题描述: 同时使用 R3 和 R6,jar 包冲突的解决方案 分析与解决方法: V9 使用别名包,驱动名称为 com.kingbase86.Driver。连接串示例:jdbc:kingbase86://localhost:54321/test 12.1.33 jar 包的版本号 问题描述: 如何查看 jar 包的版本号? 分析与解决方法: java -jar kingbase8-9.0.0.jar -version 12.1.34 R3 客户端无法使用 scram-sha-256 认证 问题描述: JDBC 驱动连接数据库时,报错如下:提示“The authentication type 10 is not supported. Check that you have configured the sys_hba.conf file to include the client’s IP address or subnet, and that it is using an authentication scheme supported by the driver.” 分析与解决方法: R3 的驱动无法使用 scram-sha-256 认证,只能使用 MD5 认证 82 第 12 章 接口 12.2 Spring-JDBC 常见问题 12.2.1 大字段的设置--lobHandler 问题描述: 大字段的相关设置 分析与解决方法: LobHandler 接口为操作 BLOB/CLOB 提供了统一访问接口,而不管底层数据库究竟是以大对象的方式还是以一 般数据类型的方式进行操作。 大部分数据库厂商的 JDBC 驱动程序(如 DB2)都以 JDBC 标准的 API 操作 LOB 数据,但 Oracle 9i 及以前 的 JDBC 驱动程序采用了自己的 API 操作 LOB 数据,Oracle 9i 直接使用自己的 API 操作 LOB 数据,且不允许 通过 PreparedStatement 的 setAsciiStream()、setBinaryStream()、setCharacterStream() 等方法填充流数据。Spring 提供 LobHandler 接口主要是为了迁就 Oracle 特立独行的作风。所以 Oracle 必须使用 OracleLobHandler 实现类, 而其它的数据库统一使用 DefaultLobHandler 就可以了。Oracle 10g 改正了 Oracle 9i 这个异化的风格,所以 Oracle 10g 也可以使用 DefaultLobHandler。 Oracle 数据库的 LobHandler 配置 一般数据库 LobHandler 的配置 12.2.2 Cannot determine a dialect for org.springframework.jdbc.core 问题描述: 报错:Cannot determine a dialect for org.springframework.jdbc.core 分析与解决方法: org.springframework.data.jdbc.repository.config.DialectResolver$NoDialectException: Cannot determine a dialect for org.springframework.jdbc.core.JdbcTemplate@7c90b7b7. Please provide a Dialect. 堆栈信息: 83 第 12 章 接口 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jdbcConverter' defined in class path resource [org/springframework/boot/autoconfigure/data/jdbc/ JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration.class]: Unsatisfied dependency expressed through method 'jdbcConverter' parameter 4; nested exception is org.springframework.beans.factory. BeanCreationException: Error creating bean with name 'jdbcDialect' defined in class path resource [org/ springframework/boot/autoconfigure/data/jdbc/JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration. class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans. BeanInstantiationException: Failed to instantiate [org.springframework.data.relational.core.dialect. Dialect]: Factory method 'jdbcDialect' threw exception; nested exception is org.springframework.data.jdbc. repository.config.DialectResolver$NoDialectException: Cannot determine a dialect for org.springframework. jdbc.core.JdbcTemplate@7c90b7b7. Please provide a Dialect. 解决办法: 出现该问题是因为使用了 spring-boot-starter-data-jdbc 包,该包要求提供 jdbcDialect,目前未适配,推 荐使用 spring-boot-starter-jdbc。 12.3 Hibernate 使用常见问题 12.3.1 Hibernate 配置方言包 问题描述: Hibernate 使用时如何配置方言包 分析与解决方法: Hibernate 的使用需要配置方言包,使用方言包的版本需要根据 Hibernate 核心包的版本来确定。Hibernate 核心 包通常由客户从网络下载,核心包的包名为 hibernate-core-xxx.jar 或 hibernate-xxx.jar 或 hibernatex.jar。目前 R2、 R3 提供以下版本的方言包。 84 第 12 章 接口 方言包 适用范围 hibernate-2.0.3dialect.jar [2.0,2.1) hibernate-3.1dialect.jar [3.1,3.2) hibernate-3.2.7gadialect.jar [3.2,3.3) hibernate-3.3dialect.jar [3.3,3.6) hibernate-3.6.10dialect.jar [3.6,4.0) hibernate-4.0.1finaldialect.jar [4.0,4.3) hibernate-4.3.11finaldialect.jar [4.3,5.0) hibernate-4.3.2finaldialect.jar [4.3,5.0) hibernate-5.0.12.Finaldialect.jar [5.0,5.2) hibernate-5.2.17.Finaldialect.jar [5.2,5.4) hibernate-5.4.6.Finaldialect.jar [5.4,6.0) V7 的方言包类名都是 KingbaseDialect,V92 的方言包类名都是 Kingbase8Dialect。请注意类名配置。 使用时注意配置是否填写正确 V7 的 hibernate 的 dialect 配置例子 org.hibernate.dialect.KingbaseDialectcom.kingbase.Driverjdbc:kingbase://192.168.87.128:5421/TEST V92 的 hibernate 的 dialect 配置例子 org.hibernate.dialect.Kingbase8Dialectcom.kingbase8.Driverjdbc:kingbase8://192.168.87.128:54333/TEST 在运行项目时如果遇到以下两种异常,均是因为项目未导入方言包: 1.java.lang.ClassNotFoundException: Could not load requested class : org.hibernate.dialect.Kingbase8Dialect 2.org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.hibernate.dialect.Kingbase8Dialect] as strategy [org.hibernate.dialect.Dialect] 目前遇到的情况有: 1. 未将方言包加入项目的 classpath 中; 85 第 12 章 接口 2. 将核心包当成方言包导入。 12.3.2 V9 Hibernate 非法 long 值问题 问题描述: V9 Hibernate 报错非法 long 值 分析与解决方法: 这个问题是由于 V9 hibernate 把 TEXT 类型默认对应到 CLOB 类型处理,但是 CLOB 是通过 OID 来访问的, 所以造成类型转换报错。解决办法更换新的方言包,新的 dialect。 方言包把 TEXT 类型默认对应到 LONGVARCHAR 就解决了。 12.3.3 Hibernate 无法确定参数类型 $1 问题描述: Hibernate 报错无法确定参数类型 $1 分析与解决方法: 1. 使用 cast 函数对于不识别的类型进行强转,如 cast(? as timestamp),as 后面的类型需要为 hibernate 类型, hibernate 类型自行百度。 2. 对于 V7,这个问题可能是用户打开了 Hibernate 的 SQL 注释功能,改为 false 即可。 false parse JDBC_STATEMENT_7: select testdb0_.id as id0_, testdb0_.username as username0_, testdb0_.btest as btest0_ from hibernate_test testdb0_ where testdb0_.username=$2 ERROR: could not determine data type of parameter $1 12.3.4 TEXT 与 BYTEA 的转换错误 问题描述: Hibernate 错误: 字段的类型为 TEXT, 但表达式的类型为 BYTEA,需要重写或转换表达式 分析与解决方法: 这个问题原因是 JDBC 指定了 bytea 的 OID 传给服务器,而服务器实际字段类型是 TEXT,不支持类型转换。 查看 hibernate 源码: 86 第 12 章 接口 public Query setParameter(int position, Object val) throws HibernateException { if (val == null) { setParameter( position, val, Hibernate.SERIALIZABLE ); } } 看出对于 null 值,hibernate 都是按照 Hibernate.SERIALIZABLE 类型处理。而 Hibernate.SERIALIZABLE 类 型使用 Hibernate.BINARY.set(st, toBytes(value), index)。 Hibernate.BINRAY 底层使用 JDBC 的 setBinaryStream 或者 setBytes 绑定参数。 解决办法: JDBC 直接修改所有 Bind 参数传 bytea 的地方都改成 0。如仍需绑定为 bytea,可通过连接参数 bytestype=bytea 来指定。 12.3.5 Hibernate 控制输出真实 SQL 日志 问题描述: Hibernate 如何控制输出 SQL 日志 分析与解决方法: 编辑 hibernate.cfg.xml,配置方法: 1. 参数:show_sql=true 打印 SQL 语句; 2. 参数:format_sql=true 使 SQL 语句格式更加美观统一; 3. 参数:use_sql_comments=true 使 SQL 语句中自动注入注释,增加可读性。 true //控制台打印 SQL 语句 true //格式化 SQL 语句 true //指出是什么操作生成了该语句 12.3.6 Springboot JPA 配置方言包问题 问题描述: 报错:org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’entityManagerFactory’ defined in class path resource Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when ’hibernate.dialect’ not set 分析与解决方法: Hibernate SQL 方言没有设置导致的,在 properties 文件中增加下面这行: 87 第 12 章 接口 或 spring.jpa.database-platform=org.hibernate.dialect.Kingbase8Dialect 者 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Kingbase8Dialect 12.3.7 hibernate-spatial 方言包配置 问题描述: 如何配置 hibernate-spatial 方言包 分析与解决方法: hibernate-spatial 是 方 言 包, 目 前 只 有 nate hibernate 5.3.7 的 数 据 空 间 插 件, 该 方 言 包 只 在 兼 容 版 提 供, 依 赖 于 pg 一 个 版 本, 使 用 该 方 言 只 需 要 将 原 先 配 置 的 hibernate hiber- 方言的名称改为 org.hibernate.spatial.dialect.kingbase.PostgisDialect 即可,其他参见 hibernate 配置。如: org.hibernate.spatial.dialect.kingbase.PostgisDialect 12.3.8 hibernate 使用 numeric 或 char(1) 映射 java 的 boolean 问题描述: 报错:报“对于字符类型来说这个值太长了 (1)“ 分析与解决方法: 当 java 类型为 boolean, 数 据 库 字 段 类 型 为 char(1) 或 numeric 类 型 时, 需 将 映 射 类 型 设 置 为 org.hibernate.type.NumericBooleanType,例如: 否则,映射为 char(1) 的时候会报“对于字符类型来说这个值太长了 (1)”的错误,映射为 numeric 时且当该字 段作为查询条件时,会在查询的时候无结果,原因是 jdbc 实际绑定的参数都是 0 和 1,但 oid 类型为 boolean,所以 数据库查询时会自动推断类型,参数值被推断为 f 和 t,但实际存储的是 0 和 1,导致查询无结果。 这个问题在后续已修复,可直接更换新的驱动包。但是对于类似于 from Person p where p.sex=true; 的 bool 作为查询条件参数写死的 hql,还需导入扩展方言 hibernate-dialect-extension.jar,方言包名称修改为: org.hibernate.dialect.Kingbase8ExtensionDialect。该方言包依赖原先的方言包。 12.3.9 The column name sequence_catalog was not found in this ResultSet. 问题描述: 报错:The column name sequence_catalog was not found in this ResultSet. 88 第 12 章 接口 分析与解决方法: Hibernate 查询 sequence 的语句从 5.4 开始发生了改变,该错误需替换对应版本的方言包,目前我们提供了 5.4.6 版本的方言包,使用 5.4 版本以上的核心包,使用 5.4.6 的方言包。 12.3.10 主键自增策略 hilo 问题描述: 如何使用主键自增策略 hilo 分析与解决方法: 使用 hilo 策略,默认的表 hibernate_unique_key 需要自己建立,而且必须拥有默认的字段 next_hi,建表后, 需要插入一条数据作为起始值。 create table hibernate_unique_key (next_hi integer not null); insert into hibernate_unique_key (next_hi) values(1); 12.3.11 Method com.kingbase8.jdbc.KbPreparedStatement.setCharacterStream(int, Reader, long) is not yet implemented. 问题描述: 报错:Method com.kingbase8.jdbc.KbPreparedStatement.setCharacterStream(int, Reader, long) is not yet implemented. 分析与解决方法: 该问题通常因为客户未使用 ES 的 hibernate 方言包,在使用了 ES 的 hibernate 方言包时,不会走到 ES 驱动未 实现的方法中,解决方案就是配置 ES 的 hibernate 方言包。 12.3.12 Hibernate 的 hql 不支持部分数据库函数的使用 问题描述: 报错:Method com.kingbase8.jdbc.KbPreparedStatement.setCharacterStream(int, Reader, long) is not yet implemented. 分析与解决方法: 1. 将 hql 语句转换为 sql 语句,createQuery 使用的是 hql,createSQLQuery 使用的是 sql 语句; 2. 在方言包里注册函数解决。 89 第 12 章 接口 12.3.13 Hibernate 设置为 update 已经建好表,仍旧去建表 问题描述: Hibernate 设置为 update 已经建好表,仍旧去建表。 分析与解决方法: 原因为使用了大小写不敏感的数据库,在大小写不敏感的库中,查询返回的表名与建表时的大小写保持一致。如 果建表时使用小写,Hibernate 查询返回的表名为小写,本地的表名是转为大写去比较,找不到所以会去建表,请改 为大小写敏感的数据库。 修改后可能存在的问题: 1. 索引重复创建 应用可能是从 MySQL、SQLServer 迁移过来的。索引名称在某些数据库中(如 MySQL、SQLServer), 索引是以表为维度创建的,在不同的表中的索引是可以重名的;而在另外的一些数据库中(如 PostgreSQL、Oracle、KingbaseES),索引是以数据库为维度创建的,即使是作用在不同表上的索引,它们 也要求其名称的唯一性。所以需要修改索引名称。 12.3.14 java.lang.NoSuchMethodError: javax.persistence.Table.indexes()[Ljavax/ persistence/Index; 问题描述: 报错:java.lang.NoSuchMethodError: javax.persistence.Table.indexes()[Ljavax/persistence/Index; 分析与解决方法: jar 包冲突,有多个 jar 包存在 javax/persistence/Index 类。 12.3.15 表取名 user 的规避 问题描述: 表取名 user 怎么规避? 分析与解决方法: 在映射上 @Table(name=“t_user”) 换个名字或者 @Table(name=”user”,schema=”xxx”) 显示指定模式名 12.3.16 其它模式下有同名表的处理机制 问题描述: 其它模式下有同名表,导致当前模式没有表但未去建表 90 第 12 章 接口 分析与解决方法: 目前已知 5.0.12 这个版本的 hibernate 在查找表时,如果没有显示指定模式名,查询顺序为先查当前模式,没有 查找默认模式,再没有就查找全模式,其他模式下有表,就会导致当前模式下创建失败,解决方法:1. 在 @Table 显 示指定 schema;2. 删除其他模式下的同名表;3. 升级 hibernate 版本。 12.4 Mybatis 常见问题 12.4.1 Mybatis 设置 SQL 超时时间 问题描述: Mybatis 如何设置 SQL 超时时间 分析与解决方法: mybatis 如果不指定, 默认超时时间是不做限制的, 默认值为 0. mybatis sql 配置超时时间有两种方法: 1. 全局配置 在 mybatis 配置文件的 settings 节点中, 增加如下配置 以秒为单位的全局 SQL 超时时间设置, 当超出了设置的超时时间时, 会抛出 SQLTimeoutException 2. Mapper XML 配置 在 mapper xml 文件中对具体一个 sql 进行设置, 方法为在 select/update/insert 节点中配置 timeout 属性, 超时时间并只作用于这一个 sql. 91 第 12 章 接口 12.4.2 Mybatis 非法 long 值问题 问题描述: 如何处理 Mybatis 非法 long 值问题 分析与解决方法: 1. 这个问题是由于 V7 的 JDBC 默认把 TEXT 类型对应为 LONGVARCHAR,而 Mybatis 又把 LONGVARCHAR 类型默认按照 CLOB 对象处理,造成和 Hibernate 非法 long 值的情形类似,但是 Mybatis 没有提供方言机制, 所以无法像 Hibernate 那样同过方言包控制,只能把 V7 的 JDBC 的 TEXT 类的值对应到 Varchar 来处理,就 解决非法值问题。 2. 如果用新的 JDBC 还出此问题,说明用户自己把 string 类型的 jdbcType 手动设置为 LONGVARCHAR 了。解 决办法:就是把 jdbcType 去掉或者设置为 VARCAHR 即可。 12.4.3 TEXT 与 BYTEA 的转换问题 问题描述: Mybatis 报错:字段的类型为 TEXT, 但表达式的类型为 BYTEA 你需要重写或转换表达式 分析与解决方法: 1. 这个问题需要查看出错 SQL 的 mapper 文件,需要知道 mapper 中参数是否指定了类型,从正常逻辑上来说不 应该出现这样的转换,应该可通过调整参数类型解决。 2. 这个也可以从 JDBC 入手,把所有 Bind 参数设置 Oid.BYTEA 的全都改为 0,让服务器自己推断类型。 12.4.4 Mybatis 控制 JDBC 底层不走预编译 问题描述: Mybatis 控制 JDBC 底层不走预编译的逻辑 分析与解决方法: 在 mapper 文件中可以使用 statementType 标记使用什么的对象操作 SQL 语句。 statementType:标记操作 SQL 的对象,如 statementType=”STATEMENT” 要实现动态传入表名、列名,需要做如下修改,sql 里的所有变量取值都改成 ${xxxx},而不是 #{xxx} 取值说明: 1. STATEMENT: 直接操作 sql,不进行预编译,获取数据:$—Statement 2. PREPARED: 预处理,参数,进行预编译,获取数据:#—–PreparedStatement: 默认 3. CALLABLE: 执行存储过程————CallableStatement 92 第 12 章 接口 12.4.5 Mybatis 控制 Bind 参数 问题描述: Mybatis 控制 Bind 参数的使用 分析与解决方法: #{}:相当于 JDBC 中的 PreparedStatement,走 Bind 报文。 ${}:是输出变量的值,字串替换,不走 Bind。 简单说,#{} 是经过预编译的,是安全的;${} 是未经过预编译的,仅仅是取变量的值,是非安全的,存在 SQL 注入。 12.4.6 Mybatis 使用 pagehelper 插件 问题描述: Mybatis 如何使用 pagehelper 插件 分析与解决方法: Mybatis 使用该插件需要将 helperDialect 设置成 postgresql, 如 不 指 定, 会 报 错: com.github.pagehelper.PageException:无法自动获取数据库类型,请通过 helperDialect 参数指定! 1. 直接使用 Mybatis 设置如下: 2. springboot 整合 mybatis 使用如下: 在 pom 文件中引入 Pagehelper 分页插件: com.github.pagehelperpagehelper-spring-boot-starter1.2.5 配置分页插件,打开 application.properties,添加如下配置信息: 93 第 12 章 接口 # 分页插件 pagehelper.helper-dialect=postgresql 12.4.7 Mybatis 使用自动返回主键功能 问题描述: Mybatis 如何使用自动返回主键功能 分析与解决方法: 该功能使用在 V7 仅支持 insert 语句 建表语句,要求表含有主键,且主键自增: create table t_user (id int identity primary key,username text,password text,sex boolean); 在 mapper 文件里配置: insert into t_user (username,password,sex) values (#{username},#{password},#{sex}) 注意: 如果使用 tk-mybatis 提供的 mapper 接口,V7 需要 mapper 包的版本在 3.4.0 及以上,否则使用 update 相关 的接口时,会报“不能返回 generatedkeys 或没有指定返回”的错误。 12.4.8 Mybatis 配置 databaseId 问题描述: Mybatis 如何配置 databaseId 分析与解决方法: 94 第 12 章 接口 12.4.9 Mybatis 使用匿名块插入语句报错 问题描述: Mybatis 中使用 begin insert ...;insert...; end; 格式的语句插入数据,报无法识别的 GBK 编码:’0x00’ 或者指定 了连接参数 prepareThreshold=-1 报 Can‘t change resolved type for param:1 from 1043 to 25. 分析与解决方法: 该问题属于 plsql 问题需要升级数据库版本。 在升级数据库版本后,如果出现类型转换错误,则使用强转(例如?::bytea)把其转换为对应类型,出现该错误 的原因为匿名块无法识别 oid 绑定类型为 0 的参数,会将其默认识别为 text,传给下层时无法转换为对应类型,就会 报错。特别地,如果字段类型为二进制,如 bytea、blob,如果参数内容有数据库无法识别的编码的话,转换成 text 就会报无法转换的编码错误,此时指定连接参数 bytestype=bytea 即可。 12.4.10 Mybatis 使用 ScriptRunner 执行含 plsql 的 sql 脚本报错 问题描述: 如何处理 Mybatis 使用 ScriptRunner 执行含 plsql 的 sql 脚本报错问题 分析与解决方法: 1. ScriptRunner 默认按照自定义的分隔符每行执行,分隔符默认为分号,如果 sql 脚本中包含 plsql 语句,按照 分号分割出来的语句是不正确的,所以可以使用 setDelimiter(String) 来设置自定义的分隔符,如设置分隔符 为”/”,则 sql 脚本中的每条语句后都添加”/”,ScriptRunner 将会按照此对语句进行分割,连接 KingbaseES 时,普通语句之间无需使用分隔符,驱动会对普通语句进行分割; 2. 或者可以通过 runner.setSendFullScript(true); 设置将 sql 脚本一次发送,但是由于驱动不会对包含 plsql 的多 语句进行分割,所以会报”无法插入多条命令到一个准备好的语句中“,此时指定 jdbc 连接参数 preferQueryMode=simple 走简单查询报文即可。 12.4.11 Mybatis 使用游标的注册方式 问题描述: Mybatis 如何使用游标的注册 分析与解决方法: 95 第 12 章 接口 注意: 1. jdbcType 只能设置为 OTHER,不能设置为 CURSOR,Mybatis 的 CURSOR 的值为-10,是 OracleCURSOR 的值,不是 Types.REF_CURSOR 的值,我们不支持; 2. 如果没有设置 javaType 的类型,返回值的类型为 ResultSet,如果设置了返回值的类型为 ResultSet,则返回值 为 List 对象。 12.4.12 Mybatis 写 json 类型示例 问题描述: Mybatis 如何使用 json 类型 分析与解决方法: 建表: create table t_json(id serial,content json); 实体类: package com.test.entity; public class JsonEntity { private int id; private Object fcontent; public int getId() { return id; } public void setId( int id) { this.id = id; } public Object getContent() { return fcontent; } public void setContent(Object b) { 96 第 12 章 接口 this.fcontent = b; } @Override public String toString() { return "id=" + this.id ; } } JsonTypeHandler.java package com.test.handler; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import com.test.utils.JsonUtil; // 继承自 BaseTypeHandler