MatrixGate 常见问题
本文档介绍 MatrixGate 使用中的常见问题。
- MatrixGate 工具介绍详情可见数据加载服务器 MatrixGate
1 数据加载性能低
做数据加载时,发现磁盘 I/O 利用率高,但是加载速度很慢。
问题分析
使用 gpcheckperf 命令看磁盘性能,网络性能,发现磁盘性能仅 80MB/s。
解决方案
加载多块磁盘提升 I/O 性能,将 WAL 和 Data 数据盘分开, 尽可能提升 I/O 性能。
2 failed to acquire resources on on or more segments ,fatal out of memory
mxgate 同时开启加载 30 张表时,出现 OOM 异常。
问题分析
YMatrix 是多进程模式,高并发请求过来,连接数过多,无法分配内存给相应的请求,从而报错。
解决方案
调整 /etc/sysctl.conf
中的内核参数 vm.overcommit_memory = 2
。
调整 mxgate prepared
参数,从 prepared=10
改为 prepared = 5
。
3 mxgate 发生锁等待卡住
问题分析
查看 mxgate 进程状态:
-
mxgate status 查看 mxgate 的进程状态
-
查看是否有数据正常入库
-
也可用通过
ps -ef|grep mxgate
查看 mxgate 的进程状态
查看锁等待信息:
granted
列值为 false
,表示尚未获得锁的进程。可使用如下 SQL 语句查看:
=# CREATE VIEW v_locks_monitor AS
WITH t_wait AS
(
SELECT a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.granted,
a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a.transactionid,a.fastpath,
b.state,b.query,b.xact_start,b.query_start,b.usename,b.datname,b.client_addr,b.client_port,b.application_name
FROM pg_locks a,pg_stat_activity b WHERE a.pid=b.pid AND NOT a.granted
),
t_run AS
(
SELECT a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.granted,
a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a.transactionid,a.fastpath,
b.state,b.query,b.xact_start,b.query_start,b.usename,b.datname,b.client_addr,b.client_port,b.application_name
FROM pg_locks a,pg_stat_activity b WHERE a.pid=b.pid AND a.granted
),
t_overlap AS
(
SELECT r.* FROM t_wait w JOIN t_run r ON
(
r.locktype IS NOT DISTINCT FROM w.locktype AND
r.database IS NOT DISTINCT FROM w.database AND
r.relation IS NOT DISTINCT FROM w.relation AND
r.page IS NOT DISTINCT FROM w.page AND
r.tuple IS NOT DISTINCT FROM w.tuple AND
r.virtualxid IS NOT DISTINCT FROM w.virtualxid AND
r.transactionid IS NOT DISTINCT FROM w.transactionid AND
r.classid IS NOT DISTINCT FROM w.classid AND
r.objid IS NOT DISTINCT FROM w.objid AND
r.objsubid IS NOT DISTINCT FROM w.objsubid AND
r.pid <> w.pid
)
),
t_unionall AS
(
SELECT r.* FROM t_overlap r
UNION ALL
SELECT w.* FROM t_wait w
)
SELECT locktype,datname,relation::regclass,page,tuple,virtualxid,transactionid::text,classid::regclass,objid,objsubid,
string_agg(
'Pid: '||CASE WHEN pid IS NULL THEN 'NULL' ELSE pid::text END||chr(10)||
'Lock_Granted: '||CASE WHEN granted IS NULL THEN 'NULL' ELSE granted::text END||' , Mode: '||CASE WHEN mode IS NULL THEN 'NULL' ELSE mode::text END||' , FastPath: '||CASE WHEN fastpath IS NULL THEN 'NULL' else fastpath::text END||' , VirtualTransaction: '||CASE WHEN virtualtransaction IS NULL THEN 'NULL' else virtualtransaction::text END||' , Session_State: '||CASE WHEN state IS NULL THEN 'NULL' else state::text END||chr(10)||
'Username: '||CASE WHEN usename IS NULL THEN 'NULL' else usename::text END||' , Database: '||CASE WHEN datname IS null THEN 'NULL' else datname::text END||' , Client_Addr: '||CASE WHEN client_addr IS NULL THEN 'NULL' else client_addr::text END||' , Client_Port: '||CASE WHEN client_port IS NULL THEN 'NULL' else client_port::text END||' , Application_Name: '||CASE WHEN application_name IS NULL THEN 'NULL' else application_name::text END||chr(10)||
'Xact_Start: '||CASE WHEN xact_start IS NULL THEN 'NULL' else xact_start::text END||' , Query_Start: '||CASE WHEN query_start IS NULL THEN 'NULL' else query_start::text END||' , Xact_Elapse: '||CASE WHEN (now()-xact_start) IS NULL THEN 'NULL' else (now()-xact_start)::text END||' , Query_Elapse: '||CASE WHEN (now()-query_start) IS NULL THEN 'NULL' else (now()-query_start)::text END||chr(10)||
'SQL (Current SQL in Transaction): '||chr(10)||
CASE WHEN query IS NULL THEN 'NULL' else query::text END,
chr(10)||'--------'||chr(10)
ORDER BY
( CASE mode
WHEN 'INVALID' THEN 0
WHEN 'AccessShareLock' THEN 1
WHEN 'RowShareLock' THEN 2
WHEN 'RowExclusiveLock' THEN 3
WHEN 'ShareUpdateExclusiveLock' THEN 4
WHEN 'ShareLock' THEN 5
WHEN 'ShareRowExclusiveLock' THEN 6
WHEN 'ExclusiveLock' THEN 7
WHEN 'AccessExclusiveLock' THEN 8
ELSE 0
END ) DESC,
(CASE WHEN granted THEN 0 ELSE 1 END)
) AS lock_conflict
FROM t_unionall
GROUP BY
locktype,datname,relation,page,tuple,virtualxid,transactionid::text,classid,objid,objsubid ;
查看特定表名锁信息, 如果有其他处于 idle in transaction
的进程,则找到 mppsessionid
:
=# SELECT * FROM pg_locks WHERE relation='t1_p'::regclass;
locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | g
ranted | fastpath | mppsessionid | mppiswriter | gp_segment_id
----------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+--------+------------------+--
-------+----------+--------------+-------------+---------------
relation | 693089 | 2693588 | | | | | | | | 23/40692 | 100289 | RowExclusiveLock | t
| t | 37099 | t | -1
relation | 693089 | 2693588 | | | | | | | | 33/198609 | 100676 | AccessShareLock | t
| t | 37099 | t | 4
relation | 693089 | 2693588 | | | | | | | | 33/198609 | 100676 | RowExclusiveLock | t
| t | 37099 | t | 4
(3 rows)
查看事务是否处于 waiting
状态:
[mxadmin@sdw21 gpconfigs]$ gpssh -f ./seg_host
=> ps -ef|grep 37099
[sdw18] mxadmin 213588 152755 0 21:19 ? 00:00:00 postgres: 8000, mxadmin test 192.168.100.32(31024) con37099 seg8 idle
[sdw18] mxadmin 213589 152762 0 21:19 ? 00:00:00 postgres: 8001, mxadmin test 192.168.100.32(20614) con37099 seg9 idle
[sdw18] mxadmin 213590 152766 0 21:19 ? 00:00:00 postgres: 8002, mxadmin test 192.168.100.32(22542) con37099 seg10 idle
[sdw18] mxadmin 213591 152778 0 21:19 ? 00:00:00 postgres: 8003, mxadmin test 192.168.100.32(45560) con37099 seg11 idle
[sdw18] mxadmin 213592 152782 0 21:19 ? 00:00:00 postgres: 8004, mxadmin test 192.168.100.32(27438) con37099 seg12 idle
[sdw18] mxadmin 213593 152788 0 21:19 ? 00:00:00 postgres: 8005, mxadmin test 192.168.100.32(47258) con37099 seg13 idle
[sdw18] mxadmin 213594 152791 0 21:19 ? 00:00:00 postgres: 8006, mxadmin test 192.168.100.32(62898) con37099 seg14 idle
[sdw18] mxadmin 213966 212889 0 21:20 pts/2 00:00:00 grep --color=auto 37099
[sdw19] mxadmin 236149 203253 0 21:19 ? 00:00:00 postgres: 8000, mxadmin test 192.168.100.32(27718) con37099 seg16 idle
[sdw19] mxadmin 236150 203248 0 21:19 ? 00:00:00 postgres: 9007, mxadmin test 192.168.100.32(37320) con37099 seg15 idle
[sdw19] mxadmin 236151 203267 0 21:19 ? 00:00:00 postgres: 8003, mxadmin test 192.168.100.32(64854) con37099 seg19 idle
[sdw19] mxadmin 236152 203263 0 21:19 ? 00:00:00 postgres: 8002, mxadmin test 192.168.100.32(65230) con37099 seg18 idle
[sdw19] mxadmin 236153 203257 0 21:19 ? 00:00:00 postgres: 8001, mxadmin test 192.168.100.32(40968) con37099 seg17 idle
[sdw19] mxadmin 236154 203269 0 21:19 ? 00:00:00 postgres: 8004, mxadmin test 192.168.100.32(54360) con37099 seg20 idle
[sdw19] mxadmin 236155 203278 0 21:19 ? 00:00:00 postgres: 8005, mxadmin test 192.168.100.32(41424) con37099 seg21 idle
[sdw19] mxadmin 236156 203279 0 21:19 ? 00:00:00 postgres: 8006, mxadmin test 192.168.100.32(41532) con37099 seg22 idle
[sdw19] mxadmin 236157 203280 0 21:19 ? 00:00:00 postgres: 8007, mxadmin test 192.168.100.32(23184) con37099 seg23 idle
[sdw19] mxadmin 236295 235047 0 21:20 pts/1 00:00:00 grep --color=auto 37099
[sdw20] mxadmin 188516 35758 0 21:19 ? 00:00:00 postgres: 8000, mxadmin test 192.168.100.32(47346) con37099 seg24 idle
[sdw20] mxadmin 188517 35773 0 21:19 ? 00:00:00 postgres: 8003, mxadmin test 192.168.100.32(59058) con37099 seg27 idle
[sdw20] mxadmin 188518 35779 0 21:19 ? 00:00:00 postgres: 8004, mxadmin test 192.168.100.32(58736) con37099 seg28 idle
[sdw20] mxadmin 188519 35767 0 21:19 ? 00:00:00 postgres: 8002, mxadmin test 192.168.100.32(11736) con37099 seg26 idle
[sdw20] mxadmin 188520 35783 0 21:19 ? 00:00:00 postgres: 8005, mxadmin test 192.168.100.32(45638) con37099 seg29 idle
[sdw20] mxadmin 188521 35760 0 21:19 ? 00:00:00 postgres: 8001, mxadmin test 192.168.100.32(52888) con37099 seg25 idle
[sdw20] mxadmin 188522 35784 0 21:19 ? 00:00:00 postgres: 8006, mxadmin test 192.168.100.32(42540) con37099 seg30 idle
[sdw20] mxadmin 188523 35785 0 21:19 ? 00:00:00 postgres: 8007, mxadmin test 192.168.100.32(41324) con37099 seg31 idle
[sdw20] mxadmin 188650 187294 0 21:20 pts/1 00:00:00 grep --color=auto 37099
解决方案
-
如果确实发现处于
waiting
的事务,或者事务一直没有完成,尽管拿到的是行级锁,也会影响自动创建子分区。 -
找到具体的 pid ,然后通过
SELECT pg_terminate_backend(pid);
语句杀掉此进程。 -
plpython UDF 不接受 kill 信号。
-
建议采用
kill -3
杀掉进程,最好不要用 kill -9。
4 mxgate 排除某一列
命令行使用时,通过参数 --exclude-columns
排除指定的列即可, 如是以后台运行模式,则在配置文件修改参数 exclude-columns=["列名"]
, 重启生效即可。
示例
以命令的方式进行加载 CSV 文件(有表头),采用 tail -n +2
命令排除第一列。
$ tail -n +2 /home/mxadmin/workspace/nyc-taxi-data/yellow_tripdata_2016-01.csv | mxgate --source stdin --db-database postgres --db-master-host mdw --db-master-port 5432 --db-user mxadmin --time-format raw --target trip --parallel 256 --delimiter ',' --exclude-columns trip_duration
5 mxgate 流式加载增加列不停服的办法
- 准备测试数据
// 建表
CREATE TABLE t1(id int,a int);
// 生成测试数据
INSERT INTO t1 SELECT i,i FROM generate_series(1,10) AS i;
// 导出到文件
COPY t1 TO '/home/mxadmin/data/t1.csv' WITH delimiter '|';
// 清空
TRUNCATE TABLE t1;
- 生成配置文件
$ mxgate config --db-database postgres \
--db-master-host localhost \
--db-master-port 6432 \
--db-user mxadmin \
--target public.t1 \
--time-format raw \
--delimiter '|' \
> mxgate.conf
- 启动 mxgate
$ mxgate start --config mxgate.conf
******************************************************
__ __ _ _ ____ _
| \/ | __ _| |_ _ __(_)_ __/ ___| __ _| |_ ___
| |\/| |/ _` | __| '__| \ \/ / | _ / _` | __/ _ \
| | | | (_| | |_| | | |> <| |_| | (_| | || __/
|_| |_|\__,_|\__|_| |_/_/\_\\____|\__,_|\__\___|
Version: v4.6.5+Dev (git: master 4f01c039)
Your Copy is Licensed to: http://www.ymatrix.cn
******************************************************
Launching MatrixGate daemon...
MatrixGate daemon started successfully
- 加载数据
curl http://localhost:8086/ -X POST -H 'Content-Type: text/plain' --data-binary "@t1.csv"
- 查看数据
postgres=# SELECT * FROM t1;
id | a
-----+-----
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
- 暂停 mxgate
指定进程 pid 暂停。
$ mxgate pause -X -S -p 133478
指定 job 名称 schema.table 暂停。
$ mxgate pause -X -S --job public.t1
pause 默认是异步的,这时还有行排他锁。如果要添加字段,会等待行排他锁结。
加上 -S
参数,就代表是暂停 mxgate 进程是同步执行的。
输出如下:
******************************************************
__ __ _ _ ____ _
| \/ | __ _| |_ _ __(_)_ __/ ___| __ _| |_ ___
| |\/| |/ _` | __| '__| \ \/ / | _ / _` | __/ _ \
| | | | (_| | |_| | | |> <| |_| | (_| | || __/
|_| |_|\__,_|\__|_| |_/_/\_\\____|\__,_|\__\___|
Version: v4.6.5+Dev (git: master 4f01c039)
Your Copy is Licensed to: http://www.ymatrix.cn
******************************************************
begin to pause all jobs, please wait...
public.t1 paused
暂停 mxgate 任务时,会将 web 外部表的定义删除。
- 增加一个字段
=# ALTER TABLE t1 ADD COLUMN b int;
- 重新启动指定的任务
$ mxgate resume -R --job public.t1
恢复 mxgate 进程时,会再次创建外部表。
- 加载数据
$ curl http://localhost:8086/ -X POST -H 'Content-Type: text/plain' --data-binary "@t1.csv"
数据加载正常。
6 mxgate socket 文件缺失?
正常情况下 socket 文件如下:
$ cat /tmp/.s.MXGATED.4329.17056.lock
## This mxgate process is part of MatrixDB internal tools
90969
/var/log/matrixdb/matrixgate.2022-09-15_093212-90969.log
0
4329.17056
17056
/tmp/mxgate.conf
经过排查,是 /tmp/.s.MXGATED.8086.0.lock
文件如果长时间没有被使用,文件可能会被系统删除。
解决方案
$ ps -ef |grep mxgate
mxadmin 59272 277634 0 11:57 pts/1 00:00:00 grep --color=auto mxgate
mxadmin 68731 1 40 Jan27 ? 7-11:13:10 /opt/ymatrix/matrixdb-5.0.0+enterprise/bin/mxgated daemon --config mxgate_chj_iot.conf
$ kill 68731
$ touch /tmp/.s.MXGATED.8086.0.lock
$ cat /tmp/.s.MXGATED.8086.0.lock # 内容不重要,关键是文件要有 6 行
336941
$ wc -l /tmp/.s.MXGATED.8086.0.lock
6 /tmp/.s.MXGATED.8086.0.lock
$ chmod 644 .s.MXGATED.8086.0.lock
$ mxgate status
******************************************************
__ __ _ _ ____ _
| \/ | __ _| |_ _ __(_)_ __/ ___| __ _| |_ ___
| |\/| |/ _` | __| '__| \ \/ / | _ / _` | __/ _ \
| | | | (_| | |_| | | |> <| |_| | (_| | || __/
|_| |_|\__,_|\__|_| |_/_/\_\\____|\__,_|\__\___|
Version: v4.3.13 (git: HEAD cef61ced)
Your Copy is Licensed to: yMatrix.cn; 2022-04-13; any
******************************************************
PID 336941 alive
Launched At 2022-01-28 21:08:16
Up For 18 days 0 hours 39 minutes 15 seconds
Binary /opt/ymatrix/matrixdb-5.0.0+enterprise/bin/mxgated
Log
Config
7 data format error: invalid input syntax for type integer: "1970-01-01 00:00:01"
问题分析
mxgate 设计之初主要是为了快速加载时序类数据,默认第一列为时间类型。
解决方案
mxgate 中的参数 time-format
默认为 unix-second
,将其改为 raw
即可。
8 mxgate 入库时间字段默认值相差 8 小时
问题分析
mxgate 在参数 time-format
默认为 unix-second
,会导致入数相差 8 小时。
解决方案
mxgate 中的参数 time-format
默认为 unix-second
,将其改为 raw
即可。
9 Aborting operation regardless of REJECT LIMIT value, last error was: invalid input syntax for type timestamp: ""22:31:01"", column batch_num
问题分析
mxgate 数据加载,源端和目标端数据类型不一致报错。
表结构。
=# CREATE TABLE s1.test1
id character varying(36),
created_date_time timestamp(6) without time zone ,
modified_date_time timestamp(6) without time zone ,
substep character varying(36) ,
substep_id character varying(6) ,
txdate date ,
batch_num time(0) without time zone
)
DIETRIBUTED BY (id)
执行命令。
$ mxgate --source transfer --src-host 172.26.14.15 --src-port 5432 --src-db wdp --src-user user1 --src-password password1 --src-schema s1 --src-table test1 --compress "gzip" --port-base 9000 --local-ip 172.26.14.17 --db-master-host 172.26.14.17 --db-database wdp --target s1.test1 --format csv --time-format raw --use-auto-increment=false
后台 Segment 报错日志。
"Aborting operation regardless of REJECT LIMIT value, last error was: invalid input syntax for type timestamp: ""22:31:01"", column batch_num",
解决方案
将目标端的 batch_num
修改为time(0) without time zone
类型,两边的数据类型需要保持一致。
10 ERROR c.s.o.matrixdb.MatrixdbSource 77 -MatrixdbSource sendingPostRequest errorCode: 400, errorMsg: target table name is empty
问题分析
在通过 HTTP 方式写入 mxgate 时提示表为空。
解决方案
- 检查 HTTP 写入时的表填写是否正确。
- 查看
mxgate.conf
配置文件中表名与数据库中的表是否正确。
11 responseCode:500 errorMsg: ERROR: invalid byte sequence for encoding "UTF8": 0x81
问题分析
在通过 HTTP 方式写入 mxgate 时提示编码错误。
解决方案
请检查源数据中是否有 ASCII 符号。
12 body size exceeds the given limit
问题分析
在通过 HTTP 方式写入 mxgate 时发送的数据量超过了 max-body-bytes
的限制,默认值是 4M
,可以在 mxgate.conf
配置文件中查看。
解决方案
按需修改 mxgate.conf
的 max-body-bytes
大小,然后进行重启。
13 you license is expired 2022-11-02
启动 MatrixGate 报错:
you license is expired 2022-11-02
问题分析
License 授权到期。
解决方案
首先,向 YMatrix 售后技术人员或者销售人员申请新的 License。
然后,在所有节点上将老的 License 文件删除。
$ cd /opt/ymatrix/matrixdb5/bin
$ rm LICENSE_${OLD}
在所有节点上将新的 License 文件上传到 /opt/ymatrix/matrixdb5/bin
,并授予 755 权限。
$ chmod 755 LICENSE_${NEW}
14 使用 MatrixGate 迁移数据报错:Cannot start source: --local-ip localhost is not a valid IP address
问题分析
使用 mxgate 迁移数据报错。
迁移代码:
[mxadmin@mdw ~]$ mxgate --source transfer \
--src-host localhost \
--src-port 5432 \
--src-db mxdb_poc \
--src-user mxadmin \
--src-password 123123 \
--src-schema public \
--src-table t_hash \
--compress "lz4" \
--port-base 9393 \
--local-ip localhost \
--db-database mxdb_poc \
--db-user mxadmin \
--db-password 123123 \
--target public.t_hash_new \
--format csv \
--parallel 256 \
--stream-prepared 0 \
--interval 250 \
--time-format raw
报错日志:
main.go:210: 2022-12-24:21:29:43.018 matrixgate:mxadmin:sdw4:023119-[CRITICAL]:-2022-12-24:21:29:43.018 matrixgate:mxadmin:sdw4:023119-[CRITICAL]:-Cannot start source: --local-ip localhost is not a valid IP address
github.com/ymatrix-data/go-common-libs/utils/logger.FatalOnError
/home/runner/go/pkg/mod/github.com/ymatrix-data/go-common-libs@v1.12.4/utils/logger/logger.go:395
main.failQuit.func1
/home/runner/work/matrixdb-ci/matrixdb-ci/src/bin/mxgated/main.go:210
sync.(*Once).doSlow
/opt/hostedtoolcache/go/1.19.2/x64/src/sync/once.go:74
sync.(*Once).Do
/opt/hostedtoolcache/go/1.19.2/x64/src/sync/once.go:65
main.failQuit
/home/runner/work/matrixdb-ci/matrixdb-ci/src/bin/mxgated/main.go:207
main.main
/home/runner/work/matrixdb-ci/matrixdb-ci/src/bin/mxgated/main.go:113
runtime.main
/opt/hostedtoolcache/go/1.19.2/x64/src/runtime/proc.go:250
runtime.goexit
/opt/hostedtoolcache/go/1.19.2/x64/src/runtime/asm_amd64.s:1594
exit status 1
解决方案
将迁移模式当中的参数 --local-ip
改写成实际的物理 IP 地址,例如:192.168.247.132。
改写后的迁移代码如下:
[mxadmin@mdw ~]$ mxgate --source transfer \
--src-host localhost \
--src-port 5432 \
--src-db mxdb_poc \
--src-user mxadmin \
--src-password 123123 \
--src-schema public \
--src-table t_hash \
--compress "lz4" \
--port-base 9393 \
--local-ip 192.168.247.132 \
--db-database mxdb_poc \
--db-user mxadmin \
--db-password 123123 \
--target public.t_hash_new \
--format csv \
--parallel 256 \
--stream-prepared 0 \
--interval 250 \
--time-format raw
15 使用 MatrixGate 数据加载表数据存在双引号
问题分析
我们可以通过创建测试表来分析此问题。具体步骤如下:
- 创建测试表
[mxadmin@mdw ~]$ psql -d mxdb
mxdb=# CREATE TABLE public.test(order_no text,info text) DIETRIBUTED BY(order_no);
- 查看测试数据
[mxadmin@mdw ~]$ cat test.csv
"1x01"|"A"
"1x02"|"B"
"2x01"|"C"
"2x02"|"D"
"3x01"|"E"
"3x02"|"F"
- 使用 MatrixGate 执行数据加载命令
[mxadmin@mdw ~]$ cat test.csv| \
mxgate --source stdin \
--db-database mxdb_poc \
--db-master-host 127.0.0.1 \
--db-master-port 5432 \
--db-user mxadmin \
--db-password 123123 \
--time-format raw \
--delimiter "|" \
--target public.test \
--parallel 256 \
--stream-prepared 0 \
--interval 250
- 查看数据表里面的数据,发现存在双引号,问题得到复现
mxdb=# SELECT * FROM test;
order_no | info
----------+------
"1x01" | "A"
"1x02" | "B"
"3x01" | "E"
"2x01" | "C"
"2x02" | "D"
"3x02" | "F"
(6 rows)
而我们想要的理想结果应当如下:
mxdb=# SELECT * FROM test;
order_no | info
----------+------
1x01 | A
1x02 | B
2x01 | C
2x02 | D
3x01 | E
3x02 | F
(6 rows)
解决方案
执行数据加载的时候,加上参数 --format csv
。
[mxadmin@mdw ~]$ cat test.csv| \
mxgate --source stdin \
--db-database mxdb_poc \
--db-master-host 127.0.0.1 \
--db-master-port 5432 \
--db-user mxadmin \
--db-password 123123 \
--time-format raw \
--format csv \
--delimiter "|" \
--target public.test \
--parallel 256 \
--stream-prepared 0 \
--interval 250
这时,再查看数据表里面的数据,得到理想结果。
mxdb=# SELECT * FROM test;
order_no | info
----------+------
1x01 | A
1x02 | B
2x01 | C
2x02 | D
3x01 | E
3x02 | F
(6 rows)
16 MatrixGate 升级
问题描述
MatrixGate 在使用过程中因为特殊原因需要升级,但不知如何操作。
解决方案
-
将 MatrixGate 的写入程序关闭。
-
使用 mxadmin 用户将 MatrixGate 启动的 HTTP 服务停止。
[root@mdw ~]# su - mxadmin
[mxadmin@mdw ~]$ mxgate stop
- 使用 root 用户,关闭 Supervisor 服务。
[root@mdw ~]# systemctl stop matrixdb.supervisor.service
- 使用 root 用户,替换 MatrixGate 二进制文件。
首先,进入到 /bin
目录。
[root@mdw ~]# cd /usr/local/matrixdb/bin/
然后,将原来的二进制 MatrixGate 文件备份。
[root@mdw ~]# mv mxgate mxgate."bak."`date +%Y%m%d%H%M`
[root@mdw ~]# mv mxgated mxgated."bak."`date +%Y%m%d%H%M`
将新的 MatrixGate 二进制文件上传到 /usr/local/matrixdb/bin/
, 并赋予 755 权限。
[root@mdw ~]# chmod 755 mxgate
[root@mdw ~]# chmod 755 mxgated
最后,查看替换后的版本信息。
[root@mdw ~]# su - mxadmin
[mxadmin@mdw ~]$ mxgate --version
- 使用 root 用户,启动 Supervisor 服务。
[root@mdw ~]# systemctl start matrixdb.supervisor.service
- 启动 MatrixGate。
[root@mdw ~]# su - mxadmin
[mxadmin@mdw ~]$ mxgate start --config /home/mxadmin/mxgate.conf
- 启动 MatrixGate 前端的数据写入业务。
17 MatrixGate 需要加载包含 unix 时间数据的数据文件,但数据文件中 unix 数据所在的字段不是第一个字段
问题描述
使用 MatrixGate 加载 unix 时间数据,但数据文件中 unix 数据所在的字段不是第一个字段,因无法进行类型转换而报错。 我们可以通过创建测试表来复现并分析此问题。示例如下:
- 创建测试表
[mxadmin@mdw ~]$ psql testdb
testdb=# CREATE TABLE dest2(
c1 int,
c2 text,
time timestamp,
c3
)DISTRIBUTED BY(c1);
- 准备测试数据
[mxadmin@mdw ~]$ cat test2.csv
1,2,1603777821678,2
1,2,1603777822670,3
1,2,1603777823628,4
1,2,1603777824673,5
1,2,1603777825578,6
- 执行 MatrixGate 数据加载命令
[mxadmin@mdw ~]$ cat test2.csv| \
mxgate \
--source stdin \
--db-database testdb \
--db-master-host mdw \
--db-master-port 5432 \
--db-user mxadmin \
--time-format unix-ms \
--target dest2 \
--delimiter ',' \
--parallel 256 \
--stream-prepared 0
报错信息如下:
stdin.go:168: 2022-04-15:12:38:52.443 matrixgate:mxadmin:mdw:006560-[ERROR]:-[Source.STDIN] load error: data format error: invalid input syntax for type integer: "1970-01-01 00:00:00.001", column c1
问题分析
MatrixGate 默认把第一个字段当成时间字段进行转换。
解决方案
-
版本要求 MatrixGate v4.4.7 及更高版本。
-
生成 mxgate 配置文件
[mxadmin@mdw ~]$ mxgate config --db-database testdb \ --db-master-host localhost \ --db-master-port 5432 \ --db-user mxadmin \ --target public.dest2 \ --format csv \ --time-format unix-ms \ --delimiter ',' \ --parallel 256 \ --stream-prepared 0 \ --interval 250 \ --transform plain \ --source stdin \ > mxgate.conf
-
修改 mxgate 配置文件
[mxadmin@mdw ~]$ vi mxgate.conf #找到对应的地方进行修改 [[job.target]] # deduplicate-key = [] delimiter = "," # error-handling = "accurate" # exclude-columns = [] format = "csv" name = "job_csv_to_public.dest2" # null-as = "" schema = "public" table = "dest2" time-format = "unix-ms" # upsert-key = [] # use-auto-increment = true #找到对应的地方进行修改 transform = "plain" [transform.plain] mapping = [ # secondsToTimestamp 秒级时间戳转换 1603777825 => 2020-10-27 05:50:25 # millisecondsToTimestamp 毫秒级时间戳转换 1603777825123 => 2020-10-27 05:50:25.123 # microsecondsToTimestamp 微秒级时间戳转换 1603777825123456 => 2020-10-27 05:50:25.123456 # nanosecondsToTimestamp 纳秒级时间戳转换 1603777825123456789 => 2020-10-27 05:50:25.123457(注意:目前数据库只支持到微秒级时间戳精度,纳秒级时间戳会失真) {table-name = "public.dest2", field-map = [{dest = "c1", source = "0", enabled = true}, {dest = "c2", source = "1", enabled = true}, {dest = "ts", source = "2", enabled = true,transform = ["millisecondsToTimestamp"]}, {dest = "c3", source = "3", enabled = true}, ]} ]
-
配置说明
- table-name = "public.dest2" 指定表名;
- dest对应数据库每一列中的列名;
- source表示从进入mxgate的数据源获取dest对应列的方式:
- plain:进入 MatrixGate 的是csv数据,对应的source表示csv中的某一列的列号;
- json:进入 MatrixGate 的是JSON数据,对应的source是从一个JSON结构中获取dest对应值的JSON-Path表达式(关于JSON-Path可以参考这个文档JSON Path相关资料汇总 )
- enable=true表示该列数据需要通过 MatrixGate 写入到数据库,如果为false,则不写入;
- transform表示时间戳精度的转换函数:
- secondsToTimestamp:秒级时间戳转换
- millisecondsToTimestamp:毫秒级时间戳转换
- microsecondsToTimestamp:微秒级时间戳转换
- nanosecondsToTimestamp:纳秒级时间戳转换
注意
目前数据库只支持到微秒级时间戳精度,纳秒级时间戳会失真。
- 执行加载
[mxadmin@mdw ~]$ tail -n +2 test2.csv| mxgate --config mxgate.conf
18 MatrixGate 加载数据文件中有 \N
字符
问题分析
我们可以通过创建测试表来复现并分析此问题。示例如下:
- 创建测试表
[mxadmin@mdw ~]$ psql -d mxdb
mxdb=# CREATE TABLE test(f1 int,f2 varchar(50),f3 varchar(50));
- 查看测试数据
[mxadmin@mdw ~]$ cat test.csv
1|test|\N
- 使用 MatrixGate 执行数据加载命令
[mxadmin@mdw ~]$ cat test.csv| \
mxgate --source stdin \
--db-database mxdb_poc \
--db-master-host 127.0.0.1 \
--db-master-port 5432 \
--db-user mxadmin \
--db-password 123123 \
--time-format raw \
--format csv \
--delimiter "|" \
--target public.test \
--parallel 256 \
--stream-prepared 0 \
--interval 250
- 查看数据表里面的数据,存在 N
mxdb=# SELECT * FROM test;
f1 | f2 | f3
----+------+----
1 | test | N
理想结果应当如下:
mxdb=# SELECT * FROM test;
f1 | f2 | f3
----+------+----
1 | test |
解决方案
- 使用 MatrixGate 执行数据加载,加上参数 --null-as '\N'
[mxadmin@mdw ~]$ cat test.csv| \
mxgate --source stdin \
--db-database mxdb_poc \
--db-master-host 127.0.0.1 \
--db-master-port 5432 \
--db-user mxadmin \
--db-password 123123 \
--time-format raw \
--format csv \
--delimiter "|" \
--target public.test \
--parallel 256 \
--stream-prepared 0 \
--interval 250 \
--null-as '\N'
- 查看数据表里面的数据,得到理想结果
mxdb=# SELECT * FROM test;
f1 | f2 | f3
----+------+----
1 | test |
19 MatrixGate 通过迁移模式写入时出现 Handshaking was terminated on port XXX
问题分析
根据错误描述,初步确定是 SSH 握手中断导致。
继续排查源端数据库日志出现 lz4 | COPY XXX TO PROGRAM ssh -o StrictHostKeyChecking=no -p XXX
这样的报错,发现源端的操作系统是 Redhat 8.3,默认没有安装 lz4 软件包,导致 lz4 命令不识别,但是在写入命令有 --compress lz4
参数,所以导致报错。
解决方案
- 源端操作系统安装 lz4 软件包。
- 写入命令中去掉
--compress lz4
或者将参数调整为--compress zstd
。
20 MatrixGate 可以实现任意列时间戳转换吗?
可以的。
注意!
此功能只在 MatrixGate v4.4.7 及更高版本支持。
- 数据库表结构样例
[mxadmin@mdw ~]$ psql testdb
testdb=# CREATE TABLE vehicle_basic_data_mars2(
daq_time timestamp,
vin varchar(32) ,
lng float ,
lat float ,
speed float ,
license_template varchar(16) ,
flag integer
);
Table "public.vehicle_basic_data_mars2"
Column | Type | Collation | Nullable | Default
------------------+-----------------------------+-----------+----------+---------
daq_time | timestamp without time zone | | |
vin | character varying(32) | | |
lng | double precision | | |
lat | double precision | | |
speed | double precision | | |
license_template | character varying(16) | | |
flag | integer | | |
- mxgate config 文件配置
- 在 [transform]tag 下,首先配置 transform 的类型:
- transform = "json":进入mxgate 的数据格式是 JSON;
- transform = "plain":进入 mxgate 的数据格式是 CSV。
[transform] ## Overall parallel level for transform, only for non-strict mode # parallel = 16 ## Transform decodes input data and perform type/format conversion ## Types restricted to: plain/json/nil/tsbs # transform = "json" # [transform.json] # mapping = [ # # secondsToTimestamp # # millionSecondsToTimestamp # # microsecondsToTimestamp # # nanosecondsToTimestamp # {table-name = "public.vehicle_basic_data_mars2", field-map = [{dest = "daq_time", source = "$.daq_time", enabled = true}, # {dest = "vin", source = "$.vin", enabled = true}, # {dest = "lng", source = "$.lng", enabled = true}, # {dest = "lat", source = "$.lat", enabled = true}, # {dest = "speed", source = "$.speed", enabled = true}, # {dest = "license_template", source = "$.license_template"}, # {dest = "flag", source = "$.flag", enabled = true}, # ]} # ] transform = "plain" [transform.plain] mapping = [ # secondsToTimestamp # milliSecondsToTimestamp # microsecondsToTimestamp # nanosecondsToTimestamp {table-name = "public.vehicle_basic_data_mars2", field-map = [{dest = "daq_time", source = "0", enabled = true, transform = ["secondsToTimestamp"]}, {dest = "vin", source = "1", enabled = true}, {dest = "lng", source = "2", enabled = true}, {dest = "lat", source = "3", enabled = true}, {dest = "speed", source = "4", enabled = true}, {dest = "license_template", source = "5"}, {dest = "flag", source = "6", enabled = true}, ]} ]
- 配置说明:
- table-name = "public.vehicle_basic_data_mars2" 指定表名;
- dest 对应数据库每一列中的列名;
- source 表示从进入 mxgate 的数据源获取 dest 对应列的方式:
- plain:进入 mxgate 的是 CSV 数据,对应的 source 表示 CSV 中的某一列的列号;
- json:进入 mxgate 的是 JSON 数据,对应的 source 是从一个 JSON 结构中获取 dest 对应值的 JSON-Path 表达式;
- enable=true 表示该列数据需要通过 mxgate 写入到数据库,如果为
false
,则不写入; - transform 表示时间戳精度的转换函数:
- secondsToTimestamp:秒级时间戳转换
- milliSecondsToTimestamp:毫秒级时间戳转换
- microsecondsToTimestamp:微秒级时间戳转换
- nanosecondsToTimestamp:纳秒级时间戳转换
注意!
目前数据库只支持到微秒级时间戳精度,纳秒级时间戳会失真。
- 注意事项
(1). format 配置为 CSV
- 全局 format 配置
## Data format to be read: text or csv ## text : faster but cannot have delimiter or line breaks in textual fields ## csv : supports delimiter or line break in textual fields, must be double-quoted format = "csv"
- Job format 配置
## Schema and table name must be in lower-case [[job.target]] # delimiter = "|" format = "csv" name = "public.vehicle_basic_data_mars2" schema = "public" table = "vehicle_basic_data_mars2" time-format = "raw"
(2). mapping 中,数据库的每一列都需要配置,不能只配置需要时间戳转换的列,如果有哪一列没有配置,则该列的数据无法写入到 YMatrix。
(3). 原来的 time-format 需要配置为raw
。
(4). 支持同时配置多列时间戳转换。
(5). 对于 transform 中json
或者plain
的配置,同一个 mxgate 进程同一时间只能配置一个。
21 MatrixGate JAVA SDK JAR 包可以下载到本地导入吗?
可以的。
首先,点击下载 SDK 最新版本,按照如下图示操作,图示中为 v1.0.17,按照图示步骤替换为最新版本即可。
在此介绍三种导入本地 JAR 包的方法:使用 Maven 工具,使用 Gradle 工具,以及使用 IntelliJ IDEA 集成开发环境,任选其一即可。导入方法多元,你也完全可以选用其他开发环境和工具使操作更为顺手。
- 使用 Maven 工具
随后,在 pom.xml
文件中配置如下内容:
<!-- 在 pom.xml 文件中配置 -->
<dependencies>
...
<dependency>
<groupId>cn.ymatrix</groupId>
<artifactId>mxgate-sdk-java</artifactId>
<version>1.0</version>
<scope>system</scope>
<!-- systemPath中填入 JAR 包的绝对路径, 这里 ${project.basedir} 指的是当前 project 文件夹路径 -->
<systemPath>${project.basedir}/lib/mxgate-sdk-java-1.0.jar</systemPath>
</dependency>
...
</dependencies>
注意!
若你使用 IntelliJ IDEA 集成开发环境操作,可以设置 auto-reloading 自动更新文件。若未设置 auto-reloading,运行完毕新添加代码后,需点击右上角“m”按钮手动更新文件。
最后,为了保障 JAR 包的使用(不会出现 class not found
相关报错),还需要在 pom.xml
中增加以下内容,使得 target 文件夹包含所需依赖。
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<!-- 指定 jdk 版本,与本地一致即可, 若为1.8 则填入8即可-->
<source>8</source>
<target>8</target>
<compilerArguments>
<!-- 指定 local jar 所在目录,下例中在project下lib目录存放local jar -->
<extdirs>${project.basedir}/lib</extdirs>
</compilerArguments>>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifest>
<!-- 在生成jar文件时向MANIFEST.MF中添加 classpath -->
<addClasspath>true</addClasspath>
<!-- 定义上述 classpath 的前缀, 需要与下面 maven-dependency-plugin 的 outputDirectory 一致 -->
<classpathPrefix>lib</classpathPrefix>
<mainClass>Main.Main</mainClass>
</manifest>
<manifestEntries>
<!-- 把 jar 加入到 MANIFEST.MF -->
<Class-Path>lib/mxgate-sdk-java-1.0.jar</Class-Path>
</manifestEntries>>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- 在 maven 产物target目录下生成lib目录,并把所有远程和本地的jar拷贝到该目录下 -->
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
完成。
- 使用 Gradle 工具
假设 JAR 包存放在本地 libs 路径下,使用以下代码导入本地 JAR 包:
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
implementation name: 'cn.ymatrix:mxgate-sdk-java:1.0.17'
}
- 使用 IntelliJ IDEA 集成开发环境
选择本地路径下的 mxgate-sdk-java.jar
文件。
确认 JAR 包已经成功导入到当前工程。
22 Kafka 消费 key
字段包含 @
符号,数据解析找不到 value
问题分析
特殊字符 @
无法正常解析。
问题复现
- 测试数据
{ "@timestamp": "2023-04-21T04:00:23.413+08:00", "@version": "1", "message": ">End--->.<Tid 189> Response(code=330110, description=, responseTime=1682020823413, responseBody=FlowVO(tips=请求异常,请稍后再试, flowData=null, queryTime=1682020823411, errCode=1))", "logger": "com.reachauto.cloud.log.aop.LogAspect", "thread": "XNIO-1 task-3", "level": "DEBUG", "levelVal": 10000, "springAppName": "reachcloud-vsp-sdk-bff-auth", "kafaServer": "test1.com.com:9092,test2.com:9092", "springProfileActive": "test", "callerSource": "auth_sdk", "ydtargs": "[89860803192030000383]", "ydtpath": "/api/v1/flow/query", "ydtuserid": "5816d78e4rh31aa5a3c1bce523a764deea36cfd551fcbdbb8", "callerVersion": "1.30.17", "ydttype": "message", "ydtmethod": "GET", "PtxId": "6883576", "PspanId": "-5187341585210826311", "grayVersion": "unknown", "ydtrequrl": "http://vsp-show-vehicle.reachauto-mobility.com/api/v1/flow/query", "ydttime": "233", "ydtusertype": "VU", "ydtclass": "FlowController.queryFlow(String)", "caller": { "class": "com.reachauto.cloud.log.aop.LogAspect", "method": "around", "file": "LogAspect.java", "line": 99 } }
- 在图形化界面(Mxui)配置对应的 Kafka 数据接入
解决方案
- 在图形化界面配置失败后,找到对应生成的
mxgate.conf
文件。修改对应的transform.json
source = "$.@timestamp" --> source = "$['@timestamp']" source = "$.@Version" --> source = "$['@Version']"
- 在主机层面通过命令行启动服务,
key
字段包含@
符号,数据消费正常。
23 mxgate 迁移模式非 mxadmin 用户提示没有权限
当使用 mxgate 的迁移模式时报错:
Create external table failed: create external table error for public.ddd_back, ERROR: permission denied: no privilege to create a readable gpfdist(s) external table (SQLSTATE 42501), will retry after 3 seconds
问题分析
用户使用 mxgate 迁移模式时需要通过创建外部表来同步数据,而使用非 mxadmin
用户时则没有创建外部表的权限。
解决方案
-
使用 mxgate 迁移模式时,使用
mxadmin
用户,使用mxadmin
用户不会改变原表的权限。 -
给其他用户赋予外部表的权限,或者把其他用户提升为高权限。