Python MySQL Cursor执行SELECT时因只读权限触发权限拒绝问题求助
你的问题根本不是SELECT语句本身的权限问题——毕竟直接在数据库里用同一用户执行SELECT完全正常,问题出在Python连接初始化时触发了隐含的写操作,而当前用户已被移除WRITE权限,因此被拒绝。
旧版本的mysql-connector(2.2.9确实属于较老版本)在建立连接时,可能会自动执行一些会话级的写操作,比如设置字符集、时区或默认参数,这些操作需要WRITE权限;另外你封装的MySQLDatabase类也可能在底层做了额外初始化,比如创建临时表、修改会话变量等,这些都会触发权限检查。
可行的解决办法
1. 给只读连接添加read_only=True参数
建立只读库的连接时,显式指定该参数,告诉MySQL服务器这是只读连接,它会自动限制该连接的操作,同时避免那些隐含的写操作:
def get_connection(database, username, password, read_only=False): return MySQLDatabase( host=getenv(DATABASE_HOST), port=getenv(DATABASE_PORT), database=database, user=username, password=password, read_only=read_only # 新增只读参数 ).connection # 建立只读连接时传入True self.read_connection = self.get_connection(database, usr, pwd, read_only=True)
如果你的MySQLDatabase封装类未暴露该参数,可直接调用底层的mysql.connector.connect方法,手动传入read_only=True。
2. 检查MySQLDatabase封装类的初始化逻辑
查看该类的实现,确认是否在连接建立后自动执行了需要写权限的语句(比如SET @@session.some_var = ...、创建临时表等)。如果有,将这些操作移至写连接中,或针对只读连接跳过此类初始化步骤。
3. 更换更现代的Python MySQL连接库
mysql-connector 2.2.9是2018年的老旧版本,对只读场景的支持不完善。推荐更换为以下两个库:
- mysqlclient:性能优异,兼容MySQL官方协议,对只读连接的处理更成熟
- pymysql:纯Python实现,安装便捷,对只读模式支持友好
以pymysql为例,代码示例如下:
import pymysql from os import getenv def get_connection(database, username, password, read_only=False): return pymysql.connect( host=getenv(DATABASE_HOST), port=int(getenv(DATABASE_PORT)), database=database, user=username, password=password, read_only=read_only ) # 使用方式与原逻辑一致 self.read_connection = self.get_connection(database, usr, pwd, read_only=True) cursor_read = self.read_connection.cursor() cursor_read.execute("SELECT * FROM operative_function") results = cursor_read.fetchall()
4. 再次验证数据库权限配置
虽然你提到直接执行SELECT正常,但仍可确认用户对目标表的SELECT权限是否明确授予:
SHOW GRANTS FOR 'myuser'@'10.64.XXX.XX';
确保输出中包含SELECT ON 你的数据库名.operative_function TO 'myuser'@'10.64.XXX.XX'这类权限条目。
内容的提问来源于stack exchange,提问作者Daniel Vilas-Boas

