Docker本地Spark环境跨会话无法访问持久化表如何解决
问题根因
你遇到的表仅单会话可见的问题是两个默认配置导致的:
- 默认创建SparkSession时未启用Hive支持,此时Spark使用的是会话级临时元数据存储,会话销毁后元数据会丢失,即使磁盘上有表数据文件,新会话也无法识别元数据
- 若开启Hive支持但未做固定路径配置,Spark默认使用嵌入式Derby作为元数据库,元数据文件默认存放在当前执行脚本的工作目录下,不同工作目录启动的Spark进程会生成独立的元数据库,自然无法跨会话共享库表元数据
解决方案
方案1:本地测试/轻量CICD场景(用固定路径的嵌入式Derby)
所有脚本创建SparkSession时统一指定元数据和数据仓库的固定绝对路径,同时开启Hive支持,示例代码如下:
修改后的创建库表脚本 Create_script.py
from pyspark.sql import SparkSession def main(): spark = SparkSession.builder \ .appName('Example') \ # 开启Hive支持,启用持久化元数据 .enableHiveSupport() \ # 固定数据仓库存储路径,填写Docker内的绝对路径即可 .config("spark.sql.warehouse.dir", "/opt/spark/persist_warehouse") \ # 固定Derby元数据库的存储路径 .config("javax.jdo.option.ConnectionURL", "jdbc:derby:;databaseName=/opt/spark/persist_metastore_db;create=true") \ .getOrCreate() columns = ["language", "users_count"] data = [("Java", "20000"), ("Python", "100000"), ("Scala", "3000")] rdd = spark.sparkContext.parallelize(data) df = rdd.toDF(columns) spark.sql("create database if not exists schema1") df.write.mode("ignore").saveAsTable('schema1.table1')
修改后的读表脚本 load_data.py
from pyspark.sql import SparkSession spark = SparkSession.builder \ .appName('example') \ .enableHiveSupport() \ .config("spark.sql.warehouse.dir", "/opt/spark/persist_warehouse") \ .config("javax.jdo.option.ConnectionURL", "jdbc:derby:;databaseName=/opt/spark/persist_metastore_db;create=true") \ .getOrCreate() # 此时可以正常查到库表 print(spark.catalog.listDatabases()) df = spark.sql("select * from schema1.table1") df.show()
Docker环境下建议把/opt/spark/persist_warehouse和/opt/spark/persist_metastore_db两个路径挂载到宿主机,避免容器销毁后数据丢失,CICD场景下可以把这两个路径设为流水线缓存目录。
方案2:生产/CICD高频使用场景
如果需要多进程同时访问元数据,嵌入式Derby不支持并发读写,建议搭建独立的Hive Metastore服务,用MySQL/PostgreSQL作为元数据存储,所有Spark会话统一连接该Metastore服务即可实现全集群跨会话元数据共享。
内容的提问来源于stack exchange,提问作者Dipesh
相关产品推荐
相关产品推荐

