Practique data lake iceberg Lección 30 mysql->iceberg, diferentes clientes tienen problemas de zona horaria

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














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

inserte la descripción de la imagen aquí

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.
inserte la descripción de la imagen aquí

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:

  1. Resultados de la consulta lateral de Flink sql:
Flink SQL> select i,ts_code,update_time,update_timestamp from stock_basic2_iceberg_sink;

inserte la descripción de la imagen aquí
2. Resultados de la consulta en el lado de mysql:
inserte la descripción de la imagen aquí
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:

inserte la descripción de la imagen aquí

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:
inserte la descripción de la imagen aquí
Resultado de la consulta de flink-sql:
inserte la descripción de la imagen aquí

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

Supongo que te gusta

Origin blog.csdn.net/spark_dev/article/details/124302929
Recomendado
Clasificación