楔子
今天折腾了接近一下午,就为了使用SAP HANA自带的命令行工具来导出数据备份。
SAP HANA(后续简称Hana)是内存数据库,性能这一方面上还真没怕过谁。
由于SAP HANA提供了Hana Studio这个桌面工具来方便运维和DBA使用,官方的教程也是用Hana Studio进行演示的,但是这有点麻烦:
Hana运行在服务器上,Hana Studio作为客户端运行在终端电脑上,使用Hana的场景基本上就是数据量大导致查询慢的场景,都这种情况了,难不成还得把备份完整不压缩的数据放到运维的电脑上?
跨主机导入、导出受带宽和交换机的性能影响,传输效率会不会太低了点呢?
普通电脑的配置不会太高,CPU和网卡的性能不见得会很快,导入、导出效率低势必会让操作人花费大量的时间
Hana Studio是基于eclipse开发的,本质上是个Java程序,占用内存会比较多,如果因为导出、导入时数据太大把Hana Studio内存给撑爆了呢?这不又得重新操作了嘛!
而且导数据期间,这电脑基本干不了啥事了。
那么有没有一种办法能不占用运维、DBA的主机网络、硬盘,效率还能翻上几翻的办法呢?
- 有的,兄弟,有的。
- 那就是命令行操作,在数据库服务器上使用一部分CPU、硬盘去执行备份。
- 命令行操作还有个好处是可以在传输前在服务器本地压缩一下,大大减少硬盘使用量以及传输压力。
本文采用SAP HANA的命令行工具hdbsql进行处理,由于在网上找资料和AI问答都很费劲,这才花时间整理出这篇资料。
一方面这符合我目前的DevOps的工作定位————提升效率,
另一方面也能减少被Hana Studio支配的苦恼————谁愿意装这种破玩意儿,操作逻辑反人类!
我会在本文中放上官方文档相关内容以待读者自行参考,在文章最后放上我踩坑总结的操作方法。
心动不如行动,我们开始吧,始吧,吧……(说话有回音才能显得我比较高大)
环境
公司目前使用hana官方的express edition 2.00.xx.00.20240701.1镜像部署测试环境数据库。
命令同样适用于2.00.xx其他版本(暂未在其他大版本上试验过,读者可自行尝试),
理论上命令行工具的设计应是跨版本一致的。
文中 SYSTEM
假定密码为 abcdefg
,普通用户 GCREPORT_PRD
假定密码为 12345678
。
迁移导入到普通用户 GCREPORT_TEST
假定密码为 87654321
。
数据库用户及组ID为12000:79
。
官方文档
参考自《SAP HANA数据库–SQL参考手册》数据导入导出语句 章节。
EXPORT
- 导出命令
语法:
EXPORT <object_name_list> AS <export_format> INTO <path> [WITH <export_option_list>]
语法元素:
WITH <export_option_list>: 可以使用 WITH 子句传入 EXPORT 选项。
<object_name_list> ::= <OBJECT_NAME>,... | ALL
<export_import_format> ::= BINARY | CSV
<path> ::= 'FULL_PATH'
<export_option_list> ::= <export_option> | <export_option_list> <export_option>
<export_option> ::=
REPLACE |
CATALOG ONLY |
NO DEPENDENCIES |
SCRAMBLE [BY <password>] |
THREADS <number_of_threads>
描述:
EXPORT
命令以指定的格式 BINARY
或者 CSV
,导出表、视图、列视图、同义词、序列或者存储过程。临时表的数据和"no logging"表不能使用 EXPORT 导出表。
OBJECT_NAME
将导出对象的 SQL 名。欲导出所有集合下的所有对象,你要使用 ALL 关键字。如果你想导出指定集合下的对象,你应该使用集合名和星号,如"SYSTEM".“*”。
BINARY
表数据将以内部 BINARY 格式导出。使用这种方式导出数据比以 CSV 格式快几个数量级。只有列式表可以以二进制格式导出。行式表总是以 CSV 格式导出,即使指定了 BINARY 格式。
CSV
表数据将以 CSV 格式导出。导出的数据可以导入至其他数据库中。另外,导出的数据顺序可能被打乱。列式和行式表都可以以 CSV 格式导出。
FULL_PATH
将导出的服务器路径。
注意:当使用分布式系统,FULL_PATH 必须指向一个共享磁盘。由于安全性原因,路径可能不包含符号链接,也可能不指向数据库实例的文件夹内,除了’backup’ 和 'work’子文件夹。有效路径(假设数据库实例位于/usr/sap/HDB/HDB00)的例子:
'/tmp' '/usr/sap/HDB/HDB00/backup' '/usr/sap/HDB/HDB00/work'
REPLACE
使用 REPLACE 选项,之前导出的数据将被删除,而保存最新导出的数据。如果未指定 REPLACE 选项,如果在指定目录下存在先前导出的数据,将抛出错误。
CATALOG ONLY
使用 CATALOG ONLY 选项,只导出数据库目录,不含有数据。
NO DEPENDENCIES
使用 NO DEPENDENCIES 选项,将不导出已导出对象的相关对象。
SCRAMBLE
以 CSV 格式导出时,使用 SCRAMBLE [BY '<password>']
,可以扰乱敏感的客户数据。当未指定额外
的数据库,将使用默认的扰乱密码。只能扰乱字符串数据。导入数据时,扰乱数据将以乱序方式
导入,使最终用户无法读取数据,并且不可能回复原状。
THREADS
表示用于并行导出的线程数。
使用的线程数给定 THREADS 数目指定并行导出的对象数,默认为 1。增加数字可能减少导出时间,但也会影响系统性能。
应当考虑如下:
对于单个表,THREADS 没有效果。
对于视图或者存储过程,应使用 2 个或更多的线程(最多取决于对象数)。
对于整个集合,考虑使用多于 10 个线程(最多取决于系统内核数)。
对于整个 BW / ERP 系统(ALL 关键字)的上千张表,数量大的线程是合理的(最多 256)。
系统和监控视图:
你可以使用系统视图 M_EXPORT_BINARY_STATUS 监控导出的进度。
你可以在如下语句中,使用会话 ID 从相应的视图中终止导出会话。
ALTER SYSTEM CANCEL [WORK IN] SESSION 'sessionId'
导出的详细结果存储在本地会话临时表#EXPORT_RESULT。
例子:
EXPORT "SCHEMA"."*" AS CSV INTO '/tmp' WITH REPLACE SCRAMBLE THREADS 10
IMPORT
- 导入命令
语法:
IMPORT <object_name_list> [AS <import_format>] FROM <path> [WITH <import_option_list>]
语法元素:
WITH <import_option_list>:
可以使用 WITH 子句传入 IMPORT 选项。
<object_name_list> ::= <object_name>,... | ALL
<import_format> ::= BINARY | CSV
<path> ::= 'FULL_PATH'
<import_option_list> ::= <import_option> | <import_option_list> <import_option>
<import_option> ::=
REPLACE |
CATALOG ONLY |
NO DEPENDENCIES |
THREADS <number_of_threads>
描述:
IMPORT
命令导入表、视图、列视图、同义词、序列或者存储过程。临时表的数据和"no logging"表不能使用 IMPORT 导入。
OBJECT_NAME
将导入对象的 SQL 名。欲导入路径中的所有对象,你要使用 ALL 关键字。如果你想将对象导入至指定集合下,你应该使用集合名和星号,如"SYSTEM".“*”。
BINARY | CSV
导入过程可能忽略格式的定义,因为在导入过程中,将自动检测格式。将以导出的同样格式导入。
FULL_PATH
从该服务器路径导入。
注意:当使用分布式系统,FULL_PATH 必须指向一个共享磁盘。如果未指定 REPLACE 选项,在指定目录下存在相同名字的表,将抛出错误。
CATALOG ONLY
使用 CATALOG ONLY 选项,只导入数据库目录,不含有数据。
NO DEPENDENCIES
使用 NO DEPENDENCIES 选项,将不导入已导入对象的相关对象。
THREADS
表示用于并行导入的线程数。
使用的线程数给定 THREADS 数目指定并行导入的对象数,默认为 1。增加数字可能减少导入时间,但也会影响系统性能。
应当考虑如下:
- 对于单个表,THREADS 没有效果。
- 对于视图或者存储过程,应使用 2 个或更多的线程(最多取决于对象数)。
- 对于整个集合,考虑使用多余 10 个线程(最多取决于系统内核数)。 对于整个 BW / ERP 系统(ALL 关键字)的上千张表,数量大的线程是合理的(最多 256)。
系统和监控视图:
你可以使用系统视图 M_IMPORT_BINARY_STATUS 监控导入的进度。
你可以在如下语句中,使用会话 ID 从相应的视图中终止导入会话。
ALTER SYSTEM CANCEL [WORK IN] SESSION 'sessionId'
导入的详细结果存储在本地会话临时表#IMPORT_RESULT。
IMPORT FROM
- 将外部 csv 文件的数据导入至一个已有的表中
语法:
IMPORT FROM [<file_type>] <file_path> [INTO <table_name>] [WITH <import_from_option_list>]
语法元素:
WITH <import_from_option_list>:
可以使用 WITH 子句传入 IMPORT FROM 选项。
<file_path> ::= '<character>...'
<table_name> ::= [<schema_name>.]<identifier>
<import_from_option_list> ::= <import_from_option> | <import_from_option_list> <imp
ort_from_option>
<import_from_option> :: =
THREADS <number_of_threads> |
BATCH <number_of_records_of_each_commit> |
TABLE LOCK |
NO TYPE CHECK |
SKIP FIRST <number_of_rows_to_skip> ROW |
COLUMN LIST IN FIRST ROW |
COLUMN LIST ( <column_name_list> ) |
RECORD DELIMITED BY '<string_for_record_delimiter>' |
FIELD DELIMITED BY '<string_for_field_delimiter>' |
OPTIONALLY ENCLOSED BY '<character_for_optional_enclosure>' |
DATE FORMAT '<string_for_date_format>' |
TIME FORMAT '<string_for_time_format>' |
TIMESTAMP FORMAT '<string_for_timestamp_format>' |
描述:
IMPORT FROM
语句将外部 csv 文件的数据导入至一个已有的表中。
THREADS
:表示可以用于并行导出的线程数。默认值为 1,最大值为 256。
BATCH
:表示每个提交中可以插入的记录数。
THREADS
和 BATCH 可以通过启用并行加载和一次提交多条记录,实现加载的高性能。一般而言, 对于列式表, 10 个并行加载线程以及 10000 条记录的提交频率是比较好的设置。
TABLE LOCK
:锁住表为了更快的导入数据至列式表。如果指定了 NO TYPE CHECK,记录将在插入时,不检查每个字段的类型。
SKIP FIRST <int> ROW
:跳过插入前 n 条记录。
COLUMN LIST IN FIRST ROW
:表示在 CSV 文件中第一行的列。
COLUMN LIST ( <column_name_list> )
:表示将要插入的字段列表。
RECORD DELIMITED BY '<string>'
:表示 CSV 文件中的记录分隔符。
FIELD DELIMITED BY '<string>'
:表示 CSV 文件中的字段分隔符。
OPTIONALLY ENCLOSED BY '<character>'
:表示字段数据的可选关闭符。
DATE FORMAT '<string>'
:表示字符的日期格式。如果 CSV 文件有日期类型,将为日期类型字段使用指定的格式。
TIME FORMAT '<string>'
:表示字符的时间格式。如果 CSV 文件有时间类型,将为时间类型字段使用指定的格式。
TIMESTAMP FORMAT '<string>'
:表示字符的时间戳格式。如果 CSV 文件有时间戳类型,将为日期类型字段使用指定的格式。
例子:
IMPORT FROM CSV FILE '/data/data.csv' INTO "MYSCHEMA"."MYTABLE" WITH RECORD DELIMITED BY
'\n' FIELD DELIMITED BY ',';
踩坑总结
坑1:Hana镜像的SYSTEM用户竟然没有备份的权限,只有导入的权限。
坑2:虽然SYSTEM用户有部分权限的授予权限,但Hana限制当前用户不能为当前用户赋权,导出只能由普通用户执行。
坑3:不像传统数据库SQL那样,hdbsql登录后可以输入英文单引号和双引号,但是这两者并不等同!
以下命令均在数据库服务器所在环境中执行。
导出
(仅首次需要)为用户授备份与导出权限,这里为GCREPORT_PRD用户赋权。
hdbsql -i 90 -d HXE -u SYSTEM -p 'abcdefg'
GRANT BACKUP ADMIN,EXPORT TO GCREPORT_PRD;
\q
登录GCREPORT_PRD用户,执行4线程导出操作。
hdbsql -i 90 -d HXE -u GCREPORT_PRD -p '12345678'
EXPORT GCREPORT_PRD."*" AS BINARY INTO '/hana/mounts/GCREPORT_PRD' WITH REPLACE THREADS 4;
\q
特别注意:
"*"
用得是英文双引号,前边的用户SCHEMA名称也可以用英文双引号包围,不能用单引号!
压缩、迁移与解压
cd /hana/mounts
tar zcf GCREPORT_PRD.tar.gz GCREPORT_PRD
假设已将GCREPORT_PRD.tar.gz移到另一个服务上,解压
cd /hana/mounts
tar zxf GCREPORT_PRD.tar.gz
授权(仅供参考)
chown 12000:79 -R GCREPORT_PRD
导入
使用SYSTEM用户导入就行,这里切换了SCHEMA,由GCREPORT_PRD导入为GCREPORT_TEST。
hdbsql -i 90 -d HXE -u SYSTEM -p 'abcdefg'
IMPORT ALL AS BINARY FROM '/hana/mounts/GCREPORT_PRD' WITH REPLACE RENAME SCHEMA GCREPORT_PRD TO GCREPORT_TEST THREADS 4;
\q
如需使用普通用户导入,则使用SYSTEM用户登录hdbsql为其赋权,执行
GRANT IMPORT TO 用户名;
,然后再使用普通用户登录与导入。
今天的文章就到这里了,如果对你有启发,给我来个点赞、关注呗!
我是Hellxz,下次见!