背景
本文主要描述導入問題的排查思路和常見問題解決方法。這里簡單闡述下不同導入方式的流程,方便大家理解導入流程和排查問題,具體的可參考文檔導入章節。
排查流程
Stream Load
Stream load內部調用鏈路
Stream Load是一種同步執行的導入方式。用戶通過 HTTP 協議發送請求將本地文件或數據流導入到 StarRocks中,並等待系統返回導入的結果狀態,從而判斷導入是否成功。
不支持在 Docs 外粘貼 block
- 通過返回值判斷
{
"Status":"Fail", "BeginTxnTimeMs":1, "Message":"too many filtered rows", "NumberUnselectedRows":0, "CommitAndPublishTimeMs":0, "Label":"4682d766-0e53-4fce-b111-56a8d8bef390", "LoadBytes":69238389, "StreamLoadPutTimeMs":4, "NumberTotalRows":7077604, "WriteDataTimeMs":4350, "TxnId":33, "LoadTimeMs":4356, "ErrorURL":"http://192.168.10.142:8040/api/_load_error_log?file=__shard_2/error_log_insert_stmt_e44ae406-32c7-6d5c-a807-b05607a57cbf_e44ae40632c76d5c_a807b05607a57cbf", "ReadDataTimeMs":1961, "NumberLoadedRows":0, "NumberFilteredRows":7077604 }
- 返回值Status:非Success,
a. 存在ErrorURL
Curl ErrorURL,例如
curl "http://192.168.10.142:8040/api/_load_error_log?file=__shard_2/error_log_insert_stmt_e44ae406-32c7-6d5c-a807-b05607a57cbf_e44ae40632c76d5c_a807b05607a57cbf"
b.不存在ErrorURL
{
"TxnId":2271727, "Label":"4682d766-0e53-4fce-b111-56a8d8bef2340", "Status":"Fail", "Message":"Failed to commit txn 2271727. Tablet [159816] success replica num 1 is less then quorum replica num 2 while error backends 10012", "NumberTotalRows":1, "NumberLoadedRows":1, "NumberFilteredRows":0, "NumberUnselectedRows":0, "LoadBytes":575, "LoadTimeMs":26, "BeginTxnTimeMs":0, "StreamLoadPutTimeMs":0, "ReadDataTimeMs":0, "WriteDataTimeMs":21, "CommitAndPublishTimeMs":0 }
查看本次導入的load_id和調度到的be節點
grep -w $TxnId fe.log|grep "load id" #輸出例子: 2021-12-20 20:48:50,169 INFO (thrift-server-pool-4|138) [FrontendServiceImpl.streamLoadPut():809] receive stream load put request. db:ssb, tbl: demo_test_1, txn id: 1580717, load id: 7a4d4384-1ad7-b798-f176-4ae9d7ea6b9d, backend: 172.26.92.155
在對應的be節點查看具體原因
grep $load_id be.WARNING|less
Broker Load
用戶在提交導入任務后,FE 會生成對應的 Plan 並根據目前 BE 的個數和文件的大小,將 Plan 分給多個 BE 執行,每個 BE 執行一部分導入任務。BE 在執行過程中會通過 Broker 拉取數據,在對數據預處理之后將數據導入系統。所有 BE 均完成導入后,由 FE 最終判斷導入是否成功。
不支持在 Docs 外粘貼 block
目前一個Broker Load的任務流程會經過PENDING–>LOADING–>FINISHED(或CANCELLED)的流程,當狀態為CANCELLED的時候需要介入排查。
- Show load查看任務狀態,狀態為CANCELLED的時候進一步跟進
- 如果URL不為空,則curl $URL查看具體報錯信息
- 如果URL為空,通過fe日志查看load id和be
- 檢查hdfs文件路徑是否指定正確,可以指定到具體文件也可以指定某目錄下的所有文件
- hdfs導入請檢查一下是否有k8s認證,並進行配置
grep $JobnId fe.log
- be中查看具體異常
grep $load_id be.INFO
ErrorMsg中的type取值:
-
USER-CANCEL: 用戶取消的任務
-
ETL-RUN-FAIL: 在ETL階段失敗的導入任務
-
ETL-QUALITY-UNSATISFIED: 數據質量不合格,也就是錯誤數據率超過了 max-filter-ratio
-
LOAD-RUN-FAIL: 在LOADING階段失敗的導入任務
-
TIMEOUT: 導入任務沒在超時時間內完成
-
UNKNOWN: 未知的導入錯誤
Routine Load
+-----------------+
fe schedule job | NEED_SCHEDULE | user resume job +-----------+ | <---------+ | | | | v +-----------------+ ^ | | +------------+ user(system)pause job +-------+----+ | RUNNING | | PAUSED | | +-----------------------> | | +----+-------+ +-------+----+ | | | | | +---------------+ | | | | STOPPED | | | +---------> | | <-----------+ | user stop job+---------------+ user stop job | | | +---------------+ | | CANCELLED | +-------------> | | system error +---------------+
上圖表示的是routine load的任務狀態機
show routine load for db.job_name
MySQL [load_test]> SHOW ROUTINE LOAD\G;
*************************** 1. row *************************** Id: 14093 Name: routine_load_wikipedia CreateTime: 2020-05-16 16:00:48 PauseTime: 2020-05-16 16:03:39 EndTime: N/A DbName: default_cluster:load_test TableName: routine_wiki_edit State: PAUSED DataSourceType: KAFKA CurrentTaskNum: 0 JobProperties: {"partitions":"*","columnToColumnExpr":"event_time,channel,user,is_anonymous,is_minor,is_new,is_robot,is_unpatrolled,delta,added,deleted","maxBatchIntervalS":"10","whereExpr":"*","maxBatchSizeBytes":"104857600","columnSeparator":"','","maxErrorNum":"1000","currentTaskConcurrentNum":"1","maxBatchRows":"200000"} DataSourceProperties: {"topic":"starrocks-load","currentKafkaPartitions":"0","brokerList":"localhost:9092"} CustomProperties: {} Statistic: {"receivedBytes":162767220,"errorRows":132,"committedTaskNum":13,"loadedRows":2589972,"loadRowsRate":115000,"abortedTaskNum":7,"totalRows":2590104,"unselectedRows":0,"receivedBytesRate":7279000,"taskExecuteTimeMs":22359} Progress: {"0":"13824771"} ReasonOfStateChanged: ErrorReason{code=errCode = 100, msg='User root pauses routine load job'} ErrorLogUrls: http://172.26.108.172:9122/api/_load_error_log?file=__shard_54/error_log_insert_stmt_e0c0c6b040c044fd-a162b16f6bad53e6_e0c0c6b040c044fd_a162b16f6bad53e6, http://172.26.108.172:9122/api/_load_error_log?file=__shard_55/error_log_insert_stmt_ce4c95f0c72440ef-a442bb300bd743c8_ce4c95f0c72440ef_a442bb300bd743c8, http://172.26.108.172:9122/api/_load_error_log?file=__shard_56/error_log_insert_stmt_8753041cd5fb42d0-b5150367a5175391_8753041cd5fb42d0_b5150367a5175391 OtherMsg: 1 row in set (0.01 sec)
當任務狀態為PAUSED或者CANCELLED的時候需要介入排查
任務狀態為PAUSED時:
- 可以先查看ReasonOfStateChanged定位下原因,例如“Offset out of range”
- 若ReasonOfStateChanged為空,查看ErrorLogUrls可查看具體的報錯信息
curl ${ErrorLogUrls}
Spark Load
Insert Into
Insert into也是大家目前遇到問題比較多的導入方式。目前Insert into支持以下兩種方式:
- 方式一:Insert into table values ();
- 方式二:Insert into table1 xxx select xxx from table2
方式一不建議在線上使用
由於insert into導入方式是同步的,執行完會立即返回結果。可以通過返回結果判斷導入成功或失敗。
Flink-connector
寫入StarRocks是封裝的stream load,內部流程可參考Stream Load導入
無法復制加載中的內容
由於Flink-connector底層走的是stream load的方式,所以可以參考stream load排查方式進行。
- 首先從Flink日志中搜索"_stream_load"關鍵字,確認成功發起了stream load任務
- 然后排查搜索對應stream load的label,搜索該label的導入返回結果,如下圖
{
"Status":"Fail", "BeginTxnTimeMs":1, "Message":"too many filtered rows", "NumberUnselectedRows":0, "CommitAndPublishTimeMs":0, "Label":"4682d766-0e53-4fce-b111-56a8d8bef390", "LoadBytes":69238389, "StreamLoadPutTimeMs":4, "NumberTotalRows":7077604, "WriteDataTimeMs":4350, "TxnId":33, "LoadTimeMs":4356, "ErrorURL":"http://192.168.10.142:8040/api/_load_error_log?file=__shard_2/error_log_insert_stmt_e44ae406-32c7-6d5c-a807-b05607a57cbf_e44ae40632c76d5c_a807b05607a57cbf", "ReadDataTimeMs":1961, "NumberLoadedRows":0, "NumberFilteredRows":7077604 }
- 接下來參考stream load排查流程即可
Flink-CDC
寫入StarRocks是封裝的stream load,內部流程可參考Stream Load導入
- Flink任務沒有報錯的時候
第一步:確認binlog是否開啟,可以通過 SHOW VARIABLES LIKE 'log_bin’查看;
第二步:確認flink、flink-cdc、flink-starrocks-connector和mysql版本(MySQL版本為5.7和8.0.X)是否滿足要求,flink、flink-cdc和flink-starrocks-connector的大版本需要一致,例如都是1.13版本
第三步:逐步判斷是查源表還是寫starrocks的問題,這里利用下面的sql文件演示一下,該文件是Flink-cdc中第7步生成的flink-create.1.sql
CREATE DATABASE IF NOT EXISTS `test_db`; CREATE TABLE IF NOT EXISTS `test_db`.`source_tb` ( `id` STRING NOT NULL, `score` STRING NULL, PRIMARY KEY(`id`) NOT ENFORCED ) with ( 'username' = 'root', 'password' = 'xxx', 'database-name' = 'test', 'table-name' = 'test_source', 'connector' = 'mysql-cdc', 'hostname' = '172.26.92.139', 'port' = '8306' ); CREATE TABLE IF NOT EXISTS `test_db`.`sink_tb` ( `id` STRING NOT NULL, `score` STRING NULL PRIMARY KEY(`id`) NOT ENFORCED ) with ( 'load-url' = 'sr_fe_host:8030', 'sink.properties.row_delimiter' = '\x02', 'username' = 'root', 'database-name' = 'test_db', 'sink.properties.column_separator' = '\x01', 'jdbc-url' = 'jdbc:mysql://sr_fe_host:9030', 'password' = '', 'sink.buffer-flush.interval-ms' = '15000', 'connector' = 'starrocks', 'table-name' = 'test_tb' ); INSERT INTO `test`.`sink_tb` SELECT * FROM `test_db`.`source_tb`;
安裝的Flink目錄下執行下面語句進入flink-sql
bin/sql-client.sh
首先驗證讀取source表是否正常
#分別把上面的sql粘貼進來判斷是查詢源表的問題還是寫入到starrocks的問題 CREATE DATABASE IF NOT EXISTS `test_db`; CREATE TABLE IF NOT EXISTS `test_db`.`source` ( `id` STRING NOT NULL, `score` STRING NULL, PRIMARY KEY(`id`) NOT ENFORCED ) with ( 'username' = 'root', 'password' = 'xxx', 'database-name' = 'test', 'table-name' = 'test_source', 'connector' = 'mysql-cdc', 'hostname' = '172.26.92.139', 'port' = '8306' ); #驗證source是否正常 select * from `test_db`.`source_tb`;
再驗證寫入starrocks是否正常
CREATE TABLE IF NOT EXISTS `test_db`.`sink_tb` ( `id` STRING NOT NULL, `score` STRING NULL PRIMARY KEY(`id`) NOT ENFORCED ) with ( 'load-url' = 'sr_fe_host:8030', 'sink.properties.row_delimiter' = '\x02', 'username' = 'root', 'database-name' = 'test_db', 'sink.properties.column_separator' = '\x01', 'jdbc-url' = 'jdbc:mysql://sr_fe_host:9030', 'password' = '', 'sink.buffer-flush.interval-ms' = '15000', 'connector' = 'starrocks', 'table-name' = 'test_tb' ); INSERT INTO `test`.`sink_tb` SELECT * FROM `test_db`.`source_tb`;
- Flink任務出錯
第一步:確認flink集群是否有啟動,可能有的同學本地下載的flink沒有啟動,需要./bin/start-cluster.sh啟動下flink
第二步:根據具體的報錯再具體分析
DataX
寫入StarRocks是封裝的stream load,內部流程可參考Stream Load導入
無法復制加載中的內容
由於DataX底層也是走的stream load方式,所以可以參考stream load排查方式進行。
- 首先從datax/log/YYYY-MM-DD/xxx.log日志中搜索"_stream_load"關鍵字,確認成功發起了stream load任務
A. 如果沒有stream load生成,具體查看datax/log/YYYY-MM-DD/xxx.log日志,分析異常解決
B. 如有stream load生成,在datax/log/YYYY-MM-DD/xxx.log搜索對應stream load的label,搜索該label的導入返回結果,如下圖
{
"Status":"Fail", "BeginTxnTimeMs":1, "Message":"too many filtered rows", "NumberUnselectedRows":0, "CommitAndPublishTimeMs":0, "Label":"4682d766-0e53-4fce-b111-56a8d8bef390", "LoadBytes":69238389, "StreamLoadPutTimeMs":4, "NumberTotalRows":7077604, "WriteDataTimeMs":4350, "TxnId":33, "LoadTimeMs":4356, "ErrorURL":"http://192.168.10.142:8040/api/_load_error_log?file=__shard_2/error_log_insert_stmt_e44ae406-32c7-6d5c-a807-b05607a57cbf_e44ae40632c76d5c_a807b05607a57cbf", "ReadDataTimeMs":1961, "NumberLoadedRows":0, "NumberFilteredRows":7077604 }
- 接下來參考stream load排查流程即可
常見問題
- “Failed to commit txn 2271727. Tablet [159816] success replica num 1 is less then quorum replica num 2 while error backends 10012”,
這個問題具體原因需要按照上面排查流程在be.WARNING中查看具體異常
- close index channel failed/too many tablet versions
導入頻率太快,compaction沒能及時合並導致版本數過多,默認版本數1000
降低頻率,調整compaction策略,加快合並(調整完需要觀察內存和io),在be.conf中修改以下內容
base_compaction_check_interval_seconds = 10 cumulative_compaction_num_threads_per_disk = 4 base_compaction_num_threads_per_disk = 2 cumulative_compaction_check_interval_seconds = 2
- Reason: invalid value ‘202123098432’.
導入文件某列和表中的類型不一致導致
- the length of input is too long than schema
導入文件某列長度不正確,比如定長字符串超過建表設置的長度、int類型的字段超過4個字節。
- actual column number is less than schema column number
導入文件某一行按照指定的分隔符切分后列數小於指定的列數,可能是分隔符不正確。
- actual column number is more than schema column number
導入文件某一行按照指定的分隔符切分后列數大於指定的列數,可能是分隔符不正確。
- the frac part length longer than schema scale
導入文件某decimal列的小數部分超過指定的長度。
- the int part length longer than schema precision
導入文件某decimal列的整數部分超過指定的長度。
- the length of decimal value is overflow
導入文件某decimal列的長度超過指定的長度。
- There is no corresponding partition for this key
導入文件某行的分區列的值不在分區范圍內。
- Caused by: org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response
Stream load端口配置錯誤,應該是http_port
- flink demo,按要求建立了測試庫表,然后程序沒有任何報錯日志,數據也無法sink進去,請問有什么排查思路呢
可能是無法訪問be導致,當前flink封裝的stream load,fe接收到請求后會redirect $be:$http_port,一般本地調試的時候,能訪問fe+http_port,但是無法訪問be+http_port,需要開通訪問be+http_port的防火牆
- Transaction commit successfully,But data will be visible later
該狀態也表示導入已經完成,只是數據可能會延遲可見。原因是有部分publish超時,也可以調大fe配置publish_version_timeout_second
- get database write lock timeout
可能是fe的線程數超了,建議可以調整下be配置:thrift_rpc_timeout_ms=10000(默認5000ms)
- failed to send batch 或 TabletWriter add batch with unknown id
請參照章節導入總覽/通用系統配置/BE配置,適當修改 query_timeout 和 streaming_load_rpc_max_alive_time_sec
- LOAD-RUN-FAIL; msg:Invalid Column Name:xxx
- 如果是Parquet或者ORC格式的數據,需要保持文件頭的列名與StarRocks表中的列名一致,如 :
(tmp_c1,tmp_c2)
SET ( id=tmp_c2, name=tmp_c1 )
表示將Parquet或ORC文件中以(tmp_c1, tmp_c2)為列名的列,映射到StarRocks表中的(id, name)列。如果沒有設置set, 則以column中的列作為映射。
注意:如果使用某些Hive版本直接生成的ORC文件,ORC文件中的表頭並非Hive meta數據,而是
(_col0, _col1, _col2, ...) , 可能導致Invalid Column Name錯誤,那么則需要使用set進行映射。
Can't get Kerberos realm
A:首先檢查是不是所有的broker所在機器是否都配置了
/etc/krb5.conf 文件。
如果配置了仍然報錯,需要在broker的啟動腳本中的
JAVA_OPTS 變量最后,加上
-Djava.security.krb5.conf:/etc/krb5.conf 。
- orc數據導入失敗ErrorMsg: type:ETL_RUN_FAIL; msg:Cannot cast ‘<slot 6>’ from VARCHAR to
ARRAY<VARCHAR(30)>
導入源文件和starrocks兩邊列名稱不一致,set的時候系統內部會有一個類型推斷,然后cast的時候失敗了,設置成兩邊字段名一樣,不需要set,就不會cast,導入就可以成功了
- No source file in this table
表中沒有文件
- cause by: SIMPLE authentication is not enabled. Available:[TOKEN, KERBEROS]
kerberos認證失敗。klist檢查下認證是否過期,並且該賬號是否有權限訪問源數據
- Reason: there is a row couldn’t find a partition. src line: [];
導入的數據在starrocks表中無指定分區




