如何通过SQLAlchemy设置Oracle只读连接,无需修改数据库配置?
SQLAlchemy连接Oracle配置会话只读实现方案
核心结论
create_engine没有直接提供名为READONLY的配置参数,但可以通过SQLAlchemy的事件机制搭配Oracle原生的会话级只读语句实现完全等效的效果,不需要修改任何数据库侧的用户权限、角色等配置,设置仅对当前会话生效,不影响其他程序的正常读写操作。
实现原理
Oracle 12c及以上版本支持会话级别的只读设置,执行ALTER SESSION SET READ ONLY = TRUE后,当前会话所有事务都默认只读,尝试执行DML/DDL操作会直接抛出错误;11g及更早版本支持事务级别的只读设置,每次事务启动前执行SET TRANSACTION READ ONLY即可限制当前事务仅允许查询操作。
具体实现方式
方式1:全局配置所有连接默认只读(推荐)
通过监听connect事件,每次新建数据库连接时自动执行只读设置,不需要手动重复配置:
from sqlalchemy import create_engine, event # 导入text用于SQL语句构造,SQLAlchemy 2.0+ 要求显式使用text包裹原生SQL from sqlalchemy import text # 按实际情况替换数据库连接串 engine = create_engine("oracle+cx_oracle://<用户名>:<密码>@<主机地址>:<端口>/<服务名>") # Oracle 12c及以上版本使用会话级配置 @event.listens_for(engine, "connect") def set_readonly_connection(dbapi_connection, connection_record): cursor = dbapi_connection.cursor() cursor.execute("ALTER SESSION SET READ ONLY = TRUE") cursor.close() # Oracle 11g及更早版本使用事务级配置,替换上面的事件监听即可 """ @event.listens_for(engine, "begin") def set_readonly_transaction(conn): conn.execute(text("SET TRANSACTION READ ONLY")) """
方式2:单次连接临时设置只读
仅需要部分连接为只读时,可在获取连接后手动执行配置:
from sqlalchemy import create_engine, text engine = create_engine("oracle+cx_oracle://<用户名>:<密码>@<主机地址>:<端口>/<服务名>") with engine.connect() as conn: # 执行只读设置 conn.execute(text("ALTER SESSION SET READ ONLY = TRUE")) # 后续操作均为只读,尝试写入会直接报错 res = conn.execute(text("SELECT * FROM 你的表名")) print(res.all())
注意事项
- 会话级只读设置仅对当前连接生效,完全不会影响其他程序的数据库读写操作。
- 如果需要恢复当前连接的可写权限,执行
ALTER SESSION SET READ WRITE = TRUE即可。 - 11g及更早版本的Oracle不支持会话级只读配置,必须使用事务级的
SET TRANSACTION READ ONLY语句,每次新事务启动都需要执行一次。
内容的提问来源于stack exchange,提问作者aturegano
相关产品推荐
相关产品推荐

