跳到主要内容

一个帖子 标记为 "Oracle Compatible"

查看所有标记

· 1 分钟阅读

IvorySQL v4 基于 PostgreSQL 17,引入了逻辑复制槽同步至热备份数据库的功能。这一改进有效解决了旧版本中主数据库与备份数据库切换后逻辑复制中断的问题。对于那些追求数据高可用性和业务连续性的数据库来说,这无疑是一个重大的利好消息。它不仅提升了系统的整体稳定性,还确保了在故障发生时,数据复制过程能够无缝继续,从而最大程度地降低了业务中断的可能性。

img

复制槽同步机制

前提条件

  1. 物理复制槽:主数据库与备份数据库之间必须存在物理复制槽,作为逻辑复制槽同步的基础,确保数据在主备之间有效传输。。
  2. 配置参数
    • 在备份数据库上配置 primary_slot_name 参数,并在使用 pg_basebackup 工具时指定复制槽。这一配置步骤确保了备份数据库能够正确接收主数据库数据。
    • 启用备份数据库的 hot_standby_feedback 功能,确保其能接收并反馈 WAL 日志。这一功能的启用保证了备份数据库在接收数据时的活跃性和反馈机制的完整性。
    • primary_conninfo 参数中指定有效的数据库名称(dbname)。这一配置确保了复制过程中的目标数据库是明确且正确的。
  3. 推荐配置:在主数据库上配置 standby_slot_names 参数以保持复制槽同步的一致性。这一配置有助于维护主备数据库间复制槽的一致状态,从而提高复制过程的可靠性。

实现方式

  1. 创建逻辑复制槽: 调用 pg_create_logical_replication_slot 函数时设置 failover=true,指定复制槽同步至备份数据库。这一设置至关重要,因为它决定了复制槽在主备切换时的行为。

  2. 订阅配置: 使用 CREATE SUBSCRIPTION 语句时指定 failover=true,确保复制槽同步至备份数据库。这为数据库管理员提供了灵活的配置选项,使他们能够根据实际业务需求和环境特点定制复制策略。

  3. 手动同步: 在备份数据库上执行 pg_sync_replication_slots 函数,手动同步复制槽。这种方法提供了一种即时同步的手段,特别适用于需要立即反映主数据库变更的场景。

  4. 自动同步: 设置备份数据库的 sync_replication_slots = on,实现定期自动同步,无需重启数据库。这一自动化功能简化了数据库的维护工作,使管理员能够将更多精力投入到其他关键任务中。

下图是配置及创建同步逻辑复制槽的流程图,详细的顺序讲解了如何配置同步逻辑复制槽基础参数,以及如何创建一个同步逻辑复制槽。

img

函数与参数

  1. pg_create_logical_replication_slot
  • 新增了 failover 参数,其默认值为 false。若设置为 true,则表示该复制槽需同步至备份数据库。
  • 示例语法:
    SELECT pg_create_logical_replication_slot('test_slot', 'test_decoding', false, false, true)
  • 这一函数的引入,为数据库管理员提供了更精细的控制手段,使得逻辑复制槽的管理更加灵活和高效。
  1. pg_sync_replication_slots
  • 该函数用于手动同步复制槽至备份数据库。
  • 示例语法:
    SELECT pg_sync_replication_slots()
  • 通过这一函数,可以即时地将主数据库的变更同步到备份数据库,确保数据的一致性和完整性。
  1. sync_replication_slots
  • 在备份数据库上设置该参数为 on,可实现复制槽变更的定期自动同步,无需重启数据库。
  • 这一自动化设置极大地减轻了数据库管理员的负担,使得复制槽的维护工作更加轻松和高效。

img

img

如上图所示,为主库和备库的复制槽的状态,主库创建了逻辑复制槽 test_slots2,并定义属性 failover 为 true,开启了这个槽的故障转移功能,通过手动或自动的方式,可以将逻辑复制槽 test_slots2 的状态及信息同步至备库,当发生主备切换或者故障转移时,备库被提升为新主时,逻辑复制槽 test_slots2 的信息将会保留,从而保证订阅端间断、不丢失数据。

操作步骤与验证

手动同步复制槽

搭建主数据库与备份数据库环境,确保主数据库和备份数据库的配置正确,包括物理复制槽和流复制用户。这一过程需要仔细规划和执行,以确保复制环境的稳定性和可靠性。

  1. 创建复制槽:
  • 执行
    SELECT pg_create_logical_replication_slot('test_slot2', 'test_decoding',false, false, true)
  • 这一操作是逻辑复制槽同步的起点,它为后续的数据复制奠定了基础。
  1. 在备份数据库上手动同步复制槽:
  • 执行
    SELECT pg_sync_replication_slots()
  • 这一操作确保了复制槽的变更能够及时反映到备份数据库上,从而保证了数据的同步性和一致性。
  1. 验证复制槽同步:
  • 在备份数据库上执行查询,以确保复制槽已同步至备份数据库。
  • 执行
    SELECT \* FROM pg_replication_slots
  • 这一验证步骤是确认复制槽同步成功的关键环节,它确保了复制过程的正确性和完整性。

自动同步复制槽

  1. 在备份数据库上设置 sync_replication_slots = on
  • 执行
    ALTER SYSTEM SET sync_replication_slots = on
  • 然后执行
    SELECT pg_reload_conf()
  • 这一自动化设置使得复制槽的同步工作更加简便和高效,管理员无需手动介入即可完成同步任务。
  1. 验证自动同步:

    在主数据库插入数据,观察备份数据库复制槽的变化,以确保主数据库复制槽的变更能够自动同步到备份数据库。这一验证步骤是确认自动同步功能正常工作的关键环节,它确保了复制过程的自动化和可靠性。

img

模拟主数据库与备份数据库的切换

  1. 在备份数据库上执行主数据库提升操作:
  • 模拟主数据库故障,将主数据库关机。
  • 在备份数据库上执行
    pg_ctl -D data promote
  • 这一操作模拟了主数据库发生故障时的应急切换,是测试复制槽同步功能在实际故障场景中表现的重要步骤。
  1. 在新的主数据库上继续进行逻辑复制:

    在新的主数据库绑定 VIP,以确保逻辑复制能够继续进行。这一操作确保了在主数据库切换后,逻辑复制能够无缝地继续进行,从而保证了业务的连续性和数据的一致性。

img

img

上图为切换后的新主,保留了原有的逻辑复制槽 my_subscription 和发布信息 my_publication。并且配置其他必要参数后,恢复新备库的逻辑复制槽同步能力。

订阅端根据 VIP 路由至新主数据库,继续使用同步的逻辑复制槽,保证逻辑复制的正常数据复制。

img

总结

逻辑复制槽同步功能提升了 IvorySQL 在高可用性环境下的可靠性,解决了主数据库与备份数据库切换后逻辑复制槽丢失的问题。这一功能的引入,使得数据库面对主备切换时,保证逻辑复制槽的信息不丢失,确保了数据复制过程的连续性和一致性。

同步过程需满足以下条件:

  • 设置 failover=true 的复制槽;
  • 主数据库与备份数据库间配置物理复制槽;
  • 备份数据库启用 hot_standby_feedback
  • 备份数据库的 primary_conninfo 参数配置正确的数据库名称;
  • 推荐配置 standby_slot_names 参数以确保一致性;
  • 通过 pg_sync_replication_slotssync_replication_slots 参数,备份数据库可以手动或自动同步复制槽,确保逻辑复制能够无缝切换。

这一系列的措施和功能,共同构成了 IvorySQL 中逻辑复制槽同步功能的强大和灵活,为数据库管理员提供了强大的工具,以应对各种复杂和挑战性的数据复制场景。

· 1 分钟阅读

前言

随着数据库应用场景的多样化,用户对数据管理的灵活性和隐私性提出了更高要求。IvorySQL 作为一款基于 PostgreSQL 并兼容 Oracle 的开源数据库,始终致力于在功能上保持领先和创新。在最新发布的 4.0 版本中,IvorySQL 新增了 Oracle 兼容特性 Invisible Column(不可见列),这一功能由社区贡献者 Imran Zaheer 提供,体现了开源社区协作的力量

Invisible Column 的引入,为开发者提供了在不影响现有应用的情况下动态调整数据库结构的新选择,进一步提升了 IvorySQL 在数据灵活性管理上的能力,为用户在数据库升级、兼容性优化等方面提供了更大的便利性。

本文将详细介绍这一特性的功能、使用场景以及使用方式。

什么是 Invisible Column?

在现代数据库开发中,列的可见性管理在一定程度上影响了应用程序的灵活性与迁移效率。Oracle 12c 提供了一项强大的功能:Invisible Column(不可见列)。这是一种隐藏数据列的特性,用于增强数据安全性和实现业务逻辑。这一功能为开发者提供了灵活性和控制能力,特别是在应用程序迁移或版本升级的场景中。

在 Oracle 中,Invisible Column 是指那些对大多数 SQL 查询和工具不可见的列。通过将列设置为不可见列:

  • 它不会出现在常规的 SELECT * FROM 查询结果中。
  • 它不会在 SQL*PlusOCI 的描述操作中显示。
  • 它不会包含在基于 %ROWTYPE 属性的记录定义中。

然而,不可见列仍然存在于表中,可以通过显式指定列名来访问或引用。另外,不可见列在使用时也有限制,要注意在外部表(External Tables)、聚簇表(Cluster Tables)、临时表(Temporary Tables)中无法使用不可见列。

Invisible Column 的应用场景

1. 应用程序迁移

不可见列在应用程序迁移过程中非常有用。当我们向现有表中添加新列时,不可见列可以避免影响旧应用程序的功能。旧的应用程序不会察觉新列的存在,而新的应用程序可以显式引用这些列。从而使应用程序的在线迁移变得更加简单顺畅。

2. 敏感数据保护

某些敏感数据可以通过不可见列存储,避免被大多数默认查询工具访问,从而降低意外暴露的风险。

3. 数据模型优化

在数据模型调整或调试过程中,可以临时将一些列设置为不可见列,确保它们不会影响常规查询,避免查询结果混淆。

在 IvorySQL 中使用 Invisible Column

Invisible Column 为 IvorySQL 4.0 版本中新增加的兼容特性,使用前请先确保您的版本为 4.0。

1. 创建不可见列

可以在创建表时直接将列定义为不可见列:

CREATE TABLE employees (
emp_id NUMBER,
emp_name VARCHAR2(50),
emp_salary NUMBER INVISIBLE
);

在此示例中,emp_salary 是不可见列,对默认查询不可见:

select*from employees ;
emp_id | emp_name
--------+----------
(0 rows)

2. 向不可见列插入数据

在向表中插入数据时,可以通过显式指定列名的方式向不可见列插入数据:

INSERT INTO employees(emp_id,emp_name,emp_salary) VALUES(1,'Jack',20000);
INSERT 0 1
INSERT INTO employees(emp_id,emp_name,emp_salary) VALUES(2,'Lucy',30000);
INSERT 0 1;

不带命名列的插入不能包含不可见列:

INSERT INTO employees VALUES(3,'Peter');
INSERT 0 1

3. 显示/修改现有列为不可见列

通过 VISIBLE 关键字,可以将不可见列改回普通列:

ALTER TABLE employees MODIFY emp_salary VISIBLE;
ALTER TABLE

如果需要将现有列设置为不可见列,可以使用 INVISIBLE

ALTER TABLE employees MODIFY emp_salary INVISIBLE;
ALTER TABLE

注意,不能将所有的列设置为不可见列。

4. psql \d 元命令

在 psql 中使用 \d 元命令时不会显示该表的不可见列信息:

\d employees
Table "public.employees"
Column | Type | Collation | Nullable | Default
------------+--------------+-----------+----------+---------
emp_id | number | | |
emp_name | varchar2(50) | | |
emp_salary | number | | |

可以使用含有更多表信息的 \d+ 元命令查看该表的不可见列信息:

\d+ employees
Table "public.employees"
Column | Type | Collation | Nullable | Default | Invisible | Storage | Compression | Stats target | Description
------------+--------------+-----------+----------+---------+-----------+----------+-------------+--------------+-------------
emp_id | number | | | | | main | | |
emp_name | varchar2(50) | | | | | extended | | |
emp_salary | number | | | | invisible | main | | |
Access method: heap

5. 访问 Invisible Column

在使用 SELECT* 查询表数据时,不会显示不可见列的数据:

SELECT * FROM employees ;
emp_id | emp_name
--------+----------
1 | Jack
2 | Lucy
3 | Peter
(3 rows)

虽然不可见列对默认查询不可见,但开发者仍然可以通过显式指定列名来访问它:

SELECT emp_name,emp_salary FROM employees ;
emp_name | emp_salary
----------+------------
Jack | 20000
Lucy | 30000
Peter |
(3 rows)

结语

不可见列功能是一项设计精妙的特性,为数据库开发和管理提供了更高的灵活性和安全性。通过合理利用不可见列,开发者可以轻松应对复杂的应用迁移场景,同时保持系统的稳定性和可扩展性。

如果您有正在使用 IvorySQL 数据库的项目,不妨尝试将此功能集成到您的解决方案中,提升整体效率和可靠性。

· 1 分钟阅读

日前,IvorySQL 4.0 发布,该版本新增了兼容 Oracle 包功能的新特性。

为了大家能够更好地理解和使用 IvorySQL 4.0,本文将简要介绍实现此功能时的设计思路。

Oracle 的包是什么?

包是包含了逻辑上相关的 PL/SQL 类型、变量、常量、子过程、游标和异常的一个模式对象。包被编译并存储在数据库中,多个应用可以共享包的内容。

包总是有一个包规范,包规范中声明了公有对象,这些公有对象可以在包外被引用。

如果公有对象中包含了游标或子过程,则包必须有一个包体。包体必须定义公有游标和公有子过程的代码。包体也可以声明并定义私有对象,私有对象不能在包外被引用,但可用于包内使用。最后,包体可以有一个初始化部分,这部分用于初始化变量,做一些一次性的设置步骤和异常处理。修改包体的时候,可以不修改包规范或引用包的公有对象的数据库对象,因此可以认为包体是一个黑盒。

IvorySQL 中包的实现

从内容来看,包体与嵌套子过程类似,包规范只是定义包体对外的接口,因此,从实现角度来看,包的实现过程可以和嵌套子过程类似。

我们主要处理的工作有如下几个方面:包的创建、更新、实例化、删除以及外部过程对包规范中包对象的引用。

  • 包的创建: 修改 psql 语法,使 psql 能将整个包的创建语句整体发到服务器,在服务器中增加包的创建语法,语法结构基本上和普通函数类似,因此与函数类似,无需在 SQL 端展开。包创建经过语法解析后走 DDL 流程,调用包的创建函数,将包的内容存储到系统表里面去。
  • 包的更新: 在 SQL 端支持更新语法,经语法解析后,调用包的更新函数,更新系统表内容,调用 plisql_package_Handler 走一遍 pl_gram.y,并失效包规范元组或包体元组,这样避免在运行时编译包和包体。
  • 包的删除: 需要在 SQL 端支持其删除语法,经语法解析后,调用包的删除函数,删除系统表该包的内容。
  • 包的实例化: 在第一次引用包的时候,如果包的内容没有在内存中(具体来说是一个 hash 表,类似于 portal 的 hash 表存储),则调用包的实例化函数,将包重新实例化,实例化其实是调用 PL/iSQL 端的 compile 函数,将包规范与包体重新编译,并将编译的结果放在当前进程的内存里,包的实例化应该是将包与包体的整体内容加载到内存中。
  • 包对象引用: 在 parse 阶段,提供查找包规范中的变量,类型、子过程的接口,优先在本模式下查找包中类型,然后查找系统表中的类型,在查找子过程时,优先在嵌套函数、包中、系统表中查找。
  • 包的失效与包的状态: 包中如果全是常量与类型,则包无状态,否则包是有状态的。包的状态在访问包的变量与函数时设置,在重建包时,会让包的本地实例失效,并且本地重新编译实例化,其他进程的包实例,如果包是有状态的,访问包中变量或类型,则首次访问报包的状态丢失错误,其后正常访问。

IvorySQL 中包的设计

新增的系统表与缓存

为了存储包体与包规范内容,新增了 2 个系统表:

系统表名称作用
pg_package.h存储包规范内容
pg_package_body.h存储包体内容

对应的系统缓存则有 4 个:

系统缓存名称作用
PKGBODYOID根据包体的 OID 查找包体的元组
PKGBODYPKGID根据包规范的 OID 查找包体的元组
PKGNAMEARGSNSP根据包名和模式的 OID 查找包的元组
PKGOID根据包规范的 OID 查找包的元组

包的实例化

包的实例化,类似于函数编译,是将用字符串定义的数据,转换成结构化数据。包的内容是由包规范和包体两部分构成,因此,包的编译需要进行一些特殊处理。增加相应的新函数分别编译包规范和包体,并将结果缓存到哈希表中。

另外,为了处理在删除包与包体的时候,本地缓存会失效,在创建包缓存的时候,注册一个包的失效函数,用来处理包的失效时,需要清除包的缓存状态。

/* register invalid cache */
CacheRegisterSyscacheCallback(PKGBODYOID, InvalidatePackageCacheCallback, (Datum) 0);
CacheRegisterSyscacheCallback(PKGOID, InvalidatePackageCacheCallback, (Datum) 0);

InvalidatePackageCacheCallback 将根据 hash 值,遍历 hash 表中的每一项,更新相应包的缓存状态。

包的缓存状态用一个 char 来表示,目前只用到三位 bit,0x01 表示包规范被更新了,0x02 表示包是否有包体,0x04 表示包体被更新了。

包中对象的引用

提供查找包中函数、类型、变量的接口,供 parse 阶段使用,以下是部分函数列表。

函数名称参数返回值说明
LookupPkgTypeByTypenameConst List* namesBool missing_okPkgType*根据语法阶段构造类型名称列表,查看是否是包中的类型。
LookupPkgVarByvarnamesConst List _names, Bool missing_okPkgVar*根据变量名称,查看是否是包中的变量
LookupPkgEntryByTypenameconst List *names, bool missing_okPkgEntry 根据名称,返回包中属性(类型或变量)
LookupPkgFuncParseState *pstate, List *fargs, FuncCall *fnFuncExpr根据函数名称,查看是否是包中的函数

在 PL/iSQL 非包内函数使用包的类型时,只需将类型的地址引用过来,而使用变量时,则需做一份本地映射,当涉及到该类的变量赋值时,需要进行特殊处理。一般来说,主要是切换到包的内存上下文,然后调用包的赋值函数。

函数形参或返回值引用包的类型

该部分需要修改 pg_proc 系统表的结构,需要增加字段来记录参数类型和返回值类型的名称,故在系统表中增加参数类型名称和返回值类型名称两列即可解决。

类似于 proargnames,增加 protypenames 用于记录参数类型的类型名称,增加 rettypename 记录返回值类型的名称。只有当相关项引用包的类型时赋值,不然为空。

因为 protypnames 是一个 text 数组,因此当有一个函数参数是包中类型时,该数组就不为空,且参数类型为包的项是由 TypeName 结构字符序列化得到,其他非包的参数类型为空字符串。

standard 包

支持 sys 模式下的 standard 包,可以不用带包名进行访问包中规范的对象,用户可以自行创建 standard 包。

DISCARD PACKAGE 语法

该功能是为兼容 PostgreSQL 的 DISCARD 功能做的,目前 PostgreSQL 支持 DISCARD SEQUENCEDISCARD TEMPDISCARD PLAN 等用来删除当前 session 的序列、临时表以及计划等缓存,并且 DISCARD ALL 支持删除本 session 的 PORTAL、临时表、计划、序列等临时存储。

IvorySQL 支持 DISCARD PACKAGE 语法,并且在 DISCARD ALL 中调用函数删除本 session 的包缓存。

逻辑备份还原支持包

pg_dump 工具中,包功能也得到了支持,用户可以使用 pg_dump 对包功能在内的数据进行备份恢复。

总结

以上就是实现兼容 Oracle 包功能时的设计思路。

通过包的形式将相关的功能模块化,使得数据库的过程、函数、变量和其他编程元素组织在一起形成自包含单元,便于管理和维护。由于实现细节隐藏在包体中,提高了代码的安全性和可维护性。包体中的代码在第一次调用时被加载到内存中,后续调用可以直接使用,减少了解析和加载时间。

· 1 分钟阅读

日前,IvorySQL 4.0 重磅发布,全面支持 PostgreSQL 17,并且增强了对 Oracle 的兼容性。

本篇文章将详细描述,如何从 IvorySQL 3.x 升级到 IvorySQL 4.0。

pg_upgrade 工具介绍

pg_upgrade 工具是 PostgreSQL 内置的跨版本升级工具,能够对数据库就地升级,不需要执行导出和导入操作。IvorySQL 源自于 PG,因此也能够使用 pg_upgrade 工具进行大版本升级。

pg_upgrade 提供了升级前的兼容性检查(-c 或者 --check 选项)功能,可以发现插件、数据类型不兼容等问题。如果指定了 --link 选项,新版本服务可以直接使用原有的数据库文件而不需要执行复制,通常可以在几分钟内完成升级操作。

常用的参数包括:

  • -b bindir,--old-bindir=bindir:旧的 IvorySQL  可执行文件目录
  • -B bindir,--new-bindir=bindir:新的 IvorySQL 可执行文件目录
  • -d configdir,--old-datadir=configdir:旧版本的数据目录
  • -D configdir,--new-datadir=configdir:新版本的数据目录
  • -c,--check:只检查升级兼容性,不更改任何数据
  • -k,--link:硬链接方式升级

下面介绍一下在 CentOS 8 平台上如何使用 pg_upgrade 将 IvorySQL 升级到最新的 4.0 版本。

升级准备

首先停止旧版本的 IvorySQL 3.4 数据库:

img

然后安装新版本的 IvorySQL 4.0 数据库:

img

初始化新版 IvorySQL 4.0 数据目录:

img

检查版本兼容性:

img

最后出现 Clusters are compatible 表明两个版本之间的数据不存在兼容性问题,可以进行升级。

正式升级

img

img

看到 Upgrade Complete 说明升级已经顺利完成。

更新统计信息

pg_upgrade 会创建新的系统表,并重用旧的数据进行升级,统计信息并不会随升级过程迁移,所以在启用新版本之前,应该首先重新收集统计信息,避免没有统计信息导致错误的查询计划。

首先启动新版本数据库:

img

手动运行 vacuum 命令:

img

升级后的清理

确认没有问题后删除旧库:

img

至此,我们就完成了整个升级过程。

如果您在后续的升级过程中,遇到问题,可以在 GitHub 上提交 issue,我们将及时为您解答。同时,如果您对 IvorySQL 后续的功能迭代有任何想法或者期待,也可以提交 issue 反馈给我们。

· 1 分钟阅读

2022 年渥太华时间 5 月 26 日瀚高北美研究院负责人 Grant Zhou 在会上发表 IvorySQL 项目的技术讲解。本次会议内容主要介绍了我们是谁、IvorySQL 是什么、IvorySQL 的关键功能点、社区贡献指南、开发者指南等。重点介绍了基于 PostgreSQL 14,IvorySQL 在 PostgreSQL 基础之上添加了一些令人兴奋的功能点!!

IvorySQL 在 PostgreSQL 的基础上增加的主要功能特点包括

  • Oracle 兼容包

  • Oracle 兼容 PL/iSQL 过程语言

  • GUC 在 Oracle 和 PostgreSQL 模式之间切换

  • Oracle 兼容各种 DDL 操作的语法

  • Oracle 兼容的日期/时间函数

  • 内置 Orafce (https://github.com/orafce/orafce)

更多功能特性描述,可参阅https://www.ivorysql.org/zh-CN/releases-page的发布说明。

大家可以通过 IvorySQL 产品路线图(https://github.com/IvorySQL/IvorySQL/issues)定期查看GitHub中的问题选项卡可获得最新的功能列表。

bilibili 视频讲解链接

PGCon2022 会议回顾|IvorySQL 项目的技术讲解_哔哩哔哩_bilibili

因为时差的原因,有许多小伙伴没有看到,小助理特意为大家整理好了会议视频内容以及中文 PPT 材料,有需要的小伙伴们,关注公众号,添加小助理微信即可获得。


通过订阅邮件列表加入 IvorySQL 社区:

欢迎在Github给我们一个 ⭐

· 1 分钟阅读

IvorySQL 是一个开源项目,该项目的核心目标之一是提供 oracle 兼容功能,以便在 IvorySQL 数据库服务器上使用 oracle 代码。

在 PostgreSQL 之上提供 Oracle 兼容是一项多维任务。 从提供与 Oracle 兼容的 SQL 语法到添加对 PostgreSQL 中缺失或行为不同的数据类型的支持。 Oracle 兼容性的主要核心之一是在 PostgreSQL 中提供兼容的过程语言 PL(procedural language),它在功能和语法上与 Oracle 的 PL/SQL 兼容

为此,IvorySQL 添加了一种新的 PL 语言 PL/iSQL,它接受、理解和执行 PL/SQL 语法。 如您所知,Oracle PL/SQL 的核心特性之一是 PACKAGES(包)。Package(包)是 Oracle 中的一个模式对象,它包含一组相关功能的定义,是 Oracle 使用最广泛的特性之一。

因此,本文将介绍 Package(包),并举例说明如何用 IvorySQL 创建、使用和销毁 Oracle 样式的包

包(Package)

那么什么是 Package(包)? 包是 PL/iSQL 代码的分组,按逻辑程序单元划分。 换句话说,一个包可以被认为是相关函数、过程、变量或游标的集合,这个集合可以通过通用公共名称来访问。

IvorySQL 内置 PL/iSQL 语言,可以接受、理解和执行 PL/SQL 代码。包使用相同的语言,并且有两个主要组件。

  • 包规范(Specification)

包规范列出了可以从包外部访问的所有项目,例如函数、过程、变量和游标。这也称为公共规范。

  • 包体(Body)

包体包含包规范中列出的所有函数和过程的实现。除此之外,它还可以实现更多的功能、过程或其他元素。

这些不在包规范中的元素将被视为包的私有成员,并且只能在包内引用它们。 不允许外部访问。

包体也可以有一个特殊的代码块,称为初始化块。 这是一个特殊的块,因为这个块在每个会话中只执行一次,在包第一次被访问的最开始。

让我们看一些代码示例,看看包是如何运行的。

示例

通用示例

首先让我们设置兼容模式,这样我们就可以访问 IvorysSQL 数据库中可用的 Oracle 兼容特性。

SET compatible_mode TO oracle;

CREATE TABLE books (
id INT,
title VARCHAR2(100),
author VARCHAR2(100),
price NUMBER);
INSERT INTO books VALUES (10, 'The Hobbit', 'J. R. R. Tolkien', 10.0);
INSERT INTO books VALUES (11, 'Winnie-the-Pooh', 'A. A. Milne', 5.0);
INSERT INTO books VALUES (12, 'Peter Pan', 'James Matthew Barrie', 4.0);
INSERT INTO books VALUES (13, 'Charlie and the Chocolate Factory', 'Roald Dahl', 5.0);
INSERT INTO books VALUES (14, 'SThe Jungle Book', 'Rudyard Kipling', 9.0);
INSERT INTO books VALUES (15, 'The Little White Bird', 'James Matthew Barrie', 3.0);

让我们来创建一个简单的包。这个包声明了一个游标来列出所有可用的图书,并包含一些子程序来列出、添加和删除书籍。同时,它还声明了一些私有变量来计数和保存图书信息。

CREATE OR REPLACE PACKAGE mybooks AS
CURSOR booksinfo IS SELECT * from BOOKS;

PROCEDURE list_books;
FUNCTION add_book(title VARCHAR2(100), author VARCHAR2(100),
price NUMBER) RETURN bool;
PROCEDURE remove_book(book_title VARCHAR2(100));
END;
ivorysql$# /
CREATE PACKAGE
CREATE OR REPLACE PACKAGE BODY mybooks AS

-- declare private variables
bookinfo booksinfo%rowtype;
books_count INT;

PROCEDURE list_books AS
BEGIN
OPEN booksinfo;
RAISE INFO 'Book Info:';
RAISE INFO '';
LOOP
FETCH booksinfo into bookinfo;
EXIT WHEN NOT FOUND;

RAISE INFO ' Name = %', bookinfo.title;
RAISE INFO ' Author = %', bookinfo.author;
RAISE INFO ' Price = %', bookinfo.price;
RAISE INFO '------------------------------';
END LOOP;
RAISE INFO 'Total Books = %', books_count;
CLOSE booksinfo;
END;

FUNCTION add_book(title VARCHAR2(100), author VARCHAR2(100),
price NUMBER) RETURN bool AS
BEGIN
INSERT INTO BOOKS VALUES (
books_count + 1,
title,
author,
price);

books_count := books_count + 1;
RETURN true;

EXCEPTION WHEN OTHERS THEN
RETURN false;
END;

PROCEDURE remove_book(book_title VARCHAR2(100)) AS
BEGIN
DELETE FROM BOOKS WHERE title = book_title;

EXCEPTION WHEN OTHERS THEN
RAISE INFO 'Book % not found', book_title;
END;

-- initializer block
BEGIN
books_count := 0;
SELECT count(*) INTO books_count
FROM BOOKS;
END;
ivorysql$# /
CREATE PACKAGE BODY

让我们检验这些数据。这匿名块试图访问该包的私有成员,这将会导致错误。

ivorysql=# DECLARE
ivorysql$# nbooks int := 0;
ivorysql$# BEGIN
ivorysql$# nbooks := mybooks.books_count;
ivorysql$# RAISE INFO 'Total Books = %', nbooks;
ivorysql$# END;
ivorysql$# /
2022-05-26 16:35:32.328 PKT [63554] ERROR: package private variable ("mybooks.books_count") is not accessible

让我们使用包的子程序列出所有可用的书籍。 list_books mybooks

ivorysql=# BEGIN
ivorysql$# mybooks.list_books;
ivorysql$# END;
ivorysql$# /
INFO: Book Info:
INFO:
INFO: Name = The Hobbit
INFO: Author = J. R. R. Tolkien
INFO: Price = 10
INFO: ------------------------------
INFO: Name = Winnie-the-Pooh
INFO: Author = A. A. Milne
INFO: Price = 3
....
....
INFO: Total Books = 6
DO
ivorysql=#

让我们使用包的子程序添加一本新书。 add_book mybooks

DECLARE
added bool;
BEGIN
added := mybooks.add_book('The Cat in the Hat', 'Dr. Seuss', 10);
IF added = TRUE THEN
RAISE INFO 'new book added';
END IF;
END;
/

删除包

可以使用以下命令删除包体或完成包:

  • DROP PACKAGE BODY [package name]
ivorysql=# DROP PACKAGE BODY mybooks;
DROP PACKAGE BODY
  • DROP PACKAGE [package name]
ivorysql=# DROP PACKAGE mybooks;
DROP PACKAGE

具有不同权限的包调用

我们将创建两个具有调用者和定义者权限的包,并查看结果以了解它们之间的区别。

ivorysql=> SELECT current_user;
current_user
--------------
ivorysql
(1 row)

--创建具有 INVOKER 权限的包

CREATE OR REPLACE PACKAGE pkg_invrights AUTHID CURRENT_USER AS
PROCEDURE curr_user;
END;
/

CREATE OR REPLACE PACKAGE BODY pkg_invrights AS
PROCEDURE curr_user AS
BEGIN
RAISE INFO 'Current User: %', current_user;
END;
END;
/

--创建一个具有 DEFINER 权限的包

CREATE OR REPLACE PACKAGE pkg_defrights AUTHID DEFINER AS
PROCEDURE curr_user;
END;
/

CREATE OR REPLACE PACKAGE BODY pkg_defrights AS
PROCEDURE curr_user AS
BEGIN
RAISE INFO 'Current User: %', current_user;
END;
END;
/

让我们先查看具有调用程序权限的包。

ivorysql=> CALL pkg_invrights.curr_user;
INFO: Current User: ivorysql
CALL

让我们来看看具有定义权限的包。

ivorysql=> CALL pkg_defrights.curr_user;
INFO: Current User: ivorysql
CALL

让我们切换到另一个名为 ivuser 的用户。

ivorysql=> \c ivorysql ivuser;
You are now connected to database "ivorysql" as user "ivuser".

让我们先看看具有调用程序权限的包。

ivorysql=> CALL pkg_invrights.curr_user;
INFO: Current User: ivuser
CALL

让我们看看具有定义权限的包。

ivorysql=> CALL pkg_defrights.curr_user;
INFO: Current User: ivorysql
CALL

总结

如上所示,当调用具有调用者权限(pkg_invrights)的包时,它使用的是调用该包的用户的特权。但是,当调用(pkg_defrights)时,它仍然使用包所有者的特权。

· 1 分钟阅读

硅谷Postgres会议是西海岸最大的PG会议,也是美国乃至全球Postgres年度重要会议之一,于2022年4月7日至8日(PDT)在美国加利福尼亚州圣何塞希尔顿酒店召开。作为面向全球PostgreSQL技术专家、从业者、爱好者的年度技术交流活动,硅谷会议致力于汇集和讨论关于人、Postgres和数据间的关系!会议与主办地硅谷一样极具包容和公平精神,这里汇集了最优秀的演讲者、听众和赞助商,所有人努力为全球Postgres生态系统创造发展机会。

会议现场人数大概有200多人,是疫情以来聚集人数最多的一次线下会议。

社区核心人员Bruce Momjian出席,会议由PostgresConf,Joshua D.Drake, Jim Mlodgenski 等组织。来自中国、美国、加拿大、巴西、西班牙、德国、印度、巴基斯坦等多个国家的人员参与。

瀚高北美研究院兼中国PostgreSQL分会国际顾问委员会秘书长Grant Zhou作为唯一中国代表,将携IvorySQL项目亮相本次会议。

以下是由IvorySQL开源数据库社区为您带来的硅谷Postgres两日会议简报。

部分演讲议题

IvorySQL--一个基于PostgreSQL的兼容Oracle的开源数据库 --by GRANT ZHOU

有很多用户需要将他们的应用程序从Oracle迁移到开放源码的Postgres,但是为了支持新的数据库,用户经常需要重新开发应用程序,这很不方便。如果有一个基于Postgres的数据库,并且兼容大多数Oracle语法和函数,对客户来说就太方便了。然而官方的Postgres项目不接受这种代码提交。毕竟,Postgres是Postgres, Oracle是Oracle。因此,IvorySQL项目团队创建一个Oracle兼容的数据库。

本演讲中介绍了如何基于PG实现与Oracle语法兼容的数据库,并介绍IvorySQL项目。这个项目是一个开源项目(Apache 2.0),由Highgo软件领导,目前已经发布了基于PostgreSQL 14.2版本的IvorySQL 1.2。

同时欢迎大家为这个开源的侧重Oracle兼容性的数据库——IvorySQL做出贡献。

非关系型Postgres --by Bruce Momjian

Postgres一直对关系存储提供强大的支持。然而,在许多情况下,关系存储要么效率低下,要么限制过度。这个演讲展示了Postgres扩展到支持非关系存储的许多方式,特别是在一个数据库字段中存储和索引多个值(甚至是不相关的值)的能力。这种存储可以提高效率和访问的简单性,还可以避免实体-属性-值(eav)存储的缺点。演讲涵盖多个字段多值存储的例子,包括数组、范围类型、几何图形、全文搜索、xml、json和记录。

数字权力和隐私:21世纪的关注--by Andres Arrieta

30多年来,电子前沿基金会一直在保护和争取我们的公民自由。在这30年里发生了很多事情:我们与互联网的关系从根本上发生了改变,然而,在很多方面,我们对互联网如何运作的理解仍然停滞不前。如今,互联网已经成为我们生活中不可或缺的核心部分,我们越来越依赖互联网。虽然我们比以往任何时候都更容易接触到互联网提供的众多礼物,但决策者和执法机构对互联网如何运作的理解仍然滞后。在此期间,电子前沿基金会及其使命已经涵盖了技术带来的好或坏的许多方面,并帮助保护那些受其影响的人,同时确保一个光明的未来,通过创新改善我们的生活。

Andres Arrieta向大家介绍了我们的一些工作、一些关切的领域以及Andres Arrieta认为将有助于我们朝着更美好的未来努力的一些事情。主要是关于数据隐私和消费者权利的理论视角。讨论了隐私的不同方面以及保护个人隐私的选项。

逻辑复制的过去、现在和未来--by Amit Kapila

在这次演讲中,Amit Kapila讲述了逻辑复制在PostgreSQL中是如何发展的。这将解释最近的一些最近的主要增强,比如促进两阶段和正在进行的大型事务的逻辑复制。并分享了Amit Kapila对如何利用该技术为大型企业构建高度可伸缩和可用的数据库解决方案的看法。在那之后,还讨论了在PostgreSQL未来版本中在这个技术领域中讨论的一些重要增强。并且介绍如何增强这项技术,以便将数据从PostgreSQL迁移到其他数据库。

现代原生云应用的传记--by Karthik Ranganathan

现代云原生应用程序过着令人兴奋的生活 - 从它们在云中诞生,到处理巨大的计划外成功,再到在云中断中幸存下来并处理全球客户。在本次演讲中,Yugabyte 首席技术官 Karthik Ranganathan 从数据层的角度介绍了Yugabyte 如何处理双向表级复制和高可用性。

Aurora的亚马逊Babelfish--by chandra pathivada

现在奥罗拉的Babelfish已经上市了。这个演示是关于Babelfish如何帮助客户迁移SQL Server工作负载到Postgres。在这个演示中,chandra pathivada演示了什么是Babelfish, Aurora的内部结构,使用Babelfish的SQL Server dba的Aurora,以及应用程序迁移实验室。

现场照片

p

p

p

p

p

更多详情内容

2022年硅谷Postgres会议官方网址: https://postgresconf.org/conferences/SV2022

关于IvorySQL

IvorySQL项目是一个具有广泛生态基础和中国特色的PG开源衍生项目,是瀚高公司设计研发的一款具备强大Oracle兼容能力的开源数据库。 具备高兼容性和高可用性,并致力于遵守open-source ways。 IvorySQL社区欢迎并赞赏所有类型的贡献,期待您的加入!


通过订阅邮件列表加入IvorySQL社区:

还有,别忘了在Github给我们一个 ⭐

· 1 分钟阅读

Hi~各位朋友们,我们的PostgresWorld Webinars又回来啦!

PostgreSQL在国内数据库的发展过程中承担了非常重要的角色,全球众多数据库产品选择PostgreSQL作为技术发展路线。但是应用程序从Oracle迁移到开源Postgres的问题成为了最大的阻碍,因此我们创建了IvorySQL开源项目,它是基于最新的PostgreSQL 14并具有强大Oracle兼容性的数据库。 然而我们为什么一定要做IvorySQL开源项目?它和Postgres、Oracle技术上有什么区别?本次网络研讨会邀您一起探讨。

本期网络研讨会由Grant Zhou带来《IvorySQL - 一个基于PostgreSQL的兼容Oracle的开源数据库》为主题的分享,共同探讨基于PG并兼容Oracle的开源数据库。

嘉宾介绍

Grant Zhou目前居住在加拿大,他是瀚高北美研究院的负责人,并领导PostgreSQL公司开发团队,团队成员来自加拿大,中国和巴基斯坦。他同时担任PostgreSQL中国分会国际顾问委员会的秘书长,也很自豪能成为PostgresConf的组织者和亚洲联络人。他在阿尔卡特朗讯(诺基亚)公司工作了十多年,在高可用性、实时电信系统、数据库技术和Unix/Linux编程方面拥有丰富的经验。 2021年12月,该团队宣布了IvorySQL数据库的第一个可用版本,这是目前唯一一款基于PostgreSQL、兼容Oracle的开源数据库。2022年2月28日,基于PostgreSQL 14.2发布了IvorySQL 1.2。

研讨会要点介绍

有许多用户需要将他们的应用程序从Oracle迁移到开源Postgres,但是为了支持新的数据库,用户经常需要重新开发应用程序,这很不方便。如果有一个基于Postgres的数据库,并且与大多数Oracle语法和函数兼容,那么对于客户来说就太方便了。 但是,官方的Postgres项目不会接受这种代码提交。毕竟,Postgres是Postgres,Oracle是Oracle。 因此,我们创建了一个具有Oracle兼容功能的开源数据库项目。 本次演讲将介绍如何基于PG实现与Oracle语法兼容的数据库,详细介绍IvorySQL项目的研发过程

时间与链接


Join the IvorySQL community by subscribing to mailing lists:

Also, don't forget to give us a ⭐ on Github

· 1 分钟阅读

Hello

正当全世界都在为节日打包行李,迎接新年的到来时,我们正努力工作,并为我们的团队从2021年初开始的项目做最后的润色。那天是12月15日,就在那天结束之前,我们得到了所有的绿灯,在清理桌子之前,我们默默地发布了IvorySQL的第一个版本。

IvorySQL概览

IvorySQL是Apache 2.0许可的开源Oracle兼容PostgreSQL。IvorySQL的第一个版本源自PostgreSQL 14,它坚定地承诺始终保持100%的PostgreSQL兼容性,并可以直接替换PostgreSQL的最新版本。

IvorySQL在现有标准PostgreSQL配置参数的基础上添加了一个兼容的_db GUC。 compatible_db 是一个切换开关,用于在Oracle和PostgreSQL兼容模式之间切换。IvorySQL的第二大亮点是 PL/iSQL 支持oracle PL/SQL语法的过程语言。这两个新增功能在不破坏标准PostgreSQL兼容性的情况下,是IvorySQL的Oracle兼容性的核心。compatible_db 切换在Oracle和PostgreSQL中存在的函数和对象的行为,并以不同的方式运行,而PL/iSQL 为在最小的更改上运行IORYSQL的Oracle代码奠定了基础。

IvorySQL具有许多与Oracle兼容的功能,包括Oracle风格的PACKAGES, DATA Types, 和 Conversion Functions. 有关IvorySQL中Oracle兼容性功能的详细信息,请参阅 IvorySQL文档

我们致力于遵循开源方式的原则

IvorySQL致力于遵守 open-source ways 我们坚信建设一个健康、包容的社区。我们坚持认为好的想法可以来自任何地方,最好的想法应该获胜。只有包含不同的观点,我们才能做出最佳决策。虽然IvorySQL的第一个版本主要关注Oracle兼容性功能,但未来的路线图和功能集将由社区以开源的方式确定。

为IvorySQL做贡献

有很多方法可以帮助IvorySQL。您可以通过提供文档更新和文档翻译来做出贡献。如果你有设计技能,你可以为IvorySQL网站项目做出贡献。 测试IvorySQL和报告问题,通过发布bug修复或新功能的pull请求,或回答邮件列表上的问题,是对IvorySQL项目做出贡献的一些方式,IvorySQL社区欢迎并赞赏所有类型的贡献。

快速开始

所有与IvorySQL相关的项目,包括数据库服务器、网站和文档,都通过Github托管和管理。您可以通过IvorySQL Github page下载源代码或发布的软件包.

浏览 http://www.ivorysql.org 阅读项目文档和贡献指南。


通过订阅邮件列表加入IvorySQL社区:

还有,别忘了在Github给我们一个 ⭐