清除过滤器
文章
姚 鑫 · 十二月 14, 2024
# 第五十章 File 输入 输出
本页介绍在 `IRIS` 数据平台中使用顺序文件。
重要:在大多数情况下,可以使用 `%Library.File` 类提供的 `API`,而不需要此页面上的详细信息。请参阅使用 `%Library.File` 。
# 介绍
所有操作系统都将磁盘 `I/O` 文件视为顺序文件。 `Windows` 系统将打印机视为顺序文件 `I/O` 设备(除非打印机通过串行通信端口连接)。 `UNIX`® 系统将打印机视为终端 I/O` 设备。有关打印机的更多详细信息,请参阅打印机。
本节讨论 `IRIS` 如何处理顺序文件。它提供了顺序文件 `I/O` 的介绍以及相关命令的说明。
- 要访问顺序文件,必须首先使用`OPEN`命令打开该文件,并提供文件名作为参数。还可以选择指定`OPEN`模式参数。如果`OPE`N指定的文件不存在,则模式参数指定是否创建新文件。您可以同时打开多个文件。
- 打开顺序文件后,必须指定USE命令来访问该文件,并提供文件名作为参数。 `USE`命令使指定文件成为当前设备;因此一次只能使用一个文件。 `USE`命令还可以指定模式参数。
- 然后,可以对该文件发出多个`READ`或`WRITE`命令。每个`READ`或`WRITE`命令都会向文件传送一条记录或从文件传送一条记录。除非使用`“W”`模式参数打开该文件,否则无法写入该文件。尝试读取超过文件末尾会导致错误。
- 您可以使用`$ZSEEK`函数设置文件位置,该位置由从连续文件的开头、当前位置或结尾开始的字符计数偏移量指定。 `$ZPOS`特殊变量包含从当前顺序文件开头算起的当前字符计数位置。
- 完成文件 `I/O` 后,可以发出`CLOSE`命令来关闭顺序文件。
这些操作也可以使用 `%Library.File` 类的方法来执行。
`%Library.File.Exists()` 方法告诉您指定名称的连续文件是否已存在。
`%Library.File.Size` 属性返回顺序文件中当前的字符数。
打开文件时以及关闭文件时(如果已修改),`%Library.File.DateModified` 属性将更新为当前本地日期和时间。
如果文件已通过 `%Library.File.Open()` 方法打开,则 `%Library.File.IsOpen` 属性仅返回 `1`; `OPEN`命令不设置此布尔属性。
# 指定文件
顺序文件可以由规范(完整)路径名或系统扩展为完整路径名的相对(部分)路径名指定。路径名可以是规范的 (`c:\InterSystems\IRIS\mgr\user\myfiles\testfile.txt`) 或相对于当前目录 (`testfile.txt`)。前导句点 (`.`) 指定当前目录。前导双句点 (`..`) 指定当前目录的父目录。如果`OPEN`命令创建新文件,则指定的目录必须已经存在。
`%SYSTEM.Process.OSError()`方法返回操作系统返回的文件访问错误,例如`The system Cannot find the file specified` 。此方法返回用尖括号括起来的操作系统错误号,后跟错误文本。下面的 `Windows` 示例显示了这一点:
```java
USER>OPEN "C:\InterSystems\IRIS\mgr\nodir\testfile.txt":("WNS"):5
USER>w $SYSTEM.Process.OSError()
The system cannot find the path specified.
USER>w ##class(%File).TempFilename("txt","C:\InterSystems\IRIS\mgr\nodir\testfile",.oserrnum)
USER>w $SYSTEM.Process.OSError()
The system cannot find the path specified.
```
以下 `Windows` 示例均在当前命名空间 (`USER`) 目录中创建文件:
- 完整路径名:` OPEN "C:\InterSystems\IRIS\mgr\user\testfile1.txt":("WNS"):10`
- 文件名扩展: `OPEN "testfile2.txt":("WNS"):10`
- 当前目录扩展: `OPEN ".\testfile3.txt":("WNS"):10`
以下 `Windows` 示例在当前命名空间 (`USER`) 目录的现有子目录中创建一个文件:
- 当前目录的子目录:` OPEN "mytemp\testfile4.txt":("WNS"):10`
以下 `Windows `示例使用父目录 (`..`) 语法创建文件:
- 父目录( `C:\InterSystems\IRIS\mgr\` ): OPEN "..\testfile5.txt":("WNS"):10
- 当前目录(父目录的子目录) `C:\InterSystems\IRIS\mgr\user\ : OPEN "..\user\testfile6.txt":("WNS"):10` 。
- 父目录`C:\InterSystems\IRIS\mgr\temp\`的另一个子目录: `OPEN "..\temp\testfile7.txt":("WNS"):10` 。
- 父目录`C:\InterSystems\IRIS\`的父目录: `OPEN "..\..\testfile8.txt":("WNS"):10 `。
`Windows` 路径名使用 `\`(反斜杠)目录分隔符; `UNIX` 路径名使用 `/`(斜杠)目录分隔符。有效字符可以是 `8` 位 `ASCII` 或 `ISO Latin-1` `Unicode`。
`Windows` 文件路径名规范具有以下格式:
```
device:\directory\file.type
```
例如, `C:\InterSystems\IRIS\mgr\user\myfiles\testfile.txt` 。类型后缀是可选的。
`UNIX`® 文件路径名规范具有以下格式:
```
../directory/name
```
完全展开时,文件路径名不得超过 `256` 个字符。如果所有目录的路径名长度超过 `256`,则会生成` ` 错误。如果由于文件名长度原因路径名长度超过 `256`,则会生成` ` 错误。
`UNIX®` 文件路径名最多可以包含 `255` 个任何类型的字符。虽然字符句点(`“.”`)和下划线(`“_”`)可以出现在文件名中的任何位置,但您通常使用它们将名称划分为有意义的部分。例如,您可以定义文件名`pat_rec.dat `,使用`.dat`作为文件类型。
访问当前 `UNIX®` 默认目录中的文件时,通常只需指定名称。系统填写目录的默认值。
`DLL` 名称可以指定为完整路径名或部分路径名。如果指定部分路径名,`IRIS` 会将其扩展至当前目录。通常,`DLL` 存储在二进制目录(`“bin”`)中。要定位二进制目录,请调用 `%SYSTEM.Util 类的 BinaryDirectory()` 方法。
文章
Louis Lu · 八月 30, 2023
大家可以通过InterSystems IRIS 管理门户SMP查看当前数据库剩余空间,路径是 Management Portal: System Operation > Database
当然大家也可以通过下面的代码查看数据库的可用磁盘空间:
/// ZISJ.mac
Set stmt=##class(%SQL.Statement).%New()
Set status=stmt.%PrepareClassQuery("SYS.Database","FreeSpace")
Set rs=stmt.%Execute()
While rs.%Next() {
Write !
For i=1:1:9 {
Write rs.%GetData(i),","
}
}
文章
Lele Yang · 二月 2, 2023
正如之前在 2022 年全球峰会上宣布的那样,InterSystems 将停止交付或安装基于 Apache 的web服务器(通常称为私有web服务器或 PWS);此更改目前计划用于 InterSystems IRIS 2023.2。
使用这种新方法,您可以完全控制选择最适合您目的的 Web 服务器,以及如何配置、维护和更新它。这一变化的一个主要好处是您将不再需要等待 InterSystems 的更新套件来获得最新版本,这在安全漏洞情况下尤其重要。 InterSystems 将提供可用于帮助配置 Apache 或 IIS 的工具。 (请注意,InterSystems IRIS Community Edition 将继续安装 PWS。)
安装 Web 服务器是一个常见的过程,通常很容易 - 各个 Web 服务器供应商都有详细的文档记录。
以下是适用于 Ubuntu、Windows 和 macOS 的示例。它们演示了快速安装,因此您可以看到当 InterSystems 产品不包含或安装 Web 服务器时的新行为。 (请注意,此代码按原样提供,不受支持,也不足以托管关键任务或数据敏感的应用程序。)
提供了常见问题解答,其中提供了更多信息并可访问用于尝试此新过程的工具包。请参阅本文末尾链接的 PDF 以获取常见问题解答,或者如果您想添加到讨论中,请访问https://community.intersystems.com/post/discontinue-apache-web-server-installations-faq 。
安装 Web 服务器通常有多种方法,请选择您熟悉且最适合您的方法。
已为希望试用不包含 PWS 的新安装程序的客户创建了一个新的抢先体验计划 (EAP)。如果您希望成为此 EAP 的一部分并访问这些工具包,请发送电子邮件至 nopws@InterSystems.com 。
如需反馈或疑虑,请通过nopws@InterSystems.com联系我们。
以下是 Microsoft Windows 的示例:
使用 Microsoft Windows 安装 IIS。
安装后,您可以安装 InterSystems IRIS,它将询问用户是否应配置 IIS。
下面是一个使用 Ubuntu 的例子:
先决条件:允许用户使用 sudo,Ubuntu 操作系统,未安装 PWS
对于 Ubuntu,Apache 的官方存储库可以与 apt-get 命令一起使用。
更新存储库
$ sudo apt-get update
安装Apache
$ sudo apt-get install apache2
验证是否已安装
$apache2 -v
安装 InterSystems IRIS
使用 SMP 进行测试 ( http://localhost/iris/csp/sys/UtilHome.csp )
如果您只是出于测试目的安装了 apache2,您可以使用以下命令删除 apache2:
$ sudo apt-get remove apache2
这是一个使用 macOS 的示例:
安装
$ brew install apache-httpd
在升级或安装后重新启动 httpd:
$ brew services restart httpd
通过使用启动它
sudo apachectl -k start
或使用重新启动它
$ sudo apachectl -k restart
测试它是否通过将您的浏览器定位到
http://localhost:8080
它应该显示:"It works"
安装 IRIS(请注意新的安装对话框,因为它是新的)
重新启动web服务器
$ sudo apachectl -k restart
使用 SMP 进行测试 ( http://localhost:8080/iris/csp/sys/UtilHome.csp )
如果您只是出于测试目的安装了 apache-http,您可以使用以下命令删除 apache-http:
$ brew remove apache-httpd
删除 Apache 相关设置或安装
请小心删除设置或配置,并自行承担使用风险。
删除单个实例的 apache httpd 配置。
找到 Apache httpd.conf 文件。它的位置取决于平台:
macOS:/usr/local/etc/httpd/httpd.conf
SuSE Linux: /etc/apache2/httpd.conf
红帽 Linux:/etc/httpd/conf/httpd.conf
Ubuntu Linux: /etc/apache2/apache2.conf
AIX:/opt/freeware/etc/httpd/conf/httpd.conf_64(如果使用 64 位 httpd)
/opt/freeware/etc/httpd/conf/httpd.conf(如果使用 32 位 httpd)
以 root 身份编辑 httpd.conf 并在文件末尾删除以下部分,从
#### 开始-ApacheCSP-SECTION-<INSTANCENAME> ####
开始结束于
#### 开始-ApacheCSP-SECTION-<INSTANCENAME> ####。
使用命令“sudo apachectl -k restart”重新启动 Apache
要删除单个实例的 Web Gateway 配置:
如果更改了 WebGateway 安装目录的默认目录,请使用以下说明中的适当路径。
以 root 身份编辑 /opt/webgateway/conf/CSP.ini 并删除以下行:
在“[SYSTEM_INDEX]”部分中删除行 <INSTANCENAME>=Enabled
在“[APP_PATH_INDEX]”部分中删除行“/<nstancename>=Enabled”
删除部分“[APP_PATH:/<instancemame>]”
从所有 IRIS 实例中清除 Apache httpd:
Apache配置
找到 Apache httpd.conf 文件。它的位置取决于平台:
macOS:/usr/local/etc/httpd/httpd.conf
SuSE Linux: /etc/apache2/httpd.conf
红帽 Linux:/etc/httpd/conf/httpd.conf
Ubuntu Linux: /etc/apache2/apache2.conf
AIX:/opt/freeware/etc/httpd/conf/httpd.conf_64(如果使用 64 位 httpd)
/opt/freeware/etc/httpd/conf/httpd.conf(如果使用 32 位 httpd)
以 root 身份编辑 httpd.conf 并在文件末尾删除以下所有部分,以
#### 开始-ApacheCSP-
开始并结束于
#### 结束 ApacheCSP
使用命令“sudo apachectl -k restart”重新启动 Apache
要从所有 IRIS 实例中清除 Web Gateway:
要删除单个实例的 Web Gateway 配置:
如果更改了 WebGateway 安装目录的默认目录,请使用以下说明中的适当路径。
sudo rm -rf /opt/webgateway
sudo rm -f /usr/local/etc/irissys/CSP_options
PWS Removal FAQ
文章
姚 鑫 · 九月 13, 2022
[toc]
# 第三十一章 管理许可(四)
## 显示本地许可证信息的方法
下面列出的子例程转储实例共享内存中本地包含的许可证表的内容。一般来说,他们识别客户:
`$System.License.DumpLocalAll` 将所有本地许可证表条目转储到当前目录中的 `all.dmp` 文件中:
```java
USER> Do $System.License.DumpLocalAll()
25 条目转储到 c:\intersystems\irishealth\mgr\user\all.dmp
```
`all.dmp` 文件的内容示例:

`$System.License.DumpLocalInUse` 将所有正在使用的本地许可证表条目转储到当前目录中的 `inuse.dmp` 文件:
```java
USER> Do $System.License.DumpLocalInUse()
2 条目转储到 c:\intersystems\irishealth\mgr\user\inuse.dmp
```
`inuse.dmp` 文件内容示例:

`$System.License.DumpLocalPID` 将进程 `ID` 使用的本地许可证表转储到当前目录中的 `piduse.dmp` 文件中:
```java
USER> Do $System.License.DumpLocalPID()
33 条目转储到 c:\intersystems\irishealth\mgr\user\piduse.dmp
```

## 显示许可证服务器信息的方法
以下子例程转储许可证服务器维护的许可证表的内容。输出文件位于运行活动许可证服务器的主机上的指定目录中。
`$System.License.ShowSummary` 显示许可证服务器上的许可证信息摘要。分布式许可证使用部分提供许可证服务器当前支持的所有 `IRIS` 实例的许可证使用的集体视图。本地许可证使用部分展示了运行程序的单个 `IRIS` 实例的许可证使用视图:
```java
USER> Do $System.License.ShowSummary()
软件许可服务器活动密钥摘要视图.
分布式软件许可使用:
当前使用的软件许可单元 = 2
使用的最大软件许可单元数 = 2
授权的软件许可单元 = 25
本地软件许可使用:
当前连接 = 2 最大连接数 = 6
当前用户 = 2 最大用户数 = 3
```
`$System.License.DumpServer` 将与运行此例程的服务器相关的许可服务器数据库信息转储到运行许可服务器的主机上的文件 `dumpserver.txt` 中:
```java
USER> Do $System.License.DumpServer()
License server database dumped to: c:\intersystems\irishealth\mgr\dumpserver.txt at LAPTOP-ARLL3DSO
```

`$System.License.DumpServers` 将所有已知服务器的许可证服务器数据库信息转储到运行许可证服务器的主机上的文件 `dumpservers.txt` 中:
```java
USER> Do $System.License.DumpServers()
1 server database[s] dumped to: c:\intersystems\irishealth\mgr\dumpservers.txt at LAPTOP-ARLL3DSO
```

`$System.License.DumpKey` 将此实例和共享它的实例使用的密钥转储到运行许可证服务器的主机上的文件 `dumpkey.txt` 中:
```java
USER> Do $System.License.DumpKey()
License server Client data dumped to: c:\intersystems\irishealth\mgr\dumpkey.txt at LAPTOP-ARLL3DSO
```

`$System.License.DumpKeys` 转储所有密钥,将使用它们的实例和客户端显示到运行许可证服务器的主机上的文件 `dumpkeys.txt` 中:
```java
USER> Do $System.License.DumpKeys()
License server Client data (1 key[s]) dumped to: c:\intersystems\irishealth\mgr\dumpkeys.txt at LAPTOP-ARLL3DSO
```

注意:请注意,本地许可方法显示的信息比许可服务器方法显示的信息更新;许可证服务器只定期更新,而本地数据是实时的。
可能会暂时超出许可限制,因为登录是在本地控制的,但许可服务器会强制执行该限制。每个实例根据其在实例共享内存中维护的本地许可证表允许或拒绝登录。每个实例都会定期向许可证服务器发送更新,描述本地许可证表的更改。如果所有实例的组合许可证使用超过限制,则许可证服务器将发送否定确认以更新来自每个实例的消息。
这种否定确认会导致每个实例拒绝新的登录,因为没有额外的许可单元可用。当尝试启动的 `IRIS` 进程的许可用户 `ID` 与任何当前进程的许可用户 `` 不匹配时,登录被视为新登录。这种状态一直持续到所有实例的组合使用量低于授权限制,此时许可证服务器开始发送肯定确认以响应实例更新。然后各个实例允许新的登录。
文章
Johnny Wang · 二月 6, 2022
本文是上一篇关于如何从流行数据库(如 PostgreSQL 和 MySQL)迁移到 IRIS 的后续文章。
我们将使用与从 PostgreSQL 迁移相同的过程。 但是,您会发现它更容易,因为 MySQL 中的数据类型与 IRIS 非常相似。 这就是为什么我们不需要在列中创建转换规则。
获取示例数据到迁移过程
在 GitHub 中,可以下载 docker-compose 项目来构建和运行 2 个数据库:
源数据库:带有示例数据库的 MySQL 数据库 Docker 实例。
目标数据库:InterSystems IRIS 数据平台 Docker 实例,具有用于接收源数据库的现成模式。
要获取示例并运行它,请执行以下步骤:
转到 git 存储库 https://github.com/yurimarx/migration-mysql-iris。 克隆项目:https://github.com/yurimarx/migration-mysql-iris.git。 转到项目文件夹migration-mysql-iris。 进行构建:docker-compose build。 执行容器:docker-compose up -d。 如果一切正常,请使用实例检查您的 docker 桌面:
关于要迁移的数据
要迁移的数据与第一部分中使用的数据模型相同,在这里表示:
所以,从 MySQL 到 IRIS 的迁移过程会迁移:
8张表
5000行销售数据。
2500 行用户数据。
200 行产品数据。
50行商店数据。
100行国家数据。
30行城市数据。
5 行 status_name。
迁移目标将是 InterSystems IRIS 数据库中 USER 命名空间内的 dc_test 模式。
从 MySQL 迁移到 IRIS 的开源工具:DBeaver
在第一部分中,我们使用 DBeaver 社区版进行迁移。 我们将再次使用它。
DBeaver 是一个数据库工具,用于连接、创建、删除、选择、更新和删除市场上主要数据库产品中的数据对象。 从以下网址下载:https://openexchange. intersystems.com/package/DBeaver。 现在按照安装说明将这款出色的产品安装到您的笔记本电脑或台式机中。
DBeaver 可用于在数据库连接之间迁移数据,即使它们来自不同的制造商和版本。
使用 DBeaver 连接源数据库和目标数据库
现在我们将设置要迁移的数据库连接。
设置 MySQL 到 DBeaver 的连接: 1. 在 DBeaver 中,转到文件 > 新建。 2. 选择数据库连接并单击下一步:
3. 选择 SQL 选项卡 > MySQL,然后单击下一步:
4. 填写 Main 选项卡中的 MySQL 连接字段,如下图所示:
主机:本地主机
端口:3306
数据库:db
用户名:user
密码:密码
5. 转到驱动程序属性选项卡并将 allowPublicKeyRetrieval 设置为值 TRUE:
6. 在驱动程序属性选项卡中继续,并将 useSSL 设置为值 FALSE:
7. 如果 DBeaver 请求下载 MySQL 驱动程序,请按 Yes 或 OK。
8. 单击完成。
设置 InterSystems IRIS 与 DBeaver 的连接:
在第一部分中,您配置了 IRIS 连接,但如果您没有保存它,请执行以下操作: 1. 在 DBeaver 中,转到文件 > 新建。 2. 选择数据库连接并单击下一步:
3. 选择 SQL 选项卡 > InterSystems IRIS 并单击下一步:
4. 如果 DBeaver 请求下载 InterSystems IRIS 驱动程序,请按 Yes 或 OK。 5. 设置 InterSystems IRIS 连接字段,如下图所示:
主机:本地主机
数据库/架构:用户
用户名:_SYSTEM
密码:SYS
单击文本连接并完成。
连接(db 和 user)在 Database Navigator 中可用:
进行迁移
迁移过程与第一部分中描述的非常相似。只需按照以下步骤操作:
1. 展开 db connection > Databases > db > Tables 并选择所有表。 在选定的表上单击鼠标右键,然后选择导出数据,如下图所示:
2. 选择数据库,如图所示,然后单击下一步:
3. 单击选择按钮:
4. 选择 dc_test 并点击 OK(注:如果您需要在目标和源列之间创建高级转换,请点击 Columns 按钮)。
5. 现在,单击下一步。
6. 将 Fetch size 设置为 1000000,然后单击下一步。
7. 接受数据加载设置中的默认值,然后单击下一步。
8. 在确认中单击继续。
9. 现在,如果您打开 Database Navigator,您将能够看到 InterSystems IRIS dc_test 模式中的所有 MySQL 表。
就像 PostgreSQL 迁移一样,MySQL 迁移过程对于表来说非常简单。 但是,对于视图、函数、触发器和存储过程,您需要使用 ObjectScript 或 SQL 重写 SQL 源代码。
请跟第一篇连起来形成系列,谢谢!
公告
Claire Zheng · 五月 24, 2021
5月27日,CHIMA大讲堂第十九期邀请医院信息化专家和InterSystems技术专家,共同探讨集成平台赋能智慧医院建设这一话题。欢迎大家围观参会!InterSystems专家演讲概要如下:
演讲人
李岩 ( @Li.Yan ),InterSystems中国业务拓展经理演讲主题构建更智慧的医院信息平台演讲概要在需求的拉动下和政策、标准的推动下,为了给患者提供更好的就医体验,给医务人员提供更好的临床服务,给管理者提供更好参考和手段,智慧医院的建设如火如荼地发展起来了。智慧医院的建设并不是某一应用、某一系统的点状建设,而是打通各个环节、各个系统的全面的建设。
作为医院系统互通的核心的医院信息平台,如何更加“智慧”,如何更好地赋能智慧医院建设?希望本期分享能为您带来一些启发。
演讲人
乔鹏 (@Qiao.Peng) ,InterSystems中国技术总监演讲主题从集成平台到医院信息平台演讲概要当前医院信息化建设是否需要一个集成平台?是不是仅仅因为互联互通才需要集成平台?
集成平台是否只是一个过渡性的产品?医院信息平台是集成平台的发展方向吗?
此次分享将和大家一起讨论这些问题,探究集成平台出现的原因、它的价值和不足,以及目前医疗信息化建设对集成平台的挑战。探讨医院信息平台作为集成平台的未来,它的核心价值、能力、设计思路和实施路径。
完整日程如下:
手机端请扫描图片中二维码,电脑端请复制下方链接观看。https://djt.chima.org.cn/
欢迎大家报名、围观、参会!
陆主任会从目前平台建设存在的问题、平台框架选择、平台建设注意事项等全方位,多角度的介绍广医二院的医疗信息平台建设
文章
Louis Lu · 一月 7, 2021
本文介绍了 InterSystems 客户围绕 SDDC 和 HCI 解决方案的注意事项。
采用软件定义数据中心 (SDDC) 和超融合基础架构 (HCI) 解决方案的 InterSystems 客户需要重点关注的事项
越来越多的 IT 组织正在探究使用SDDC 和 HCI 解决方案的可行性。 这些解决方案看上去很有吸引力,其市场定位为跨异构数据中心和云基础设施可以使得 IT 管理更容易、投入的成本花费更少。 对于 IT 组织来说,潜在的好处是巨大的,许多 InterSystems 客户正在拥抱 SDDC、HCI 或两者兼有。
如果您正在考虑 SDDC 或 HCI 解决方案,请联系您的销售客户经理或销售工程师,安排与技术架构师的通话。 这对于确保成功非常重要。
这些解决方案具有高度的可配置性,组织可以从许多软件和硬件的组合中自由选择。 我们看到了我们的客户使用各种 SDDC 和 HCI 解决方案,通过这些经验,我们意识到,仔细考虑解决方案配置以避免风险是非常重要。 在某些情况下,有些客户的实施不符合关键事务型数据库系统所需的性能和弹性需求。 这导致了应用性能不佳和意外停机的出现。 如果客户的目标是为关键事务型数据库系统提供高弹性和低延迟的存储能力,则组件的选择和配置需要针对您的情况进行仔细考虑和规划,包括:
* 选择适当的组件
* 正确配置这些组件
* 使用适当的操作步骤
SDDC 和 HCI 提供了灵活性和易管理性,它们在操作系统和物理存储层之间的管理程序层内或旁路运行。 这会增加不同程度的开销。 如果配置错误,会从根本上影响磁盘延迟,这对于应用的性能而言是灾难性的。
InterSystems IRIS、Caché 和 Ensemble 的设计注意事项
以下最低要求和设计注意事项列表基于我们对 SDDC 和 HCI 解决方案的内部测试。 请注意,这不是一个参考架构,意味着您的应用需求将根据您的实际情况和性能目标有所更改。
网络
* 每节点拥有两个或更多的 10Gb NIC 接口,专门用于存储流量。
* 本地两台无阻塞速率 10Gb 交换机,实现交换机的弹性连接。
* 当然也可以选择 25、40、50 或 100Gb 而不是 10Gb速率,将其作为对 HCI 的前瞻性投资,以满足特定基准和测量应用程序的要求。
**计算**
* 至少一个六节点群集,以便在维护和故障期间提供更高的弹性和可预测的性能。
* 英特尔可扩展 Gold 或 Platinum 处理器或更高版本,2.2Ghz 或更高主频。
* 以每个 CPU 插槽 6 个 DDR4-2666 DIMM 为一组的形式安装 RAM(最少 384GB)。
存储
* 全闪存存储。 这是唯一推荐的存储选项。 InterSystems 强烈建议不要将混合或分层 HCI 存储用于生产工作负载。
* 每个物理节点至少两个磁盘组。 每个磁盘组应支持至少三个大容量驱动器。
* 独占使用写入密集型 12Gbps SAS SSD 或 NVMe SSD。
* 对于具有缓存和容量层的全闪存解决方案,建议将 NVMe 用于缓存层,将写入密集型 12Gbps SAS 用于容量层。
* 对 Linux 虚拟机使用 LVM PE 条带化,从而将 IO 分布在多个磁盘组(请联系 InterSystems 获得指南)。
* 对于 Linux 虚拟机上的所有数据库和写入映像日志 (WIJ) 文件使用异步 IO 及 rtkaio 库。 这样可以绕过文件系统缓存并降低写入延迟(请参见[文档](http://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls)或与 WRC 联系以获取有关在 Linux 上正确启用异步 IO 的帮助)。
这些最低要求建议已证明可以减轻 SDDC 和 HCI 的开销,但并不确保应用性能。 与任何新技术一样,测试您自己的应用的性能和弹性对于任何成功部署都是至关重要的。
重申一次,如果您正在考虑 SDDC 或 HCI 解决方案,请联系您的销售客户经理或销售工程师,他们会为你安排与技术架构师的通话。这对于确保成功至关重要。
公告
Michael Lei · 四月 29, 2022
我们很高兴向您介绍我们新的反馈门户网站--InterSystems Ideas!
我们的目标是改善我们的反馈机制,使您可以建议我们的产品如何发展以满足您的业务挑战。在开发者社区提问是与您的同行就特定的代码问题进行互动的好方法,而我们的客户支持网站WRC则一如既往地是解决实时问题的方法。
这个新的门户是为了获得您更高层次的想法。不是关于今天如何,更多是关于未来,您想看到我们的产品在未来如何更好地工作。您可以发布您自己的反馈,也可以对其他人提供的反馈进行评论/投票。InterSystems将查看你提交的任何反馈,直接回应你的反馈,并且如果您的建议有了任何进展,我们将及时更新状态。
所以,欢迎提出您的想法,为了我们共同的未来!谢谢!
公告
Claire Zheng · 十月 17, 2023
嗨,开发者们!
我们决定将🏆InterSystems开发者社区中文版第二届技术征文大赛 🏆的参赛时间延长至11月24日,请参赛者关注重要时间节点的变化。
📝 2023年9月19日-11月23日(北京时间),文章发布与点赞收集!在社区发布文章后即可开始为您的文章收集点赞。越早发布文章,就越有时间收集更多点赞(这是您获得“开发者社区奖”的关键)。
📝 2023年11月23日(北京时间),专家打分截止(专家提名奖)。
🎉 2023年11月24日(北京时间),公布获奖名单。
欢迎大家继续积极投稿,赢取大奖!
了解参赛规则及文章样例:点击此处
了解奖品详情:点击此处
欢迎投稿参赛!
快乐分享技术,期待您的大作!✨
🏆InterSystems开发者社区中文版第二届技术征文大赛 🏆(←点击链接进入参赛页面,浏览所有参赛文章)
问题
Michael Lei · 一月 11, 2023
当我在 Intersystems Studio 中编写代码时,代码完成与在 VS Code 中不同。如果 VS Code 在代码完成时以相同的方式做出反应,那就太好了。Studio是这样的:
在 VS Code 中执行此操作时,它不显示对象但显示 “所有可能的项目”吗?
欢迎大家参与讨论,也欢迎大家参考英文社区的讨论内容:https://community.intersystems.com/node/531651
文章
姚 鑫 · 一月 18, 2023
# 第四十九章 使用 ^SystemPerformance 监视性能 - 复制配置文件
# 复制配置文件
可以使用以下 `API` 命令将现有配置文件复制到具有不同名称的文件:
```java
set rc=$$copyprofile^SystemPerformance("sourceprofilename","targetprofilename")
```
必须指定:
- `sourceprofilename` - 现有配置文件的名称
- `targetprofilename` - 要创建的配置文件的名称。这必须用双引号引起来。
如果成功,该函数返回 `1`。如果不成功,它返回一个 `0` 后跟一个 `carat` 和任何错误的原因。
其中 `sourceprofilename` 是现有配置文件的名称,`targetprofilename` 必须是唯一的并且不能包含空格或空白字符。
例如,要复制 `2minrun` 配置文件,请输入以下内容:
```java
set rc=$$copyprofile^SystemPerformance("2minrun","5minrun")
```
下次运行 `^SystemPerformance` 实用程序时,配置文件列表包括以下配置文件名称和说明:
```java
2minrun A 2-minute run sampling every 30 seconds
5minrun A 2-minute run sampling every 30 seconds
```
现在可以按照本指南这一部分的编辑配置文件中的说明编辑新配置文件。
# 删除配置文件
可以使用以下 `API` 命令删除现有配置文件(预定义的“测试”配置文件除外):
```java
set rc=$$delprofile^SystemPerformance("profilename")
```
- `profilename` - 要删除的配置文件的名称。这必须用双引号引起来。
如果成功,该函数返回 `1`。如果不成功,它返回一个 `0` 后跟一个 `carat` 和任何错误的原因。
例如,要删除 `2minrun` 配置文件,请输入以下内容:
```java
set rc=$$delprofile^SystemPerformance("2minrun")
```
下次运行 `^SystemPerformance` 实用程序时,配置文件列表不包括 `2minrun` 配置文件。
# ^SystemPerformance Utility 创建的性能报告
`^SystemPerformance` 实用程序生成特定于平台的报告,如本章所述。该报告分为几个部分,如下面的清单所示:
```java
Configuration
IRISTEST3 on machine testsystem
Customer: InterSystems Development
License : 123456
InterSystems IRIS Version String: InterSystems IRIS for Windows (x86-32) 2018.1 (Build 508) Fri Jan 26 2018 17:51:22 EDT
--------------------------------------------------------------
Profile
Profile run "test" started at 10:07 on Jun 01 2016.
Run over 10 intervals of 30 seconds.
--------------------------------------------------------------
license
Product=Enterprise
License Type=Concurrent User
Server=Multi
Platform=Heterogeneous
Licensed Users=1000
Licensed CPUs=16
.
.
.
--------------------------------------------------------------
End of InterSystems IRIS Performance Data Report
```
本节中的表格描述了每个特定于平台的报告的部分。这些部分在每个表中按字母顺序列出,以帮助您更轻松地找到特定部分。仅收集一次的数据标有星号 (`*`)。其余数据是在整个配置文件运行过程中收集的。
注意:在以下所有表格中,标有 `*` 的数据每次运行收集一次。
文章
Jingwei Wang · 三月 24, 2022
REST是一种架构风格,而不是一种格式。尽管REST经常使用HTTP来传输消息,使用JSON来传递数据,但你也可以用XML或纯文本来传递数据。REST利用了现有的网络标准,如HTTP、URL、XML和JSON。
虽然它可以使用XML来描述数据,但它更常使用JSON,这是一个轻量级的数据封装器。
InterSystems REST服务
InterSystems REST服务由以下组件组成:
规范类(%REST.Spec的一个子类):这个类包含了REST服务的OpenAPI 2.0规范(Swagger)。InterSystems支持几个扩展属性,你可以在规范中使用。
调度类(%CSP.REST的一个子类):这个类负责接收HTTP请求并在实现类中调用合适的方法。
实现类(%REST.Impl的子类):这个类定义了实现REST调用的方法。
Web应用程序:它通过InterSystems Web Gateway提供对REST服务的访问。
使用API 管理工具创建REST服务 - 基于 OpenAPI 2.0规范
/api/mgmnt/
可以使用/api/mgmnt服务来创建、更新和删除REST服务。
使用/api/mgmnt创建 .disp .impl 和 .spec 类
使用http://localhost:52773/api/mgmnt/v2/namespace/myapp
注意: 命名空间必须已经存在,myapp可以自己定义,使用POST。
生成成功消息:
{
"msg": "New application myapp created"
}
创建Web应用程序 名字:/csp/namespace 分派类:myapp.disp 应用角色: %DB_%DEFAULT
补全实现类中的方法
使用^%REST Routine创建REST服务 - 基于 OpenAPI 2.0规范
do ^%REST
使用%REST.API类创建REST服务 - 基于 OpenAPI 2.0规范
可以用它来发现服务器上的REST服务,为这些REST服务生成OpenAPI 2.0规范,并在服务器上创建、更新、或删除REST服务。
使用%REST.API 创建 .disp .impl 和 .spec 类
set file="c:/temp/swagger.json"
set obj = ##class(%DynamicAbstractObject).%FromJSON(file)
do ##class(%REST.API).CreateApplication("petstore",.obj,,.new,.error)
//examine error and decide how to proceed...
...
创建Web应用程序
名字:/csp/namespace
分派类:myapp.disp
应用角色: %DB_%DEFAULT
补全实现类中的方法
基于%CSP.REST 手动创建REST 服务 - 不需要定义OpenAPI 2.0规范
创建REST 分派类,继承 %CSP.REST 类
定义URL map
Class REST.Interface.RestHandler Extends %CSP.REST
{
Parameter CONTENTTYPE = "application/json";
Parameter CONVERTINPUTSTREAM = 1;
Parameter CHARSET = "utf-8";
XData UrlMap
{
<Routes>
<Map Prefix="/coffee/sales" Forward="MyLib.coffee.SalesREST"/>
<Map Prefix="/coffee/repairs" Forward="MyLib.coffee.RepairsREST"/>
<Map Prefix="/coffee" Forward="MyLib.coffee.MiscREST"/>
</Routes>
}
}
创建REST 服务类,继承 %CSP.REST 类
REST 服务类URL map 定义,例如MyLib.coffee.SalesREST类中URL map定义REST 服务类
Class MyLib.coffee.SalesREST Extends %CSP.REST
{
Parameter HandleCorsRequest = 1;
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/request" Method="GET" Call="Request" />
<Route Url="/request" Method="POST" Call="Request" />
</Routes>
}
/// 根据文档号,输出其HTML格式
/// pDocNo:文档编号
ClassMethod Request() As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
Try
{
Set tSC = ##class(REST.Util).GetSales(pName)
W tSC
}
Catch (e)
{
Set tSC=e.AsStatus()
}
Return tSC
}
}
创建Web应用程序
名字:/csp/namespace 或其他名字 分派类:REST.Interface.RestHandler 应用角色: %DB_%DEFAULT
文章
Jingwei Wang · 七月 25, 2022
本章介绍了使用InterSystems IRIS作为企业服务总线,描述了InterSystems IRIS ESB架构,并提供了部署ESB的概述。
企业服务总线的概念
企业服务总线(ESB)提供了一个单点来访问和管理具有SOAP、REST或其他网络API的应用程序。ESB提供了以下功能。
提供一个中心来发现和访问服务。
将应用程序与服务隔离开来,允许你在一个地方改变服务的描述,而不需要更新所有依赖它的应用程序。例如,你可以改变服务器的地址,甚至服务的API,并在ESB中处理这些变化。这为你的应用程序提供了协议独立性。如果一个应用程序是使用SOAP API开发的,但一个新的服务用REST API提供了额外的功能,ESB可以使新的REST服务作为REST和SOAP API可用,允许你添加新服务的功能,同时保持对现有应用程序的兼容性。
提供一种机制来组织和跟踪企业使用的应用程序以及这些应用程序之间的依赖关系。。
ESB架构
InterSystems IRIS ESB架构有以下组成部分。
将传入的请求与服务器连接起来的路由机制。这是由具有专门业务服务(BS)和业务操作(BO)的 production实现的,也可以选择业务流程(BP)。
公共服务注册中心--这个服务注册中心可以通过ESB公共REST API被ESB客户访问。开发人员使用它来获取有关通过 ESB 可用的服务的信息。
外部服务注册中心--这个服务注册中心只能在ESB production中访问。它向ESB业务主机提供端点信息。
SAML令牌验证服务。
ESB production和服务注册处都应该被定义在一个专门用于ESB的命名空间中。
注意:InterSystems建议在一个InterSystems IRIS实例上只运行一个ESB production。
在其最简单的形式中,ESB由透传服务、透传操作和服务注册表组成。下面说明了一个简单的ESB的架构。
通常,应用程序开发人员使用网页或应用程序来查询 ESB 服务注册表,以了解可用的服务并获得提供对底层服务的访问的透传业务服务的 URL。这个查询和服务发现过程是在开发者创建客户端应用程序时进行的。一旦开发者拥有了访问服务所需的URL、文档和其它信息,客户端应用程序就不需要为了调用服务而访问服务注册表。在某些环境中,客户端应用程序可能会对公共API进行运行时调用,以确保注册表项在上次访问后没有被修改。
客户机应用程序调用透传服务。透传服务将消息发送到在其目标设置中指定的透传操作。透传操作被配置为在外部服务注册表中查找端点URL。然后,它使用该端点URL调用外部服务。外部服务将响应返回给透传操作,后者将响应指向透传服务。透传服务反过来将响应返回给客户端应用程序。
除了透传服务和操作外,你还可以定义更复杂的服务、操作和业务流程,以增加一些功能,例如,根据呼叫的内容,将呼叫从一个传入的服务路由到多个外部服务。这允许ESB提供一个单一外部服务所不能提供的服务。客户端应用程序与实现扩展服务所需的外部服务隔绝。
修改用于服务的参数或协议。如果一组应用程序是使用一种服务开发的,但后来有了具有不同 API 的高级服务,与其修改每个应用程序,不如在 ESB 中进行转换。客户端应用程序与从一个外部服务转换到另一个服务所需的变化隔绝。直接在ESB上实现服务。如果没有符合需求的外部服务,可以使用ObjectScript在ESB上实现一个。
但是,将这些更复杂的服务添加到 ESB 上有一个效率成本。这些复杂服务的额外处理成本减缓了ESB处理请求的时间,降低了吞吐量。对于需要非常高吞吐量的ESB系统,你可以通过消除持久化消息来减少处理请求的开销。持久性消息是指从透传服务发送到透传操作的对象,以及由操作返回给服务的对象。这些对象被存储在InterSystems IRIS数据库中。这些持久性的消息在跟踪和报告ESB处理的调用以及排除任何问题时非常有用。但创建这些对象需要资源,对于吞吐量非常高的系统,这些对象所需的存储量可能非常大。为了维护系统,你必须经常清除这些信息。你可以抑制对持久化消息的使用,以获得效率,但代价是降低灵活性。更多信息请参见 "在通过式服务和操作中抑制持久化消息"。
注意:如果你正在运行HealthShare产品,HealthShare服务注册表与InterSystems IRIS服务注册表不同。HealthShare服务注册表提供了与InterSystems IRIS外部服务注册表类似的功能。在大多数情况下,你应该继续使用HealthShare服务注册表,而不是使用InterSystems IRIS外部服务注册表。
配置ESB
下面包含安装和配置InterSystems IRIS的几个配置程序:
创建一个具有互操作性的命名空间,以包含ESB production和服务注册。
配置Web网关。
创建外部服务注册表条目,定义ESB所使用的外部服务的端点。
创建 ESB production,添加提供服务的业务服务和业务操作,并启动该 production。
创建通过管理门户和公共 REST API 访问公共服务注册中心所需的角色和用户。
创建将业务服务提供给客户所需的Web应用程序。
创建公共服务注册表条目,描述通过ESB访问的服务。
文章
姚 鑫 · 七月 14, 2021
# 第三章 处理文件和目录名
`%Library.File`类提供了几个可用于处理文件名和目录名的类方法。在大多数情况下,文件和目录不需要存在即可使用这些方法。
## 获取文件名和目录名
`%Library.File`类提供可用于获取部分文件名和目录名的类方法。
在给定完整路径名的情况下,使用`GetDirectory()`和`GetFilename()`分别获取目录和短文件名。对于此方法,不允许使用部分目录名。
```java
DHC-APP>set filename = "e:\temp\config.txt"
DHC-APP>write ##class(%File).GetDirectory(filename)
E:\temp\
DHC-APP>write ##class(%File).GetFilename(filename)
config.txt
```
在给定文件名的情况下,使用`CanonicalFilename()`从根目录获取完整路径:
```java
DHC-APP>set filename = "cache.dat"
DHC-APP>write ##class(%File).CanonicalFilename(filename)
e:\dthealth\db\dthis\data\cache.dat
DHC-APP>write ##class(%File).CanonicalFilename("foo.dat")
```
如果文件无法打开,`CanonicalFilename()`方法将返回空字符串。
给定一个目录名,使用`ComputeFullDBDir()`构造目录名的规范形式。
```java
DHC-APP>write ##class(%File).ComputeFullDBDir("foodirectory")
C:\InterSystems\Cache\mgr\foodirectory\
```
在给定目录名的情况下,使用`GetDirectoryLength()`和`GetDirectoryPiess()`分别获取目录中的片断数和特定片断的片断数。片断可以用斜杠(`/`)或反斜杠(`\`)分隔,具体取决于操作系统。
```java
DHC-APP>set dir = "e:\temp"
DHC-APP>write ##class(%File).GetDirectoryLength(dir)
2
DHC-APP>write ##class(%File).GetDirectoryPiece(dir,1)
E:
```
在给定文件名或目录名的情况下,使用`ParentDirectoryName()`获取父目录。
```java
DHC-APP>set dir = "stream"
DHC-APP>write ##class(%File).ParentDirectoryName(dir)
E:\DtHealth\db\dthis\data\
````
## 规范化文件名和目录名
`%Library.File`类提供返回规范化文件名和目录名的类方法(遵循运行服务器的操作系统的命名规则)。当通过将名称片段附加到现有名称来创建新的文件名和目录名时,这些选项非常有用。
给定一个文件名,`NormalizeFilename()`返回规范化的文件名.
给定目录名,`NormalizeDirectory()`返回规范化的目录名。
这些方法返回适合在底层操作系统上使用的规范化名称,并将尝试标准化斜杠(`/`)或反斜杠(`\`)路径分隔符。
Windows示例:
```java
DHC-APP>write ##class(%File).NormalizeDirectory("stream")
E:\DtHealth\db\dthis\data\stream\
DHC-APP>write ##class(%File).NormalizeFilename("c:\temp//config.txt")
C:\temp\config.txt
```
UNIX示例:
```java
USER>set filename = "/tmp//samples/myfile.txt"
USER>write ##class(%File).NormalizeFilename(filename)
/tmp/samples/myfile.txt
USER>write ##class(%File).NormalizeDirectory("stream")
/InterSystems/IRIS/mgr/user/stream/
```
在调用这些方法之一以规范化相对于指定目录的目录名或文件名时,请添加第二个参数。该目录必须存在。
Windows示例:
```java
DHC-APP>write ##class(%File).NormalizeFilename("config.txt", "e:\temp")
E:\temp\config.txt
DHC-APP>write ##class(%File).NormalizeDirectory("stream", "")
E:\DtHealth\db\dthis\data\stream\
```
Unix示例:
```java
USER>write ##class(%File).NormalizeFilename("myfile.txt", "/tmp/samples")
/tmp/samples/myfile.txt
USER>write ##class(%File).NormalizeDirectory("stream", "")
/InterSystems/IRIS/mgr/user/stream/
```
`SubDirectoryName()`方法类似于`NormalizeDirectory()`的双参数形式,只是参数的顺序相反。此外,该目录不需要存在。在第三个参数中传递1以添加尾部分隔符,或者传递0以省略它(默认值)。
Windows示例:
```java
DHC-APP>write ##class(%File).SubDirectoryName("C:\foobar", "samples")
C:\foobar\samples
DHC-APP>write ##class(%File).SubDirectoryName("", "stream", 1)
E:\DtHealth\db\dthis\data\stream\
```
Unix示例:
```java
USER>write ##class(%File).SubDirectoryName("/foobar", "samples")
/foobar/samples
USER>write ##class(%File).SubDirectoryName("", "stream", 1)
/InterSystems/IRIS/mgr/user/stream/
```
## 用空格处理文件和目录名
对于包含空格的文件名和目录名,请使用`NormalizeFilenameWithSpaces()`,它会根据主机平台处理路径名中的空格。与规格化文件名()和规格化目录()不同,此方法只接受一个参数,不能相对于另一个目录规格化文件或目录名,也不能相对于默认目录规格化部分文件或目录名。
在Windows系统上,如果路径名包含空格,并且文件或目录不存在,则该方法返回用双引号括起来的路径名。如果路径名包含空格,并且文件或目录确实存在,则该方法返回路径名的简短形式。如果路径名不包含空格,该方法将原封不动地返回路径名。
```java
DHC-APP>write ##class(%File).NormalizeFilenameWithSpaces("C:\temp\nonexistant folder") "C:\temp\nonexistant folder"
DHC-APP>write ##class(%File).NormalizeFilenameWithSpaces("C:\temp\existant folder") "C:\temp\existant folder"
DHC-APP>write ##class(%File).NormalizeFilenameWithSpaces("iris.dat")
iris.dat
DHC-APP>write ##class(%File).NormalizeFilenameWithSpaces("cache.dat")
cache.dat
```
在Unix系统上,如果路径名包含空格,该方法将返回用双引号括起来的路径名。如果路径名不包含空格,该方法将原封不动地返回路径名。
```java
USER>write ##class(%File).NormalizeFilenameWithSpaces("/InterSystems/my directory")
"/InterSystems/my directory"
USER>write ##class(%File).NormalizeFilenameWithSpaces("iris.dat")
iris.dat
```
## 构建和解构文件和目录名
`%Library.File`类提供的类方法允许从路径数组构造文件名,或将文件名解构为路径数组。
给定一个路径数组,`Construct()`组装路径并返回文件名。构造的文件名适合服务器平台。在没有参数的情况下调用此方法会返回默认目录。
给定一个文件名,`Deconstruct()`分解文件名并返回一个路径数组。阵列的内容适合服务器平台。
下面的Windows示例将数组目录传递给`Construction()`。最后一个数组位置中的空字符串表示返回的文件名应以`a \`结尾。
```java
USER>zwrite dirs
dirs=4
dirs(1)="C:"
dirs(2)="Temp"
dirs(3)="samples"
dirs(4)=""
USER>write ##class(%File).Construct(dirs...)
C:\Temp\samples\
```
下面的Unix示例在不带参数的情况下调用`Construction()`。该方法返回默认目录。
```java
USER>set default = ##class(%File).Construct()
USER>write default
/InterSystems/IRIS/mgr/user
```
下面的Unix示例调用`Deconstruct()`,它获取变量default中的路径并将它们存储在数组`defaultdir`中。
```java
USER>do ##class(%File).Deconstruct(default, .defaultdir)
USER>zwrite defaultdir
defaultdir=4
defaultdir(1)="InterSystems"
defaultdir(2)="IRIS"
defaultdir(3)="mgr"
defaultdir(4)="user"
```
## 获取System Manager目录
使用`ManagerDirectory()`方法获取`installdir/mgr`目录的完全限定名称。例如:
```java
DHC-APP>write ##class(%File).ManagerDirectory()
C:\InterSystems\Cache\mgr\
```
文章
姚 鑫 · 五月 8, 2021
# 第三章 使用多维存储(全局变量)(四)
# 管理事务
InterSystems IRIS提供了使用全局变量实现完整事务处理所需的基本操作。
InterSystems IRIS对象和SQL自动利用这些特性。
如果直接将事务性数据写入全局变量,则可以使用这些操作。
事务命令是`TSTART`,它定义事务的开始;
`TCOMMIT`,它提交当前事务;
和`TROLLBACK`,它将中止当前事务,并撤消自事务开始以来对全局变量所做的任何更改。
例如,下面的ObjectScript代码定义了事务的开始,设置了一些全局变量节点,然后根据`ok`的值提交或回滚事务:
```java
/// w ##class(PHA.TEST.Global).GlobalTro(0)
ClassMethod GlobalTro(ok)
{
TSTART
Set ^Data(1) = "Apple1"
Set ^Data(2) = "Berry1"
If (ok) {
TCOMMIT
}
Else {
TROLLBACK
}
zw ^Data
q ""
}
```
TSTART在InterSystems IRIS日志文件中写入事务开始标记。
这定义了事务的起始边界。
在上面的示例中,如果变量`ok`为`true`(非零),则`TCOMMIT`命令标记事务成功结束,并将事务完成标记写入日志文件。
如果`ok`为`false(0)`,那么`TROLLBACK`命令将撤消自事务开始以来进行的每一个`set`或`kill`操作。
在这种情况下,`^Data(1)`和`^Data(2)`被恢复到原来的值。
**注意,在事务成功完成时,不会写入任何数据。
这是因为事务期间对数据库的所有修改都是在事务过程中正常执行的。
只有在回滚的情况下,数据库中的数据才会受到影响。
这意味着本例中的事务具有有限的隔离性;
也就是说,其他进程可以在事务提交之前看到修改后的全局值。
这通常被称为未提交的读取。
这是好是坏取决于应用程序的需求;
在许多情况下,这是完全合理的行为。
如果应用程序需要更高级别的隔离,则可以通过使用锁来实现。
这将在下一节中进行描述。**
## 锁和事务
要创建隔离事务-也就是说,为了防止其他进程在提交事务之前看到修改的数据-需要使用锁。在ObjectScript中,可以通过`lock`命令直接获取和释放锁定。锁按照约定工作;对于给定的数据结构(如用于持久对象),所有需要锁的代码都使用相同的逻辑锁引用(即,锁命令使用相同的地址)。
在事务中,锁有一个特殊的行为;
在事务过程中获取的任何锁在事务结束之前都不会被释放。
要了解为什么会这样,请考虑典型事务执行的操作:
1. 使用`TSTART`启动事务。
2. 获取要修改的一个或多个节点上的锁。这通常被称为“写”锁。
3. 修改一个或多个节点。
4. 释放锁(或多个锁)。因为我们处于事务中,所以这些锁在此时实际上不会被释放。
5. 使用`TCOMMIT`提交事务。此时,上一步中释放的所有锁实际上都已释放。
如果另一个进程想要查看此事务中涉及的节点,并且不想看到未提交的修改,则它只需在从节点读取数据之前测试锁(称为“读”锁)。因为写锁定一直保持到事务结束,所以在事务完成(提交或回滚)之前,读取进程看不到数据。
大多数数据库管理系统使用类似的机制来提供事务隔离。InterSystems IRIS的独特之处在于它让开发人员可以使用这种机制。这使得有可能为新的应用程序类型创建自定义数据库结构,同时仍然支持事务。当然,可以简单地使用InterSystems IRIS对象或SQL来管理数据,并让事务得到自动管理。
## 对TSTART的嵌套调用
InterSystems IRIS维护一个特殊的系统变量`$TLEVEL`,该变量跟踪`TSTART`命令被调用的次数。`$TLEVEL`从值`0`开始;每次调用`TSTART`时,`$TLEVEL`的值递增`1`,而每次调用`TCOMMIT`时,`$TLEVEL`的值递减`1`。如果调用`TCOMMIT`导致将`$TLEVEL`设置回`0`,则事务结束(以`COMMIT`结束)。
调用`TROLLBACK`命令总是终止当前事务,并将`$TLEVEL`设置回`0`,而不管`$TLEVEL`的值是多少。
此行为使应用程序能够将事务包装在本身包含事务的代码(如对象方法)周围。例如,持久对象提供的`%Save`方法始终将其操作作为事务执行。通过显式调用`TSTART`和`TCOMMIT`,可以创建包含几个对象保存操作的更大事务:
```java
TSTART
Set sc = object1.%Save()
If ($$$ISOK(sc)) {
// 第一次保存有效,执行第二次保存
Set sc = object2.%Save()
}
If ($$$ISERR(sc)) {
// 其中一个保存失败,正在回滚
TROLLBACK
}
Else {
// 提交
TCOMMIT
}
```
# 管理并发性
设置或检索单个全局变量节点的操作是原子的;它可以保证始终成功并获得一致的结果。对于多个节点上的操作或控制事务隔离,InterSystems IRIS提供获取和释放锁的功能。
锁由IRIS锁管理器管理。在ObjectScript中,可以通过`lock`命令直接获取和释放锁定。(InterSystems IRIS对象和SQL根据需要自动获取和释放锁)。
# 检查最新的全局变量引用
**最新的全局变量引用记录在ObjectScript `$ZREFERENCE`特殊变量中。`$ZREFERENCE`包含最新的全局引用,包括下标和扩展全局引用(如果指定)。请注意,`$ZREFERENCE`既不指示全局引用是否成功,也不指示指定的全局是否存在。InterSystems IRIS只记录最近指定的全局引用。**
## 裸全球变量引用
在带下标的全局引用之后,InterSystems IRIS会将裸指示符设置为该全局名称和下标级别。然后,可以使用裸全局引用(省略全局名称和更高级别的下标)对相同的全局变量和下标级别进行后续引用。这简化了在相同(或更低)下标级别对相同全局变量的重复引用。
在裸引用中指定较低的下标级别会将裸指示符重置为该下标级别。因此,在使用裸全局变量引用时,始终使用由最新全局引用建立的下标级别。
裸指示符值记录在`$ZREFERENCE`特殊变量中。裸露指示符被初始化为空字符串。在未设置裸指示器的情况下尝试裸全局引用会导致`` 错误。更改命名空间会重新初始化裸体指示符。可以通过将`$ZREFERENCE`设置为空字符串(`“”`)来重新初始化裸指示符。
在下面的示例中,第一个引用中指定了带下标的GLOBAL `^Produce(“fruit”,1)`。InterSystems IRIS将此全局变量名称和下标保存在裸体指示符中,以便后续的裸体全局引用可以省略全局名称`“Production”`和更高下标级别的`“Fruit”`。当`^(3,1)`裸引用达到更低的下标级别时,此新的下标级别将成为任何后续裸全局变引用的假设。
```java
/// w ##class(PHA.TEST.Global).GlobalNake()
ClassMethod GlobalNake()
{
SET ^Produce("fruit",1)="Apples" /* 完整的全局变量引用 */
SET ^(2)="Oranges" /* 裸全局变量全局引用 */
SET ^(3)="Pears" /* 假设下标级别为2 */
SET ^(3,1)="Bartlett pears" /* 转到下标级别3 */
SET ^(2)="Anjou pears" /* 假设下标级别为3 */
WRITE "latest global reference is: ",$ZREFERENCE,!
ZWRITE ^Produce
KILL ^Produce
q ""
}
```
```java
DHC-APP>w ##class(PHA.TEST.Global).GlobalNake()
latest global reference is: ^Produce("fruit",3,2)
^Produce("fruit",1)="Apples"
^Produce("fruit",2)="Oranges"
^Produce("fruit",3)="Pears"
^Produce("fruit",3,1)="Bartlett pears"
^Produce("fruit",3,2)="Anjou pears"
```
除了极少数例外,每个全局变量变引用(全引用或裸引用)都会设置裸指示器。`$ZREFERENCE`特殊变量包含最新全局变引用的完整全局名称和下标,即使这是一个裸全局引用。`ZWRITE`命令还显示每个全局的完整全局名称和下标,无论它是否使用裸引用设置。
应谨慎使用裸全局变量引用,因为InterSystems IRIS在不总是明显的情况下设置裸指示器,包括以下情况:
- 完整全局变量引用最初设置裸露指示符,随后的完整全局引用或裸露全局引用会更改裸露指示符,即使全局引用不成功。例如,试图写入不存在的全局变量的值会设置裸指示符。
- 无论InterSystems IRIS如何计算后置条件,引用下标全局的后置条件命令都会设置裸指示符。
- 引用下标全局变量的可选函数参数可能设置或不设置裸指示符,具体取决于IRIS是否计算所有参数。例如,`$get`的第二个参数总是设置裸指示符,即使它包含的默认值没有使用。InterSystems IRIS按从左到右的顺序计算参数,因此最后一个参数可能会重置由第一个参数设置的裸指示符。
- 回滚事务的`TROLLBACK`命令不会将裸指示符回滚到事务开始时的值。
如果完整全局变量引用包含扩展全局变量引用,则后续的裸全局变量引用将采用相同的扩展全局引用;不必将扩展引用指定为裸全局引用的一部分。