我正在为Oracle数据库创建一个Docker镜像,并且将从同一个镜像生成许多不同的容器。
当我启动 Oracle 实例时,由于某种原因,一些字节被写入所有活动数据文件。Docker 保存了从容器到基础镜像的差异,差异是更改的整个文件,因此每次我启动容器时,仅仅为了启动数据库,就会有超过 6 GB 的内容被写入磁盘。
那么,为什么 Oracle 在启动数据库时会写入数据文件?最合乎逻辑的行为是仅在更改和提交数据时才写入数据文件。我可以做些什么来改变这种情况吗?
除了 Oracle Linux(这是我的图像的基础)之外,我也在 Windows 上尝试过,并且行为是一样的,所有数据文件都已写入。
我尝试将表空间设置为只读。这可以避免写入操作,但是当我将表空间设置为读写时,它会立即写入文件,从而再次导致问题。
需要明确的是,我需要表空间可写,但只有当数据实际发生变化时才可以。
答案1
这是无法避免的。除了用户数据之外,Oracle 还包含大量元数据 - 这些也必须维护。Oracle 内部维护一个称为 SCN(系统更改号)的数字。每当数据库中的“某些内容”发生变化时,此数字就会增加。
此 SCN 号写入每个数据文件的头部,也写入每个控制文件。打开(启动)数据库时,Oracle 会检查此号在所有文件中是否相同。然后它假定文件是一致的。
即使数据库没有负载,此 SCN 也会递增。此外,统计信息收集等后台作业也会产生一些负载。用户还可以创建系统触发器ON DATABASE STARTUP
,在数据库启动时执行某些作业。
通常,Oracle 数据库服务器并不适合虚拟化。Oracle 内部的日志记录人员也会这样做,因此您需要保留相同的数据两次(这些文件称为存档重做日志)。因此,如果您删除容器差异(仅适用于数据文件),Oracle 将能够幸存下来,因为它将能够从重做日志中重放事务。
PS:克隆数据库时,您还应考虑将数据库 SID 更改为唯一的。或者至少应使用 nid 来更改数据库唯一编号 DBID。否则,在恢复 RMAN 数据库备份时可能会遇到麻烦。