搜索​​​​

清除过滤器
文章
Michael Lei · 八月 6, 2024

监控数据库增长 – 第 1 部分_数据收集

# 数据收集 这篇分步说明指南将讲解如何创建任务来收集 InterSystems 数据库及其全局变量的相关数据(如关联的 Open Exchange App 所示,其中包含所有相关代码) **免责声明:此软件仅用于测试/演示目的。 InterSystems 不支持将此代码作为任何发布产品的一部分。 它由 InterSystems 提供,作为特定产品和版本的演示/测试工具。 用户或客户全权负责此软件交付后的维护和测试,InterSystems 对此代码的错误或误用不承担任何责任**。 1) 首先,通过管理门户导入文件“DataCollection.xml”,并确保没有错误。 如果存在错误,则可能是版本问题,请发送电子邮件至 ari.glikman@intersystems.com 联系 Ari Glikman 获取适合你的版本的支持。 另外,确保将数据导入到你想要收集其内部数据以供后续检查的命名空间中。 2) 导入完成后,应该看到 Sample 软件包以及几个子软件包 ![image](/sites/default/files/inline/images/1_74.png) 如果服务器上已经存在 Sample 软件包,那么你仍然应该可以看到新的子软件包以及先前存在的其他文件夹。 3) 现在,运行单元测试以确保一切正常运行。 a. 创建可以被 InterSystems Terminal 读取的名为 Unit Tests 的文件夹,例如,由于我有一个本地安装,我需要在 C 盘中创建一个文件夹。 ![image](/sites/default/files/inline/images/2_50.png) b. 我们现在将把 Sample.DBExpansion.Test.CaptureTest 类导出到此文件夹中,作为一个 xml 文件 ![image](/sites/default/files/inline/images/3_39.png) c. 在终端中,设置 ^UnitTestRoot = “>”。 根据上面的示例,它将是(注意,你必须位于导入软件包的同一命名空间中)C:\(**注意,不是**“C:\Unit Tests”!) ``` set ^UnitTestRoot = "C:\" ``` d. d. 最后,运行单元测试。 从终端运行以下代码行: ``` do ##class(Sample.DBExpansion.Test.TestManager).RunTest("Unit Tests", "/noload/nodelete") ``` 我们实际上是在告诉程序运行在 C:\Unit Tests 文件夹中找到的所有测试。 目前我们只有一个文件,也就是在 3.b 中创建的文件。 输出应如下所示 ![image](/sites/default/files/inline/images/4_31.png) 如果单元测试没有通过,程序就还不能运行。 在获得表明所有测试都通过的输出之前,不要执行后续步骤。 4) 恭喜! 现在可以构建任务了。 需要执行以下操作: 打开管理门户,转到 System Operation > Task Manager > New Task *注意,你的用户必须有权访问 %SYS 命名空间, 否则任务将运行但不会收集任何数据* ![image](/sites/default/files/inline/images/5_19.png) 现在,你将获得几个字段来填写想要创建的任务。 选择导入软件包的命名空间并为任务命名。 应该给出描述,以供未来参考。 最好不要选中快速复选框,虽然任务将运行得更慢,但收集的数据更完整。 如果运行时间过长(取决于数据库及其全局变量的大小),那么可以在这里勾选并选择更快的任务。 HowManyGlobals 表示应该收集多少个全局变量:-1 表示所有全局变量,这是推荐选项。 选择 Next,选择任务运行的频率,然后点击 Finish。 ![image](/sites/default/files/inline/images/6_17.png) b. 现在,你将看到 Task Schedule,显示所有任务(包括新创建的任务)的预计运行时间。 如果你希望现在运行,选择右侧的 Run。 选择 Task History 确保其已成功创建。 运行任务后,你应该会看到它也成功运行。 否则,这里会出现错误。 此任务将创建两个表: *Sample_DBExpansion_Data.DBAnalysisInfo* 此表将存储有关数据库本身的数据。 我们将其称为“元数据”。 可以在下图中看到它存储的信息。 快速标志将指示 4.a 中的选择。 ![image](/sites/default/files/inline/images/7_14.png) *Sample_DBExpansion_Data.GlobalAnalysisInfo* 这将包含有关数据库中全局变量的信息。 注意,如果有与全局变量关联的类名,我们将在这里看到它以及它们的大小。 最后,注意 MetaDataID 字段与 Sample_DBExpansion_Data.DBAnalysisInfo 表的 ID 字段相对应。 这意味着在捕获数据库信息时,其对应全局变量信息也被捕获,并且它们共享这个标识号(这些是当时数据库中的全局变量信息)。 这样可以查看数据库中的全局变量以及数据库本身如何随时间演变。 ![image](/sites/default/files/inline/images/8_16.png) 5) 接下来是稍微漂亮一点的用户界面。 ![image](/sites/default/files/inline/images/9.gif) 它以更易理解的方式显示表中的全局变量和数据库信息。 有 3 个图表:第一个显示数据的历史记录,第二个显示所选全局变量的历史大小(通过下拉菜单或搜索),最后是所有全局变量大小的概览。 在底部的表中,可以输入要显示的全局变量数量,并按大小排列。 在 %Change 列中,黄色高亮表示大小变化极小,绿色表示大小减小,红色表示大小显著增大。 在[这里](https://github.com/Ari-Glikman/DataCollection-UI)可以找到有关设置的分步说明。 如果你不喜欢图表,可以在[这里](https://github.com/Ari-Glikman/DataAnalysis)继续进行数据分析。 ## Docker ### 先决条件 确保已安装 [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) 和 [Docker 桌面](https://www.docker.com/products/docker-desktop)。 ### 安装 将仓库克隆/git pull 到任意本地目录 ``` $ git clone https://github.com/rcemper/PR_DataCollection.git ``` ``` $ docker compose up -d && docker compose logs -f ``` 容器启动 创建适当的目录 «/home/irisowner/dev/Unit Tests» 设置 ^UnitTestRoot = «/home/irisowner/dev/» 打开 IRIS 终端: ``` $ docker-compose exec iris iris session iris USER> ``` 或使用 **WebTerminal**。 http://localhost:42773/terminal/ 访问 IRIS 系统管理门户 http://localhost:42773/csp/sys/UtilHome.csp 访问 UnitTestPortal http://localhost:42773/csp/sys/%25UnitTest.Portal.Indices.cls?$NAMESPACE=USUARIO 如何通过管理门户导入文件“DataCollection.xml” ? 系统资源管理器 - > 类 -> 开始 点击 ‘导入’ 进入管理门户,点击菜单“系统资源管理器“>"类">"导入"。注意改命名空间为你的目标命名空间
文章
Jingwei Wang · 五月 4, 2022

IntegratedML 演练

InterSystems IRIS IntegratedML功能用于使用AutoML技术获得机器学习的预测结果和概率。AutoML是一种机器学习技术,用于选择更好的机器学习算法/模型基于已有数据(用于训练AutoML模型的数据)来预测状态、数字和结果。你不需要一个数据科学家,因为AutoML会测试最常见的机器学习算法,并根据分析的数据特征选择更好的算法给你。在这篇文章中可以看到更多管乐IntegratedML的信息。 InterSystems IRIS有一个内置的AutoML引擎,但也允许你使用H2O和DataRobot。在这篇文章中,我将向你展示使用InterSystems AutoML引擎的每个步骤。 第1步 - 下载样例应用程序做练习 1. 转到 https://openexchange.intersystems.com/package/Health-Dataset 2. Clone/git 将 Repo拉到任何本地目录中 $ git clone https://github.com/yurimarx/automl-heart.git 3. 在同一个目录中打开一个Docker终端并运行 $ docker-compose build 4. 运行IRIS容器 $ docker-compose up -d 第2步--了解业务场景和可用数据 业务场景是利用过去的数据预测心脏疾病,数据如下: SELECT age, bp, chestPainType, cholesterol, ekgResults, exerciseAngina, fbsOver120, heartDisease, maxHr, numberOfVesselsFluro, sex, slopeOfSt, stDepression, thallium FROM dc_data_health.HeartDisease 心脏病表(heartDisease)的数据字典来源(https://data.world/informatics-edu/heart-disease-prediction/workspace/data-dictionary): Column name Type Description age Integer In years sex Integer (1 = male; 0 = female) chestPainType Integer Value 1: typical angina -- Value 2: atypical angina -- Value 3: non-anginal pain -- Value 4: asymptomatic bp Integer Resting blood pressure (in mm Hg on admission to the hospital) cholesterol Integer Serum cholestoral in mg/dl fbsOver120 Integer (fasting blood sugar > 120 mg/dl) (1 = true; 0 = false) ekgResults Integer Resting electrocardiographic results -- Value 0: normal -- Value 1: having ST-T wave abnormality (T wave inversions and/or ST elevation or depression of > 0.05 mV) -- Value 2: showing probable or definite left ventricular hypertrophy maxHr Integer Maximum heart rate achieved exerciseAngina Integer Exercise induced angina (1 = yes; 0 = no) stDepression Double ST depression induced by exercise relative to rest slopeOfSt Integer The slope of the peak exercise ST segment -- Value 1: upsloping -- Value 2: flat -- Value 3: downsloping numberOfVesselsFluro Integer Number of major vessels (0-3) colored by flourosopy thallium Integer 3 = normal; 6 = fixed defect; 7 = reversable defect heartDisease String Value 0: < 50% diameter narrowing -- Value 1: > 50% diameter narrowing 心脏病(heartDisease)是我们需要预测的属性 第3步--准备好训练数据 HeartDisease表有270行。我们将得到250行来训练我们的预测模型。为了做到这一点,我们需要创建VIEW ,通过 管理门户>系统资源管理器>SQL。 CREATE VIEW automl.HeartDiseaseTrainData AS SELECT * FROM dc_data_health.HeartDisease WHERE ID < 251 第4步 - 准备验证数据 我们将得到20行来验证预测的结果。 为了做到这一点,我们需要创建VIEW ,通过 管理门户>系统资源管理器>SQL。 CREATE VIEW automl.HeartDiseaseTestData AS SELECT * FROM dc_data_health.HeartDisease WHERE ID > 250 第5步--创建AutoML模型来预测心脏疾病 IntegratedML允许创建一个AutoML模型来做预测和概率(详见https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GIML_BASICS)。要做到这一点,需要创建以下模型,通过 管理门户>系统资源管理器>SQL。 CREATE MODEL HeartDiseaseModel PREDICTING (heartDisease) FROM automl.HeartDiseaseTrainData 这个模型将从automl.HeartDiseaseTrainData view中获得训练数据(学习)。 第6步 - 执行训练 执行训练,了做到这一点,执行下面训练SQL语句,通过 管理门户>系统资源管理器>SQL。 TRAIN MODEL HeartDiseaseModel 第7步 - 验证训练后的模型 为了验证训练结果,在 管理门户>系统资源管理器>SQL 中执行以下SQL指令。 VALIDATE MODEL HeartDiseaseModel FROM automl.HeartDiseaseTestData 使用automl.HeartDiseaseTestData view 中的测试数据验证了HeartDiseaseModel。 第8步 - 获取验证指标 为了查看验证过程中的验证指标,在 管理门户>系统资源管理器>SQL 中执行以下SQL 指令。 SELECT * FROM INFORMATION_SCHEMA_ML_VALIDATION_METRICS 要了解返回的结果,请见 https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GIML_VALIDATEMODEL. InterSystems IRIS 文件从验证结果中详细说明了以下内容。: 验证指标,可以在INFORMATION_SCHEMA_ML_VALIDATION_METRICS表中查看 对于回归模型,以下指标会被保存: 方差 R-squared 平均平方误差 均方根误差 对于分类模型,以下指标会被保存: Precision — 这是用真阳性数除以预测阳性数(真阳性与假阳性之和)计算出来的。 Recall — 这是用真阳性数除以实际阳性数(真阳性与假阴性之和)来计算的。 F-Measure — 这是由以下表达式计算的:F = 2 * (精度*召回率) / (精度+召回率) Accuracy — 这是用真阳性和真阴性的数量除以整个测试集的总行数(真阳性、假阳性、真阴性和假阴性之和)来计算的。 第9步 - 使用你的新AutoML模型执行预测 - 最后一步! 为了查看验证过程中的验证指标,在 管理门户>系统资源管理器>SQL 中执行以下SQL指令。 SELECT *, PREDICT(HeartDiseaseModel ) AS heartDiseasePrediction FROM automl.HeartDiseaseTestData 比较列 heartDisease(真实值)和 heartDiseasePrediction(预测值)。
文章
Michael Lei · 二月 13, 2023

何时使用列存储

InterSystems IRIS 2022.2 中,我们引入了列存储作为持久化 IRIS SQL 表的新选项,可以将您的分析查询性能提高一个数量级。该功能在 2022.2 和 2022.3 中标记为实验性,但将在即将发布的 2023.1 版本中“升级”为完全支持的生产能力。 产品文档和这个介绍性视频已经描述了行存储(仍然是 IRIS 上的默认设置并在我们的整个客户群中使用)与列表存储之间的区别,并提供了有关为您的用例选择合适的存储布局的高级指导。在本文中,我们将详细阐述这个主题,并根据行业实践建模原则、内部测试和抢先体验计划参与者的反馈分享一些建议。 通常,我们为您的 IRIS SQL 模式选择合适的表布局的指南如下: 如果您正在部署利用 IRIS SQL 或对象的应用程序,例如电子病历、ERP 或事务处理应用程序,则无需将其当前的行存储布局更改为列式存储布局。为最终用户应用程序或编程事务发出的大多数 SQL 查询仅检索或更新有限数量的行,结果行通常对应于表行,聚合函数的使用非常有限。在这种情况下,列式存储和矢量化查询处理提供的优势不适用。 如果在应用程序还嵌入了操作分析,如果相应的分析查询的当前性能不令人满意,请考虑添加列索引。这包括,例如,显示当前库存的仪表板或实时数据的基本财务报告。查找聚合中使用的数字字段(例如数量、货币)或范围条件中使用的高基数字段(例如时间戳)。这种机会的一个很好的指标是当前使用位图索引来加速大量行的过滤,通常是在低基数字段(例如分类或有序字段)上。无需替换这些位图索引;附加的柱状索引与它们一起工作得很好,旨在避免从主地图或常规索引地图(每行单个 gref)中过度读取。 如果您的 IRIS SQL 表包含的行数少于一百万,则无需考虑列式存储。我们不希望将自己固定在特定数字上,但矢量化查询处理的好处不太可能在这些低范围内产生影响。 如果您正在为数据仓库、商业智能或类似的分析用例部署 IRIS SQL 架构,请考虑将其更改为默认的列式存储。星型模式、雪花模式或其他非规范化表结构以及位图索引和批量摄取的广泛使用是这些用例的良好指标。从列式存储中获益最多的分析查询是那些扫描大量行并在它们之间聚合值的查询。在定义“柱状表”时,IRIS 会透明地对该表中不适合柱状存储的列采用行布局,例如流、长字符串或串行字段。 IRIS SQL 完全支持这种混合表布局,并将对查询计划中符合条件的部分使用矢量化查询处理。位图索引在柱状表上的附加值有限,可以忽略不计。 技术使用与否将根据环境和数据相关参数而有所不同。因此,我们强烈建议客户在具有代表性的设置中测试不同的场景。列索引可以很容易地添加到常规的按行组织的表中,并且会很快产生对查询性能优势的现实看法。这与混合表格布局的灵活性一起,是 InterSystems IRIS 的一个关键差异化因素,可帮助客户实现数量级的性能改进。 随着我们在完整的生产版本中获得更多的实际经验,我们打算使这些建议更加具体。显然,我们可以通过抢先体验计划和 POC 参与,根据客户的实际架构和工作量提供更具体的建议,并期待客户和社区成员的反馈。 列存储Columnar Storage 是 InterSystems IRIS Advanced Server 高级版的一部分,在 InterSystems IRIS 和 IRIS for Health 社区版中也可以试用。有关完全脚本化的演示环境,请参阅这里的 GitHub资源 。
文章
姚 鑫 · 五月 1, 2023

第四十五章 管理镜像 - 使用 ^MIRROR 状态监视器

# 第四十五章 管理镜像 - 使用 ^MIRROR 状态监视器 # 使用 ^MIRROR 状态监视器 `^MIRROR` 例程提供基于字符的镜像状态监视器。 `^MIRROR Status Monitor` 选项显示镜像成员的状态,包括类型、状态、日志传输延迟和 `dejournal` 延迟(请参阅镜像成员日志传输和 `Dejournaling` 状态)。监视器可以在任何镜像成员上运行,但在故障转移成员上运行它会提供有关仲裁器配置和所有连接的异步成员的信息,而在异步成员上运行它则不会。 要启动状态监视器,请打开终端窗口,在 `%SYS` 命名空间中运行 `^MIRROR` 例程(请参阅使用 `^MIRROR` 例程),然后从镜像状态菜单中选择状态监视器。以下是在故障转移成员上运行时监视器的输出示例: ```java Status of Mirror MIR25FEB at 17:17:53 on 02/27/2018 Member Name+Type Status Journal Transfer Dejournaling -------------------------- --------- ---------------- -------------- MIR25FEB_A Failover Primary N/A N/A MIR25FEB_B Failover Backup Active Caught up MIR25FEB_C Disaster Recovery Connected Caught up Caught up MIR25FEB_D Read-Only Reporting Connected Caught up Caught up Arbiter Connection Status: Arbiter Address: 127.0.0.1|2188 Failover Mode: Arbiter Controlled Connection Status: Both failover members are connected to the arbiter Press RETURN to refresh, D to toggle database display, Q to quit, or specify new refresh interval ``` 当在异步成员上运行状态监视器时,仅列出故障转移成员和该异步成员,并且还会显示异步(正在运行或已停止)上的 `dejournaling` 状态,例如: ```java Status of Mirror MIR25FEB at 17:17:53 on 02/27/2018 Member Name+Type Status Journal Transfer Dejournaling -------------------------- --------- ---------------- -------------- MIR25FEB_A Failover Primary N/A N/A MIR25FEB_B Failover Backup Active Caught up MIR25FEB_C Disaster Recovery Connected Caught up Caught up Dejournal Status: running (process id: 12256) Press RETURN to refresh, D to toggle database display, Q to quit, or specify new refresh interval ``` 默认情况下,不显示有关镜像数据库的信息。在提示符处输入 `d` 以列出有关镜像中每个数据库的信息,包括名称、目录、状态和要取消的下一条记录,如使用镜像监视器中所述,例如: ```java Mirror Databases: Last Record Name Directory path Status Dejournaled ------------- ----------------------------------- ----------- ----------- MIR25FEB_DB1 C:\InterSystems\20182209FEB25A\Mgr\MIR25FEB_DB1\ Active Current,c:\intersystems\20182209feb25a\mgr\journal\MIRROR-MIR25FEB-20180227.001,40233316 MIR25FEB_DB2 C:\InterSystems\20182209FEB25A\Mgr\MIR25FEB_DB2\ Active Current,c:\intersystems\20182209feb25a\mgr\journal\MIRROR-MIR25FEB-20180227.001,40233316 ``` # 监控镜像通信进程 每个系统(主要和备份故障转移成员,以及每个连接的异步成员)上运行的进程负责镜像通信和同步。 ## 主要故障转移成员上的镜像进程 在主要故障转移成员上运行系统状态例程 (^%SS) 会显示下表中列出的进程。 注意:本节的 `^%SS` 输出中有意省略了 `CPU`、`Glob` 和 `Pr` 列。 #### 主要故障转移成员上的镜像进程 Device| Namespace| Routine| User/Location ---|---|---|--- /dev/null| %SYS |MIRRORMGR |Mirror Master MDB2| %SYS| MIRRORCOMM| Mirror Primary* 192.168.1.1 |%SYS |MIRRORCOMM |Mirror Svr:Rd* 这些过程定义如下: - `Mirror Master`:该进程在系统启动时启动,负责各种镜像控制和管理任务。 - `Mirror Primary`:这是出站数据通道;这是一个单向通道。每个连接的系统有一个作业(备份故障转移或异步成员)。 - `Mirror Svr:Rd*`:这个是入站确认通道;这是一个单向通道。每个连接的系统有一个作业(备份故障转移或异步成员)。 每个连接的异步成员都会在主故障转移成员上产生一组新的 `Mirror Master`、`Mirror Primary` 和 `irror Svr:Rd*` 进程。 ## 备份故障转移/异步成员上的镜像进程 在备份故障转移/异步成员上运行系统状态例程 (`^%SS`) 会显示下表中列出的进程。 #### 备份故障转移/异步成员上的镜像进程 Device| Namespace| Routine| User/Location ---|---|---|--- /dev/null| %SYS |MIRRORMGR |Mirror Master /dev/null |%SYS|MIRRORMGR| Mirror Dejour /dev/null| %SYS|MIRRORMGR| Mirror Prefet* /dev/null |%SYS |MIRRORMGR| Mirror Prefet* MDB1 |%SYS|MIRRORMGR |Mirror Backup /dev/null| %SYS|MIRRORMGR |Mirror JrnRead 此表中标识的进程也出现在每个连接的异步成员上: - `Mirror Master`:该进程在系统启动时启动,负责各种镜像控制和管理任务。 - `Mirror JrnRead (Mirror Journal Read)`:该过程将备份生成的日志数据读入内存,并将这些更改排队等待 `dejournal` 作业取消。 - 镜像延迟(`Mirror Dejournal`):这是备份故障转移成员上的延迟作业;它将接收到的日志数据中的 `sets` 和 `kills` 发送到镜像数据库。 - `Mirror Prefet*`(镜像预取):这些进程负责在`dejournal` 作业实际尝试使用它们之前将 `dejournal` 作业所需的磁盘块预取到内存中。这样做是为了加快 `dejournaling` 过程。系统上通常配置了多个镜像预取作业。镜像备份:这个过程是一个双向通道,将从主服务器接收到的日志记录写入备份的镜像日志文件,并向主服务器返回确认。
文章
Hao Ma · 一月 15, 2021

ObjectScript错误管理

InterSystems编程语言的错误管理技术一直在发展。接下来,我们将展示几种不同的错误管理实现方式,以及为什么要使用TRY/THROW/CATCH机制。 您可以点击这里阅读官方的错误处理建议。 为了支持遗留应用程序,InterSystems不会废弃非推荐的错误管理方法。我们建议使用objectscriptQuality等工具来检测遗留的非推荐用例以及其他可能的问题和错误。 $ZERROR $ZERROR是一种较老的错误管理机制,支持与标准“M”不同的实现。虽然$ZERROR现在仍然有效,但我们非常不推荐使用。 如果您已经使用了$ZERROR,那么很容易对该变量进行错误的设计使用。$ZERROR是一个全局公共变量,可以被当前进程中正在执行的所有routine(宏)(来自InterSystems或自定义的)进行访问和修改。因此,它的值仅在产生错误的时候是可靠的。InterSystems不保证$ZERROR在调用系统库时会保留旧值。 我们在这里对一些案例展开分析。 案例1:自定义代码中的错误代码 Line Code Comments $ZERROR value 1 Set ... "" 2 Set ... "" ... Do ... "" ... ... "" N-m Do CacheMethodCall() Call to another Caché system methods "" ... "" N Set VarXX = MyMethod() The custom method generates an ObjectScript error <UNDEFINED>B+3^InfinityMethod *varPatient N+1 Set … <UNDEFINED>B+3^InfinityMethod *varPatient N+2 Do OtherCacheMethodCall() Caché system method. $ZERROR is not updated if there is no error. <UNDEFINED>B+3^InfinityMethod *varPatient ... If ... <UNDEFINED>B+3^InfinityMethod *varPatient ... ... <UNDEFINED>B+3^InfinityMethod *varPatient ... While ... <UNDEFINED>B+3^InfinityMethod *varPatient ... If $ZERROR’=”” Quit “Error” <UNDEFINED>B+3^InfinityMethod *varPatient N+m Quit "OK" <UNDEFINED>B+3^InfinityMethod *varPatient 案例2:内部Caché错误出现误报 在这种情况下,自定义代码运行良好,但内部Caché错误引发了一个错误。 Line Code Comments $ZERROR value 1 Set … "" 2 Set … "" .. Do … "" .. … "" N-m Do CacheMethodCall() Internal error but it is managed internally and decides to continue execution <UNDEFINED>occKl+3^ MetodoInternoCache *o0bxVar .. <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar N Set VarXX = MyMethod() // OK <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar N+1 Set … <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar N+2 Do OtherCacheMethodCall() // OK <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar … If … <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar … … <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar … While … <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar … If $ZERROR’="" Quit "Error" An error is detected while there is no error at all <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar N+m Quit "OK" <UNDEFINED>occKl+3^ MetodoInterno *o0bxVa 案例3:在Caché内部代码中重置$ZERROR时出现误报 在这种情况下,即使不存在错误,也会直接或间接调用一个内部Caché方法或routine(宏)来重置公共变量$ZERRO Line Code Comments $ZERROR 1 Set ... "" 2 Set ... "" ... Do ... "" ... ... "" N-m Do CacheMethodCall() <UNDEFINED>occKl+3^ MetodoInternoCache *o0bxVar ... <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar N Set VarXX = MyMethod() <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar N+1 Set … <UNDEFINED>occKl+3^ MetodoInterno *o0bxVar N+2 Do OtherCacheMethodCall() Internal method that resets $ZERROR whether there is error or not "" ... If ... "" ... ... "" ... While ... "" ... If $ZERROR’="" Quit "Error" Error not detected "" N+m Quit "OK" "" $ZTRAP $ZTRAP是在上下文中进行错误管理的,因此不存在在上下文环境之外被意外覆盖的风险。当出现错误时,控件返回到调用堆栈中的第一个错误控件。 当出现错误并处理完成后,必须清除$ZTRAP,以便在发生另一个错误时避免出现无限循环。 因此,$ZTRAP在错误管理方面比$ZERROR更先进,但开发人员在添加操作时有可能会产生更多的错误。 如果想要进一步了解此方法的使用,可以查看官方文档中的“$ZTRAP错误处理”节选内容。 %Status 该方法用于系统库中,因此是调用系统库时必须使用的机制。 可以点击这里查看用法。 TRY/THROW/CATCH 这是最现代的错误管理方法,也是目前比较推荐的方法。 您可以点击这里查看用法。 此方法可在上下文中管理错误,并且不需要开发人员管理内部错误变量。 优点 关于TRY/THROW/CATCH的文献有很多,这里列举了一些它的优点: 提供了一种清晰的方式进行异常情况处理,将错误代码与常规代码分开处理 简化了错误检测,所以无需在每次操作后检查错误 允许错误传播到上层 支持运行时错误,允许在崩溃后恢复并继续运行 缺点 最明显的缺点是轻微的性能损失,因此您必须知道需要在什么时候使用该方法。 通常,没有必要在每种方法上都使用TRY/THROW/CATCH,在很多情况下在操作前多进行几次简单的验证就可以避免很多避免错误,从而避免不必要地使用TRY/THROW/CATCH方法。 结论 避免使用$ZERROR和$ZTRAP。 只有在调用系统库时才使用%STATUS。 可以使用TRY/THROW/CATCH管理错误,但不要滥用。
文章
Jingwei Wang · 七月 4, 2022

IRIS/HealthConnect 高可用机制

高可用性(HA)指的是使系统或应用程序在很高比例的时间内保持运行,最大限度地减少计划内和计划外的停机时间。 维持系统高可用性的主要机制被称为故障转移。在这种方法下,一个故障的主系统被一个备份系统所取代;也就是说,生产系统故障转移到备份系统上。许多HA配置还提供了灾难恢复(DR)的机制,即在HA机制无法保持系统的可用性时,也能及时恢复系统的可用性。 本文简要讨论了可用于基于InterSystems IRIS的应用程序的HA策略机制,提供了HA解决方案的功能比较,并讨论了使用分布式缓存的故障转移策略。 操作系统级别的集群HA 在操作系统层面上提供的一个常见的HA解决方案是故障转移集群,其中主要的生产系统由一个(通常是相同的)备用系统补充,共享存储和一个跟随活动成员的集群IP地址。在生产系统发生故障的情况下,备用系统承担生产工作量,接管以前在故障主系统上运行的程序和服务。备用机必须能够处理正常的生产工作负载,只要恢复故障主机所需的时间就可以了。也可以选择让备用机成为主机,一旦主机恢复,故障主机将成为备用机。 InterSystems IRIS的设计可以轻松地与所支持的平台的故障转移集群技术相结合(如InterSystems支持的平台中所述)。InterSystems IRIS实例安装在集群的共享存储设备上,以便两个集群成员都能识别它,然后添加到集群配置中,这样它将作为故障转移的一部分在备用机上自动重新启动。在故障转移后重新启动时,系统自动执行正常的启动恢复,保持结构和逻辑的完整性,就像InterSystems IRIS在故障系统上重新启动一样。如果需要,可以在一个集群上安装多个InterSystems IRIS实例。 InterSystems IRIS 镜像 具有自动故障转移功能的 InterSystems IRIS 数据库镜像为计划内和意外停机提供了经济有效的高可用性解决方案。镜像依赖于数据复制而不是共享存储,避免了存储故障导致的重大服务中断。 InterSystems IRIS 镜像由两个物理上独立的 InterSystems IRIS 系统组成,称为故障转移成员。每个故障转移成员在镜像中维护每个镜像数据库的副本;应用程序更新是在主故障转移成员上进行的,而备机故障转移用户的数据库则通过主成员的日志文件保持数据同步。 镜像会自动将主节点的角色分配给两个故障转移成员中的一个,而另一个故障转移成员则自动成为备机系统。当主 InterSystems IRIS 实例失败或变得不可用时,备机将自动快速接管并成为主机。 第三个系统称为仲裁机,它与故障转移成员保持持续的联系,在无法直接通信时安全地做出故障转移决策,为他们提供所需信息。在每个故障转移系统主机上运行的代理(称为 ISCAgents )进程也有助于自动故障转移逻辑。除非备机能够确认主节点确实处于停机状态或不可用状态,并且无法再作为主节点运行,否则备机将无法接管。在仲裁机和 ISCAgents 之间,这可以在几乎每个中断场景下完成。 当镜像配置使用 virtual IP address(虚拟 IP 地址)时,将应用程序连接重定向到新主节点是透明的。如果连接是通过 ECP,它们会自动重置到新的主节点。用于重定向应用程序连接的其他机制也是可用的。 当主机实例恢复正常时,它将自动成为备机实例。操作员启动的故障转移也可在计划的维护或升级停机期间维护可用性。 自动故障转移机制 镜像主旨在当主节点失败或变得不可用时,为备机提供安全的自动故障转移。本部分描述了允许这种情况发生的机制,包括: • 自动故障转移的安全性要求 • 自动故障转移规则 • 对于各种中断情况的镜像响应 • 自动故障转移机制详节 自动故障转移的安全性要求 备机的 InterSystems IRIS 实例只有在能够确保满足以下两个条件时才能自动接管主节点: • 备机实例已从主节点接收到最新的日志数据。 这一要求保证了主节点上镜像数据库的所有持久更新都已经或将要对备机的相同数据库进行,从而确保不会丢失任何数据。 • 主机实例不再作为主机实例运行,并且在没有手动干预的情况下无法这样做。 这个要求消除了两个故障转移成员同时作为主节点的可能性,这可能导致逻辑数据库性能下降和完整性损失。 自动故障转移规则 备机状态和自动故障转移 在正常镜像操作期间,备机故障转移成员的日志传输状态为活动,这意味着它已从主节点接收到所有日志数据,并与其同步。活跃的备机接收写在主机上的当前日志数据,主机等待备机确认收到日志之后才考虑该数据的持久化。因此,备机为活跃状态满足故障转移的第一个条件。 如果活跃备机在Quality of Service(QoS)(服务质量超时)内不能确定已从主节点接收新数据,主节点会撤销备机的活动状态,断开备机并暂时进入故障状态。当处于故障状态时,主节点不提交任何新的日志数据(可能导致应用程序暂停),确保充足的时间,使故障转移成员在不发生异步的情况下恢复联系或进行适当的安全故障转移决策 当备机重新连接到主节点时,它首先通过从主节点获取所有最近的日志数据来跟上,然后变为活动状态。当备机通过从主节点同步了最新的日志数据并确认其接收而跟上时,将恢复其活动状态。 备机处于活动状态时的自动故障转移 当备机处于活动状态时,如果它能够确认故障转移的第二个条件,主节点不可以再作为主节点,并且在没有人工干预的情况下不能继续成为主节点,那么它就有资格作为主机进行接管。备机可以通过以下三种方式中的任意一种来接管主节点: • 通过接收来自主机的请求接管的通信 这发生在主机实例正常关闭期间或主机实例检测到主机实例挂起时。一旦主节点发送了这条消息,它就不能再作为主机了,活动备机可以安全地接管它。如果前一个主机被挂起,新的主机就会迫使它关机。 • 通过从仲裁机处收到信息,得知其已与主机失去联系。 当一个网络事件同时将主节点与备机和仲裁机隔离时,它将无限期地进入故障状态。因此,如果一个活跃备机与主机失去联系,并且从仲裁机那里得知它也与主机用失去了联系,那么备机可以安全地接管,因为主机用必须要么已经出现故障,要么被隔离并处于故障状态,因此不能再作为主节点运行了。当连接恢复时,如果前一个主节点挂起,新的主节点就会将之前的主节点强制关闭。 • 通过从主机的 ISCAgent 接收主机实例已关闭或挂起的信息。 当仲裁机不可用或未配置仲裁机时,与主机实例失去联系的活动备机可以尝试联系主机实例的 ISCAgent(只有在主机实例主机系统仍在运行时才可能)以确认主机实例已关闭或处于挂起状态。一旦代理确认主节点不能再作为主机,并且故障转移因此是安全的,备机就会接管。 备机不处于活动状态时的自动故障转移 不活动的备机可以尝试与主机实例的 ISCAgent 联系,以确认主机实例处于关闭状态,或在挂起时强制关闭主机实例,并从代理获取主机实例最近的日志数据。如果在这两方面都成功,那么备机可以安全地作为主机接管。 不活动且无法与主机的 ISCAgent 联系的备机无法确保主机不再作为主机,并且无法保证此时的备机拥有主机最新的日志更新,因此无法接管主机。 当备机没有活动时,仲裁机在故障转移机制中不起任何作用。 对于各种中断情况的镜像响应 自动故障转移中主机中断场景的响应 在以下几种主要的主节点中断情况下,活动的备机故障转移成员会自动接管: 主节点的计划中断(例如出于维护目的)通过关闭其 InterSystems IRIS 实例来启动。 自动故障转移发生是因为主机指示活跃备机接管。 主 InterSystems IRIS 实例由于意外情况而挂起。 自动故障转移发生是因为主节点检测到它被挂起并指示活跃备机接管。 主 InterSystems IRIS 实例由于意外情况而被迫关闭或完全失去响应。 在此情况下,主节点不能指示备机接管。然而,活动备机可以在从仲裁机那里得知它也与主节点失去联系后接管,也可以通过与主机的 ISCAgent 联系并获得主机停机的确认后接管。 主机存储的子系统失败。 存储失败的典型后果是主机实例挂起,原因是 I/O 错误,在这种情况下,主节点检测到它被挂起,并指示活动的备机接管(如场景 2)。然而,在某些情况下,场景 3 或场景 5 描述的行为可能适用。 主机的主机系统发生故障或失去响应。 如果活动的备机从仲裁机获悉它也与主机失去联系,则发生自动故障转移。 如果没有配置仲裁机,或者仲裁机在主机故障前已经不可用,则不可能进行自动故障转移;在这些情况下,可以选择手动强制备机成为主机。 一个网络问题隔离了主机。 如果配置了仲裁机,并且在网络故障时两个故障转移成员都不能连接到它,则主节点将无限地进入故障状态。 • 如果活动的备机从仲裁机获悉它也与主机失去联系,则发生自动故障转移。 • 如果备机在与主节点失去联系的同时失去与仲裁机的联系,则不可能进行自动故障转移。如果两个故障转移成员都已启动,则在还原网络时,备机将与主节点联系,主节点恢复操作。或者,可以手动指定主节点。 如果没有配置仲裁机,或者在网络故障发生前,故障转移成员之一已经与仲裁机断开,则无法进行自动故障转移,主节点将继续作为主机运行。 一个未活动的备机(例如备机正在启动或未追上主机最新日志)可以通过与主节点的 ISCAgent 联系并获得最新的日志数据,在上述场景 1 到 4 下接管。未活动的备机不能在场景 5 和 6 中接管,因为它不能与 ISCAgent 联系;在这些情况下,手动强制使备机成为主机可能是一种选择。 自动故障转移机制详解 代理控制模式 当镜像启动时,故障转移成员在代理控制模式下开始操作。如果仲裁机不可用或未配置仲裁机,则保持此模式。当处于代理控制模式时,故障转移成员响应彼此之间的联系丢失,如下所述。 主机对失联的反应 如果主节点失去了与活动备机的连接,或者超过了等待它确认数据接收的 QoS timeout (QoS 超时),则主程序撤消备机的活动状态并进入故障状态,等待备机确认其不再活动。当主节点收到来自备机的确认或故障超时(是 QoS 超时的两倍)过期时,主程序退出故障状态,恢复为主程序运行。 如果主节点失去了与非活动备机的连接,则它将继续作为主程序运行,不会进入故障状态。 备机对失联的反应 如果备机失去了与主节点的连接,或者超过了等待来自主机的消息的 QoS timeout (QoS 超时),那么它将尝试与主客户的 ISCAgent 联系。如果代理报告主机实例仍作为主机实例运行,则备机重新连接。如果代理确认主节点处于关闭状态,或者它已将其强制关闭,则备机行为如下: • 如果备机处于活动状态,且代理确认主节点在故障超时内处于停机状态,则备机将作为主服务端接管。 • 如果备机未处于活动状态,或者超过了故障超时时间,那么如果代理确认主节点已停机,并且能够从代理获得最新的日志数据,则备机将接管。 无论是否处于活动状态,备机永远无法在代理控制模式下自动接管,除非主节点自身确认它已挂起,或者主服务的代理确认主服务已停机(可能是在强制停机之后),如果主节点已停机或网络隔离,这两种情况备机无法自动接管。 注意: 当其中一个故障转移成员重启时,它会尝试联系另一个成员的 ISCAgent,其行为与不活动备机的描述一样。 仲裁机控制模式 当故障转移成员相互连接时,两者都连接到仲裁机,并且备机是活动的,它们进入仲裁机控制模式,在该模式中,故障转移会员根据仲裁机提供的关于另一个故障转移成员的信息对它们之间的联系丢失做出响应。因为每个故障转移成员通过测试其与另一个故障转移成员的连接来响应其仲裁连接的丢失,反之亦然,由单个网络事件引起的多个连接丢失被作为单个事件处理。 在仲裁机控制模式中,如果故障转移成员仅丢失其仲裁机连接,或者备机 丢失其活动状态,则故障转移成员协调切换到代理控制模式。 如果主节点和备机节点之间的连接在仲裁机控制模式下断开,则每个故障转移成员根据仲裁机连接的状态进行响应,如下图所述。 所有三个系统连接: 镜像进入仲裁机控制模式(如果尚未进入仲裁机控制模式) 备机失去与仲裁机的连接,但仍连接到主节点: 镜像切换到代理控制模式 主节点继续作为主节点运行 备机尝试重新连接仲裁机 主节点失去与仲裁机的连接,但仍连接到备机: 镜像切换到代理控制模式 主节点继续作为主节点运行 主节点尝试重新连接仲裁程序 故障转移成员彼此失去连接,仍然连接到仲裁机: 镜像切换到代理控制模式 主节点继续作为主节点运行 备机尝试重新连接主节点 仲裁机失败或隔离-故障转移成员失去与仲裁机的连接,但仍彼此连接: 镜像切换到代理控制模式 主节点继续作为主节点运行 两个故障转移成员都尝试重新连接仲裁机 备机中断或被隔离-主节点和仲裁机失去与备机的连接,但仍相互连接: 主节点切换到代理控制模式并继续作为主节点操作 备机(如果在操作中)切换到代理控制模式并尝试重新连接到主节点 主节点中断或被隔离-备机和仲裁机失去与主节点的连接,但仍相互连接: 主节点(如果在运行中)将无限期地保持在仲裁控制模式和故障状态 备机作为主机接管,切换到代理控制模式,并在恢复连接时强制主机关闭 三个连接全部丢失: 主节点(如果在运行中)将无限期地保持在仲裁控制模式和故障状态;如果与备机设备联系,则切换到代理控制模式并恢复主设备的运行 备机(如果在操作中)切换到代理控制模式并尝试重新连接到主节点 注意: 由于单个事件(或多个同时发生的事件)而导致所有连接丢失的情况很少见。在大多数情况下,镜像在所有连接丢失之前切换到代理控制模式,在这种情况下: 主节点(如果在运行)继续作为主节点运行 备机(如果正在运行)尝试重新连接到主节点
文章
Jeff Liu · 八月 26, 2024

在 Linux 上配置 IRIS 自动启动功能

出于实际原因,可能需要在 Linux 服务器重启后自动启动 IRIS 实例。 下面是在 Linux 服务器重启时通过 systemd 自动启动 IRIS 的步骤: 1. 在 /etc/systemd/system/iris.service 中创建一个 iris.service 文件,其中包含以下信息 [Unit] Description=InterSystems IRIS Data Platform After=network.target [Service] Type=forking User=irisusr ExecStart=/usr/bin/iris start iris ExecStop=/usr/bin/iris stop iris quietly Restart=on-failure RemainAfterExit=yes [Install] WantedBy=multi-user.target 注意:User应该填入IRIS实例的所有者。 2. 重新加载 systemd 配置管理器 sudo systemctl daemon-reload 3. 启用IRIS服务,使其自动启动 sudo systemctl enable iris 激活后将创建软链接,自动启动 IRIS: Synchronizing state of iris.service with SysV service script with /usr/lib/systemd/systemd-sysv-install. Executing: /usr/lib/systemd/systemd-sysv-install enable iris Created symlink /etc/systemd/system/multi-user.target.wants/iris.service → /etc/systemd/system/iris.service. 4. 试着重启服务器 sudo reboot 5. 查看IRIS实例是否自动启动 ssh guilbaud@192.168.102.130 guilbaud@192.168.102.130's password: Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-36-generic x86_64) $ iris all Instance Name Version ID Port Directory ---------------- ---------------- ----- -------------------------------- up >IRIS 2024.1.0.267.2 1972 /usr/irissys
文章
Michael Lei · 六月 26, 2022

跟踪数据更改 - 审计日志 - 下篇

在前一篇文章中,我已经演示了一种简单的方法来记录数据的变化。在这个时候,我改变了负责记录审计数据的 "审计抽象类 "和记录审计日志的数据结构。 我已经将数据结构改为父子结构,其中将有两个表来记录 "交易 "和在该交易中改变的 "字段的值"。 看一下新的数据模型: 看看从 "审计类 "改变的代码吧: Class Sample.AuditBase [ Abstract ]{ Trigger SaveAuditAfter [ CodeMode = objectgenerator, Event = INSERT/UPDATE, Foreach = row/object, Order = 99999, Time = AFTER ]{ #dim %compiledclass As %Dictionary.CompiledClass #dim tProperty As %Dictionary.CompiledProperty #dim tAudit As Sample.Audit Do %code.WriteLine($Char(9)_"; get username and ip adress") Do %code.WriteLine($Char(9)_"Set tSC = $$$OK") Do %code.WriteLine($Char(9)_"Set tUsername = $USERNAME") Set tKey = "" Set tProperty = %compiledclass.Properties.GetNext(.tKey) Set tClassName = %compiledclass.Name Do %code.WriteLine($Char(9)_"Try {") Do %code.WriteLine($Char(9,9)_"; Check if the operation is an update - %oper = UPDATE") Do %code.WriteLine($Char(9,9)_"if %oper = ""UPDATE"" { ") Do %code.WriteLine($Char(9,9,9)_"Set tAudit = ##class(Sample.Audit).%New()") Do %code.WriteLine($Char(9,9,9)_"Set tAudit.Date = +$Horolog") Do %code.WriteLine($Char(9,9,9)_"Set tAudit.UserName = tUsername") Do %code.WriteLine($Char(9,9,9)_"Set tAudit.ClassName = """_tClassName_"""") Do %code.WriteLine($Char(9,9,9)_"Set tAudit.Id = {id}") Do %code.WriteLine($Char(9,9,9)_"Set tSC = tAudit.%Save()") do %code.WriteLine($Char(9,9,9)_"If $$$ISERR(tSC) $$$ThrowStatus(tSC)") Do %code.WriteLine($Char(9,9,9)_"Set tAuditId = tAudit.%Id()") While tKey '= "" { set tColumnNbr = $Get($$$EXTPROPsqlcolumnnumber($$$pEXT,%classname,tProperty.Name)) Set tColumnName = $Get($$$EXTPROPsqlcolumnname($$$pEXT,%classname,tProperty.Name)) If tColumnNbr '= "" { Do %code.WriteLine($Char(9,9,9)_";") Do %code.WriteLine($Char(9,9,9)_";") Do %code.WriteLine($Char(9,9,9)_"; Audit Field: "_tProperty.SqlFieldName) Do %code.WriteLine($Char(9,9,9)_"if {" _ tProperty.SqlFieldName _ "*C} {") Do %code.WriteLine($Char(9,9,9,9)_"Set tAuditField = ##class(Sample.AuditField).%New()") Do %code.WriteLine($Char(9,9,9,9)_"Set tAuditField.Field = """_tColumnName_"""") Do %code.WriteLine($Char(9,9,9,9)_"Set tAuditField.OldValue = {"_tProperty.SqlFieldName_"*O}") Do %code.WriteLine($Char(9,9,9,9)_"Set tAuditField.NewValue = {"_tProperty.SqlFieldName_"*N}") Do %code.WriteLine($Char(9,9,9,9)_"Do tAuditField.AuditSetObjectId(tAuditId)") Do %code.WriteLine($Char(9,9,9,9)_"Set tSC = tAuditField.%Save()") do %code.WriteLine($Char(9,9,9,9)_"If $$$ISERR(tSC) $$$ThrowStatus(tSC)") Do %code.WriteLine($Char(9,9,9)_"}") } Set tProperty = %compiledclass.Properties.GetNext(.tKey) } Do %code.WriteLine($Char(9,9)_"}") Do %code.WriteLine($Char(9)_"} Catch (tException) {") Do %code.WriteLine($Char(9,9)_"Set %msg = tException.AsStatus()") Do %code.WriteLine($Char(9,9)_"Set %ok = 0") Do %code.WriteLine($Char(9)_"}") Set %ok = 1} } 通过Test()类方法改变数据,现在你可以看到审计类(Sample.Audit)中的 "父记录 "和 "审计字段 "类中的 "子字段 "被改变。(Sample.AuditField)。 d ##class(Sample.Person).Test(1)INSERT INTO Sample.Person (Name, Age) VALUES ('TEST PARENT-CHILD', '01')SQLCODE: 0ID Age Name1 01 TEST PARENT-CHILD 1 Rows(s) AffectedUPDATE Sample.Person SET Name = 'INTERSYSTEMS DEVELOPER COMMUNITY', Age = '100' WHERE Name = 'TEST PARENT-CHILD'SQLCODE:0ID Age Name1 100 INTERSYSTEMS DEVELOPER COMMUNITY 1 Rows(s) Affected 审计类: 注意Sample.AuditField记录通过Audit字段=1对Sample.Audit类进行了引用。你可以通过使用两个类的关系来查询数据,如下所示: 这样就搞定了。这样,我们有一个不同的审计日志数据结构。
问题
jingwei lu · 三月 13, 2022

关于Cache高可用架构的选择

现在我们院区也遇到这样一个问题。关于cache的高可用架构现有有两个方案: 1.选择双节点的完全无共享架构的自动转移镜像集群外加一个灾难恢复镜像 2.就像你提问的那种,两台主机先做Rose HA用一套双活存储实现高可用,然后再弄一台服务器做Rose HA的单机镜像(有可能是同步也有可能是异步那种比如灾难恢复镜像) 现在想问问如果单纯考虑切换时候对业务的影响,如果切换的中断时长什么的,用哪个最好啊?第二种方案真有很多单位用么? 希望有大神能替我解答一下,谢谢。 可以参考下历史的帖子。https://community.intersystems.com/post/backup-strategy-%E5%8F%8C%E6%9C%BA%E5%A4%87%E4%BB%BD%E7%AD%96%E7%95%A5 如果是我,会选择方案1,原因:既然 intersystems 提供了完整的 mirror 高可用方案,就没必要再和第三方的方案掺和在一起,凭空增加了问题排错的复杂度。如果真出现了服务中断,这个时候要第一要务是尽快做出正确的决策,以便尽快恢复服务。架构的复杂性会给自己造成很多不必要的麻烦以及决策上的复杂性 (个人建议,仅供参考。) 我们推荐的高可用性方案是Mirror。也就是配置至少主备两个镜像成员+灾备异步镜像成员,可选配置多个异步报表镜像成员以及多个灾备异步镜像成员。 当然同时推荐的是建立健全的外部备机机制,以及使用外部备份进行恢复的演练,手动升级灾备异步镜像成员为主机的演练。 对于大型应用一般使用ECP创建多台应用服务器,进行多用户的负载分配,再将多台应用服务器连接至数据服务器,数据服务器进行高可用性配置。 感谢分享 感谢分享 常见问题系列-系统管理篇-如何进行数据库备份 InterSystems Caché系统高可用与数据库镜像
公告
Claire Zheng · 七月 21

更新漏洞处理策略

InterSystems,我们相信负责任地披露最近发现的安全漏洞。我们向客户提供及时的信息,同时防止信息落入可能滥用信息的人之手。我们还了解每个客户在解决安全问题方面都有不同的要求。 从 2023 年开始,我们对安全漏洞修复方法进行了两项重大更改,我想强调一下: 安全漏洞补丁将包含在每个版本中 改进客户通知 每个版本中的安全漏洞补丁现在,每个版本都可能包含针对安全漏洞的补丁,而不是等待在安全版本中提供补丁。我们改进的发布节奏将及时向现场提供补丁。 改进客户通知中低影响项目(通常包括侦察攻击或跨站点脚本攻击等漏洞)将包含在每个版本中,并在产品发布说明中进行描述。 更高严重性项目的修复也将包含在每个版本中,因为它们已准备就绪,但有关修复的信息将被禁运,直到补丁包含在所有受支持的版本中。 当所有受支持的版本中都已修复这些问题时,将针对高严重性和严重性问题发布安全警报。 为什么 InterSystems 做出这些改变?我们相信这些改进将: 更快地为我们的客户获取安全补丁 帮助专注于最严重的修复 在某些情况下,可以将安全修复程序作为补丁而不是完整的工具包提供 通过按安全影响对漏洞进行分组,提高安全漏洞管理方式的透明度 允许系统管理员根据他们的需要和要求应用更多修复 当然,随着维护版本和持续交付版本的概念,这个过程变得更加复杂。为了帮助客户了解他们何时以及如何获得安全修复,我们发布了包含更详细信息的漏洞处理政策。 我期待到 2023 年,我们可以继续改善您与我们的安全和漏洞管理计划相关的体验。
文章
Jingwei Wang · 九月 1, 2023

JWT - JSON Web Token Authentication

JWT Authentication 原理及验证流程 原理 JWT 是一种结构紧凑、URL 安全的身份验证、授权或信息交换方式。在身份验证的情况下,服务器会向已通过身份验证的客户端提供一个 JWT,这样客户端在 JWT 过期之前就无需再提供密码来访问服务器上受保护的资源。 验证流程: 客户端发送Login到服务端 服务端返回 JWT给客户端 客户端校验JWT签名 客户端发送带有JWT签名的request到服务端 服务端检查JWT签名的有效期,在有效期内,则返回response给客户端,不在有效期内,返回error JWT 配置步骤 创建REST服务 配置Web Application 安全配置 客户端发送Login,从服务器获取JWT 配置成功,发送带有JWT的request 1. 创建REST服务 在InterSystems IRIS中,可以使用/api/mgmnt自动创建REST的 .disp .impl 和 .spec 类,本篇文章不介绍具体创建REST服务的流程,具体内容请参考社区文章创建REST 服务。 2. 配置Web Application IRIS管理门户:系统管理 -> 安全 -> 应用程序 -> Web 应用程序 选中 ‘Use JWT Authentication’ 复选框,并设置‘JWT Access Token Timeout’ 和‘JWT Refresh Token Timeout’, 其中,JWT Access Token Timeout 为JWT 令牌超时秒数,如果你打算长时间测试 API,建议将此值设为 1 小时(3600 秒),JWT Refresh Token Timeout(令牌刷新超时的秒数)设为 900 秒。 3. 安全配置 IRIS管理门户:系统管理 -> 安全 -> 系统安全 -> 身份验证/Web 会话选项 ‘JWT Issuer field’用于签名和验证 JWT 的签名算法。‘JWT Issuer field’将出现在 JWT 的声明部分,其目的是告知是谁给了你这个令牌。您可以将其设置为 "InterSystems"。 4. 客户端发送Login,从服务器获取JWT 使用基本 HTTP 身份验证或在请求正文中使用有效凭证发送POST请求到http://<api>/login端点,服务器端会返回一个访问令牌和一个刷新令牌,可在后续请求中使用。 body样例: { "user": "superuser", "password": "iris" } 5.配置成功,发送带有JWT的request 到此为止,您已经成功配置JWT,可以发送带有JWT的请求了。只需要在Header中添加Authorization,如下所示: -H "Authorization: Bearer {access_token}"
文章
姚 鑫 · 七月 4, 2021

第二十七章 定制SAX解析器的执行自定义实体解析

# 第二十七章 定制SAX解析器的执行自定义实体解析 # 执行自定义实体解析 XML文档可能包含对外部DTD或其他实体的引用。默认情况下,InterSystems IRIS尝试查找这些实体的源文档并解析它们。要控制InterSystems IRIS解析外部实体的方式,请使用以下步骤: 1. 定义实体解析程序类。 此类必须在扩展`%XML.SAX.EntityResolver`,并且必须实现 `resolveEntity()`方法,该方法具有以下签名: ```java method resolveEntity(publicID As %Library.String, systemID As %Library.String) as %Library.Integer ``` 每当XML处理器找到对外部实体(如DTD)的引用时,就会调用该方法;这里的public ID和systemID是该实体的Public和系统标识符字符串。 该方法应获取实体或文档,将其作为流返回,然后在将流包装在`%XML.SAX.StreamAdapter`的实例中。此类提供了用于确定流特征的必要方法。 如果无法解析该实体,则该方法应返回`$$$NULLOREF` ,以向SAX解析器指示该实体无法解析)。 尽管方法签名指示返回值为`%Library.Integer`,但该方法应返回`%XML.SAX.StreamAdapter`的实例或该类的子类。 此外,引用外部实体的标识符始终传递给文档中指定的`resolveEntity()`方法。具体地说,如果这样的标识符使用相对URL,则该标识符将作为相对URL传递,这意味着引用文档的实际位置不会传递给`resolveEntity()`方法,并且无法解析该实体。在这种情况下,请使用默认实体解析器,而不是自定义实体解析器。 2. 读取XML文档时,请执行以下操作: a. 创建实体解析程序类的实例。 b. 读取XML文档时使用该实例,如本章前面的“指定解析器选项”中所述。 ## 示例 例如,以下XML文档: ```xml Some < xhtml-content > with custom entities &entity1; and &entity2;. Here is another paragraph with &entity1; again. ``` 本文档使用以下DTD: ```xml ``` 要阅读本文档,需要如下所示的自定义实体解析器: ```java Class CustomResolver.Resolver Extends %XML.SAX.EntityResolver { Method resolveEntity(publicID As %Library.String, systemID As %Library.String) As %Library.Integer { Try { Set res=##class(%Stream.TmpBinary).%New() //check if we are here to resolve a custom entity If systemID="http://www.intersystems.com/xml/entities/entity1" { Do res.Write("Value for entity1") Set return=##class(%XML.SAX.StreamAdapter).%New(res) } Elseif systemID="http://www.intersystems.com/xml/entities/entity2" { Do res.Write("Value for entity2") Set return=##class(%XML.SAX.StreamAdapter).%New(res) } Else //otherwise call the default resolver { Set res=##class(%XML.SAX.EntityResolver).%New() Set return=res.resolveEntity(publicID,systemID) } } Catch { Set return=$$$NULLOREF } Quit return } } ``` 下面的类包含一个demo方法,该方法解析前面显示的文件并使用此自定义解析器: ```java Include (%occInclude, %occSAX) Class CustomResolver.ParseFileDemo { ClassMethod ParseFile() { Set res= ##class(CustomResolver.Resolver).%New() Set file="c:/temp/html.xml" Set parsemask=$$$SAXALLEVENTS+$$$SAXERROR Set status=##class(%XML.TextReader).ParseFile(file,.textreader,res,,parsemask,,0) If $$$ISERR(status) {Do $system.OBJ.DisplayError(status) Quit } Write !,"Parsing the file ",file,! Write "Custom entities in this file:" While textreader.Read() { If textreader.NodeType="entity"{ Write !, "Node:", textreader.seq Write !," name: ", textreader.Name Write !," value: ", textreader.Value } } } } ``` 下面显示了此方法在终端会话中的输出: ```java GXML>d ##class(CustomResolver.ParseFileDemo).ParseFile() Parsing the file c:/temp/html.xml Custom entities in this file: Node:13 name: entity1 value: Value for entity1 Node:15 name: entity2 value: Value for entity2 Node:21 name: entity1 value: Value for entity1 ``` ## 示例2 例如,读取包含以下内容的XML文档: ```xml ``` 在本例中,将在`publicId`设置为 `-//OASIS//DTD DocBook XML V4.1.2//EN`并将`systemId`设置为`c:\test\doctypes\docbook\docbookx.dtd.`的情况下调用`resolveEntity`方法。 `resolveEntity`方法确定外部实体的正确源,将其作为流返回,并将其包装在`%XML.StreamAdaptor`的实例中。XML解析器从这个专用流中读取实体定义。 例如,请参考InterSystems IRIS库中包含的`%XML.Catalog`和`%XML.CatalogResolverclass。%XML.Catalog`类定义一个简单的数据库,该数据库将公共和系统标识符与URL相关联。`%XML.CatalogResolver`类是一个实体解析器类,它使用此数据库查找给定标识符的URL。`%XML.Catalogclass`可以从SGML样式的编录文件加载其数据库;该文件将标识符映射到标准格式的URL。
文章
姚 鑫 · 三月 10, 2022

第七十七章 SQL函数 LENGTH

# 第七十七章 SQL函数 LENGTH 返回字符串表达式中字符数的字符串函数。 # 大纲 ```java LENGTH(string-expression) {fn LENGTH(string-expression)} ``` # 参数 - `string-expression` - 字符串表达式,可以是列名、字符串文字或另一个标量函数的结果,其中基础数据类型可以表示为任何字符类型(例如 `CHAR` 或 `VARCHAR`)。 `LENGTH` 返回 `INTEGER` 数据类型。 # 描述 `LENGTH` 返回一个整数,表示给定字符串表达式的字符数,而不是字节数。字符串表达式可以是字符串(从中删除尾随空格)或数字( IRIS 将其转换为规范形式)。 请注意,`LENGTH` 可用作 ODBC 标量函数(使用花括号语法)或 SQL 通用函数。 `LENGTH` 和其他长度函数(`$LENGTH`、`CHARACTER_LENGTH`、`CHAR_LENGTH` 和 `DATALENGTH`)都执行以下操作: - `LENGTH` 返回字段的逻辑(内部数据存储)值的长度,而不是显示值,无论 `SelectMode` 设置如何。所有 SQL 函数始终使用字段的内部存储值。 - `LENGTH` 返回数字的规范形式的长度。规范形式的数字不包括前导零和尾随零、前导符号(单个减号除外)和尾随小数分隔符。 `LENGTH` 返回数字字符串的字符串长度。数字字符串不会转换为规范形式。 - `LENGTH` 不排除字符串中的前导空格。可以使用 `LTRIM` 函数从字符串中删除前导空格。 在执行以下操作时,`LENGTH` 与其他长度函数(`$LENGTH`、`CHARACTER_LENGTH`、`CHAR_LENGTH` 和 `DATALENGTH`)不同: - `LENGTH` 不包括尾随空格和字符串终止字符。 `$LENGTH`、`CHARACTER_LENGTH`、`CHAR_LENGTH` 和 `DATALENGTH` 不排除尾随空格和终止符。 - 如果传递一个 `NULL` 值,`LENGTH` 返回 `NULL`,如果传递一个空字符串,则返回 `0`。 如果传递 `NULL` 值,`CHARACTER_LENGTH`、`CHAR_LENGTH` 和 `DATALENGTH` 也返回 `NULL`,如果传递空字符串,则返回 `0`。如果传递一个 `NULL` 值,则 `$LENGTH` 返回 `0`,如果传递一个空字符串,则返回 `0`。 - `LENGTH` 不支持数据流字段。为字符串表达式指定流字段会导致 `SQLCODE -37`。 `$LENGTH` 也不支持流字段。 `CHARACTER_LENGTH`、`CHAR_LENGTH` 和 `DATALENGTH` 函数确实支持数据流字段。 # 示例 在以下示例中, IRIS 首先将每个数字转换为规范形式(删除前导零和尾随零,解析前导符号,并删除尾随小数分隔符)。每个 `LENGTH` 返回长度为 `1`: ```sql SELECT {fn LENGTH(7.00)} AS CharCount, {fn LENGTH(+007)} AS CharCount, {fn LENGTH(007.)} AS CharCount, {fn LENGTH(00000.00)} AS CharCount, {fn LENGTH(-0)} AS CharCount 1 1 1 1 1 ``` 在以下示例中,第一个 `LENGTH` 删除前导零,返回长度值 `2`;第二个 `LENGTH` 将数值视为字符串,并且不删除前导零,返回长度值 `3`: ```sql SELECT LENGTH(0.7) AS CharCount, LENGTH('0.7') AS CharCount 2 3 ``` 以下示例返回值 `12`: ```sql SELECT LENGTH('INTERSYSTEMS') AS CharCount 12 ``` 以下示例显示了 `LENGTH` 如何处理前导和尾随空格。第一个 `LENGTH `返回 `15`,因为 `LENGTH` 不包括尾随空格,但不包括前导空格。第二个 `LENGTH` 返回 `12`,因为 `LTRIM` 排除了前导空格: ```sql SELECT LENGTH(' INTERSYSTEMS ') AS CharCount, LENGTH(LTRIM(' INTERSYSTEMS ')) AS CharCount 15 12 ``` 以下示例返回 `Sample.Person` 表中每个 `Name` 值中的字符数: ```sql SELECT Name,{fn LENGTH(Name)} AS CharCount FROM Sample.Person ORDER BY CharCount ``` 以下示例返回 `DOB`(出生日期)字段中的字符数。请注意,返回的长度(由 `LENGTH`、`CHAR_LENGTH` 和 `CHARACTER_LENGTH`)是日期的内部 (`$HOROLOG`) 格式,而不是显示格式。 `DOB`的显示长度为十个字符;所有三个长度函数都返回 5 的内部长度: ```sql SELECT DOB,{fn LENGTH(DOB)} AS LenCount, CHAR_LENGTH(DOB) AS CCount, CHARACTER_LENGTH(DOB) AS CtrCount FROM Sample.Person ``` 以下嵌入式 SQL 示例给出了 `Unicode` 字符字符串的长度。返回的长度是字符数 (7),而不是字节数。 ```java /// d ##class(PHA.TEST.SQLCommand).Length() ClassMethod Length() { s a = $CHAR(920,913,923,913,931,931,913) &sql(SELECT LENGTH(:a) INTO :b ) if SQLCODE'=0 { w !,"Error code ",SQLCODE } else { w !,"The Greek Sea: ",a,!,$LENGTH(a),!,b } } ``` ```java DHC-APP>d ##class(PHA.TEST.SQLCommand).Length() The Greek Sea: ΘΑΛΑΣΣΑ 7 7 ```
文章
姚 鑫 · 九月 12, 2022

第三十章 管理许可(三)

# 第三十章 管理许可(三) # 确定许可证容量和使用情况 如何知道已使用了多少许可证以及由谁使用?类中的 `%SYSTEM.License` 提供了到 `IRIS` 许可证应用程序编程接口 (`API`) 的接口,并提供了许多方法和相关查询,可以使用这些方法和相关查询来查询许可证容量和当前使用情况。 可以使用 `%Library.%ResultSet` 类的 `RunQuery` 方法运行多个许可查询。例如: ``` USER>do ##class(%ResultSet).RunQuery("%SYSTEM.License","Summary") LicenseUnitUse:Local:Distributed: 当前使用的软件许可单元 :2:2: 使用的最大软件许可单元数 :3:2: 授权的软件许可单元 :25:25: 当前连接 :2:2: 最大连接数 :6:6: ``` 可以从管理门户的许可证使用页面(系统操作 > 许可证使用)查看这些查询的输出,详细信息如下表所示: 许可证使用页面上的链接| `License Query` ---|--- `Summary` |`Summary()` — 返回许可证使用摘要,如 `$System.License.ShowSummary` 所示。 `Usage by Process`| `ProcessList()` — 返回操作系统进程标识符 (`PID`) 使用的许可证,如 `$System.License.DumpLocalPID` 所示。 `Usage by User`| `UserList()` —按用户 ID 返回许可证使用。 `Distributed License Usage`| `AllKeyConnectionList()` — 返回按用户排序的当前分布式许可证使用情况。 (当没有连接许可服务器时禁用此功能。) 还可以使用 `%SYSTEM.License` 中的以下类方法来显示信息,或将许可证数据库转储到文件中: `$System.License.CKEY` 显示密钥。该子例程由 `^CKEY` 程序调用,该程序为保持兼容性而保留: ```java USER>Do $System.License.CKEY() InterSystems IRIS Key display: Based on the active key file 'c:\intersystems\irishealth\mgr\iris.key' LicenseCapacity = InterSystems IRIS 2021.2 Enterprise - Concurrent Users for x86-64 (Microsoft Windows):25, Natural Language Processing (NLP), En CustomerName = ISC DC Moderators - Xin Yao OrderNumber = 202224285 ExpirationDate = 7/15/2023 AuthorizationKey = 4125500002500002500000XXXXXXXXXXXXXXXXX01 MachineID = 当前可用 = 23 最小可用 = 22 最大可用 = 25 ``` `$System.License.ShowCounts` 总结了在本地系统共享内存中跟踪的许可证使用情况: ```java USER> Do $System.License.ShowCounts() 本地软件许可使用视图. 25 授权的总数量 LU 23 当前可用 LU 22 最小可用 LU 2 当前用户处于活动状态 3 处于活动状态的最大用户数 1 当前 CSP 用户处于活动状态 1 处于活动状态的最大 CSP 用户数 0 当前 CSP 会话处于宽限期 0 处于宽限期的最大 CSP 会话数 ``` `.License.ShowServer` 显示活动的许可证服务器地址和端口: ```java USER> Do $System.License.ShowServer() 活动软件许可服务器地址 = 127.0.0.1 端口 = 4002 ``` 如果开发了基于 `REST` 的应用程序,许可证将随着使用而消耗。为防止这种情况发生,请配置可以建立的 `Web Gateway` 连接数。从 `Web Gateway` 管理部分的管理门户: 1. 导航到服务器访问。 2. 选择无状态参数。 3. 将最大值设置为比许可证小 `2` 或 `3` 的数字,以允许服务器端登录。 **注意:根据应用程序的服务器端需求,需要对此进行调整。** 通过在所有可用连接都忙时执行此操作,新请求将排队而不是被拒绝。由于超出许可计数,不会看到拒绝。随着数量的增长,客户端的响应时间会减慢。这表明需要购买更多许可证。 如果开发了基于 REST 的应用程序,许可证将随着使用而消耗。为防止这种情况发生,请配置可以建立的 Web Gateway 连接数。从 Web Gateway 管理部分的管理门户 姚老师,上面描述的这段是从哪里进入的啊,可以给与相应的导航图吗
公告
Claire Zheng · 十月 19, 2022

【目前点赞排名】投票倒计时五天:继续为你喜欢的征文作品投票吧!

2022年9月5日-10月24日(北京时间),我们正在举办🏆InterSystems开发者社区中文版首届技术征文大赛🏆(←点击链接进入参赛页面,浏览所有参赛文章)!投票截止至10月23日,你的支持与喜爱,是优秀作品获得“开发者社区奖”的关键!我们先来看看目前作品排名情况吧!距离投票截止还有五天(截止至10月23日),我们暂时无法获得专家评审分数,以下根据作品“点赞”进行排名。 N 作者 标题 点赞⬇ 查看数 奖励项目个数 1 Zhe Wang IRIS如何进行CRUD操作 36 197 3 2 Meng Cao Caché数据库私有apache版本升级 33 336 1 3 sun yao 前端操作自动生成BS、BP、BO 22 123 2 4 John Pan 论集成标准的选择对医院信息集成平台建设的影响 21 113 1 5 lizw lizw 关于%Dictionary.CompiledClass类在实际业务中的一些应用 20 114 1 6 聆严 周 使用Prometheus监控Cache集群 18 175 3 7 Chang Liu 在国产系统上安装Healthconnect2021 17 104 2 8 Zhe Wang IRIS快速查询服务思路分享 17 58 3 9 Zhe Wang 使用Global进行数据可视化---商业智能(BI) 16 37 2 10 John Pan 如何调用Ensemble/IRIS内置的HL7 V2 webservice - Java,PB9,Delphi7样例 14 96 2 11 Zhe Wang 小工具:IRIS管理页打开显示查询功能 14 62 2 12 water huang 对 %XML.PropertyParameters类的探索 13 39 1 13 姚 鑫 IRIS与Caché的23种设计模式 13 59 3 14 Zhe Wang Rest实现Post、Get、Put、Delete几种操作方式 13 30 2 15 聆严 周 Cache / IRIS 操作数据的3种基本方式 11 153 1 16 he hf 10分钟快速开发一个连接到InterSystems IRIS数据库的C#应用 11 193 2 17 shaosheng shengshao HEALTHSHARE2018版如何实现AES(CBC)的HEX输出,并可以实现加密和解密 11 63 3 18 water huang Ens.Util.JSON类的启发 9 54 2 19 bai hongtao 第三方HA软件结合MIRROR使用方法探讨 9 69 1 20 li wang HealthConnect访问HTTPS开头地址 8 21 2 21 shaosheng shengshao windows下处理IIS在未安装但Healthshare已安装的时候,部署IIS服务并代理Healthshare 8 43 1 22 zhanglianzhu zhanglianzhu Cache死循环检测和申明式事务 8 101 0 23 Liu Tangh 在Cache系统中使用负载均衡服务的探讨 8 25 1 24 yaoguai wan IRIS架构的浅显理解以及windows10、docker安装IRIS Health详解流程及部分问题浅析 6 30 2 25 Zhe Wang COS的基本语法 3 12 3 *奖励项目详见参赛规则:点击阅读 我们此次征文大赛计分规则如下: 🥇【专家提名奖】评选规则,由经验丰富的专家评审团进行评选打分,与其他加分项综合后进行排名。 🥇【开发者社区奖】评选规则,每个点赞计分为1分,与其他加分项综合后进行排名。 🥇【入围奖】评选规则,成功参赛的其余用户都将获得特别奖励。 每位作者只可以获得一个奖项(即:您只可以获得一次专家提名奖/开发者社区奖/入围奖); 当出现票数相当的平手情况时,将以专家评选投票数作为最终票数高低的判断标准。 那么,抓住最后五天的投票时间,为你喜欢的作品“点赞”投票吧!你的点赞是优秀作品获得【开发者社区奖】的关键! 10月24日,我们将通过Online Meetup宣布获奖名单,敬请留意后续参会信息! 欢迎关注InterSystems开发者社区中文版首届技术征文大赛