adg备库上select any table不生效,因其依赖数据字典写访问而备库只读;必须显式授权具体对象,如grant select on cmsprod.portal_user_profile to cmsreadonly。
adg备库上创建只读用户,不能直接用 select any table,否则会报错 ora-01031:insufficient privileges。
为什么备库上 SELECT ANY TABLE 不生效
Oracle 19c ADG物理备库(Physical Standby)默认处于 READ ONLY WITH APPLY 或 READ ONLY 状态,此时数据库是只读的,但系统权限如 SELECT ANY TABLE 被显式禁用——它依赖于对数据字典表的写访问能力,而备库不允许任何 DML/DDL 修改,包括隐式字典访问。即使你用 SYS 登录并执行 GRANT SELECT ANY TABLE TO ro_user,该语句能成功,但后续查询仍会触发 ORA-01031。
- 这是 Oracle 的硬性限制,不是权限没刷或缓存问题
-
SELECT ANY DICTIONARY同样无效,备库不开放数据字典的“任意读”通道 - 唯一可行路径是基于具体对象(schema + table)显式授权
正确做法:用 GRANT SELECT ON schema.table TO user
必须明确指定源 schema 和表名,且该 schema 必须存在于备库中(即主库已同步过来)。常见错误是直接对 SCOTT.EMP 授权,但备库里 SCOTT 用户没被同步(尤其当主库未启用 ENABLE PLUGGABLE DATABASE 或未传输用户元数据时)。
- 先确认目标表存在:
SELECT owner, table_name FROM dba_tables WHERE owner = 'CMSPROD' AND table_name = 'PORTAL_USER_PROFILE'; - 授权语句必须用大写 schema 名(Oracle 默认大写,除非建库时加引号):
GRANT SELECT ON CMSPROD.PORTAL_USER_PROFILE TO cmsreadonly; - 不能省略 schema 名,
GRANT SELECT ON PORTAL_USER_PROFILE TO ...会报 ORA-00942 - 若需批量授权,用如下脚本生成语句(在备库上执行,确保
CMSPROD已同步):SELECT 'GRANT SELECT ON CMSPROD.' || table_name || ' TO cmsreadonly;' FROM dba_tables WHERE owner = 'CMSPROD';
角色方式更安全:建 READER_ROLE 再授给用户
比起逐个表授权,用角色集中管理更易维护,也避免漏表。但注意:角色本身不能跨 PDB 自动继承,如果你的 ADG 是多租户环境(CDB+PDB),必须在目标 PDB 内创建角色并授权。
- 在备库的目标 PDB 中执行(先
ALTER SESSION SET CONTAINER = ORA19CPDB;):CREATE ROLE reader_role; GRANT SELECT ON CMSPROD.PORTAL_USER_PROFILE TO reader_role; GRANT SELECT ON CMSPROD.BEDC_BANK TO reader_role; GRANT reader_role TO cmsreadonly;
- 角色不会自动获得新表权限,新增表后需手动补授权
- 不要用
GRANT SELECT ANY TABLE TO reader_role—— 这条在备库上语法通过但实际无效
同义词和连接权限别漏掉
用户有了表权限,不代表能直接用短名查。如果应用代码写的是 SELECT * FROM PORTAL_USER_PROFILE,而没带 schema,就必须建同义词;否则得改代码或加 synonym。
- 同义词必须在用户自己的 schema 下创建:
CREATE SYNONYM cmsreadonly.PORTAL_USER_PROFILE FOR CMSPROD.PORTAL_USER_PROFILE; - 连接权限不可少:
GRANT CREATE SESSION TO cmsreadonly;(CONNECT角色在 19c 中已不推荐,显式授CREATE SESSION更清晰) - 如果用户要查
V$或GV$视图(如监控 SQL 执行),需额外授权:GRANT SELECT ON V_$SESSION TO cmsreadonly;(注意是V_$SESSION,不是V$SESSION)
最常被忽略的一点:ADG 备库的只读权限必须在备库实例上单独配置,不能只在主库操作然后指望同步过去。所有 GRANT、CREATE ROLE、CREATE SYNONYM 都得在备库当前打开的 PDB 里执行,且需确认 OPEN_MODE 是 READ ONLY 或 READ ONLY WITH APPLY(用 SELECT open_mode FROM v$database; 检查)。否则命令会失败或权限不生效。











