在 Firebird 2.1 中将表从一个数据库复制到另一个数据库

Copying tables from one database to another, in Firebird 2.1

我需要在 Firebird 2.1 中将表从一个数据库复制到另一个数据库,但在某种程度上这非常快,您可以 运行 在控制台上执行此操作。

我用了FBcopy,但是老大说太慢了。这必须在多个事务中完成,因为表非常大。我有什么想法可以做到这一点?

一种可能的解决方案是使用源 table(或至少:您要传输的数据)的布局创建 external tables,一个在源数据库中,另一个在目标数据库中数据库。

在源数据库中,您 select 您想要从源 table 传输的内容并将其插入(空的)外部 table。完成后,您可以将文件复制到其他数据库。如果它们在同一台服务器上,则可以直接使用相同的文件(我没有使用外部 tables 足以指出下面指出的风险之外的风险)。

在目标数据库上,您可以从外部 table select 插入最终目标 table.

创建和使用外部 table 时,请牢记以下几点:

  • 外部 tables 文件是固定宽度的 binary 数据格式,我的文档 link 展示了如何制作它看起来像一个固定宽度的文本格式,但实际上不是。

  • 字符数据的正确解释取决于字符集(正确的字符转换和数据长度),例如 UTF8 列是其声明长度的 4 倍。创建外部 tables 时,显式声明字符集以避免出现问题 - 例如 - 数据库之间的默认字符集不同。

    使用单字节字符集与使用 4 字节字符集的区别会导致严重损坏,因为 WIN1252 数据库中的 CHAR(100) 将 written/read 为 100 字节,但在UTF8 数据库,它将 written/read 为 400 字节。所以一定要明确使用字符集,例如CHAR(100) CHARACTER SET WIN1252.

  • 鉴于其未压缩的特性,如果您的数据允许,最好使用单字节字符集而不是 - 例如 - UTF8。

  • 外部 table 不支持 blob 或数组。

  • 您不能删除或更新外部 table 中的行。要清除它,您需要删除底层外部文件(Firebird 会在必要时自动创建一个新文件)。

  • 无法定义主键或外键约束,也无法在外部 tables

    上定义索引

为了能够使用外部 tables,您需要配置 Firebird 以允许它访问这些文件。在服务器的 firebird.conf 中,将 ExternalFileAccess 设置从默认的 None 更改为 ExternalFileAccess = Restrict <path>,其中路径是文件夹或分号分隔的文件夹列表,其中 Firebird有访问权限。阅读配置文件中有关此选项的文档!

一个(非常)小的例子。假设两个数据库都在同一台服务器上,并且您的数据库有一个 CUSTOMER table 要传输:

create table customer (
    id integer constraint pk_customer primary key,
    customer varchar(25) character set win1252 not null
)

然后创建等效的外部 table:

create table ext_customer external file 'D:\data\DB\exttables\ext_customer.dat' (
    id integer not null,
    customer varchar(25) character set win1252 not null
)

在源数据库和目标数据库中创建这个table。

然后在源数据库中把客户数据放在外部table:

insert into ext_customer (id, customer) select id, customer from customer;

确保提交。

在目标数据库中,您就可以使用数据了。例如,如果 customer table 当前为空,您可以简单地执行我们在源代码中所做的相反操作:

insert into customer (id, customer) select id, customer from ext_customer;

如果您需要更多控制,请考虑查看 MERGE

这是一个老问题但是;

您可以尝试禁用目标 table 上的索引。 复制数据,然后启用索引。

您还可以检查目标 table 上的触发器并禁用不需要的触发器。是否有从其他 table 中选择或插入其他 table 的触发器?

您还可以在目标数据库上禁用 "forced writes"。我假设您有一台带有冗余电源和 raid 磁盘系统(或云)的服务器 复制后,您可以重新打开 "forced writes"。 https://www.firebirdsql.org/pdfmanual/html/gfix-sync.html