#Caché

0 关注者 · 975 帖子

  

InterSystems Caché 是一个多模型 DBMS 和应用服务器。

查看此处提供的更多详细信息

文档

InterSystems 官方 Claire Zheng · 五月 30, 2024

从发布InterSystems IRIS®数据平台2022.3开始,InterSystems修改了许可证强制执行机制,以包括REST和SOAP请求。由于这种变化,在升级后,使用REST或SOAP的非处理器核数的许可证环境下,用户可能会遇到更高的许可证消耗。要确定此警报是否适用于您的InterSystems许可证,请按照下面链接的FAQ中的说明进行操作。

下表总结了强制执行变更情况:

产品

许可证强制执行中是否包含REST & SOAP 请求?

InterSystems Caché®

InterSystems Ensemble®

InterSystems IRIS, InterSystems IRIS® for Health, and Health Connect prior to 2022.3

InterSystems IRIS, InterSystems IRIS for Health, and Health Connect 2022.3 and later

1
0 142
文章 Qiao Peng · 五月 25, 2022 1m read

%SYS.Journal.Record 类有一个查询(query), List, 可以列出Journal文件中记录的数据修改历史。例如,要查询谁对global节点^QP(1,2)做过修改,可以使用如下代码。它查询Journal文件(输入参数pFilePath)中的global节点(输入参数pSearchGlobal)的操作:

1
2 400
文章 姚 鑫 · 十二月 27, 2023 2m read

百讲知识点索引

简介

  • B站已更新截止到2023.12.31之前的所有百讲课程,总计261讲。
  • 什么是百讲?百讲是一个主要介绍IRISCache编程知识的免费课程。
  • 课程的特点是,将每一个知识点,都会用示例演示出来、了解原理,而不是仅仅告诉有这个功能。
  • 每周一期,每期会请到有多年开发经验的老师来给大家讲解课程。
  • 百讲观看地址:https://www.bilibili.com/video/BV1cw41147xr/

在这里插入图片描述

知识点索引

  • 1IRISObjectScript 简介

    • ObjectScript 特点
  • 2讲 初识ObjectScript程序

    • 概述
    • 变量
    • 支持几种变量
    • 表达式
    • 函数
  • 3讲 语法规则

    • 区分大小写
    • 空格
    • 不需要空格
    • 需要空格
    • 注释
    • 字面常量
    • 标识符
    • 标签
  • 4讲 数据类型 - 字符串

  • 5讲 数据类型 - 位串

  • 6讲 数据类型 - 数字

    • 数字字符串
    • 科学记数法
    • 符号配置
    • 规范数字
    • 混合数字
    • 小数
    • 最大数
  • 7讲 数据类型 - 对象

  • 8讲 数据类型 - 布尔

  • 9讲 数据类型 - 日期

  • 10讲 变量

    • 局部变量
    • 百分比变量
    • ProcedureBlock使用
    • 进程私有Global
    • 使用^GETPPGINFO
    • 全局变量Global
    • 数组变量
    • 变量类型和转换
    • 使用#Dim定义变量类型
  • 11讲 运算符 - 逻辑运算符

    • 运算符符号表
    • 运算符优先级
    • 逻辑比较运算符
      • 逻辑表达式
      • Not运算符(')
  • 12讲 运算符 - 算术运算符

    • 一元运算符
    • 加法运算符(+)
    • 减法运算符(-)
    • 乘法运算符(*)
    • 除法运算符(/)
    • 求幂运算符(**)
    • 整除运算符(\)
    • 取余运算符(#
  • 13讲 关系运算符

    • 数值关系运算符
    • 小于<
    • 大于>
    • 大于等于>=
    • 小于等于<=
    • 字符串关系运算符
    • 等于=
    • 不等于'=
    • 包含[
    • 不包含'[
    • 跟随]
    • 不跟随']
    • 排序]]
    • 非排序']]
  • 14讲 运算符 - 模式匹配

    • 模式代码
    • 模式可以出现的次数
    • 多组模式
    • 组合模式
    • 交替模式
    • 使用不完整的模式
    • 多重模式解释
    • 非模式匹配运算符
    • 模式复杂性
  • 15讲 运算符 - 间接寻址

    • 名称间接寻址
    • 模式匹配间接寻址
    • 参数间接寻址
    • 下标间接寻址
    • $TEXT参数间接寻址
  • 16讲 命令梗概

    • 通用概念
    • 命令后置条件表达式
  • 17讲 命令 - 赋值命令

    • Set命令
    • Kill命令
      • 使用参数传递对KILL影响
    • Zkill命令
    • New命令
    • Merge命令
  • 18讲 命令 - 条件命令

    • ifelseifelse命令
    • IF中使用QUIT
    • IF中使用GOTO
  • 19讲 命令 - 循环命令

    • For命令
    • while命令
    • Do While命令
  • 20讲 命令 - 退出命令

    • Continue命令
    • Quit命令
    • Retrun命令
  • 21讲 命令 - 输出命令

    • WRITE命令
      • 有参数WRITE
      • 无参数WRITE
    • ZWRITE命令
    • ZZDUMP命令
    • ZZWRITE命令
    • WRITEZWRITEZZDUMPZZWRITE异同
  • 22讲 命令 - 调用命令

    • Do命令
  • 23讲 命令 - 调用命令 - JOB

  • 24讲 命令 - 调用命令 - JOB - 使用多进程

  • 25讲 命令 - 调用命令 - JOB - 消息队列

  • 26讲 命令 - 调用命令 - XECUTE命令

  • 27讲 命令 - 调用命令 - GOTO命令

  • 28讲 方法 - 方法概念

    • Routines
    • Subroutines
    • Functions
    • Label
    • Procedures
    • Methods
    • ClassMethods
    • SystemFunctions
    • Program
    • 简单区别
  • 29讲 参数 - 参数传递

    • 按值传递
    • 按引用传递
    • 可变参数
  • 30讲 嵌入式代码

    • 嵌入式HTML
    • &html标记语法
    • 嵌入式JavaScript
    • 嵌入式SQL
  • 31讲 多维数组

    • 什么是多维数组
    • 多维树形结构
    • 稀疏多维存储
    • 多维数组的设置
    • 操作多维数组
    • 多维数组,进程全局变量,全局变量效率对比
  • 32讲 系统函数梗概

  • 33讲 分隔函数 $PIECE

    • 两种用法
    • 使用SET $PIECE替换子字符串
  • 34讲 截取函数 $EXTRACT

    • 两种用法
    • 使用SET $EXTRACT替换子字符串
    • DTM模式下的$EXTRACT
  • 35讲 长度函数 $LENGTH,对齐函数 $JUSTIFY,查找函数 $FIND,反转函数 $REVERSE

  • 36讲 转换函数 $ZCONVERT

  • 37讲 替换函数 $REPLACE$TRANSLATE$CHANGE

    • 比较$CHANGE$REPLACE$TRANSLATE函数
  • 38讲 数组函数 - $LISTBUILD

    • SET $LISTBUILD
  • 39讲 数组函数 - $LIST

    • $List错误情况
    • 使用SET $LIST替换元素
  • 40$LIST$EXTRACT$PIECE区别

  • 41讲 数组函数 - $LISTDATA

  • 42讲 数组函数 - $LISTFIND

  • 43讲 数组函数 - $LISTGET

  • 44讲 数组函数 - $LISTLENGTH

  • 45讲 数组函数 - $LISTNEXT

  • 46讲 效率 - 对比遍历取值$LISTDATA$LIST,$LISTGET,$LISTNEXT

  • 47讲 数组函数 - $LISTSAME

  • 48讲 数组函数 - $LISTFROMSTRING,$LISTTOSTRING

  • 49讲 数组函数 - $LISTUPDATE

  • 50讲 数组函数 - $LISTVALID

  • 51讲 示例 - 结合所有列表函数 - 总结

  • 52讲 正则表达式

    • 通配符
    • 限定符
    • 字符组区间
    • 特殊字符
    • 取反
    • 单字母字符类型
    • 字词边界
    • 字符串开始或结束
    • 分组
  • 53讲 正则表达式函数 - $MATCH

    • Unicode属性字符类型
    • POSIX字符类型
    • 分组构造
    • 字符边界
    • 十六进制表示法
    • 八进制表示法
    • Unicode表示法
      • 汉字 Unicode 编码范围
    • 控制字符表示法
    • 符号表示法
    • 模式
      • Case模式
      • 单行模式
      • 文本模式
    • 注解
      • 行内注释
      • 行末注释
    • 错误信息
  • 54讲 正则表达式函数 - $LOCATE

  • 55讲 正则表达式函数 - $ZSTRIP

  • 56讲 正则表达式类 - %Regex.Matcher

  • 57讲 对比 MATCHLOCATEZSTRIP%Regex.Matcher异同

  • 58讲 什么是宏?宏的简单使用

    • 什么是宏?
    • 宏命名规范
    • 宏的空格规范
    • 宏的简单使用
  • 59讲 .inc文件的使用

    • 如何创建inc文件
    • 如何引用外部宏
  • 60讲 宏预处理器 - 定义指令 - #Def1Arg#Define#Dim##Continue

  • 61讲 宏预处理器 - 条件指令 - #If#ElseIf#Else#EndIf#IfDef#IfNDef#UnDef

  • 62讲 宏预处理器 - 编译指令 - #Execute##Expression##SafeExpression##Function##Lit

    • 异同
  • 63讲 宏预处理器 - SQL指令 - #Import#SQLCompile Audit#SQLCompile Mode#SQLCompile Path#SQLCompile Select##SQL

    • #Import#SQLCompile 区别
  • 64讲 宏预处理器 - 其他指令 - #Include#Show#NoShow#;##;##Quote##Unique

  • 65讲 使用系统宏

    • %occStatus.inc内的宏
  • 66讲 如何使用 %Status 数据类型

  • 67讲 锁 - LOCK命令

    • 什么是锁?
    • 怎么实现这个锁?
    • 锁的分类
    • LOCK 命令
      • 参数
  • 68讲 锁 - LOCK 命令的两种基本形式

    • LOCK命令的两种基本形式
      • 不带参数的锁
      • 有参数锁
  • 69讲 锁 - 独占锁

  • 70讲 锁 - 共享锁

  • 71讲 锁 - 升级锁

  • 72讲 锁 - 立即解锁

  • 73讲 锁 - 延迟解锁

  • 74讲 锁 - 增量锁

  • 75讲 锁 - 锁类型总结

  • 76讲 锁 - ^$LOCK 结构化系统变量

  • 77讲 锁 - 使用Portal管理锁

    • 查看锁表
    • 使用锁表删除锁
    • 其他方式删除锁
  • 78讲 锁 - 使用^LOCKTAB实用程序

    • 输入"?",显示帮助信息:
    • 使用命令D删除一个锁。
    • 使用命令J删除进程中的所有锁。
    • 使用命令C删除系统中的所有锁。
    • 使用命令A删除所有锁。
  • 79讲 锁 - 等待锁

    • 多进程父子节点加锁
    • 多进程父子节点加锁顺序
  • 80讲 锁 - 死锁

    • 什么是死锁
    • 死锁
    • 预防死锁
    • 解决死锁
  • 81讲 锁 - 注意点总结

  • 82讲 代码规范 - 变量

  • 83讲 代码规范 - 方法

  • 84讲 代码规范 - 类

  • 85讲 代码规范 - 锁

  • 86讲 代码规范 - 事务

  • 87讲 代码规范 - 陷阱

  • 88讲 代码规范 - 空行

  • 89讲 代码规范 - 格式

  • 90讲 代码规范 - 注释

  • 91讲 事务 - 什么是事务? 事务的特性

    • 什么是事务?
    • 事务的特性
    • 事务嵌套的层数
    • 事务与日志的同步提交
  • 92讲 事务 - 事务命令

    • TSTART
    • TCOMMIT
    • TROLLBACK
    • 回滚错误<ROLLFAIL>的几种情况
    • SQL命令与ObjectScript命令对照
  • 93讲 事务 - 什么可回滚,什么不可回滚?

    • 事务不可回滚
    • 事务锁
  • 94讲 事务 - SQL 事务命令

    • SET TRANSACTION
    • START TRANSACTION
    • COMMIT
    • ROLLBACK
    • SAVEPOINT
    • %INTRANSACTION
  • 95讲 事务 - $TLEVEL 变量

    • Terminal显示事务层数
    • SQL命令和$TLEVEL
  • 96讲 事务 - 嵌套事务的几种情况

  • 97讲 事务 - 事务使用的基本示例

  • 98讲 事务 - 事务提交方式

    • IMPLICIT 显式事务(自动事务)
    • EXPLICIT 隐式事务(关闭自动事务)
    • NONE 没有自动事务处理
  • 99讲 事务 - 并发事务带来的问题 - 脏读

  • 100讲 事务 - 并发事务带来的问题 - 丢失更新

  • 101讲 事务 - 并发事务带来的问题 - 不可重复读

  • 102讲 事务 - 并发事务带来的问题 - 幻读

  • 103讲 事务 - 并发事务带来的问题总结

    • 通俗解释
    • 不可重复读和脏读、幻读的区别
    • 不可重复读和脏读的区别
    • 不可重复读和幻读区别
  • 104讲 事务 - 隔离级别 - READ UNCOMMITTED

    • READ UNCOMMITTED(读取未提交数据)
  • 105讲 事务 - 隔离级别 - READ COMMITTED

    • READ COMMITTED(读取已提交数据)
  • 106讲 事务 - 隔离级别 - REPEATABLE READ

    • REPEATABLE READ(可重复读)
  • 107讲 事务 - 隔离级别 - SERIALIZABLE

    • SERIALIZABLE(可串行化)
  • 108讲 事务 - 隔离级别 - 总结

    • SNAPSHOT:快照
    • 数据库隔离级别总结
    • 实现事务隔离级别时加锁原理总结
  • 109讲 事务 - 查看事务日志 - 增删改对日志的影响

    • 查看日志
    • 在日志中查看INSERT数据
    • 在日志中查看UPDATE数据
    • 在日志中查看DELETE数据
    • 在日志中查看声明的事务
    • 在日志中查看嵌套事务
  • 110讲 事务 - 通过日志恢复被删除的数据

    • 模拟删表操作
    • 如何恢复数据
  • 111讲 事务 - 开放性事务原理以及如何检测开放性事务

    • 问题
    • 定义
    • 模拟开放性事务
    • 开放性事务状态
    • 发生开放性事务的几种可能
    • 开放性事务能带来哪些问题
    • 如何判断开放性事务
    • 如何解决开放性事务
  • 112讲 错误处理 - TRY 命令

    • TRY - CATCH机制
  • 113讲 错误处理 - CATCH 命令

    • CATCH命令有两种形式
      • 有参数CATCH
      • 无参数CATCH
  • 114讲 错误处理 - THROW 命令

    • 有参数THROW
    • 无参数THROW
  • 115讲 错误处理 - ZTRAP 命令

  • 116讲 错误处理 - $ZTRAP 变量

  • 117讲 错误处理 - 错误处理的工作机制原理

  • 118讲 错误处理 - $ETRAP 变量

  • 119讲 错误处理 - $ZERROR 变量以及常见错误类型

    • 显示$ze格式错误
    • 错误的附加信息
  • 120讲 错误处理 - $ECODE 变量

  • 121讲 错误处理 - $THROWOBJ 变量

  • 122讲 错误处理 - TRY - CATCH,$ZTRAP,$ETRAP区别与错误处理工具推荐

  • 123讲 错误处理 - 堆栈 - $STACK 变量

  • 124讲 错误处理 - 堆栈 - $ESTACK 变量

  • 125讲 错误处理 - 堆栈 - $STACK 函数

    • $STACK的单参数形式
    • $STACK的两个参数形式
  • 126讲 错误处理 - 堆栈 - 手写记录错误堆栈调用信息

  • 127讲 错误处理 - 堆栈 - Terminal中显示程序堆栈信息

    • Terminal字母代码
  • 128讲 错误处理 - 堆栈 - %Stack 实用程序

  • 129讲 错误处理 - 使用系统日志并查看错误堆栈信息

  • 130讲 错误处理 - 使用%ERN查看应用程序错误日志

  • 131讲 错误处理 - 常见的返回值错误处理

    • 用分隔符返回错误代码与描述信息。常见的分隔符^,等。
      • JSON处理错误方式返回。
      • %Status方式返回。
      • SQLCODE方式返回错误。
  • 132讲 错误处理 - 手写通用错误异常处理方式,包含日志,堆栈。

    • $ZtrapTry-Catch双保险方式捕捉异常
    • 原理
    • $Ztrap方式捕捉ZTrap抛出异常
  • 133讲 调试 - BREAK 命令 - 基本使用

    • BREAK命令有三种形式
    • 无参BREAK
  • 134讲 调试 - BREAK 命令 - 逐步逐行调试

    • BREAK Extended 参数以设置常规断点
  • 135讲 调试 - BREAK 命令 - 中断运行中的程序

    • Flag参数
  • 136讲 调试 - ZBREAK 命令 - 基本使用

    • 基本语法
    • ZBREAK帮助文档
    • 无参数ZBREAK
    • BREAKZBREAK的区别
  • 137讲 调试 - ZBREAK 命令 - 使用断点和监视点

    • 建立断点和监视点
    • action参数值
  • 138讲 调试 - ZBREAK 命令 - 跟踪并输出监视变量值

    • 跟踪并输出监视变量值
  • 139讲 调试 - ZBREAK 命令 - 将调试信息输出到日志txt

    • 将调试信息输出到日志txt
  • 140讲 调试 - 使用Stuido调试

  • 141讲 调试 - 使用监视窗口与监视点

    • 调试菜单
    • 监视窗口
    • 监视点
  • 142讲 调试 - 根据进程调试

  • 143讲 调试 - 调试CSP页面

  • 144讲 - 类 - 包 - 定义

    • 概念
    • 定义包
    • 注意事项
  • 145讲 - 类 - 包 - 包映射

    • 映射通用包
  • 146讲 - 类 - 包 - 使用包

    • 在类中引用包
    • 导入包
    • ObjectScript方法中引入包
  • 147讲 类 - 参数 - 定义使用类参数

    • 概念
    • 使用场景
    • 定义参数
    • 使用参数值
  • 148讲 类 - 参数 - 类参数类型

    • 运行时计算的类参数
    • 编译时计算的类参数
  • 149讲 类 - 参数 - 运行时更改类参数值与参数关键字

    • 在运行时更改类参数
    • 参数关键字
  • 150讲 类 - 方法 - 定义方法

    • 概念
    • 类别
    • 定义方法
    • 方法参数
  • .第151讲 类 - 方法 - 使用类方法与实例方法

  • 152讲 类 - 方法 - 方法关键字

    • 方法关键字列表
    • 关键字Language - 指定实现语言
    • 关键字CodeMode - 方法实现方式
    • 关键字SqlProc - 将方法映射为存储过程
    • 关键字SqlName - 自定义存储过程名称
    • 关键字Abstract - 抽象方法
    • 关键字Final - 指定方法为最终方法
    • 关键字Private - 指定方法为私有方法
  • 153讲 方法生成器 - 原理

  • 154讲 方法生成器 - 可用对象简介与示例

    • 方法生成器可用对象
    • 定义方法生成器示例
  • 155讲 方法生成器 - 父子类中的区别

    • 方法生成器在父子类中的区别
  • 156讲 类 - 对象 - %RegisteredObject

    • 对象类
    • OREF
  • 157讲 类 - 对象 - %RegisteredObject类常用方法

  • 158讲 类 - 对象 - 继承与父类类型转换

  • 159讲 类 - 属性 - 简介

    • 定义属性
    • 使用对象属性
    • i%PropertyName(实例变量)
  • 160讲 类 - 属性 - 常用关键字

    • 属性关键字列表
    • InitialExpression关键字 - 设置属性定义初始值
    • Required关键字 - 设置属性字段不能为null
    • MultiDimensional - 关键字定义多维属性
    • Aliases - 为属性指定别名
    • ReadOnly - 指定属性为只读
  • 161讲 类 - 属性 - 计算属性

    • SqlComputed关键字与SqlComputeCode关键字
    • SqlColumnNumber关键字设置属性的SQL列号
    • SqlFieldName设置SQL字段名
    • 使用关键字定义计算代码
    • 使用回调方法定义计算代码
    • SqlComputeOnChange关键字
    • Transient关键字
    • Calculated关键字
  • 162讲 类 - 属性 - 属性访问器

    • 设置属性访问器
    • 通过IDE创建属性访问器
    • 重写属性获取器方法
    • 对象属性的属性访问器
    • PropGetStored() 方法 - 直接从磁盘加载数据
    • 测试效率对比
  • 163讲 类 - 数据类型类 - 简介

    • 数据类型类的类型
    • 数据类型类的功能
    • 数据类型类的区别
    • 常用的数据格式类型
  • 164讲 类 - 数据类型类 - 常用数据类型与映射

    • 什么是ODBC,JDBC
    • 常用数据类型类
    • 常用数据类型映射
    • SqlCategory映射数据类型类
    • OdbcType映射数据类型类
    • ClientDataType分组的数据类型类
  • 165讲 类 - 数据类型 - 属性方法

    • 使用属性方法
  • 166讲 类 - 数据类型 - 数据类型参数

    • 数据类型参数
    • 常用数据类型类可使用参数
    • 使用参数
    • 参数使用示例
  • 167讲 类 - 数据类型 - 自定义数据类型类

  • 168讲 类 - %Persistent - 持久类简介与定义

    • 简介
    • 定义持久类
    • 包映射模式
    • 持久类与SQL映射关系
    • 保存对象标识符:IDOID
    • 持久类成员
  • 169讲 类 - %Persistent - Storage定义与Storage

    • %Storage.Persistent存储类
    • %Storage.SQL 存储类
    • %Storage.Persistent%Storage.SQL区别
    • 注意事项
  • 170讲 类 - %Persistent - Global使用

  • 171讲 类 - %Persistent - 生成ID相关事项

  • 172讲 类 - %Persistent - 哈希Global

  • 173讲 类 - %Persistent - 子类拓展使用

    • 持久类子类数据存储情况
      • 父子类均为持久类
      • 父类NoExtent子类持久类
  • 174讲 类 - %Persistent - 常用关键字

    • SqlTableName关键字 - 设置表名称
    • SqlRowIdName关键字 - 设置ID列名称
    • SqlRowIdPrivate关键字 - 隐藏ID
    • StorageStrategy关键字 - 指定Storage
    • DdlAllowed关键字 - 指定是否可以使用DDL语句
  • 175讲 类 - %Persistent - 持久类常用方法

    • %Save() - 保存对象
    • %Save()方法执行逻辑详解
    • %Save()回滚
    • %Save() 事务
    • %Id() - 返回持久对象ID
    • %Oid() - 返回持久对象OID
    • %ExistsId() - 测试持久对象ID是否存在
    • %OpenId - 打开保存的对象
    • 多次调用相同ID的%OpenId()情况分析
    • %Reload() - 重新加载对象
    • %DeleteId() - 根据ID删除保存的对象
    • %Delete() 根据OID删除保存的对象
    • %DeleteExtent() - 删除所有保存的对象
    • %KillExtent() - 强制删除该表数据
    • READONLY 参数 - 指定数据库为只读
  • 176讲 类 - %Persistent - Swizzling

    • Swizzling - 懒加载、交错存储、重组存储
  • 177讲 类 - %Persistent - Extent查询

  • 178讲 类 - %Persistent - 并发分析

    • 为什么使用并发参数
    • 设置并发的几种方式
    • 可以用的并发值
      • concurrency 设置为 0 - 无锁。
      • concurrency 设置为 1 - 保存后获取独占锁。
      • concurrency 设置为 2 - 与1相同
      • concurrency 设置为 3 - 总是获取共享锁。
      • concurrency 设置为 4 - 总是获取独占锁。
    • 通过$system.OBJ.SetConcurrencyMode设置当前进程并发值
    • 并发参数的代替方法
  • 179讲 类 - %Persistent - 使用列存储

  • 180讲 类 - 集合 - 简介

    • 集合的类型
    • 集合属性
    • 独立集合
  • 181讲 类 - 集合 - 使用列表集合

    • 使用列表List集合
  • 182讲 类 - 集合 - 使用数组集合

    • 使用数组Array集合
  • 183讲 类 - 集合 - 在持久类中使用基础数据列表

    • 持久类中集合属性的SQL映射
    • 使用基础数据list列表
  • 184讲 类 - 集合 - 在持久类中使用对象列表

    • 使用对象list列表
  • 185讲 类 - 集合 - 在持久类中使用序列化列表

    • 使用序列化list列表
  • 186讲 类 - 集合 - 在持久类中使用基础数据数组

    • 使用基础数据array数组
  • 187讲 类 - 集合 - 在持久类中使用对象数组

    • 使用对象array数组
  • 188讲 类 - 集合 - 在持久类中使用序列化数组

    • 使用序列化array数组
  • 189讲 类 - 集合 - 集合属性参数

    • 集合属性参数
      • STORAGEDEFAULT参数
      • SQLTABLENAME参数
      • SQLPROJECTION参数
  • 190讲 流 - 简介

    • 常用流对象
    • 二进制流和文本流的区别
  • 191讲 流 - 在持久类中使用流属性

  • 192讲 流 - 常用方法和属性

    • %Stream - 流常用方法和属性

      • Read() - 从流的当前位置开始读取指定数量的字符。
      • Write() - 从当前位置开始,将数据追加到流中。如果位置未设置为流的末尾,则覆盖现有数据。
      • Rewind() - 移至流的开头。
      • NewFileName() - 为%Stream.FileCharacter%Stream.FileBinary属性指定文件名。
    • 常用的属性

      • AtEnd - 当读取遇到数据源的末尾时,设置为true
      • Id - 在%Location指定的范围内,流实例的唯一标识符。
      • Size - 流的当前大小(以字节或字符为单位,取决于流的类型)。
  • 193讲 流 - 流中指定编码格式

    • TranslateTable - 指定读取或写入%Stream.FileCharacter流的字符集编码类型。
    • Filename - %Stream.FileBinary流当前使用的文件名,文件名包含路径+文件名。
  • 194讲 流 - 复制视频文件

    • CopyFrom() - 所有流都包含一个CopyFrom()方法,该方法复制一个流填充到另一流。
    • LinkToFile()- 类似于Filename 属性,将文件流连接到名为Filename 的文件。如果指定的文件不存在,则在%Save()后创建。
  • 195讲 流 - 在已有文件中追加数据

    • MoveToEnd() - 移动到流的末尾。
    • %Save() - 当将流类用作独立对象时,使用%Save()方法来保存流数据。
  • 196讲 流 - 使用gzip压缩文件

  • 197讲 流 - 通过嵌入式对象写入流

    • 通过嵌入式SQL读取流
    • 通过嵌入式SQL写入流
  • 198讲 流 - 使用压缩流

  • 199%SerialObject - 序列化对象简介

    • 对象组合
  • 200%SerialObject - 序列化对象使用

    • 定义序列化对象
    • 使用序列化类
  • 201讲 类 - XData - 介绍使用

    • 结构
    • 关键字
    • 使用XData
      • XML示例
      • JSON示例
      • YAML 示例
  • 202讲 类 - Projection映射 - 介绍使用

    • 使用类映射
  • 203讲 类 - 关系 - 简介

    • 类型
    • 定义关系
    • 关系属性如何保存
  • 204讲 类 - 关系 - 定义一对多关系

  • 205讲 类 - 关系 - 删除一对多关系

  • 206讲 类 - 关系 - 使用关键字OnDelete

  • 207讲 类 - 关系 - 定义主子关系

  • 208讲 类 - 关系 - 删除主子关系

  • 209讲 类 - 关系 - 在SQL查询中使用关系

  • 210讲 类 - 关系 - 使用关系定义多对多关系

  • 211讲 类 - 关系 - 使用外键定义多对多关系

  • 212Query - 简介与基本使用

  • 213Query - 自定义Query基本使用

  • 214Query - 通过%SQL.Statement,%ResultSet使用Query

    • 使用%SQL.Statement对象调用Query
    • 使用%ResultSet对象调用Query
  • 215Query - 通过Json数据或方法动态生成Query

  • 216Query - 通过Select Sql语句动态生成Query

  • 217Query - 通过Query生成动态Query

  • 218Query - 支持传统的Query并通过参数形式生成Query

  • 219Query - 定义通用Query,只需要实现Exceute方法

  • 220Query - 通过Query生成Json,通过Query生成Csv

  • 221讲 生命周期回调方法 - 从新建到保存

    • 回调方法列表

      • %OnNew()
      • %OnAddToSaveSet()
      • %OnBeforeSave()
      • %OnAfterSave()
      • %OnSaveFinally()
      • %OnValidateObject()
      • %OnRollBack()
      • %OnClose()
    • %Save回调示例

  • 222讲 生命周期回调方法 - 从打开到删除

    • %OnOpen()
    • %OnOpenFinally()
    • %OnReload()
    • %OnConstructClone()
    • %OnAfterDelete()
    • %OnDelete()
    • %OnDeleteFinally()
    • %Delete示例
  • 223讲 生命周期回调方法 - 索引

    • %OnBeforePurgeIndices()
    • %OnAfterPurgeIndices()
    • %OnBeforeBuildIndices()
    • %OnAfterBuildIndices()
    • %BuildIndices示例
  • 224讲 填充工具 - Populate实用程序简介

    • %Library.PopulateUtils填充方法列表
    • 数据填充
    • Populate()方法简介
  • 225讲 填充工具 - 集合属性

    • 集合属性
  • 226讲 填充工具 - 引用序列化对象的属性

  • 227讲 填充工具 - 关系

    • 一对多关系
    • 主子关系
    • 填充顺序
  • 228讲 填充工具 - 引用持久对象的属性

  • 229讲 填充工具 - 为非集合属性指定POPSPEC参数

  • 230讲 填充工具 - 为列表属性指定POPSPEC参数

  • 231讲 填充工具 - 为数组属性指定POPSPEC参数

  • 232讲 填充工具 - 通过SQL表指定POPSPEC参数

  • 233讲 填充工具 - 基于另外一个属性生成

  • 234讲 动态派发

    • 动态派发方法
      • %DispatchMethod()
      • %DispatchClassMethod()
      • %DispatchGetProperty()
      • %DispatchSetProperty()
      • %DispatchSetMultidimProperty()
  • 235讲 动态派发 - 动态属性示例

  • 236JSON - 简介

    • 动态JSON简介
    • JSON简单使用示例
      • 创建和操作动态实体
  • 237JSON - 使用JSON文本构造器

    • 使用字符串JSON构造函数创建动态实体
    • 使用JSON文本构造器
  • 238JSON - 使用动态表达式和点语法

    • 使用动态表达式和点语法
    • 使用点语法创建动态对象属性
    • 使用点语法创建动态数组元素
  • 239JSON - 使用 %Set(), %Get(), %Remove()

    • 使用 %Set(), %Get(), %Remove()
    • 使用%Set()%Get()%Remove()以编程方式指定JSON的键和值
    • 使用%Get()%Remove()检索嵌套的动态实体
    • 删除对象属性
    • 删除数组元素
  • 240JSON - 链式动态实体方法

  • 241JSON - 错误处理

  • 242JSON - 序列化与反序列化

    • 将动态实体转换JSON字符串
    • JSON字符串反序列化为动态对象
    • 在嵌套复杂动态实体和JSON字符串之间进行转换
  • 243JSON - 克隆JSON对象

  • 244JSON - 迭代JSON

    • 使用%GetNext()遍历动态实体
    • 遍历数组
    • 遍历对象
  • 245JSON - 解决JSON字符串超长问题

    • 将大型动态实体序列化为流
    • 读取和写入Global字符流
    • Json写入文件流
  • 246JSON - 动态数组中的null

  • 247JSON - 在数组中使用%Remove

  • 248JSON - 使用%Size()的数组迭代

  • 249JSON - 使用%IsDefined()测试有效值

  • 250JSON - 在动态数组中使用%Push%Pop

    • 使用%Push()%Pop()构建一个数组并销毁
  • 251JSON - 处理JSON 数据类型

    • 使用%GetTypeOf()返回值的数据类型
    • 迭代和数据类型检测
    • 区分动态数组,动态对象和oref
  • 252JSON - 用%Set()%Push()重写覆盖默认数据类型

    • %Set()%Push()重写覆盖默认数据类型
  • 253JSON - 解析JSON空值和布尔值

    • 解析JSON空值和布尔值
  • 254JSON - 解决Null、空字符串和未赋值

    • 解决Null、空字符串和未赋值
  • 255JSON - 动态实体方法概览

    • 创建、读取、更新、删除

      • %Set() 可以更改现有动态实体成员属性或元素的值,也可以创建新成员并为其赋值。
      • %Remove() 删除现有成员。
      • %Get() 检索成员的值。
    • 迭代数组

      • %GetIterator() 返回一个迭代器,其中包含指向动态实体每个成员的指针。
      • %GetNext() 返回迭代器标识的成员的键和值,并将光标移到下一个成员。
      • %Size() 返回成员数包括数组中未分配的元素。
      • %IsDefined() 测试成员是否具有指定的值。
    • 堆栈功能

      • %Push() 将新元素添加到动态数组的末尾。
      • %Pop() 删除数组的最后一个元素并返回其值。这些方法不适用于动态对象,因为对象属性不是按可预测的顺序存储的。
    • 序列化和反序列化

      • %FromJSON()JSON字符串转换为动态实体。
      • %FromJSONFile()
      • %ToJSON() 将动态实体序列化为规范JSON字符串。
    • 数据类型

      • %GetTypeOf() 返回一个字符串,该字符串指示指定成员值的数据类型。%Set()%Push()提供一个可选的第三个参数来显式地指定值的数据类型。
  • 256JSON - %JSON.Adaptor - 简介,对象与JSON互转

    • 导入导出
    • 实体类继承%JSON.Adaptor
    • 将对象导出为JSON字符串
    • JSON字符串导入到对象中
  • 257JSON - %JSON.Adaptor - 使用参数映射

    • %JSONFIELDNAME
    • %JSONINCLUDE
    • %JSONIGNOREINVALIDFIELD
    • %JSONIGNORENULL
    • %JSONNULL
    • %JSONREFERENCE
    • %JSONIGNOREINVALIDFIELD
  • 258JSON - %JSON.Adaptor - 使用XData映射块

    • 定义扩展数据映射块
  • 259JSON - %JSON.Adaptor - 格式化JSON

    • 格式化JSON
  • 260%Dictionary - 是什么怎么用

    • 类别
    • 判断类关键字是否存在
    • 查看类定义
    • 修改类定义
  • 261%Dictionary - 类成员对应哪些表

    • 类定义类说明
1
0 224
问题 争取在天亮前起床 · 三月 15, 2024

日志总是出现如下“严重”级别报错,这个错误要紧吗?

03/13/24-09:44:12:182 (39059) 2 [SYSTEM MONITOR] WriteDaemon Alert: Write Daemon still on pass 581

在 Documentation 里搜索关键词也只有如下信息,哪里还能找到更详细的教程或说明呢?

SYS.History.WriteDaemon — The properties in this class describe the performance of write daemon cycles. The system automatically keeps track of the last 20 write daemon cycles, and the History Monitor stores the data for the cycles that occurred in each interval. Typically, there are multiple cycles within each interval.

Cache 的资料太少了,想买本书来学习都买不到。

2
0 195
文章 聆严 周 · 九月 30, 2022 11m read

使用Prometheus监控Cache集群

Executive Summary

生产级别的Cache集群往往由多个Cache实例组成,而Cache自带的管理界面不能满足对整个集群的监控,因此在实际使用中,往往需要投入人力对实例进行性能巡检。即便如此,这种巡检模式实时性低、告警的漏报错报率高、对既往数据追溯能力差。针对Cache/IRIS集群管理的这一缺憾,本文提出以Prometheus监控Cache集群的方案,最终实现了对集群全实例监控指标的自动化采集,以及准实时监控数据展示和告警提示。

监控大屏3.主机实例监控

Prometheus及Grafana简介

Prometheus是一个开源的监控收集框架。它内置了一个数据收集服务、一个时序数据库、和一个Web UI管理界面。 Prometheus采用PULL模式拉取监控数据,使得它在众多监控解决方案中脱颖而出。这种PULL模式只需被监控对象暴露出符合Prometheus要求的接口即可,而无需配置监控服务器地址,也无需管理定时任务,对应用程序的侵入性极小。 Prometheus也有一个健全的生态。它提供各种管理接口API,如自动服务发现、告警、查询等接口,和已有开源软件互操作性好,也方便接入机构内部系统。其中Grafana是最重要的生态伙伴,它是一个开源的数据可视化工具,支持动态的更改数据源、灵活地配置报表、编写Prometheus查询语句、定义告警等。因为这些特性,它常用于性能监控领域。

下图是Prometheus的典型架构,本文只关注其中红色部分。

Prometheus Architecture

Cache常用监控指标

本文总结了License使用量、Ensemble队列消息排队数量、事务持续时长、数据库可用空间,这4个常用的数值类型的监控指标,这四个指标直接影响或指示出系统的健康程度。以下是这四个指标的获取方法。

  • License使用量
s LicenseUsed=##class(%SYSTEM.License).LUConsumed()
s LicenseAvailable=##class(%SYSTEM.License).LUAvailable()
s LicenseTotal=##class(%SYSTEM.License).GetUserLimit()
  • Ensemble队列消息排队数量
Set statement=##class(%SQL.Statement).%New(1)
Set sc=statement.%PrepareClassQuery("Ens.Queue","Enumerate")
Set rset=statement.%Execute()
  • 事务持续时长
set rs=##class(%ResultSet).%New()
set rs.ClassName="%SYS.Journal.Transaction"
set rs.QueryName="List"
set sc=rs.Execute(0)
  • 数据库可用空间
Set statement=##class(%SQL.Statement).%New(1)
Set sc=statement.%PrepareClassQuery("%SYS.DatabaseQuery","FreeSpace")
Set rset=statement.%Execute()

Cache中Prometheus接口定义

本文实现了Prometheus接口。该接口中的jsonToPrometheus()方法将JSON转换为Prometheus需要的格式,为后期扩展出通用的Prometheus监控指标采集和埋点提供了基础。接口定义如下,

Class HospModule.HxeyPrometheusMetrics.RestController Extends %CSP.REST
{

XData UrlMap
{
<Routes>
    <Route Url="/prometheus" Method="GET" Call="MetricsPrometheus" />
    <Route Url="/json" Method="GET" Call="MetricsJson" />
  </Routes>
}

ClassMethod MetricsPrometheus() As %Status
{
    set %response.ContentType="text/plain;version=0.0.4;charset=utf-8"
    s json=..getMetricsJson()
    s iter=json.%GetIterator()
    while iter.%GetNext(.key, .value) { 
        s promStr = ..jsonToPrometheus(value)
        w promStr
    }
    return $$$OK
}

ClassMethod MetricsJson() As %Status
{
    s json=..getMetricsJson()
    w json.%ToJSON()
    return $$$OK
}

/// Requires JSON format in this form: {"name":"hxey_ics_license_used","tags":[{"name","","value":""}],"desc":"已用License数","value":0}
ClassMethod jsonToPrometheus(json) As %String
{
    s retStr = ""
    s name=json.name
    s desc=json.desc
    s value=json.value
    s tags=json.tags

    s retStr = retStr_"# HELP "_name_" "_desc
    s retStr = retStr_$CHAR(10)
    s retStr = retStr_"# TYPE "_name_" gauge"
    s retStr = retStr_$CHAR(10)
    if (tags.%Size()=0) {
        s retStr = retStr_name_" "_value
        s retStr = retStr_$CHAR(10)
    } else {
        s retStr = retStr_name_"{"
        s iter2=tags.%GetIterator()
        while iter2.%GetNext(.key, .tag) { 
            s tagName=$REPLACE(tag.name,"""","")
            s tagValue=$REPLACE(tag.value,"""","")
            s retStr = retStr_tagName_"="""_tagValue_""","
        }
            
        s retStr = retStr_"} "_value
        s retStr = retStr_$CHAR(10)
    }
    return retStr
}

ClassMethod getMetricsJson() As %DynamicAbstractObject
{
    s json=[]
    IF (##class(%Dictionary.CompiledClass).%ExistsId("%SYSTEM.License")) {
        s LicenseUsed=##class(%SYSTEM.License).LUConsumed()
        s item={"name":"hxey_ics_license_used","tags":"","desc":"已用License数","value":0}
        s item.tags = []
        s item.value = LicenseUsed
        d json.%Push(item)

        s LicenseAvailable=##class(%SYSTEM.License).LUAvailable()
        s item={"name":"hxey_ics_license_avail","tags":"","desc":"可用License数","value":0}
        s item.tags = []
        s item.value = LicenseAvailable
        d json.%Push(item)

        s LicenseTotal=##class(%SYSTEM.License).GetUserLimit()
        s item={"name":"hxey_ics_license_total","tags":"","desc":"License总量","value":0}
        s item.tags = []
        s item.value = LicenseTotal
        d json.%Push(item)

        s item={"name":"hxey_ics_license_load","tags":"","desc":"License占用率","value":0}
        s item.tags = []
        s item.value = (LicenseUsed/(LicenseAvailable+LicenseUsed)) 
        d json.%Push(item)
    }

    s maxDuration=0
    IF (##class(%Dictionary.CompiledClass).%ExistsId("%SYS.Journal.Transaction")) {
        set rs=##class(%ResultSet).%New()
        set rs.ClassName="%SYS.Journal.Transaction"
        set rs.QueryName="List"
        set sc=rs.Execute(0)
        while (rs.%Next()) {
            s pid = rs.Data("Pid")
            s StartTime = rs.Data("StartTime")
            s now=$H

            s item={"name":"hxey_ics_transaction_duration","tags":"","desc":"事务持续时间","value":0}
            s item.tags = []
            s tag={}
            s tag.name="pid"
            s tag.value=pid
            d item.tags.%Push(tag)
            s tag={}
            s tag.name="ip"
            s tag.value=##class(%SYSTEM.Process).ClientIPAddress(pid)
            d item.tags.%Push(tag)
            s duration = (+now)*3600*24+$P(now,",",2)-((+StartTime)*3600*24+$P(StartTime,",",2))
            s:duration>maxDuration maxDuration=duration
            s item.value = duration
            d json.%Push(item)
        }
    }

    s item={"name":"hxey_ics_transaction_maxduration","tags":"","desc":"最长事务持续时间","value":0}
    s item.tags = []
    s item.value = maxDuration
    d json.%Push(item)

    IF (##class(%Dictionary.CompiledClass).%ExistsId("%SYS.DatabaseQuery")) {
        Set statement=##class(%SQL.Statement).%New(1)
        Set sc=statement.%PrepareClassQuery("%SYS.DatabaseQuery","FreeSpace")
        Set rset=statement.%Execute()
        while (rset.%Next()) {
            s dbName = rset.%Get("DatabaseName")
            s freeRate = rset.%GetData(7)
            s dbAvailMB = rset.%Get("AvailableNum")
            s diskAvailMB = rset.%Get("DiskFreeSpaceNum")

            s item={"name":"hxey_ics_db_load","tags":"","desc":"数据库可用空间占用率","value":0}
            s item.tags = []
            s tag={}
            s tag.name="name"
            s tag.value=dbName
            d item.tags.%Push(tag)
            s item.value = (100-freeRate) / 100
            d json.%Push(item)
        }
    }

    IF (##class(%Dictionary.CompiledClass).%ExistsId("Ens.Queue")) {
        Set statement=##class(%SQL.Statement).%New(1)
        Set sc=statement.%PrepareClassQuery("Ens.Queue","Enumerate")
        Set rset=statement.%Execute()
        while (rset.%Next()) {
            s name = rset.%Get("Name")
            s count = rset.%Get("Count")

            s item={"name":"hxey_ics_queue_load","tags":"","desc":"队列等待数量","value":0}
            s item.tags = []
            s tag={}
            s tag.name="name"
            s tag.value=name
            d item.tags.%Push(tag)
            s item.value = count
            d json.%Push(item)
        }
    }
    return json
}

}

接口服务配置如下,

Web Application Config

安装并运行Prometheus

Prometheus下载地址为https://prometheus.io/download/

安装过程如下,

  • 解压缩到安装目录。本文使用/opt/prometheus作为安装目录。下述子目录及文件均相对于该安装目录。

  • 修改配置文件prometheus.yml

    • 主要配置内容为采集间隔和采集接口列表,如下, imageimage

    • 其他配置,如告警管理服务器和告警规则,可以按需配置。本文使用Grafana配置告警,不在这里配置。

    • Prometheus启动后,会定时、或者在收到SIGHUP时重新加载该配置。

  • 启动后

    • 访问Web端口,默认ip:9090,可查看配置、服务运行情况。 image
  • 使用Systemd托管服务

    • 新增文件/usr/lig/systemd/system/prometheus.service,并写入如下内容,

      [Unit]
      Description=Prometheus Service
      After=network.target
      
      [Service]
      Type=simple
      User=app
      Restart=on-failure
      RestartSec=40s
      ExecStart=/opt/prometheus/prometheus \
              --config.file=/opt/prometheus/prometheus.yml \
              --storage.tsdb.path=/opt/prometheus/data \
              --storage.tsdb.retention=90d 
      ExecReload=/bin/kill -HUP $MAINPID
      KillMode=process
      
      [Install]
      WantedBy=multi-user.target
      
    • 添加为开机自动启动服务,在命令行执行 systemctl enable prometheus

    • 立刻启动服务,在命令行执行 systemctl start prometheus

    • 需要查看服务状态时,在命令行执行 systemctl status prometheus

    • 需要服务动态更新配置时,在命令行执行 systemctl reload prometheus

    • 需要关闭服务时,在命令行执行 systemctl stop prometheus

安装并运行Grafana

Grafana下载地址为https://grafana.com/grafana/download?pg=oss-graf&plcmt=resources

安装过程如下,

  • 解压缩到安装目录。本文使用/opt/grafana作为安装目录。下述子目录及文件均相对于该安装目录。

  • 修改配置文件conf/defaults.ini

    • 按需要修改文件存储地址,例如数据地址、日志地址。 image
    • 其他配置例如监听端口(http_port)、监听地址(http_addr)、数据库([database]章节)、接口安全配置([security]章节)都可以按需修改。
    • 默认情况,Grafana Web服务在ip:3000,使用内置SQLite数据库保存配置,接口无鉴权,默认管理员为admin
  • 启动后

    • 访问Web端口,默认ip:3000,可配置数据源、用户、报表,如下图。 image
  • 使用Systemd托管服务

    • 新增文件/usr/lig/systemd/system/grafana.service,并写入如下内容,

      [Unit]
      Description=Grafana Service
      After=network.target
      
      [Service]
      Type=simple
      User=app
      Restart=on-failure
      RestartSec=5s
      ExecStart=/opt/grafana/bin/grafana-server \
              -homepath=/opt/grafana \
              -config=/opt/grafana/conf/defaults.ini
      KillMode=process
      [Install]
      WantedBy=multi-user.target
      
    • 添加为开机自动启动服务,在命令行执行 systemctl enable grafana

    • 立刻启动服务,在命令行执行 systemctl start grafana

    • 需要查看服务状态时,在命令行执行 systemctl status grafana

    • 需要关闭服务时,在命令行执行 systemctl stop grafana

安装并运行Node Exporter

Prometheus生态中有一个Node Exporter,用于收集各操作系统的常用监控数据并暴露PULL接口。其下载地址和安装指南请参考https://grafana.com/oss/prometheus/exporters/node-exporter/

在实际应用时,Node Exporter提供的数据对不同操作系统略有差异,并且缺少必要的数据,例如与NTP时间服务器的时间偏置量。因此本文用Java实现了适合本机构的Node Exporter。为了实现稳定的跨操作系统的性能指标收集,使用 com.github.oshi:oshi-core:5.8.4库,示例代码如下,

    public double getLoad() {
        SystemInfo systemInfo = new SystemInfo();
        double load1 = systemInfo.getHardware().getProcessor().getSystemCpuLoadBetweenTicks(ticks);
        double load2 = systemInfo.getHardware().getProcessor().getSystemCpuLoadBetweenTicks(ticksLast);
        return Math.max(load1, load2);
    }

为了实现计算与NTP时间服务器的时间偏置量,使用commons-net:commons-net:3.8.0库,示例代码如下,

    public long getOffset() {
        NTPUDPClient ntpudpClient = new NTPUDPClient();
        ntpudpClient.setDefaultTimeout(5000);
        ntpudpClient.open();
        System.out.println(System.currentTimeMillis());
        InetAddress hostAddr = InetAddress.getByName(HOSTNAME);
        final TimeInfo info = ntpudpClient.getTime(hostAddr);
        ntpudpClient.close();
        info.computeDetails();
        return info.getOffset()
    }

接口实现效果如下,

# HELP hxey_memory_load 内存负载率
# TYPE hxey_memory_load gauge
hxey_memory_load{application="sysmetrics",hxey="hxey",} 0.42
# HELP disk_total_bytes Total space for path
# TYPE disk_total_bytes gauge
disk_total_bytes{application="sysmetrics",hxey="hxey",path="C:\\Users\\Administrator\\Desktop\\servermetrics\\.",} 2.78802722816E11
# HELP hxey_memory_total 内存总大小
# TYPE hxey_memory_total gauge
hxey_memory_total{application="sysmetrics",hxey="hxey",} 4.0
# HELP system_cpu_count The number of processors available to the Java virtual machine
# TYPE system_cpu_count gauge
system_cpu_count{application="sysmetrics",hxey="hxey",} 2.0
# HELP hxey_timestamp 服务器时间戳
# TYPE hxey_timestamp gauge
hxey_timestamp{application="sysmetrics",hxey="hxey",} 1.664506300883E12
# HELP hxey_disk_used 硬盘使用大小
# TYPE hxey_disk_used gauge
hxey_disk_used{application="sysmetrics",disk_label="C:\\[]",hxey="hxey",} 27.38
hxey_disk_used{application="sysmetrics",disk_label="D:\\[]",hxey="hxey",} NaN
hxey_disk_used{application="sysmetrics",disk_label="A:\\[]",hxey="hxey",} NaN
# HELP hxey_disk_total 硬盘总大小
# TYPE hxey_disk_total gauge
hxey_disk_total{application="sysmetrics",disk_label="C:\\[]",hxey="hxey",} 259.66
hxey_disk_total{application="sysmetrics",disk_label="D:\\[]",hxey="hxey",} NaN
hxey_disk_total{application="sysmetrics",disk_label="A:\\[]",hxey="hxey",} NaN

结果

搭建完成的Prometheus监控框架,能够准实时的收集和展示Cache中事务、Lisence使用率、消息队列等待长度、数据库使用率,以及操作系统时间偏置量、磁盘使用率、CPU使用率、内存使用率等指标。

image

image

image

讨论

任何监控系统,都是定时采集的,采集得到的指标是对现实中的连续指标的一个抽样。管理人员不能通过监控指标定位到故障原因,甚至不能精确定位到故障的实际发生时间。 为了弥补监控指标的缺憾,后期应为Cache集群添加日志采集系统,如Loki日志采集工具,建立起监控指标的异常和日志输出的对应关系,让异常定位更准确。

8
0 978
文章 Michael Lei · 一月 26, 2024 2m read

InterSystems 常见问题解答

如果系统24小时没有停止,旧的日志文件将根据“日志文件删除设置”在0:30删除。

导致日志文件保留的时间早于“日志文件删除设置”的一个可能原因是存在仍处于开放状态的事务。

在这种情况下,您将能够通过搜索执行事务的进程并完成事务来删除日志文件。

下面的示例检查是否存在未完成的事务,如果存在,则输出目标文件名和日志记录信息。

(示例可以从这里下载

*注意*如果要检查的日志文件较大或日志文件较多,则执行需要时间,因此请联系我们的支持中心。

0
0 86
文章 Michael Lei · 一月 15, 2024 2m read

作为针对数据导入处理性能和错误(锁定表已满)的衡量标准,可能需要调整常规内存堆 (gmheap) 和锁定表大小 (locksiz) 参数。

事实上,您可以使用终端和管理门户来检查当前分配了多少通用内存堆。


★终端用

// 一般メモリヒープサマリUSER> w $system .Config.SharedMemoryHeap.GetUsageSummary() 4992226 , 6029312 , 59441152

通用内存堆摘要以使用量、分配量和配置量(字节)的形式显示返回值。

使用量是分配的锁表、进程表等实际使用的量。
分配量是gmheap区域中锁表、进程表等分配的量。
配置量为gmheap(KB)+IRIS系统附加区,即当前最大可用量(实际通用内存堆区值)。

如上所述,配置数量与配置参数 gmheap 的独立值不匹配。
这是因为IRIS自动将内部使用的内存区域添加到配置参数gmheap中来配置通用内存堆区域。详情请参阅下面的文档。

关于gmheap

您可以使用以下命令获取锁表的使用情况:
返回值显示为可用量、用户可用量和已用量(字节)。详情请参阅这篇文章

%SYS > w##class (SYS. Lock ).GetLockSpaceInfo() 16772624 , 16764624 , 4592


★用于管理门户

您可以从“系统操作”>“系统使用情况”>“共享内存堆使用状态”进行检查。  

0
0 104
文章 Yuxiang Niu · 十一月 12, 2023 3m read

在日常Cache运维过程中可能会由于数据或者程序等原因造成锁的异常增长,导致数据库性能受到影响会出现程序报错或卡顿无法正常运行的问题。遇到此类问题需查看数据库当前锁列表情况,找到出现次数最多关键锁,根据关键锁对应的进程来判断处理。总结有以下三种方式查看关键锁。

  1. 可在portal[Locks]中查看;
  2. 可在terminal端的%sys下使用Do ^LOCKTAB命令下查看;
  3. 通过自定义程序查看。

查看方式

优点

缺点

第一种

易操作、方式简便

慢、锁数量太多无法显示

第二种

快、不受网页限制

易忘、需要输入准确命令

第三种

快、灵活、直接显示关键锁信息

需定位准确命名空间

下面给出自定义程序实例,程序逻辑为按命名空间循环所有锁信息,通过计数器方式记录所有锁当中出现次数最多的一个,输出其信息。入参为数据库中不同命名空间,输出结果为锁名称及锁的所有者,所有者一般为进程IDECP

2
0 202
文章 姚 鑫 · 五月 20, 2021 9m read

第一章 发送HTTP请求

本主题介绍如何发送HTTP请求(如POSTGET)和处理响应。

HTTP请求简介

可以创建%Net.HttpRequest的实例来发送各种HTTP请求并接收响应。此对象相当于Web浏览器,可以使用它发出多个请求。它会自动发送正确的cookie,并根据需要设置Referer标头。

要创建HTTP请求,请使用以下常规流程:

  1. 创建%Net.HttpRequest的实例。
  2. 设置此实例的属性以指示要与之通信的Web服务器。基本属性如下:
  • 服务器指定Web服务器的IP地址或计算机名称。默认值为localhost

注意:不要将http://https://作为服务器值的一部分。这将导致错误#6059:无法打开到服务器http:/的TCP/IP套接字

  1. 可以选择设置HTTP请求的其他属性和调用方法,如指定其他HTTP请求属性中所述。
  2. 然后,通过调用%Net.HttpRequest实例的get()方法或其他方法来发送HTTP请求,如“发送HTTP请求”中所述。

可以从实例发出多个请求,它将自动处理cookie和Referer标头。

注意:如果创建此HTTP请求是为了与生产出站适配器(EnsLib.HTTP.Outbound Adapter)一起使用,那么请改用该适配器的方法来发送请求。

  1. 如果需要,使用%Net.HttpRequest的同一实例发送其他HTTP请求。默认情况下,InterSystems IRIS使TCP/IP套接字保持打开状态,以便可以重复使用套接字,而无需关闭和重新打开它。

以下是一个简单的示例:

/// w ##class(PHA.TEST.HTTP).Get()
ClassMethod Get()
{
	set request=##class(%Net.HttpRequest).%New()
	set request.Server="tools.ietf.org"
	set request.Https=1
	set request.SSLConfiguration="yx"
	set status=request.Get("/html/rfc7158")
	d $System.Status.DisplayError(status) 

	s response = request.HttpResponse
	s stream = response.Data
	q stream.Read()
}

提供身份验证

如果目标服务器需要登录凭据,则HTTP请求可以包括提供凭据的HTTP Authorization标头。

如果使用的是代理服务器,还可以指定代理服务器的登录凭据;为此,请设置ProxyAuthorization属性

使用HTTP 1.0时对请求进行身份验证

对于HTTP 1.0,要验证HTTP请求,请设置%Net.HttpRequest实例的用户名和密码属性。然后,该实例使用基本访问身份验证基于该用户名和密码创建HTTP Authorization标头(RFC 2617)。此%Net.HttpRequest发送的任何后续请求都将包括此头。

重要提示:请确保还使用SSL。在基本身份验证中,凭据以base-64编码形式发送,因此易于读取。

在使用HTTP 1.1时对请求进行身份验证

对于HTTP 1.1,要验证HTTP请求,在大多数情况下,只需设置%Net.HttpRequest实例的用户名和密码属性。当%Net.HttpRequest的实例收到401 HTTP状态代码和WWW-Authenticate标头时,它会尝试使用包含支持的身份验证方案的Authorization标头进行响应。使用为IRIS支持和配置的第一个方案。默认情况下,它按以下顺序考虑这些身份验证方案:

  1. 协商(SPNEGO和Kerberos,根据RFC 4559和RFC 4178)
  2. NTLM(NT LAN Manager身份验证协议)
  3. 基本认证(RFC 2617中描述的基本接入认证)

重要:如果有可能使用基本身份验证,请确保也使用SSL(参见“使用SSL进行连接”)。 在基本身份验证中,凭据以base-64编码的形式发送,因此很容易读取。

在Windows上,如果没有指定Username属性,IRIS可以使用当前登录上下文。 具体来说,如果服务器使用401状态码和用于SPNEGOKerberosNTLMWWW-Authenticate头响应,那么IRIS将使用当前操作系统用户名和密码创建Authorization头。

具体情况与HTTP 1.0不同,如下所示:

  1. 如果认证成功,IRIS更新%NetCurrentAuthenticationScheme属性。 HttpRequest实例来指示它在最近的身份验证中使用的身份验证方案。
  2. 如果尝试获取方案的身份验证句柄或令牌失败,IRIS会将基础错误保存到%Net.HttpRequest实例的AuthenticationErrors属性中。此属性的值为$List,其中每一项都具有格式scheme ERROR: message

仅HTTP 1.1支持协商和NTLM,因为这些方案需要多次往返,而HTTP 1.0要求在每个请求/响应对之后关闭连接。

Variations

如果知道服务器允许的一个或多个身份验证方案,则可以通过包括Authorization标头来绕过服务器的初始往返行程,该标头包含所选方案的服务器的初始令牌。为此,请设置%Net.HttpRequest实例的InitiateAuthentication属性。对于此属性的值,请指定服务器允许的单个授权方案的名称。使用下列值之一(区分大小写):

  • Negotiate
  • NTLM
  • Basic

如果要自定义要使用的身份验证方案(或更改其考虑顺序),请设置%Net.HttpRequest实例的AuthenticationSchemes。对于此属性的值,请指定以逗号分隔的身份验证方案名称列表(使用上一个列表中给出的准确值)。

直接指定授权标头

对于HTTP 1.0或HTTP 1.1(如果适用于场景),可以直接指定HTTP Authorization标头。具体地说,可以将Authorization属性设置为等于正在请求的资源的用户代理所需的身份验证信息。

如果指定Authorization属性,则忽略用户名和密码属性。

启用HTTP身份验证的日志记录

要启用HTTP身份验证的日志记录,请在终端中输入以下内容:

 set $namespace="%SYS"
 kill ^ISCLOG
 set ^%ISCLOG=2
 set ^%ISCLOG("Category","HttpRequest")=5

日志条目将写入^ISCLOG global中.。要将日志写入文件(以提高可读性),请输入以下内容(仍在%SYS命名空间内):

 do ##class(%OAuth2.Utils).DisplayLog("filename")

其中,filename是要创建的文件的名称。该目录必须已存在。如果该文件已经存在,它将被覆盖。

要停止日志记录,请输入以下内容(仍在%SYS命名空间内):

 set ^%ISCLOG=0
 set ^%ISCLOG("Category","HttpRequest")=0

指定其他HTTP请求属性

在发送HTTP请求之前(请参阅发送HTTP请求),可以指定其属性,如以下各节所述:

可以为%Net.HttpRequest的所有属性指定默认值,如最后列出的部分中所指定。

Location属性

Location属性指定从Web服务器请求的资源。如果设置此属性,则在调用Get(), Head(), Post(), 或 Put()方法时,可以省略location参数。

例如,假设正在向url http://machine_name/test/index.html发送一个HTTP请求

在这种情况下,将使用下列值:

%Net.HttpRequest的示例属性

PropertiesValue
Servermachine_name
Locationtest/index.html

指定Internet媒体类型(Media Type)和字符编码(Character Encoding)

可以使用以下属性指定%Net.HttpRequest实例及其响应中的Internet媒体类型(也称为MIME类型)和字符编码:

  • Content-Type指定Content-Type标头,该标头指定请求正文的Internet媒体类型。默认类型为None。

可能的值包括application/jsonapplication/pdfapplication/postscriptimage/jpegimage/pngmultipart/form-datatext/htmltext/plantext/xml等等

  • ContentCharset属性控制请求的任何内容(例如,text/htmltext/xml)类型时所需的字符集。如果不指定此属性,InterSystems IRIS将使用InterSystems IRIS服务器的默认编码。

注意:如果设置此属性,则必须首先设置ContentType属性。

  • NoDefaultContentCharset属性控制在未设置ContentCharset属性的情况下是否包括文本类型内容的显式字符集。默认情况下,此属性为False。

如果此属性为true,则如果有文本类型的内容,并且没有设置ContentCharset属性,则内容类型中不包括任何字符集;这意味着字符集iso-8859-1用于消息输出。

  • WriteRawMode属性影响实体正文(如果包含)。它控制请求正文的写入方式。默认情况下,此属性为False,并且InterSystems IRIS以请求标头中指定的编码写入正文。如果此属性为true,则InterSystems IRIS以原始模式写入正文(不执行字符集转换)。
  • ReadRawMode属性控制如何读取响应正文。默认情况下,此属性为False,并且InterSystems IRIS假定正文在响应标头中指定的字符集中。如果此属性为true,InterSystems IRIS将以原始模式读取正文(不执行字符集转换)。

使用代理服务器

可以通过代理服务器发送HTTP请求。要设置此设置,请指定HTTP请求的以下属性:

  • ProxyServer指定要使用的代理服务器的主机名。如果此属性不为空,则将HTTP请求定向到此计算机。
  • ProxyPort指定代理服务器上要连接到的端口。
  • ProxyAuthorization指定Proxy-Authorization标头,如果用户代理必须使用代理验证其自身,则必须设置该标头。对于该值,请使用正在请求的资源的用户代理所需的身份验证信息。
  • ProxyHTTPS控制HTTP请求是针对HTTPS页面还是针对普通HTTP页面。如果未指定代理服务器,则忽略此属性。此属性将目标系统上的默认端口更改为代理端口443。
  • ProxyTunes指定是否通过代理建立到目标HTTP服务器的隧道。如果为true,则请求使用HTTP CONNECT命令建立隧道。代理服务器的地址取自ProxyServerProxyPort属性。如果ProxyHttps为true,则隧道建立后,系统间IRIS将协商SSL连接。在这种情况下,由于隧道与目标系统建立直接连接,因此将忽略https属性。

使用SSL进行连接

%Net.HttpRequest类支持SSL连接。要通过SSL发送请求,请执行以下操作:

  1. SSLConfiguration属性设置为要使用的已激活SSL/TLS配置的名称。

  2. 还要执行以下操作之一,具体取决于是否使用代理服务器:

  • 如果未使用代理服务器,请将https属性设置为true。
  • 如果使用的是代理服务器,请将ProxyHTTPS属性设置为true。

在这种情况下,要使用到代理服务器本身的SSL连接,请将https属性设置为true。

请注意,当使用到给定服务器的SSL连接时,该服务器上的默认端口假定为443(HTTPS端口)。例如,如果没有使用代理服务器,并且https为true,则会将Default Port属性更改为443。

服务器身份检查

默认情况下,当%Net.HttpRequest实例连接到SSL/TLS安全的Web服务器时,它会检查证书服务器名称是否与用于连接到服务器的DNS名称匹配。如果这些名称不匹配,则不允许连接。此默认行为可防止“中间人”攻击,在RFC 2818的3.1节中进行了描述;另请参阅RFC 2595的2.4节。

若要禁用此检查,请将SSLCheckServerIdentity属性设置为0。

HTTPVersionTimeoutWriteTimeoutFollowRedirect属性

%Net.HttpRequest还提供以下属性:

HTTPVersion指定请求页面时使用的HTTP版本。默认值是"HTTP/1.1"。你也可以使用“HTTP/1.0”

Timeout指定等待web服务器响应的时间,以秒为单位。 缺省值是30秒。

WriteTimeout指定等待Web服务器完成写入的时间(以秒为单位)。默认情况下,它将无限期等待。可接受的最小值为2秒。

FollowRedirect指定是否自动跟踪来自Web服务器的重定向请求(由300-399范围内的HTTP状态代码发出信号)。如果使用的是GET或HEAD,则默认值为TRUE;否则为FALSE。

指定HTTP请求的默认值

可以为%Net.HttpRequest的所有属性指定默认值。

  • 要指定适用于所有名称空间的默认值,请设置全局节 ^%SYS("HttpRequest","propname"),其中“PropName”是属性的名称。
  • 要为一个名称空间指定默认值,请转到该名称空间并设置节点^SYS("HttpRequest","propname")

(^%SYS全局设置会影响整个安装,^SYS全局设置会影响当前命名空间。)

例如,要为所有名称空间指定默认代理服务器,请设置全局节^%SYS("HttpRequest","ProxyServer")

1
0 323
文章 water huang · 十月 6, 2023 3m read

iris 是数据平台,更是一种数据库。对于熟悉SQL语句的人来说,会认为“既然是数据库,数据应该就能使用sql语句来查询”。这是对的,但是因为有global这个概念,保存的数据可能在global里面,而没有对应的表,也可能保存在类的参数定义里面。这些数据,不能使用sql直接查询。要查询iris数据库的数据,通常有几种方式:1.直接查询表的数据。2.查询视图。3.调用存储过程(call 命令)。其中要查询“只存于global里面或者类参数里定义的数据”,只有使用存储过程。但是存储过程有个问题,就是程序如果迁移到低版本的cache数据库后,数据类型的定义会有问题,且不再支持使用select的方式,只能使用call。这对于第三方熟悉sql的人员来说很不友好。因此结合global和表的关系,介绍一种我称为“进程表”的表。进程表,指数据只存于该进程中,global的样式为"^||global名“。通常按照默认存储新加一个持久类(对应会生成一个表),然后手动的把global改成进程global,也就是加上”||“。然后写个方法,把需要查询出来的数据写入进程global。这样就能查询出来 了。调用形式为 SELECT * FROM People WHERE People_GLB()=1。

示例如下:

2
0 199
文章 Michael Lei · 八月 31, 2023 1m read

InterSystems 常见问题解答

通过在持久类(=table)定义中提供的%BuildIndices() 方法的参数中指定要重建索引的 ID 的开始值和结束值,您可以仅重建该范围内的索引。

例如,要仅针对 ID=10 到 20 重建 Sample.Person 类中的 NameIDX 索引和 ZipCode 索引,请执行以下代码(ID 范围在第 5 个和第 6 个参数中指定)。

set status = ##class (Sample.Person). %BuildIndices ( $LB ( "NameIDX" , "ZipCode" ), 1 ,, 1 , 10 , 20 )

$LB() 是$ListBuild() 函数。 %BuildIndices() 方法使用它来指定索引名称。

有关如何重建索引的更多信息,请参阅文档

2018.1版本请参考此文档

0
0 176
问题 li liao · 八月 30, 2023

参考 https://blog.csdn.net/InterSystems/article/details/115350635 搭建 mirror ,获取数据变更,示例给出了获取数据变更的代码:

Class ZCustom.MirrorDejournal Extends SYS.MirrorDejournal
{
    Method RunFilter(
        MirrorDBName As %String,
        GlobalReference As %String,
        RecordType As %String,
        Address As %Integer) As %Integer
{
    Set ^CDCLog( $I($^CDCLog))=$lb(MirrorDBName,GlobalReference,RecordType,Address)
    Quit 1
}

示例代码将变更存储在 global 对象 CDCLog 中,想请问下获取变更前后数据,发送到外部系统,有哪些方式?

1
0 220
文章 Jimmy Xu · 八月 28, 2023 2m read

大家好,由于我目前在做一个数据分析的demo,所以需要在IRIS Data platform存储百万行数据供我测试。因此使用Populate Utility 来自动生成我需要的数据。

在这篇文章中,我将会给大家分享我使用 Populate utility 包括POPSPEC parameter的心得和经验。

1.创建两个persistent class , popPatient用于存储病人信息, popSign用于存储收集到的对应病人的生命信息。在定义persistent class时需要在后面引用(%Persistent, %Populate)以支持调用Populate Utility工具.

2.1 为了使我们生成出来的数据更贴合正常的情况,我们不能取一个超出常识的值比如心跳1000次一分钟。所以我使用(MAXVAL MINVAL)来限制了生成数据的区间。

popPatient 如图所示我限制了生成病人年龄的取值范围

popSign限制了心跳的区间

0
0 154
公告 Michael Lei · 八月 17, 2023

我们经常收到有关 InterSystems IRIS 数据平台支持的平台和框架列表最近和即将发生的更改的问题。此更新旨在分享最近的变化以及我们对即将发生的变化的当前最佳知识,但预测未来是一件棘手的事情,这不应被视为承诺的路线图。

话虽如此,接下来是更新……

IRIS 生产环境操作系统和 CPU 架构

红帽Linux企业版RHEL

0
0 160
文章 Michael Lei · 八月 10, 2023 2m read

InterSystems 常见问题解答

※如果您想比较使用Mirror、Shadow或其他机制复制的数据库,请使用此方法。

您可以使用 DATACHECK 实用程序来比较Global。请参阅下面的文档。
DataCheck 概述 [IRIS]

***

Routines比较使用系统例程 %RCMP 或管理门户。

以下是如何在管理门户中使用它。

0
0 177
文章 Lilian Huang · 七月 31, 2023 2m read

FHIR® SQL Builder或 Builder 是 InterSystems IRIS 医疗版数据平台 的一个组件。它是一种复杂的投射工具,用于将 InterSystems IRIS  医疗版数据平台FHIR 存储库中的数据创建为自定义的 SQL 模式,而无需将数据移动到单独的 SQL 存储库中。 Builder 专门设计用于与 InterSystems IRIS 医疗版数据平台中的 FHIR 存储库和多模型数据库配合使用。

Builder 的目标是使数据分析师和商业智能开发人员能够使用熟悉的SQL分析工具使用 FHIR,而无需学习新的查询语法。 FHIR 数据以复杂的有向图编码,无法使用标准 SQL 语法进行查询。基于图的查询语言 FHIRPath 旨在查询 FHIR 数据,但它是非关系型的。 Builder 使数据管理员能够使用表、列和索引创建其 FHIR 存储库的自定义 SQL 来投射,使数据分析师能够查询 FHIR 数据,而无需学习 FHIRPath 或 FHIR 搜索语法的复杂性。
存储库将加载 FHIR 资源,您所需要做的就是配置 FHIR SQL BUILDER。
对于配置,导航到http://localhost:55037/csp/fhirsql/index.csp# /

有关如何进行配置的更多详细信息,请观看此教程视频

0
0 231
文章 姚 鑫 · 七月 16, 2023 13m read

一篇文章了解IRIS/Caché编码方案

一直以来,编码问题像幽灵一般,不少开发人员都受过它的困扰。

试想你请求一个数据,却得到一堆乱码,丈二和尚摸不着头脑。有同事质疑你的数据是乱码,虽然你很确定传了UTF-8 ,却也无法自证清白,更别说帮同事 debug 了。

有时,靠着百度和一手瞎调的手艺,乱码也能解决。尽管如此,还是很羡慕那些骨灰级程序员。为什么他们每次都能犀利地指出问题,并快速修复呢?原因在于,他们早就把编码问题背后的各种来龙去脉搞清楚了。

ASCII

标准ASCII 码,使用7 位二进制数(最高位为0)来表示所有的大写和小写字母,数字09、半角标点符号,以及在英语中使用的特殊控制符号。

最早只有127个字母被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母a的编码是97,小写字母z的编码是122

IRIS/Caché中获取字符ASCII码与二进制字符串,如下代码示例:

USER>w $a("a")
97
USER>w ##class(M.Code).LogicalToDisplay(97)
10000110

经过如下二进制转十进制计算可得出 1+32+64 = 97

2**0 + 2**5 + 2**6 = 97

Unicode

GB2312GBKGB18030 都是中文编码字符集。不同国家也推出了自己的字符集和编码方案,彼此不兼容。例如中文编码集,在日文系统无法正常显示,无法适应全球化应用。为了适应全球化,由统一码联盟开发,指定了统一码(Unicode),也叫万国码、单一码,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。

Unicode已经收录的字符数量已经超过 13 万个,每个字符需占用超过 2 字节。由于常用编程语言一般没有 24 位数字类型,因此一般用 32 位数字表示一个字符。如果要用到非常偏僻的字符,就需要4个字节这样一来。同样的一个英文字母,在 ASCII中只需占用 1 字节,在 Unicode 则需要占用4 字节!

IRIS/Caché中获取字符Unicode编码,如下代码示例:

ClassMethod UnicodeEncode(str As %String) As %String
{
	q $replace($zcvt(str, "O", "URL"),"%","\")
}
USER>w ##class(Util.Impl.EncryptionUtils).UnicodeEncode("姚鑫")
\u59DA\u946B

UTF8

UTF-8Unicode的实现方式之一。UTF-8是一种 Unicode 的编码方式,主要作用对 Unicode 码的数据进行转换,转换后方便存储和网络传输。本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码(unicode transformation format)。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。

Unicode符号范围 (十六进制)UTF-8编码方式(二进制)
0000 0000-0000 007F0xxxxxxx
0000 0080-0000 07FF110xxxxx 10xxxxxx
0000 0800-0000 FFFF1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

IRIS/Caché中获取字符ASCII码与UTF8十六进制字符串,如下代码示例:

USER>w $a("鑫")
37995
USER>w $zhex(37995)
946B

GB2312、GBK和GB18030

ASICIIGB2312GBKGB18030 之间的关系可以用下图表示:

image

GB2312 兼容 ASICII 编码, GBK 兼容 GB2312 编码,GB18030 兼容 GB2312 编码 和 GBK 编码。

实际生活中,我们用到的 99% 的汉字,都属于 GB2312 编码范围 ,GB2312 每个编码对应的是哪个汉字可以参考 GB2312简体中文编码表, GBK 编码可以参考 GBK编码表, GB18030 可以参考 GB18030-2005 文档。

那么GB系列是如何兼容ASCII码的呢?

GB系列中,如果一个字节最高位 b80 ,该字节便是单字节编码,即 ASCII 码。如果字节最高位 b81 ,它就是双字节编码的首字节,与其后字节一起表示一个字符。

下图为GBK码表:

image

可以根据码表查对应汉字或全角字符对应的十六进制码表值,图中全角符号对应的GBK码表值为A1B6

ASICIIGB2312GBKGB18030Unicode之间的关系可以用下图表示:

image

ANSI

不同的国家和地区制定了不同的标准,由此产生了 GB2312GBKGB18030Big5Shift_JIS 等各自的编码标准。这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文Windows操作系统中,ANSI 编码代表 GB2312编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 JIS 编码。

下图中文Windows环境中的ANSI编码为GB18030.

image

IRIS/Caché中验证ANSI是否为GB18030

ClassMethod GBK(filename)
{
	s stream = ##class(%Stream.FileCharacter).%New()
	#; 默认使用GB18030解码
	s stream.TranslateTable = "GB18030"
	s stream.Filename = filename
	w "字符长度:",stream.Size,!
	while 'stream.AtEnd {
		s line = stream.Read()
		w line,!
	}
	q $$$OK
}
USER>w ##class(M.Code).GBK("E:\m\code\gbk.txt")
字符长度:94
《过零丁洋》宋朝·文天祥
 
辛苦遭逢起一经,干戈寥落四周星。
 
山河破碎风飘絮,身世浮沉雨打萍。
 
惶恐滩头说惶恐,零丁洋里叹零丁。
 
人生自古谁无死?留取丹心照汗青。
 
1

在程序中还是用GB18030编码方式可以解析出中文,所以验证ASNI在中文环境中的编码格式为GB18030,如果是GB2312也可以正常解析出,因为是GB18030是向下兼容的。

手写解析UTF8编码

首先创建一个UTF8txt文件。

image

通过如下代码去解析UTF8文件,其中代码s stream.TranslateTable = "UTF8"指定解析方式。

ClassMethod UTF8(filename)
{
	s stream = ##class(%Stream.FileCharacter).%New()
	s stream.Filename = filename
	s stream.TranslateTable = "UTF8"
	w "字符长度:",stream.Size,!
	while 'stream.AtEnd {
		s line = stream.Read()
		w line,!
	}
	q $$$OK
}

可以正常解析出:

USER>w ##class(M.Code).UTF8("E:\m\code\utf8.txt")
字符长度:94
《过零丁洋》宋朝·文天祥
 
辛苦遭逢起一经,干戈寥落四周星。
 
山河破碎风飘絮,身世浮沉雨打萍。
 
惶恐滩头说惶恐,零丁洋里叹零丁。
 
人生自古谁无死?留取丹心照汗青。
 
1

如果不指定s stream.TranslateTable = "UTF8"该代码将会得到如下数据:

USER>w ##class(M.Code).UTF8("E:\m\code\utf8.txt")
字符长度:133
銆婅繃闆朵竵娲嬨?嬪畫鏈澛锋枃澶╃ゥ
 
杈涜嫤閬?㈣捣涓?缁忥紝骞叉垐瀵ヨ惤鍥涘懆鏄熴??
 
灞辨渤鐮寸椋庨绲紝韬笘娴矇闆ㄦ墦钀嶃??
 
鎯舵亹婊╁ご璇存兌鎭愶紝闆朵竵娲嬮噷鍙归浂涓併??
 
浜虹敓鑷彜璋佹棤姝伙紵鐣欏彇涓瑰績鐓ф睏闈掋??
 
1

那么在无法指定编码方式的字符串当中,该如何解析UTF8编码呢?根据UTF8的编码规则编写如下RAW2UTF8方法。

方法逻辑如下:

  1. 读取1个首部字符判断UTF8所占字节大小。

  2. 获取该字符的2进制字符串。

  3. 如果为ASCII码,长度小于8位,高位补0

  4. 如果UTF8为4字节,一般为不常见的汉字。

  5. 如果UTF83字节,一般为常用汉字。

    1. 去掉标识高位
    2. 取剩余字符
    3. 将剩余字符进行二进制字符串拼接
    4. 获取该字符的十进制ASCII
  6. 如果UTF81字节 ASCII码直接取值。

ClassMethod RAW2UTF8(stream As %Stream.FileBinary) As %String
{
	s str = ""
	
	while 'stream.AtEnd {
		
		#; 读取1个首部字符判断UTF8所占字节大小
		s content = stream.Read(1)
		
		#; 获取该字符的2进制字符串
		s ascii = $a(content)
		s highBit = ..LogicalToDisplay(ascii)
		
		#; 长度小于8位,高位补0
		if ($l(highBit) < 8) {
			s highBit = highBit _ ..Repeat(0, 8 - $l(highBit))
		}
		
		#; UTF8,4字节,一般为不常见的汉字
		if ($e(highBit,4, *) = "01111") {
			s bitStr =  $e(highBit, 1, 5)
			for i = 1 : 1 : 3 {
				s lowChar = stream.Read(1)
				s bitStr = $e(..LogicalToDisplay($a(lowChar)), 1, 6) _ bitStr 
			}
			s utf8num = ..BitToDec(bitStr)
		
		#; UTF8,3字节,一般为汉字
		} elseif ($e(highBit, 5, *) = "0111") {
			
			#; 去掉标识高位
			s bitStr =  $e(highBit, 1, 4)
			
			#; 取剩余字符
			for i = 1 : 1 : 2 {
				s lowChar = stream.Read(1)
				
				#; 将剩余字符进行二进制字符串拼接
				s bitStr = $e(..LogicalToDisplay($a(lowChar)), 1, 6) _ bitStr 
			}
			
			#; 获取该字符的十进制ASCII
			s utf8num = ..BitToDec(bitStr)

		#; UTF8,2字节
		} elseif ($e(highBit, 6, *) = "011") {
			s bitStr =  $e(highBit, 1, 3)
			for i = 1 : 1 : 1 {
				s lowChar = stream.Read(1)
				s bitStr = $e(..LogicalToDisplay($a(lowChar)), 1, 6) _ bitStr 
			}
			s utf8num = ..BitToDec(bitStr)
			
		#; UTF8,1字节 ASCII码
		} elseif ($e(highBit, 8, *) = "0") {
			s bitStr =  highBit
			s utf8num = ..BitToDec(bitStr)
		
		}
		s str = str _ $c(utf8num)
	}
	
	q str
}

通过该RAW2UTF8方法去解析直接的乱码。

注:这里直接通过%Stream.FileBinary方式去解析文件流,解析出来的是不包含编码格式,为二进制串。

ClassMethod TestRAW2UTF8(filename)
{
	s stream = ##class(%Stream.FileBinary).%New()
	s stream.Filename = filename
	s str = ..RAW2UTF8(stream)
	q str
}

通过该方法就可以解析出常见的UTF8乱码。

USER> w ##class(M.Code).TestRAW2UTF8("E:\m\code\utf8.txt")
《过零丁洋》宋朝·文天祥
 
辛苦遭逢起一经,干戈寥落四周星。
 
山河破碎风飘絮,身世浮沉雨打萍。
 
惶恐滩头说惶恐,零丁洋里叹零丁。
 
人生自古谁无死?留取丹心照汗青。
 

手写解析GB18030编码

首先创建一个GB18030编码格式的文件。之前已经验证ANSI能编码格式为GB18030编码格式

image

在编写解析GB18030编码之前,需要将码表导入到系统当中:

ClassMethod ImportGB1830Table(filename As %String) As %String
{
	s stream = ##class(%Stream.FileCharacter).%New()
	s stream.Filename = filename
	w stream.Size,!
	while 'stream.AtEnd {
		s str = stream.ReadLine()
		s char = $e(str, 2)
		s word = $replace($p(str, ",", 1), char, "")
		s gbkCode = $replace($p(str, ",", 2), char, "")
		s unicode = $replace($p(str, ",", 3), char, "")
		continue:(unicode = "")
		s ^GB18030(gbkCode) = word
	}
	q $$$OK
}
 w ##class(M.Code).ImportGB1830Table("E:\m\code\GB18030对照表.csv")

查看导入的码表Global

USER>zw ^GB18030
^GB18030(8140)="丂"
^GB18030(8141)="丄"
^GB18030(8142)="丅"
^GB18030(8143)="丆"
^GB18030(8144)="丏"
...
^GB18030(9481)="攣"
^GB18030(9482)="攤"
^GB18030(9483)="攦"
^GB18030(9484)="攧"
^GB18030(9485)="攨"
^GB18030(9486)="攩"
^GB18030(9487)="攪"

根据UTF8的编码规则编写如下RAW2UTF8方法。

方法逻辑如下:

  1. 读取1个首部字符判断UTF8所占字节大小。
  2. 如果高为0ASCII直接解析即可。
  3. 如果高为1直接根据对照码表直接解析即可。
ClassMethod RAW2GB18030(stream As %Stream.FileBinary) As %String
{
	s str= ""
	
	while 'stream.AtEnd {
		//s line = stream.Read(2)
		
		#; 读取1个首部字符判断UTF8所占字节大小
		s content = stream.Read(1)
		
		#; 获取该字符的2进制字符串
		s ascii = $a(content)
		s highBit = ..LogicalToDisplay(ascii)
		
		#; 长度小于8位,高位补0
		if ($l(highBit) < 8) {
			s highBit = highBit _ ..Repeat(0, 8 - $l(highBit))
		}
		if ($e(highBit, 8, *) = "0") {
			s bitStr =  highBit
			s ascii = ..BitToDec(bitStr)
			s char = $c(ascii)
		} else {
			s hex = ""
			s hex = hex _ $zhex($a(content))
			s content = stream.Read(1)
			s hex = hex _ $zhex($a(content))
			
			if ($d(^GB18030(hex))) {
				s char = $g(^GB18030(hex))
			}
		}
		
		s str = str _ char

		
	}
	q str
}

通过该RAW2GB18030方法去解析18030编码。

ClassMethod TestRAW2GB18030(filename)
{
	s stream = ##class(%Stream.FileBinary).%New()
	s stream.Filename = filename
	s str = ..RAW2GB18030(stream)
	q str
}
USER>w ##class(M.Code).TestRAW2GB18030("E:\m\code\gbk.txt")
《过零丁洋》宋朝·文天祥
 
辛苦遭逢起一经,干戈寥落四周星。
 
山河破碎风飘絮,身世浮沉雨打萍。
 
惶恐滩头说惶恐,零丁洋里叹零丁。
 
人生自古谁无死?留取丹心照汗青。

IRIS/Caché中哪些情况如要指定编码

  • 读取文件需要指定编码,示例如下:
    • s stream.TranslateTable = "UTF8"
ClassMethod UTF8(filename)
{
	s stream = ##class(%Stream.FileCharacter).%New()
	s stream.Filename = filename
	s stream.TranslateTable = "UTF8"
	w "字符长度:",stream.Size,!
	while 'stream.AtEnd {
		s line = stream.Read()
		w line,!
	}
	q $$$OK
}
  • 在读取HTTP请求时需要指定编码,示例如下:
    • s request.ContentCharset="UTF-8"
ClassMethod HttpGetDemo() As %String
{
	/* 定义request对象 */
	#dim request as %Net.HttpRequest= ##class(%Net.HttpRequest).%New()
	
	/* 请求地址不用加http:// */
	s request.Server = "192.168.1.21"
	//s request.ContentType
	/* Timeout指定等待web服务器响应的时间,以秒为单位。 缺省值是30秒。 */
	s request.Timeout = 5
	
	/* WriteTimeout指定等待Web服务器完成写入的时间(以秒为单位)。默认情况下,它将无限期等待。可接受的最小值为2秒。 */
	s request.WriteTimeout = 5
	
	#;指定编码
	s request.ContentCharset="UTF-8"
	
	/* 添加地址对象参数 */
	d request.InsertParam("CacheUserName", "yx")
	d request.InsertParam("CachePassword", "123456")
	d request.InsertParam("CacheNoRedirect", "1")
	d request.InsertParam("ClassName", "PHA.PCCP.MOB.API")
	d request.InsertParam("MethodName", "GetPhaWardRound")
	d request.InsertParam("params", "172#O")

	/* 设置cookies 防止占用多个lic */
	d:($g(%cookies) '= "") request.SetHeader("cookie", %cookies)
	
	/* 请求地址路径 */
	s status = request.Get("/dthealth/web/csp/pha.mob.broker.csp")
	
	if (status '= 1) {
		d $System.Status.DisplayError(status) 
		q "请求失败"
	}

	/* 定义response对象 */
	#dim response as %Net.HttpResponse  = request.HttpResponse
	
	/* 获取HTTP状态码 */
	s statusCode= response.StatusCode
	if (statusCode = 200){
		
		/* 获取头信息两种方式(一) */
		s encoding = response.GetHeader("CONTENT-ENCODING")

		/* 获取头信息两种方式(二) */
		s cookie = response.Headers("SET-COOKIE")
		s %cookies = $p(cookie, ";", 1)
		
		w "输出所有头部信息:",!
		d response.OutputHeaders()
		w !
		
		/* 获取流数据 */
		#dim stream as  %GlobalBinaryStream = response.Data
		s data = stream.Read()
	}

	q $g(data)
}
  • 读取xml时需要指定编码。
<?xml version='1.0' encoding='UTF-8'?>
  • HL7数据格式时需要指定编码。
Class IHE.Msg.MSH Extends (%Persistent, %JSON.Adaptor)
{

Property FieldSeparator(CAPTION = "字段分隔符") [ InitialExpression = "|", Required ];

Property EncodingCharacters(CAPTION = "编码字符") [ InitialExpression = "^~\&", Required ];

...

Property CharacterSet(CAPTION = "字符集") [ InitialExpression = "UTF-8" ];

}

image

获取系统默认的编码格式

USER>w $$GetPDefIO^%SYS.NLS(3)
GB18030

判断文件BOM的编码格式

BOM(Byte Order Mark),字节顺序标记,出现在文本文件头部,Unicode编码标准中用于标识文件是采用哪种格式的编码。

注:大多数文本文件都不含有BOM

  • 判断是否为UTF8BOM
ClassMethod IsUTF8BOM(filename As %String) As %Boolean
{
    s file = ##class(%FileBinaryStream).%New()
	s file.Filename = filename
	s bom = file.Read(3, .sc)
    if (bom = $c(239, 187, 191)) { 
        q $$$YES
    } 
    q $$$NO
}
  • 判断判断是否为GB18030BOM
ClassMethod IsGB18030BOM(filename As %String) As %Boolean
{
    s file = ##class(%FileBinaryStream).%New()
	s file.Filename = filename
	s bom = file.Read(4, .sc)
    if (bom = $c(132, 49, 149, 51)) {
		q $$$YES
    } 
    q $$$NO
}

  • 判断文件是否为UTF16BOM
ClassMethod IsUTF16BOM(filename As %String) As %Boolean
{
    s file = ##class(%FileBinaryStream).%New()
	s file.Filename = filename
	s bom = file.Read(2, .sc)
    if (bom =  $c(255, 254) || bom = $c(254, 255)) {
		q $$$YES
    } 
    q $$$NO
}
  • 判断文件是否有BOM
ClassMethod IsBOM(filename As %String) As %Boolean
{
	q:(..IsUTF8BOM(filename)) $$$YES
	q:(..IsUTF16BOM(filename)) $$$YES
	q:(..IsGB18030BOM(filename)) $$$YES
    q $$$NO
}

总结

  • 通过了解常见的编码格式与原理,可以在遇到乱码时,知道如何去处理。
  • 在国内环境中,使用手动解析UTF8GB18030两种解码方法,可以满足日常遇到的99%乱码问题。

以上是个人对常见编码的一些理解,由于个人能力有限,欢迎大家提出意见,共同交流。

0
0 488
文章 Tete Zhang · 七月 4, 2023 3m read

本文讨论了在使用或维护InterSystems产品中遇到问题时,试图确定问题时可能用到的思路和工具。

一般故障排除

确定问题发生的地点和时间

  • 问题是什么时候开始的?多久发生一次?
  • 问题首先出现在哪里?
  • 问题在什么条件下会被触发?

审查日志中的警告、错误和警报

以下日志可能包含有关该问题的有用信息。可以尝试在以下日志中寻找问题开始前后的警告或报错。

  • 检查 messages.log(IRIS)或者 cconsole.log(Caché and Ensemble)
    • 通过文件系统(<install-dir>/mgr/messages.log)访问messages.log文件,或者
    • 通过管理门户(系统操作>系统日志>Messages Log)访问文件内容
  • 检查production事件日志 (详细信息请参见文档
  • 查看应用程序错误日志 (详细信息请参见文档
  • 查看Web Gateway/CSP Gateway日志
  • 查看网络服务器(IIS/Apache)日志

检查实例是否可以访问足够的存储空间

  • 检查文件系统剩余空间(推荐设置操作系统层级的存储空间低告警)
  • 检查数据库剩余空间
    • 通过管理门户(系统操作>数据库>Freespace View)查看数据库文件内剩余空间百分比
  • 检查Journal日志空间

检查CPU活动

0
0 212
文章 Michael Lei · 七月 3, 2023 4m read

你好社区
在本文中,我将介绍我的应用程序irisChatGPT ,它是基于LangChain Framework构建的。
首先,让我们对框架进行一个简单的概述。

全世界都在谈论ChatGPT以及大型语言模型 (LLM) 如何变得如此强大,并且表现超出预期,提供类似人类的对话。这只是将其应用于每个企业和每个领域的开始!

0
0 379
文章 Hao Ma · 六月 19, 2023 5m read

上篇文章IRIS, Caché监控指导 - 警告和告警 发出后收到要求介绍一下发送SNMP通知的具体操作,这里介绍一下。

我省去了SNMP的原理,这个有需要的可以网上查找。这里只做一个配置的操作:测试怎么从一个Windows上安装的IRIS实例发送IRIS Alert给另一台Linux服务器。

第一步: 配置 Windows SNMP

因为安全原因,Windows 10不再默认安装中启动SNMP,用户需要手工安装SNMP启动服务。以下两个文章是古老的Window 2003和新的Windows 10中配置SNMP的安装,给各位做个参考。

简单的总结一下:Windows系统中有两个服务:

  • SNMP Service:使简单网络管理协议(SNMP)请求能够在此计算机上被处理。如果此服务停止,计算机将不能处理 SNMP 请求。如果此服务被禁用,所有明确依赖它的服务都将不能启动。
  • SNMP Trap:接收本地或远程简单网络管理协议 (SNMP) 代理程序生成的陷阱消息并将消息转发到此计算机上运行的 SNMP 管理程序。如果此服务被停用,此计算机上基于 SNMP 的程序将不会接收 SNMP trap 消息。如果此服务被禁用,任何依赖它的服务将无法启动。

当前我需要从本机向远端发送SNMP, 所以只需要开启SNMP Service即可。然后需要配置SNMP Service的:

  • Community名称
  • 发送Trap的目的地址
  • Community的权限(在”安全”子页面配置,权限为读写,应该选中“发送身份验证Trap”)

如下图,Commnity是”public”, 发送trap到172.16.58.1和172.16.58.101, 分别是两台远端的服务器。

第二步: 配置IRIS SNMP

在Windows系统注册iscsnmp.dll

Windows系统中,如果IRIS安装在SNMP服务安装之前, 需要手工执行以下命令来注册iscsnmp.dll到Windows Registry。命令成功执行后要重启操作系统的SNMP Service。

打开IRIS Terminal工具,在%SYS命名空间执行:

SYS>set myStatus=$$Register^SNMP()
Cache SNMP Extension Agent DLL successfully added to Registry

上述命令行必须是在Administrator的角色执行,否则会有权限问题, 提示错误 “Unable to open Registry key 'SOFTWARE\Microsoft\Windows\CurrentVersion\CommonFilesDir”

开启 %SNMP_Monitor服务

到System>Security Management >Services, 启动%Service_Monitor服务。%Service_Monitor服务负责Caché和本地操作系统的SNMP Agent的通信,如果关闭,本地和远程的SNMP通信都将中断。

到“系统>配置>监视器配置- 配置设置。选中” 开启SNMP服务随系统启动而启动”,英文”Start SNMP Agent at System Startup”。(Cache'中本页面还包括BMC PORTAL监控软件或者WMI选项,如果不使用,可以不用关心)。

最后,为了启用修改后的配置,需要重启Caché实例。如果是测试环境, 也可以不重启,而是在Caché Terminal执行:Do start^SNMP() 或者Do start^SNMP(705,20) 来应用修改, 其中705是ensemble SNPM作为subagent的默认TCP端口号, 20是超时时间。 命令do stop^SNMP()命令可以在IRIS停止SNMP工作。

第三步: 向远端服务器发送SNMP Trap

这里,远端服务器我使用net-snamp工具。 net-snmp是linux, unix, mac os上第一选择的snmp服务和工具。简单的介绍centos 7 的net-snmp安装命令

# 安装net-snmp
[root@serverb ~]# yum install net-snmp net-snmp-utils -y

# 查看版本
[root@serverb ~]# snmpd -v

# 启动
[root@serverb ~]# systemctl start snmpd
[root@serverb ~]# systemctl status snmpd

(如果接收警告的SNMP Server是Windows系统,您可以选择一些图形化的工具做SNMP Trap的接收,比如iReasoning. )

设置snmp trap deamon

hma@CNMBPHMA ~ % snmptrapd -df -Lo
NET-SNMP version 5.6.2.1

在IRIS发送Alert

简单的制造一个alert的最简单的方法是用下面的命令,它向messages.log写一个级别为2的记录,这个记录会再写到alert.log里,通过SNMP发送给SNMP服务器。

%SYS>do ##class(%SYS.System).WriteToConsoleLog("Winter is coming",,2)

检查SNMP服务器收到警告

这时去刚才的snmptrapd终端,可以看到收到了警告。

hma@CNMBPHMA ~ % snmptrapd -df -Lo

Received 137 byte packet from UDP: [172.16.58.200]:55212->[0.0.0.0]:0
0000: 30 81 86 02  01 00 04 06  70 75 62 6C  69 63 A4 79    0.......public�y
0016: 06 0A 2B 06  01 04 01 81  81 33 04 02  40 04 AC 10    ..+......3..@.�.
0032: 3A C8 02 01  06 02 01 0E  43 03 5E E4  CB 30 5A 30    :�......C.^��0Z0
0048: 1E 06 14 2B  06 01 04 01  81 81 33 04  01 01 01 01    ...+......3.....
0064: 06 48 43 44  45 4D 4F 04  06 48 43 44  45 4D 4F 30    .HCDEMO..HCDEMO0
0080: 38 06 14 2B  06 01 04 01  81 81 33 04  01 01 01 08    8..+......3.....
0096: 06 48 43 44  45 4D 4F 04  20 5B 55 74  69 6C 69 74    .HCDEMO. [Utilit
0112: 79 2E 45 76  65 6E 74 5D  20 57 69 6E  74 65 72 20    y.Event] Winter
0128: 69 73 20 63  6F 6D 69 6E  67                          is coming

到这里,IRIS的警告通过SNMP发送已经成功,接下来,您可以做进一步的测试,比如, 如果您对镜像的警告很重视, 您可以测试做如下的测试:

接收镜像相关的警告

  • Becoming primary mirror server

    本镜像成员成为主机

  • Arbiter connection lost

    丢失和arbiter的连接。

  • MirrorServer: Connection to xxxx(backup) terminated

​ 丢失和backup的连接。

以上3个警告都会写入alert,并发送给snmp服务器。

最后,如果您熟悉其他的监控工具,这时候您可以配置您的工具来接收警告了。 我后面会贴一个zabbix上监控IRIS的介绍,其中的警告用SNMP Trap实现,有兴趣的同学可关注本作者。

0
1 244
文章 姚 鑫 · 五月 20, 2022 3m read

第148章 SQL函数 $TRANSLATE

执行逐字符替换的字符串函数。

大纲

$TRANSLATE(string,identifier[,associator])

参数

  • string - 目标字符串。它可以是字段名称、文字、主机变量或 SQL 表达式。
  • identifier - 要在字符串中搜索的字符。它可以是字符串或数字文字、主变量或 SQL 表达式。
  • associator - 可选 — 与标识符中的每个字符对应的替换字符。它可以是字符串或数字文字、主变量或 SQL 表达式。

描述

$TRANSLATE 函数在返回值字符串中执行逐字符替换。它一次处理一个字符的字符串参数。它将字符串中的每个字符与标识符参数中的每个字符进行比较。如果 $TRANSLATE 找到匹配项,它会记下该字符的位置。

  • $TRANSLATE 的双参数形式从输出字符串中删除标识符参数中的所有字符实例。
  • $TRANSLATE 的三参数形式将在字符串中找到的每个标识符字符的所有实例都替换为位置对应的关联字符。替换是基于字符而不是字符串执行的。如果标识符参数包含的字符多于关联参数,则从输出字符串中删除标识符参数中多余的字符。如果标识符参数包含的字符少于关联参数,则忽略关联参数中多余的字符。

$TRANSLATE 区分大小写。

$TRANSLATE 不能用于将 NULL 替换为字符。

如果指定的参数太少,则会发出 SQLCODE -380。如果指定的参数过多,则会发出 SQLCODE -381

$TRANSLATE and REPLACE

$TRANSLATE 执行逐字符匹配和替换。 REPLACE 执行字符串对字符串的匹配和替换。 REPLACE 可以用另一个子字符串替换一个或多个字符的单个指定子字符串,或删除指定子字符串的多个实例。 $TRANSLATE 可以用相应的指定替换字符替换多个指定字符。

默认情况下,这两个函数都区分大小写,从字符串的开头开始,并替换所有匹配的实例。 REPLACE 具有可用于更改这些默认值的参数。

示例

在以下示例中,两个参数 $TRANSLATE 通过删除标点符号(逗号、空格、句点、撇号、连字符)来修改名称值,返回仅包含字母字符的名称。请注意,标识符将撇号加倍以将其转义为文字字符,而不是字符串分隔符:

SELECT TOP 20 Name,$TRANSLATE(Name,', .''-') AS AlphaName 
FROM Sample.Person
WHERE Name %STARTSWITH 'O'

在以下示例中,三参数 $TRANSLATE 通过将逗号和空格替换为插入符号 (^) 字符来修改名称值,返回以三部分分隔的名称(姓氏、名字、中间名首字母)。请注意,关联者必须指定“^”的次数与标识符中的字符数一样多:

SELECT TOP 20 Name,$TRANSLATE(Name,', ','^^') AS PiecesNamePunc
FROM Sample.Person
WHERE Name %STARTSWITH 'O'

在以下示例中,三参数 $TRANSLATE 通过将逗号和空格替换为脱字符 (^) 字符(在标识符和关联符中指定)和删除句点、撇号和连字符(在标识符中指定,从关联人):

SELECT TOP 20 Name,$TRANSLATE(Name,', .''-','^^') AS PiecesNameNoPunc 
FROM Sample.Person
WHERE Name %STARTSWITH 'O'
1
1 213
文章 Lele Yang · 六月 8, 2023 7m read

++ 更新:2018 年 8 月 1 日

使用内置于 Caché 数据库镜像的 InterSystems 虚拟 IP (VIP) 地址有一定的局限性。特别是,它只能在镜像成员驻留在同一网络子网时使用。当使用多个数据中心时,由于增加了网络复杂性( 此处有更详细的讨论),网络子网通常不会“延伸”到物理数据中心之外。出于类似的原因,当数据库托管在云端时,虚拟 IP 通常无法使用。

负载均衡器(物理或虚拟)等网络流量管理设备可用于实现相同级别的透明度,为客户端应用程序或设备提供单一地址。网络流量管理器自动将客户端重定向到当前镜像主服务器的真实 IP 地址。自动化旨在满足灾难后 HA 故障转移和 DR 升级的需求。

0
0 160
公告 Michael Lei · 六月 8, 2023

如果您已经使用%UnitTest 框架构建了单元测试,或者正在考虑这样做,请查看InterSystems 测试管理器Test Manager

无需离开 VS Code,您现在可以浏览单元测试、运行或调试它们,并查看之前的运行结果。

InterSystems 测试管理器适用于 ObjectScript 扩展支持的两种源代码位置范例。您的单元测试类可以在 VS Code 的本地文件系统(“客户端编辑”范例)或服务器命名空间(“服务器端编辑”)中掌握。在这两种情况下,实际测试运行都发生在服务器命名空间中。

欢迎反馈。

0
0 139
公告 Michael Lei · 六月 3, 2023

InterSystems 支持的硬件OS平台更新 2023年2季度

我们经常收到有关 InterSystems IRIS 数据平台支持的平台和框架列表最近和即将发生的变化的问题。此更新旨在分享最近的更改以及我们对即将发生的更改的已知的情况,但预测未来是一项棘手的工作,不应将其视为承诺的路线图。

话虽如此,关于更新……

IRIS 生产操作系统和 CPU 架构

红帽企业 Linux

0
0 138