シリーズ記事ディレクトリ
Practice Data Lake iceberg レッスン 1 はじめに
Practice Data Lake iceberg レッスン 2 Iceberg は Hadoop の基礎となるデータ形式に基づいています
実践 data lake
iceberg sqlclient で、SQL を使用して Kafka から iceberg にデータを読み取ります (バージョンを flink1.12.7 にアップグレードします)
実践 data lake iceberg レッスン 5 ハイブ カタログの特徴演習データ lake iceberg レッスン 6 kafka からiceberg への書き込み
失敗問題解決の演習データファイル演習データ lake iceberg レッスン 10 スナップショット 削除演習データ lake iceberg レッスン 11 テスト パーティション テーブルの整合性 プロセス (数値の作成、テーブルの作成、マージ、およびスナップショットの削除)演習データ lake iceberg レッスン 12 カタログとは 演習データlake iceberg レッスン 13 メタデータデータファイルよりも何倍も大きい演習 data lake iceberg レッスン 14 データマージ (時間の経過とともにメタデータが拡張する問題を解決するため)演習 data lake iceberg レッスン 15 spark インストールと統合 iceberg (jersey パッケージの競合)演習 data lake iceberg レッスン 16 spark3 Door による氷山の認識
演習 data lake iceberg レッスン 17 Hadoop2.7、spark3 on yarn run iceberg 構成
演習 data lake iceberg 演習 18 複数のクライアントが iceberg とやり取りする 開始コマンド (よく使われるコマンド)
演習 data lake iceberg レッスン 19 flink count iceberg , 結果が出ない問題の
演習 data lake iceberg レッスン 20 flink + iceberg CDC シナリオ (バージョンの問題、テスト失敗)
練習データ lake iceberg レッスン 21 flink1.13.5 + iceberg0.131 CDC (テスト成功 INSERT、変更操作失敗)
練習データ lake iceberg レッスン 22 flink1.13.5 + iceberg0. 131 CDC (CRUD テスト成功)
練習データ lake iceberg レッスン 23 flink-sql
チェックポイントから練習データ lake iceberg を再起動する レッスン 24 iceberg メタデータの詳細 練習データ
lake iceberg を分析する レッスン 25 flink sql をバックグラウンドで実行する 追加、削除、変更の効果
実践 data lake iceberg レッスン 26 チェックポイントの設定方法
実践 data lake iceberg レッスン 27 Flink cdc テスト プログラムの失敗 再起動: 前回のチェックポイントから再起動して作業を続行できる
実践 data lake iceberg レッスン 28 公共の倉庫に存在しないパッケージをローカルにデプロイする倉庫はdata lake iceberg を実践するレッスン29
flink の jobId をエレガントかつ効率的に取得する方法
記事ディレクトリ
序文
mysql->flink-sql-cdc->アイスバーグ. flink からデータ時刻を確認しても問題ありませんが、spark-sql からはタイム ゾーンが +8 になっています。この問題を記録する
最終的な解決策: ソース テーブルにはタイムゾーンがなく、ダウンストリーム テーブルにはローカル タイムゾーンを設定する必要があるため、問題はありません。
1. Spark は氷山データを照会し、都市部のため、日付に 8 を追加します。
1. Spark SQL は、日付を含むフィールドについて iceberg にクエリを実行し、タイムゾーンに関するエラーを報告します
java.lang.IllegalArgumentException: Cannot handle timestamp without timezone fields in Spark. Spark does not natively support this type but if you would like to handle all timestamps as timestamp with timezone set 'spark.sql.iceberg.handle-timestamp-without-timezone' to true. This will not change the underlying values stored but will change their displayed values in Spark. For more information please see https://docs.databricks.com/spark/latest/dataframes-datasets/dates-timestamps.html#ansi-sql-and-spark-sql-timestamps
at org.apache.iceberg.relocated.com.google.common.base.Preconditions.checkArgument(Preconditions.java:142)
at org.apache.iceberg.spark.source.SparkBatchScan.readSchema(SparkBatchScan.java:127)
at org.apache.spark.sql.execution.datasources.v2.PushDownUtils$.pruneColumns(PushDownUtils.scala:136)
at org.apache.spark.sql.execution.datasources.v2.V2ScanRelationPushDown$$anonfun$applyColumnPruning$1.applyOrElse(V2ScanRelationPushDown.scala:191)
at org.apache.spark.sql.execution.datasources.v2.V2ScanRelationPushDown$$anonfun$applyColumnPruning$1.applyOrElse(V2ScanRelationPushDown.scala:184)
at org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$transformDownWithPruning$1(TreeNode.scala:481)
at org.apache.spark.sql.catalyst.trees.CurrentOrigin$.withOrigin(TreeNode.scala:82)
at org.apache.spark.sql.catalyst.trees.TreeNode.transformDownWithPruning(TreeNode.scala:481)
at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan.org$apache$spark$sql$catalyst$plans$logical$AnalysisHelper$$super$transformDownWithPruning(LogicalPlan.scala:30)
at org.apache.spark.sql.catalyst.plans.logical.AnalysisHelper.transformDownWithPruning(AnalysisHelper.scala:267)
at org.apache.spark.sql.catalyst.plans.logical.AnalysisHelper.transformDownWithPruning$(AnalysisHelper.scala:263)
at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan.transformDownWithPruning(LogicalPlan.scala:30)
at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan.transformDownWithPruning(LogicalPlan.scala:30)
at org.apache.spark.sql.catalyst.trees.TreeNode.transformDown(TreeNode.scala:457)
at org.apache.spark.sql.catalyst.trees.TreeNode.transform(TreeNode.scala:425)
at org.apache.spark.sql.execution.datasources.v2.V2ScanRelationPushDown$.applyColumnPruning(V2ScanRelationPushDown.scala:184)
at org.apache.spark.sql.execution.datasources.v2.V2ScanRelationPushDown$.apply(V2ScanRelationPushDown.scala:39)
at org.apache.spark.sql.execution.datasources.v2.V2ScanRelationPushDown$.apply(V2ScanRelationPushDown.scala:35)
at org.apache.spark.sql.catalyst.rules.RuleExecutor.$anonfun$execute$2(RuleExecutor.scala:211)
at scala.collection.LinearSeqOptimized.foldLeft(LinearSeqOptimized.scala:126)
at scala.collection.LinearSeqOptimized.foldLeft$(LinearSeqOptimized.scala:122)
at scala.collection.immutable.List.foldLeft(List.scala:91)
at org.apache.spark.sql.catalyst.rules.RuleExecutor.$anonfun$execute$1(RuleExecutor.scala:208)
at org.apache.spark.sql.catalyst.rules.RuleExecutor.$anonfun$execute$1$adapted(RuleExecutor.scala:200)
at scala.collection.immutable.List.foreach(List.scala:431)
at org.apache.spark.sql.catalyst.rules.RuleExecutor.execute(RuleExecutor.scala:200)
at org.apache.spark.sql.catalyst.rules.RuleExecutor.$anonfun$executeAndTrack$1(RuleExecutor.scala:179)
at org.apache.spark.sql.catalyst.QueryPlanningTracker$.withTracker(QueryPlanningTracker.scala:88)
at org.apache.spark.sql.catalyst.rules.RuleExecutor.executeAndTrack(RuleExecutor.scala:179)
at org.apache.spark.sql.execution.QueryExecution.$anonfun$optimizedPlan$1(QueryExecution.scala:138)
at org.apache.spark.sql.catalyst.QueryPlanningTracker.measurePhase(QueryPlanningTracker.scala:111)
at org.apache.spark.sql.execution.QueryExecution.$anonfun$executePhase$1(QueryExecution.scala:196)
at org.apache.spark.sql.SparkSession.withActive(SparkSession.scala:775)
at org.apache.spark.sql.execution.QueryExecution.executePhase(QueryExecution.scala:196)
at org.apache.spark.sql.execution.QueryExecution.optimizedPlan$lzycompute(QueryExecution.scala:134)
at org.apache.spark.sql.execution.QueryExecution.optimizedPlan(QueryExecution.scala:130)
at org.apache.spark.sql.execution.QueryExecution.assertOptimized(QueryExecution.scala:148)
at org.apache.spark.sql.execution.QueryExecution.$anonfun$executedPlan$1(QueryExecution.scala:166)
at org.apache.spark.sql.execution.QueryExecution.withCteMap(QueryExecution.scala:73)
at org.apache.spark.sql.execution.QueryExecution.executedPlan$lzycompute(QueryExecution.scala:163)
at org.apache.spark.sql.execution.QueryExecution.executedPlan(QueryExecution.scala:163)
at org.apache.spark.sql.execution.SQLExecution$.$anonfun$withNewExecutionId$5(SQLExecution.scala:101)
at org.apache.spark.sql.execution.SQLExecution$.withSQLConfPropagated(SQLExecution.scala:163)
at org.apache.spark.sql.execution.SQLExecution$.$anonfun$withNewExecutionId$1(SQLExecution.scala:90)
at org.apache.spark.sql.SparkSession.withActive(SparkSession.scala:775)
at org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:64)
at org.apache.spark.sql.hive.thriftserver.SparkSQLDriver.run(SparkSQLDriver.scala:69)
at org.apache.spark.sql.hive.thriftserver.SparkSQLCLIDriver.processCmd(SparkSQLCLIDriver.scala:384)
at org.apache.spark.sql.hive.thriftserver.SparkSQLCLIDriver.$anonfun$processLine$1(SparkSQLCLIDriver.scala:504)
at org.apache.spark.sql.hive.thriftserver.SparkSQLCLIDriver.$anonfun$processLine$1$adapted(SparkSQLCLIDriver.scala:498)
at scala.collection.Iterator.foreach(Iterator.scala:943)
at scala.collection.Iterator.foreach$(Iterator.scala:943)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1431)
at scala.collection.IterableLike.foreach(IterableLike.scala:74)
at scala.collection.IterableLike.foreach$(IterableLike.scala:73)
at scala.collection.AbstractIterable.foreach(Iterable.scala:56)
at org.apache.spark.sql.hive.thriftserver.SparkSQLCLIDriver.processLine(SparkSQLCLIDriver.scala:498)
at org.apache.spark.sql.hive.thriftserver.SparkSQLCLIDriver$.main(SparkSQLCLIDriver.scala:287)
at org.apache.spark.sql.hive.thriftserver.SparkSQLCLIDriver.main(SparkSQLCLIDriver.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.spark.deploy.JavaMainApplication.start(SparkApplication.scala:52)
at org.apache.spark.deploy.SparkSubmit.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:955)
at org.apache.spark.deploy.SparkSubmit.doRunMain$1(SparkSubmit.scala:180)
at org.apache.spark.deploy.SparkSubmit.submit(SparkSubmit.scala:203)
at org.apache.spark.deploy.SparkSubmit.doSubmit(SparkSubmit.scala:90)
at org.apache.spark.deploy.SparkSubmit$$anon$2.doSubmit(SparkSubmit.scala:1043)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:1052)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
2.プロンプトに従ってタイムゾーンを削除します
セットspark.sql.iceberg.handle-timestamp-without-timezone
=真;
spark-sql (default)> set `spark.sql.iceberg.handle-timestamp-without-timezone`=true;
key value
spark.sql.iceberg.handle-timestamp-without-timezone true
Time taken: 0.016 seconds, Fetched 1 row(s)
spark-sql (default)> select * from stock_basic2_iceberg_sink;
i ts_code symbol name area industry list_date actural_controller update_time update_timestamp
0 000001.SZ 000001 平安银行 深圳 银行 19910403 NULL 2022-04-14 03:53:24 2022-04-21 00:58:59
1 000002.SZ 000002 万科A 深圳 全国地产 19910129 NULL 2022-04-14 03:53:31 2022-04-21 00:59:06
4 000006.SZ 000006 深振业A 深圳 区域地产 19920427 深圳市人民政府国有资产监督管理委员会 NULL NULL
2 000004.SZ 000004 国华网安 深圳 软件服务 19910114 李映彤 2022-04-14 03:53:34 2022-04-21 00:59:11
3 000005.SZ 000005 ST星源 深圳 环境保护 19901210 郑列列,丁芃 2022-04-14 03:53:40 2022-04-22 00:59:15
Time taken: 1.856 seconds, Fetched 5 row(s)
データ レイクの時間は明らかに mysql の時間と一致しません。火花がチェックされた氷山の時間が 8 時間大幅に増加しました。
結論: 単純にタイム ゾーンに移動することはできません
3. ローカル タイムゾーンを変更する
SET `table.local-time-zone` = 'Asia/Shanghai';
セットspark.sql.iceberg.handle-timestamp-without-timezone
= true; 後
次に、タイムゾーンを設定し、それが無効であることがわかりました:
上海のタイムゾーンに設定:
spark-sql (default)> SET `table.local-time-zone` = 'Asia/Shanghai';
key value
table.local-time-zone 'Asia/Shanghai'
Time taken: 0.014 seconds, Fetched 1 row(s)
spark-sql (default)> select * from stock_basic2_iceberg_sink;
i ts_code symbol name area industry list_date actural_controller update_time update_timestamp
0 000001.SZ 000001 平安银行 深圳 银行 19910403 NULL 2022-04-14 03:53:24 2022-04-21 00:58:59
1 000002.SZ 000002 万科A 深圳 全国地产 19910129 NULL 2022-04-14 03:53:31 2022-04-21 00:59:06
4 000006.SZ 000006 深振业A 深圳 区域地产 19920427 深圳市人民政府国有资产监督管理委员会 NULL NULL
2 000004.SZ 000004 国华网安 深圳 软件服务 19910114 李映彤 2022-04-14 03:53:34 2022-04-21 00:59:11
3 000005.SZ 000005 ST星源 深圳 环境保护 19901210 郑列列,丁芃 2022-04-14 03:53:40 2022-04-22 00:59:15
Time taken: 0.187 seconds, Fetched 5 row(s)
utc タイムゾーンに設定:
spark-sql (default)> SET `table.local-time-zone` = 'UTC';
key value
table.local-time-zone 'UTC'
Time taken: 0.015 seconds, Fetched 1 row(s)
spark-sql (default)> select * from stock_basic2_iceberg_sink;
i ts_code symbol name area industry list_date actural_controller update_time update_timestamp
0 000001.SZ 000001 平安银行 深圳 银行 19910403 NULL 2022-04-14 03:53:24 2022-04-21 00:58:59
1 000002.SZ 000002 万科A 深圳 全国地产 19910129 NULL 2022-04-14 03:53:31 2022-04-21 00:59:06
4 000006.SZ 000006 深振业A 深圳 区域地产 19920427 深圳市人民政府国有资产监督管理委员会 NULL NULL
2 000004.SZ 000004 国华网安 深圳 软件服务 19910114 李映彤 2022-04-14 03:53:34 2022-04-21 00:59:11
3 000005.SZ 000005 ST星源 深圳 环境保护 19901210 郑列列,丁芃 2022-04-14 03:53:40 2022-04-22 00:59:15
Time taken: 0.136 seconds, Fetched 5 row(s)
タイム ゾーンを設定します。
テスト対象の spark.sql.session.timeZone が無効であることがわかりました
2. flink-sql を使用してクエリを実行し、時間が問題ないことを確認します
結論: 時間のセマンティクスは mysql 側と一致しています。
- Flink SQL 側のクエリ結果:
Flink SQL> select i,ts_code,update_time,update_timestamp from stock_basic2_iceberg_sink;
2. mysql 側のクエリ結果:
結論: 時間セマンティクスは mysql 側のものと一致しています。
3.タイムゾーンをソーステーブルに強制的に追加し、エラーを報告する
タイムスタンプを TIMESTAMP_LTZ に変更します
String createSql = "CREATE TABLE stock_basic_source(\n" +
" `i` INT NOT NULL,\n" +
" `ts_code` CHAR(10) NOT NULL,\n" +
" `symbol` CHAR(10) NOT NULL,\n" +
" `name` char(10) NOT NULL,\n" +
" `area` CHAR(20) NOT NULL,\n" +
" `industry` CHAR(20) NOT NULL,\n" +
" `list_date` CHAR(10) NOT NULL,\n" +
" `actural_controller` CHAR(100),\n" +
" `update_time` TIMESTAMP_LTZ\n," +
" `update_timestamp` TIMESTAMP_LTZ\n," +
" PRIMARY KEY(i) NOT ENFORCED\n" +
") WITH (\n" +
" 'connector' = 'mysql-cdc',\n" +
" 'hostname' = 'hadoop103',\n" +
" 'port' = '3306',\n" +
" 'username' = 'xxxxx',\n" +
" 'password' = 'XXXx',\n" +
" 'database-name' = 'xxzh_stock',\n" +
" 'table-name' = 'stock_basic2'\n" +
")" ;
実行エラー、
Caused by: java.lang.IllegalArgumentException: Unable to convert to TimestampData from unexpected value '1649879611000' of type java.lang.Long
at com.ververica.cdc.debezium.table.RowDataDebeziumDeserializeSchema$12.convert(RowDataDebeziumDeserializeSchema.java:504)
at com.ververica.cdc.debezium.table.RowDataDebeziumDeserializeSchema$17.convert(RowDataDebeziumDeserializeSchema.java:641)
at com.ververica.cdc.debezium.table.RowDataDebeziumDeserializeSchema.convertField(RowDataDebeziumDeserializeSchema.java:626)
at com.ververica.cdc.debezium.table.RowDataDebeziumDeserializeSchema.access$000(RowDataDebeziumDeserializeSchema.java:63)
at com.ververica.cdc.debezium.table.RowDataDebeziumDeserializeSchema$16.convert(RowDataDebeziumDeserializeSchema.java:611)
at com.ververica.cdc.debezium.table.RowDataDebeziumDeserializeSchema$17.convert(RowDataDebeziumDeserializeSchema.java:641)
at com.ververica.cdc.debezium.table.RowDataDebeziumDeserializeSchema.extractAfterRow(RowDataDebeziumDeserializeSchema.java:146)
at com.ververica.cdc.debezium.table.RowDataDebeziumDeserializeSchema.deserialize(RowDataDebeziumDeserializeSchema.java:121)
at com.ververica.cdc.connectors.mysql.source.reader.MySqlRecordEmitter.emitElement(MySqlRecordEmitter.java:118)
at com.ververica.cdc.connectors.mysql.source.reader.MySqlRecordEmitter.emitRecord(MySqlRecordEmitter.java:100)
at com.ververica.cdc.connectors.mysql.source.reader.MySqlRecordEmitter.emitRecord(MySqlRecordEmitter.java:54)
at org.apache.flink.connector.base.source.reader.SourceReaderBase.pollNext(SourceReaderBase.java:128)
at org.apache.flink.streaming.api.operators.SourceOperator.emitNext(SourceOperator.java:294)
at org.apache.flink.streaming.runtime.io.StreamTaskSourceInput.emitNext(StreamTaskSourceInput.java:69)
at org.apache.flink.streaming.runtime.io.StreamOneInputProcessor.processInput(StreamOneInputProcessor.java:66)
at org.apache.flink.streaming.runtime.tasks.StreamTask.processInput(StreamTask.java:423)
at org.apache.flink.streaming.runtime.tasks.mailbox.MailboxProcessor.runMailboxLoop(MailboxProcessor.java:204)
at org.apache.flink.streaming.runtime.tasks.StreamTask.runMailboxLoop(StreamTask.java:684)
at org.apache.flink.streaming.runtime.tasks.StreamTask.executeInvoke(StreamTask.java:639)
at org.apache.flink.streaming.runtime.tasks.StreamTask.runWithCleanUpOnFail(StreamTask.java:650)
at org.apache.flink.streaming.runtime.tasks.StreamTask.invoke(StreamTask.java:623)
at org.apache.flink.runtime.taskmanager.Task.doRun(Task.java:779)
at org.apache.flink.runtime.taskmanager.Task.run(Task.java:566)
at java.lang.Thread.run(Thread.java:748)
22/04/21 10:49:30 INFO akka.AkkaRpcService: Stopping Akka RPC service.
タイムゾーンを下流のテーブルに追加できますか?
4. 上流のテーブルにはタイムゾーンがなく、下流のテーブルにはタイムゾーンがあります
ダウンストリーム テーブル: mysql の日時とタイムスタンプ、元の対応する TIMESTAMP から TIMESTAMP_LTZ に変更
LTZ: LOCAL TIME ZONE の意味
mysql テーブル構造:
mysql表:
String createSql = "CREATE TABLE stock_basic_source(\n" +
" `i` INT NOT NULL,\n" +
" `ts_code` CHAR(10) NOT NULL,\n" +
" `symbol` CHAR(10) NOT NULL,\n" +
" `name` char(10) NOT NULL,\n" +
" `area` CHAR(20) NOT NULL,\n" +
" `industry` CHAR(20) NOT NULL,\n" +
" `list_date` CHAR(10) NOT NULL,\n" +
" `actural_controller` CHAR(100),\n" +
" `update_time` TIMESTAMP\n," +
" `update_timestamp` TIMESTAMP\n," +
" PRIMARY KEY(i) NOT ENFORCED\n" +
") WITH (\n" +
" 'connector' = 'mysql-cdc',\n" +
" 'hostname' = 'hadoop103',\n" +
" 'port' = '3306',\n" +
" 'username' = 'XX',\n" +
" 'password' = 'XX" +
" 'database-name' = 'xxzh_stock',\n" +
" 'table-name' = 'stock_basic2'\n" +
")" ;
下流のテーブル:
String createSQl = "CREATE TABLE if not exists stock_basic2_iceberg_sink(\n" +
" `i` INT NOT NULL,\n" +
" `ts_code` CHAR(10) NOT NULL,\n" +
" `symbol` CHAR(10) NOT NULL,\n" +
" `name` char(10) NOT NULL,\n" +
" `area` CHAR(20) NOT NULL,\n" +
" `industry` CHAR(20) NOT NULL,\n" +
" `list_date` CHAR(10) NOT NULL,\n" +
" `actural_controller` CHAR(100) ,\n" +
" `update_time` TIMESTAMP_LTZ\n," +
" `update_timestamp` TIMESTAMP_LTZ\n," +
" PRIMARY KEY(i) NOT ENFORCED\n" +
") with(\n" +
" 'write.metadata.delete-after-commit.enabled'='true',\n" +
" 'write.metadata.previous-versions-max'='5',\n" +
" 'format-version'='2'\n" +
")";
テストの結果、問題ないことがわかりました。
spark-sql のクエリ結果:
flink-sql クエリの結果:
結論は
日付に関する質問: ソース テーブルにはタイムゾーンがなく、ダウンストリーム テーブルにはローカル タイムゾーンを設定する必要があります