关于 Oracle Schema 级别的权限问题

ea2c6e58ea5aac5385e883752cafbf02.gif

作者 | JiekeXu

来源 |公众号 JiekeXu DBA之路(ID: JiekeXu_IT)

如需转载请联系授权 | (个人微信 ID:JiekeXu_DBA)

大家好,我是 JiekeXu,很高兴又和大家见面了,今天和大家一起来看看关于 Oracle Schema 级别的权限问题,欢迎点击上方蓝字“JiekeXu DBA之路”关注我的公众号,标星或置顶,更多干货第一时间到达!

众所周知,在 Oracle 中,一般情况下 B 用户如果需要访问 A 用户下的表、视图、索引等对象,必须要加前缀即 A.object_name 才有权限访问。所以在生产环境中,一般也是 A 用户为业务用户,具有增删改查等业务相关的权限,B 用户一般给予查询 A 用户下表等对象的权限,所以我们可以加一层 Role 角色的权限(我们暂定为 R_SELECT_A),给 B 用户一个特定的角色 R_SELECT_A,然后定期定时通过脚本化的方式对这个角色授权。我们可以这么做:

创建业务用户和业务表空间,赋予相应的权限

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.15.0.0.0


CREATE TABLESPACE A_DATA DATAFILE '+DATA' SIZE 30G UNIFORM SIZE 1M;
CREATE USER A  IDENTIFIED BY oracle 
DEFAULT TABLESPACE A_DATA  
QUOTA unlimited ON A_DATA
TEMPORARY TABLESPACE temp;


--授权
GRANT "CONNECT" TO "A";
GRANT "RESOURCE" TO "A";
GRANT "PLUSTRACE" TO "A";
GRANT DEBUG CONNECT SESSION TO "A";
GRANT CREATE SEQUENCE TO "A";
GRANT CREATE VIEW TO "A";
GRANT CREATE SYNONYM TO "A";

创建 B 用户及角色

create user B identified by oracle;
create role R_SELECT_A;
grant connect,R_SELECT_A to B;


--然后我们登录 A 用户,将 A 用户下的表对象只读权限给与角色 R_SELECT_A,
--将执行结果再次执行一遍。


SQL> select 'grant select on '||table_name||' to r_select_A;' 
from user_tables where rownum<=3;


'GRANTSELECTON'||TABLE_NAME||'TOR_SELECT_A;'
---------------------------------------------------------------------
grant select on DEPT to r_select_A;
grant select on EMP to r_select_A;
grant select on BONUS to r_select_A;

那么可能有人会问,对于已经存在的表可以这么做,但是如果有新增业务新增表,那么新增表是没有 R_SELECT_A 这个角色的,对于 B 用户而言也是查不到的。那么我们该怎么做呢?

解决办法

两个办法:第一个,如果业务部门有 A 用户使用权限,在建表时直接补一句 grant 授权,当然如果忘记或者事后则需登录 A 用户,可以直接将新增表的只读权限给角色 R_SELECT_A;

create T_NEWTABLE(id int,name varchar2(20));
grant select on T_NEWTABLE to R_SELECT_A;

对于新业务也有可能建表比较多,或者没有合理的开发规范约束,经常忘记给角色赋权,这样拥有 B 用户权限的人员就查不到了,那么就会来找 DBA,通常我们的做法则是统一赋权,对 A 用户下的所有表批量授权,或者通过定时任务来搞定。

vim grantToRole.sh


#!/bin/bash


if [ $# != 1 ] ; then
        echo "USAGE: $0 user_a|user_b|user_c|all"
        exit 1;
fi


task=$1
source /home/oracle/.bash_profile


#Write Logfile
time=`date +%Y%m%d%H%M%S`
basedir=/home/oracle/tmp
logfile=/home/oracle/tmp/grantToRole_${time}.log


#Write and Execute SQL Scripts
grantToRole()
{
echo "==============Start to execute batch sql at `date`================" >> ${logfile}
username=$1
password=$2
sqlplus -S /nolog >> ${logfile} << EOF
conn ${username}/${password}
spool ${basedir}/grantToRole_${username}_${time}.sql
set head off
set feedback off
set timing off
set verify off
set pagesize 0
set linesize 200
select 'grant select on '||table_name||' to r_select_${username};' from user_tables;
select 'grant select on '||sequence_name||' to r_select_${username};' from user_sequences;
select 'grant insert,delete,update on '||table_name||' to r_update_${username};' from user_tables;
spool off
@${basedir}/grantToRole_${username}_${time}.sql
EOF
echo "==============End up of executing batch sql at `date`===============" >> ${logfile}
}


############################################################
#             Main                                         #
############################################################


case "${task}" in


"user_a" )
grantToRole user_a passwd_oracle
;;


"user_b" )
grantToRole user_b passwd_oracle
;;


"user_c" )
grantToRole user_c passwd_oracle
;;


"all" )
grantToRole user_a passwd_oracle
grantToRole user_b passwd_oracle
grantToRole user_c passwd_oracle
;;
esac


-- rm -f ${basedir}/grantToRole_*.sql
-- crontab
-- 0 14 * * * /home/oracle/tmp/grantToRole.sh all

通过此脚本可以对单个用户或者所有用户赋权,注意我这里包括查询表及序列以及增删改的权限都有,可按照个人实际情况赋权。

在 Oracle 23c 中的解决办法

当然这样还是稍微有点麻烦,对于新增的表要再次单独授权,不是很方便,于是乎在上个月 Oracle 发布的 23c 中,有一个新特性就是 schema 级别授权,什么意思呢?就是你可以给 B 用户授予查询 A 用户 schema 级别的权限,不再需要单个表、单个对象得授权,对于 23c 的环境你 只需三步快速体验 Oracle 23c 开发版

grant select any table on schema USER_A to USER_B;
示例如下:

让我们一起来看看。

SQL*Plus: Release 23.0.0.0.0 - Developer-Release on Wed May 31 15:55:43 2023Version 23.2.0.0.0Copyright (c) 1982, 2023, Oracle. All rights reserved.Connected to:Oracle Database 23c Free, Release 23.0.0.0.0 - Developer-ReleaseVersion 23.2.0.0.0--创建业务用户并授权CREATE TABLESPACE JIEKEXU_DATA DATAFILE '/opt/oracle/oradata/FREE/FREEPDB1/jiekexu_data01.dbf' SIZE 5G UNIFORM SIZE 1M;CREATE USER jiekexu IDENTIFIED BY Oracle_21c DEFAULT TABLESPACE JIEKEXU_DATA QUOTA unlimited ON JIEKEXU_DATATEMPORARY TABLESPACE TEMP;GRANT "CONNECT","RESOURCE" to jiekexu;--创建查询用户,给予登录权限create user jiekexu_sel IDENTIFIED BY jiekexu_sel; grant create session to jiekexu_sel; set line 240 col profile for a20set pages 999 col username for a25 col ACCOUNT_STATUS for a18 select USERNAME,ACCOUNT_STATUS,CREATED,PROFILE,PASSWORD_VERSIONS,DEFAULT_TABLESPACE from dba_users where account_status='OPEN' order by CREATED asc;

接下来我们登录到业务用户 JIEKEXU,但由于自从 21c 开始强制创建容器数据库,则是 PDB 环境,我们登录 PDB 下需要配置 tns 别名进行登录。

cd $ORACLE_HOME/network/admin


[oracle@jiekexu admin]$ more tnsnames.ora 
# tnsnames.ora Network Configuration File: /opt/oracle/product/23c/dbhomeFree/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.


FREE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = jiekexu)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = FREE)
    )
  )


LISTENER_FREE =
  (ADDRESS = (PROTOCOL = TCP)(HOST = jiekexu)(PORT = 1521))


--写入如下信息
[oracle@jiekexu admin]$ vim  tnsnames.ora
FREEPDB1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = jiekexu)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = FREEPDB1)
    )
  )

然后我们登录进入业务用户创建表并插入数据。

conn jiekexu/Oracle_21c@FREEPDB1
create table test(id int,name varchar2(20));
insert into test values(1,'jiekexu'),(2,'freepdb');  
--注意:如上的新特性,在 values 后面可以跟多个值了,以前 21c 之前只能跟一个。
commit;

接下来我们用 SYS 授权 JIEKEXU_SEL 用户 schema 级别的查询权限。然后我们连接查询用户则是可以查到业务用户下的表的数据。

SQL> alter session set container=FREEPDB1;


Session altered.


SQL> grant select any table on schema jiekexu to jiekexu_sel;


Grant succeeded.


SQL> conn jiekexu_sel/jiekexu_sel@FREEPDB1
Connected.
SQL> select * from jiekexu.test;


        ID NAME
---------- --------------------
         1 jiekexu
         2 freepdb

接下来我们模拟业务新增情况,在业务用户下新建表,再去查询用户下看是否可以查询到数据。

SQL> create table t_new(id number);
SQL> insert into t_new values(1),(2),(3),(4);
4 rows created.
SQL> commit;


--切到查询用户,则可以查询到新建的表 t_new 表的数据。
SQL> conn jiekexu_sel/jiekexu_sel@FREEPDB1
Connected.
SQL> select * from jiekexu.test;


        ID NAME
---------- --------------------
         1 jiekexu
         2 freepdb


SQL> select * from jiekexu.t_new;


        ID
----------
         1
         2
         3
         4


SQL> show user;
USER is "JIEKEXU_SEL"
SQL> col OWNER for a15
SQL> col TABLE_NAME for a10
SQL> select owner,table_name from all_tables where owner not in ('SYS','MDSYS','SYSTEM','XDB','CTXSYS');


OWNER           TABLE_NAME
--------------- ----------
JIEKEXU         TEST
JIEKEXU         T_NEW

f2c59728d93185685483f9fee658b27e.png

授权 “select any table on schema” 后,JIEKEXU_SEL 用户除了原先授予的 “CREAT SESSION” 的系统权限外,没有被授予任何其他系统权限和系统角色。

根据上月初 2023 嘉年华上杨长老的演讲介绍,SCHEMA 级授权是通过对象级的继承权限获得,此时,被授权的用户可以看到原始授权用户下所有的表以及数据授权用户通过 ora_check_sys_privilege 函数获取当前是否具备访问权限,即若返回判断结果为 1,则用户有查看权限,返回结果为 0 则无权限。

SQL> select *  from dba_role_privs where grantee='JIEKEXU_SEL';


no rows selected


SQL> select  *  from dba_sys_privs where  grantee='JIEKEXU_SEL';


GRANTEE     PRIVILEGE                                ADM COM INH
----------- ---------------------------------------- --- --- ---
JIEKEXU_SEL CREATE SESSION                           NO  NO  NO


SQL> conn / as sysdba
SQL> set long 99999 pages 9999 LONGCHUNKSIZE 99999
SQL> select dbms_metadata.get_ddl('VIEW','ALL_TABLES','SYS') from dual;


来了一个新需求

现在又遇到一个新的需求,怎么个情况呢,且听我慢慢道来,新来一业务要求可以仅读取 PROD 业务用户下的表,但是所有程序 JDBC 里配置的都是 READONLY 用户,但是他的程序代码里 SQL 写的全都没有加前缀,类似于“select count(*) from test" 这样访问数据库。这样就 100% 报错了,因为 READONLY 用户是没有 test 表的,业务方又不想改代码中涉及到的表加前缀,那么只能通过创建一个触发器,当登录到 READONLY 用户时则将会立马切到业务用户 PROD,然后再给 READONLY 用户查询业务用户 PROD 的角色 R_SELECT_PROD,则就可以实现登录到 READONLY 用户也不用写前缀便可以查询到 PROD 业务用户数据了。

$ sqlplus / as sysdba 


SQL*Plus: Release 19.0.0.0.0 - Production on Wed May 31 16:13:59 2023
Version 19.15.0.0.0


Copyright (c) 1982, 2022, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.15.0.0.0


SQL> create user READONLY identified by READONLY;
SQL> grant connect,R_SELECT_PROD to READONLY;


SQL> create or replace trigger tri_default_schema_prod
after logon on READONLY.schema
begin
execute immediate 'alter session set current_schema=PROD';
end;
/


--登录只读用户查询业务用户下的表数据
CONN READONLY/READONLY
SELECT COUNT(*) FROM PROD.TEST;
SELECT COUNT(*) FROM TEST;       --均是访问 PROD.TEST 的表

我的临时解决方案是这样的,不知小伙伴们还有其他的方法吗?欢迎添加我微信一起交流讨论。另外:近期新建一个微信交流群,现 150 多人了,最终需要 200 人左右,也算比较活跃,会在群中不定期举行抽奖、红包福利,限时免费开放名额,如有需要的可添加我个人微信【JiekeXu_DBA】,备注:加群。

全文完,希望可以帮到正在阅读的你,如果觉得此文对你有帮助,可以分享给你身边的朋友,同事,你关心谁就分享给谁,一起学习共同进步~~~

欢迎关注我的公众号【JiekeXu DBA之路】,第一时间一起学习新知识!

———————————————————————————
公众号:JiekeXu DBA之路
优快云 :https://blog.youkuaiyun.com/JiekeXu
墨天轮:https://www.modb.pro/u/4347
腾讯云:https://cloud.tencent.com/developer/user/5645107
———————————————————————————

0b01dc83a9a24b01b5132eb042b1304a.gif

分享几个数据库备份脚本

Oracle 表碎片检查及整理方案

OGG|Oracle GoldenGate 基础2022 年公众号历史文章合集整理

 

Oracle 19c RAC 遇到的几个问题

OGG|Oracle 数据迁移后比对一致性

OGG|Oracle GoldenGate 微服务架构

Oracle 查询表空间使用率超慢问题一则

国产数据库|TiDB 5.4 单机快速安装初体验

Oracle ADG 备库停启维护流程及增量恢复

Linux 环境搭建 MySQL8.0.28 主从同步环境

cd4531c0720fa96798c3f5a69c89c1ba.png

<think>好的,我现在需要帮助用户解决在Oracle GoldenGate中开启schema级别附加日志功能的问题。用户提到了“schematrandata”这个命令,所以我得先回忆一下相关的配置步骤。 首先,用户的问题是关于如何为特定schema启用附加日志,也就是补充日志。补充日志在OGG中非常重要,因为它确保在捕获数据变更时,日志中包含足够的列信息,尤其是主键或唯一键,以便正确复制数据。如果没有正确配置,可能会出现数据不一致或复制错误。 我记得在Oracle GoldenGate中,启用补充日志通常使用ADD SCHEMATRANDATA命令。这个命令是针对整个schema的,所以需要指定schema名称。但具体步骤可能包括几个关键点:首先确保数据库处于归档模式,并且补充日志已经启用;其次,可能需要配置适当的权限,比如授予用户FLASHBACK权限,如引用[3]中提到的。另外,UNDO_RETENTION参数的设置也很重要,以确保Flashback Query可以正常工作。 接下来,我需要检查用户提供的引用内容。引用[1]提到OGG依赖重做日志,并且需要正确配置源系统的redo日志。引用[3]详细说明了使用Flashback Query以及如何设置UNDO参数。引用[4]则提到了创建REPLICAT进程的配置,但可能和补充日志关系不大。不过这些引用提醒我需要确保数据库的日志配置正确,包括补充日志级别。 用户可能已经知道基本配置,但需要具体的命令步骤。所以正确的步骤应该是: 1. 确保数据库级别的附加日志已启用。通常需要执行ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;。 2. 使用GGSCI命令行工具执行ADD SCHEMATRANDATA命令,指定schema名称。 3. 验证配置是否生效,可以使用INFO SCHEMATRANDATA命令查看状态。 另外,需要注意权限问题。用户需要有足够的权限执行这些操作,比如需要授予GG用户适当的系统权限,如引用[3]中提到的FLASHBACK权限。同时,确保UNDO_RETENTION设置足够大,避免快照过旧错误。 可能的疑问点:是否需要为每个表单独添加附加日志?根据我的知识,ADD SCHEMATRANDATA会自动为该schema下的所有表启用,但如果有新增表,可能需要重新执行。或者是否需要在表级别额外配置?不过根据OGG文档,通常schema级别就足够,但如果有特别的表需要更多日志信息,可能需要单独处理。 用户的问题可能还涉及到如何确认配置是否成功,所以需要说明验证步骤。例如,使用INFO SCHEMATRANDATA schema_name来检查状态是否为ENABLED,并查看是否有警告或错误。 另外,可能还需要考虑OGG版本的不同,是否存在差异。用户提到的是Oracle GoldenGate 19C,所以配置步骤应该适用。但需要确认是否有版本特定的注意事项,例如是否需要设置ENABLE_GOLDENGATE_REPLICATION参数,如引用[2]中出现的错误,但那个错误是关于该参数未设置为true,可能是在配置捕获进程时的要求,而补充日志的配置可能不需要这个参数,但为了全面性,可能需要提醒用户检查相关参数是否已设置,避免后续步骤出错。 总结步骤: 1. 确认数据库级别补充日志已开启。 2. 在GGSCI中执行ADD SCHEMATRANDATA命令。 3. 验证配置并处理可能的权限和参数问题。 最后,生成相关问题时要围绕补充日志的配置、验证、常见问题处理等方面,帮助用户扩展了解可能遇到的后续问题。</think>在Oracle GoldenGate中开启schema级别的附加日志(Supplemental Logging)需使用`ADD SCHEMATRANDATA`命令。以下是具体配置步骤: --- ### **配置步骤** 1. **开启数据库级最小补充日志** 在数据库层面启用基础补充日志,确保重做日志包含必要信息: ```sql ALTER DATABASE ADD SUPPLEMENTAL LOG DATA; ``` 2. **通过GGSCI启用schema级补充日志** 使用GoldenGate命令行工具执行以下命令,为指定schema(如`IT_MES`)启用附加日志: ```bash GGSCI> ADD SCHEMATRANDATA IT_MES ``` 此操作会为`IT_MES`下的所有表自动添加主键/唯一键的补充日志[^3]。 3. **验证补充日志状态** 检查schema级别的补充日志是否成功启用: ```bash GGSCI> INFO SCHEMATRANDATA IT_MES ``` 输出中应显示`ENABLED`状态。 4. **权限与参数配置(可选)** - 授予GoldenGate用户Flashback权限(若使用Flashback Query): ```sql GRANT FLASHBACK ANY TABLE TO ogg_user; ``` - 调整`UNDO_RETENTION`确保数据一致性: ```sql ALTER SYSTEM SET UNDO_RETENTION = 86400; --至少24小时 ``` 详见引用[3]。 --- ### **注意事项** - **新增表的处理**:`ADD SCHEMATRANDATA`会自动为新表启用补充日志,但需确保GoldenGate进程重启后生效。 - **表级覆盖**:若需为个别表添加更多日志(如全字段日志),可单独执行`ADD TRANDATA`[^3]。 - **双向复制场景**:若为双向同步配置,需同时在两端数据库启用补充日志[^4]。 --- ### **常见问题排查** - **错误OGG-02091**:检查`ENABLE_GOLDENGATE_REPLICATION`参数是否为`TRUE`(引用[2])。 - **日志不足**:确认数据库级补充日志已启用,且GoldenGate用户有足够权限。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值