You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 19:09:00