Directorio de artículos de la serie
Practica Data Lake iceberg Lección 1 Primeros pasos
Practica Data Lake iceberg Lección 2 Iceberg se basa en el formato de datos subyacente de Hadoop
Practica data lake
iceberg En sqlclient, usa SQL para leer datos de Kafka a iceberg (actualiza la versión a flink1.12.7)
practica data lake iceberg Lección 5 características del catálogo de colmena
practicar data lake iceberg Lección 6 escribir de kafka a iceberg falla resolución de problemas
practicar data lake iceberg Lección 7 escribir en iceberg
practicar data lake iceberg en tiempo real Lección 8 colmena e iceberg integrar
practicar data lake iceberg Lección 9 fusionar pequeño archivos
práctica data lake iceberg Lección 10 eliminación de instantáneas
práctica data lake iceberg Lección 11 prueba de integridad de tabla de partición Proceso (creación de números, construcción de tablas, fusión y eliminación de instantáneas)
Práctica data lake iceberg Lección 12 Qué es un catálogo
Práctica data lake iceberg Lección 13 Metadatos es muchas veces más grande que los archivos de datos
Practique data lake iceberg Lección 14 Fusión de datos (para resolver el problema de la expansión de metadatos con el tiempo) practique data lake
iceberg Lección 15 chispa instalación e integración iceberg (conflicto de paquete jersey)
cognición del iceberg a través de la puerta spark3
Practique data lake iceberg Lección 17 Hadoop2.7, spark3 en la configuración de iceberg de ejecución de hilo Practique
data lake iceberg Lección 18 Varios clientes interactúan con iceberg Comandos de inicio (comandos de uso común ) iceberg Lección 20 flink + iceberg Escenario CDC (problema de versión, prueba fallida) práctica data lake iceberg Lección 21 flink1.13.5 + iceberg0.131 CDC (prueba exitosa INSERTAR, operación de cambio fallida) Práctica data lake iceberg Lección 22 flink1.13.5 + iceberg0. 131 CDC (prueba CRUD exitosa) práctica data lake iceberg Lección 23 flink-sql reiniciar práctica data lake iceberg desde el punto de control Lección 24 detalles de metadatos iceberg Análisis de la práctica data lake iceberg Lección 25 Ejecutar flink sql en segundo plano El efecto de agregar, eliminar y modificar Práctica data lake iceberg Lección 26 método de configuración de puntos de control Práctica data lake iceberg Lección 27 Flink cdc prueba programa falla reiniciar: puede reiniciar desde el último punto de control para continuar trabajando práctica data lake iceberg Lección 28 Implementar paquetes que no existen en el almacén público a local práctica de almacén data lake iceberg Lección 29 cómo obtener flink jobId de manera elegante y eficiente práctica data lake iceberg lección 30 mysql -> iceberg, diferentes clientes tienen problemas de zona horaria práctica data lake iceberg directorio de más contenido
Directorio de artículos
- Directorio de artículos de la serie
- prefacio
- 1. Spark consulta los datos del iceberg, agregando 8 a la fecha, debido al área urbana
- 2. Use flink-sql para consultar y encontrar que el tiempo no es un problema
- 3. Agregue a la fuerza la zona horaria a la tabla de origen e informe un error
- 4. La tabla ascendente no tiene zona horaria y la tabla descendente tiene zona horaria
- en conclusión
prefacio
mysql->flink-sql-cdc->iceberg. No hay problema para verificar la hora de los datos desde flink, pero desde spark-sql, la zona horaria es +8. registrar este problema
Solución final: la tabla de origen no tiene zona horaria, y la tabla descendente necesita establecer la zona horaria local, ¡así que no hay problema!
1. Spark consulta los datos del iceberg, agregando 8 a la fecha, debido al área urbana
1. Spark SQL consulta iceberg en busca de campos con fechas e informa un error sobre la zona horaria
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. Siga las indicaciones para eliminar la zona horaria
establecer spark.sql.iceberg.handle-timestamp-without-timezone
=verdadero;
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)
La hora del lago de datos es obviamente inconsistente con la hora de mysql. Spark comprobó el tiempo de iceberg aumentado significativamente en 8 horas.
Conclusión: no puedes simplemente ir a la zona horaria
3. Cambiar la zona horaria local
SET `table.local-time-zone` = 'Asia/Shanghai';
conjunto spark.sql.iceberg.handle-timestamp-without-timezone
= verdadero; después
Luego configure la zona horaria y descubrió que no es válida:
Establecer en la zona horaria de Shanghái:
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)
Establecer en la zona horaria 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)
Establezca la zona horaria, encontró
spark.sql.session.timeZone inválido para ser probado
2. Use flink-sql para consultar y encontrar que el tiempo no es un problema
Conclusión: la semántica del tiempo es consistente con el lado mysql:
- Resultados de la consulta lateral de Flink sql:
Flink SQL> select i,ts_code,update_time,update_timestamp from stock_basic2_iceberg_sink;
2. Resultados de la consulta en el lado de mysql:
conclusión: la semántica del tiempo es consistente con la del lado de mysql
3. Agregue a la fuerza la zona horaria a la tabla de origen e informe un error
Cambiar la marca de tiempo a 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" +
")" ;
ejecutar error,
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.
¿Puedes agregar la zona horaria a la tabla descendente?
4. La tabla ascendente no tiene zona horaria y la tabla descendente tiene zona horaria
Tabla descendente: fecha y hora y marca de tiempo de mysql, cambiado del TIMESTAMP original correspondiente a TIMESTAMP_LTZ
LTZ: significado de ZONA HORARIA LOCAL
estructura de la tabla mysql:
tabla 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" +
")" ;
Tabla aguas abajo:
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" +
")";
Después de la prueba, se encontró que estaba bien.
Resultado de la consulta de spark-sql:
Resultado de la consulta de flink-sql:
en conclusión
Pregunta sobre la fecha: la tabla de origen no tiene una zona horaria y la tabla descendente necesita establecer una zona horaria local