使用Spark读取MongoDB时分区失败的授权问题排查
问题描述
尝试使用MongoDB Spark Connector读取MongoDB数据时,能够通过Spark打印数据Schema,但执行show()展示数据时出现分区失败错误,已尝试多种分区器选项仍未解决。
环境信息
- Spark版本:3.3.0
- MongoDB版本:5.5.0
- Connector版本:10.2.0
报错的Spark代码
from pyspark.sql import SparkSession from pyspark import SparkContext spark = SparkSession.builder.appName(job_name).getOrCreate() url = "mongodb://ReadUser:Password123@mongo-db.test.app:27017/db_name" df = ( spark .read .format("mongodb") .option('connection.uri',url) .option("database", "db_name") .option("collection","collection1") .option('partitioner','com.mongodb.spark.sql.connector.read.partitioner.ShardedPartitioner') .load() ) df.printSchema() df.show()
可正常运行的Python代码(pymongo)
from pymongo import MongoClient url = "mongodb://ReadUser:Password123@mongo-db.test.app:27017/db_name" client=MongoClient(url) db=client["db_name"] table = db["collection1"] x = table.find() for data in x: print(data)
Spark错误日志
com.mongodb.spark.sql.connector.exceptions.MongoSparkException: Partitioning failed.
root |-- _id: string (nullable = true) |-- created_date: double (nullable = true) |-- code: integer (nullable = true) |-- expiry_time: double (nullable = true) |-- mail_res: void (nullable = true) |-- noOf_code: integer (nullable = true) |-- type: string (nullable = true) |-- proposalId: void (nullable = true) |-- code_s: void (nullable = true) |-- twillow_res: void (nullable = true) |-- user_id: string (nullable = true) An error occurred while calling o118.showString. : com.mongodb.spark.sql.connector.exceptions.MongoSparkException: Partitioning failed. at com.mongodb.spark.sql.connector.read.partitioner.PartitionerHelper.generatePartitions(PartitionerHelper.java:69) ... Caused by: com.mongodb.MongoQueryException: Query failed with error code 13 with name 'Unauthorized' and error message 'not authorized on config to execute command { find: "collections", filter: { _id: "db_name.collection1" }, projection: { _id: 1, timestamp: 1, uuid: 1, dropped: 1, key: 1 }, limit: 1, singleBatch: true, $db: "config", lsid: { id: UUID("a835c704-429c-4b0e-99f7-739d28105be3") } }' on server mongo-db.test.app:27017 ...
问题原因分析
从错误日志的Unauthorized报错可明确:
- 当前使用的
ShardedPartitioner分区器需要访问MongoDB的config数据库中的collections集合,以获取分片集合元数据来生成分区。 - 你的
ReadUser账号仅拥有目标数据库db_name的读取权限,无访问config数据库的权限,因此触发授权失败。 - pymongo代码能正常运行是因为它直接读取目标集合,不需要访问
config库获取分片元数据。
解决方案
- 更换分区器:若MongoDB集群不是分片集群,或不需要基于分片键分区,改用无需访问
config库的分区器,比如MongoSinglePartitioner(单分区读取):.option('partitioner','com.mongodb.spark.sql.connector.read.partitioner.MongoSinglePartitioner') - 添加权限:若必须使用
ShardedPartitioner,给ReadUser账号添加config数据库的只读权限,执行MongoDB命令:use admin db.grantRolesToUser("ReadUser", [{ role: "read", db: "config" }]) - 确认集群类型:检查MongoDB是否为分片集群,若为单节点或副本集,使用
ShardedPartitioner本身不合理,会触发不必要的config库访问。
内容的提问来源于stack exchange,提问作者NIKHIL SUTHAR
相关产品推荐
相关产品推荐

