分类目录归档:ORA-xxxxx

ORA-01031: insufficient privileges

今天接到开发反馈,说数据库动态sql创建表语句无法执行,提示ORA-01031: insufficient privileges
1、数据库版本
SQL> select * from v$version where rownum=1;

BANNER
—————————————————————-
Oracle9i Enterprise Edition Release 9.2.0.4.0 – Production

2、创建用户并授权
SQL> create user test identified by xifenfei;

User created.

SQL> grant connect,resource to test;

Grant succeeded.

3、查看权限
SQL> SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE=’TEST’;

GRANTEE PRIVILEGE ADM
—————————— —————————————- —
TEST UNLIMITED TABLESPACE NO

SQL> SELECT * FROM DBA_ROLE_PRIVS WHERE GRANTEE=’TEST’;

GRANTEE GRANTED_ROLE ADM DEF
—————————— —————————— — —
TEST CONNECT NO YES
TEST RESOURCE NO YES

SQL> CONN TEST/XIFENFEI
Connected.
SQL> SELECT * FROM SESSION_PRIVS;

PRIVILEGE
—————————————-
CREATE SESSION
ALTER SESSION
UNLIMITED TABLESPACE
CREATE TABLE
CREATE CLUSTER
CREATE SYNONYM
CREATE VIEW
CREATE SEQUENCE
CREATE DATABASE LINK
CREATE PROCEDURE
CREATE TRIGGER

PRIVILEGE
—————————————-
CREATE TYPE
CREATE OPERATOR
CREATE INDEXTYPE

14 rows selected.
注:目前create table权限是通过resource role授予test用户的

4、创建存储过程(Authid Current_User)
SQL> create or replace procedure create_table(t varchar2) Authid Current_User
2 is
3 P_SQL VARCHAR2(300);
4 BEGIN
5 P_SQL := ‘create table ‘||t||’ as select * from user_tables where 1=0′;
6 EXECUTE IMMEDIATE P_SQL;
END; 7
8 /

Procedure created.

5、执行存储过程
SQL> EXEC CREATE_table(‘a’);

PL/SQL procedure successfully completed.

6、重建存储过程(不包括Authid Current_User)
SQL> create or replace procedure create_table(t varchar2)
2 –Authid Current_User
3 is
4 P_SQL VARCHAR2(300);
5 BEGIN
6 P_SQL := ‘create table ‘||t||’ as select * from user_tables where 1=0′;
7 EXECUTE IMMEDIATE P_SQL;
8 END;
9 /

Procedure created.

SQL> EXEC CREATE_table(‘b’);
BEGIN CREATE_table(‘b’); END;

*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at “TEST.CREATE_TABLE”, line 7
ORA-06512: at line 1

7、授权(create table权限)
SQL> conn / as sysdba
Connected.
SQL> grant create table to test;

Grant succeeded.

SQL> conn test/xifenfei
Connected.
SQL> EXEC CREATE_table(‘c’);

PL/SQL procedure successfully completed.

8、查看结果
SQL> select * from tab;

TNAME TABTYPE CLUSTERID
—————————— ——- ———-
A TABLE
C TABLE

9、 查询资料
默认情况下,在调用存储过程用户的角色是不起作用的,即在执行存储过程时只有Public权限。所以如果被调用的存储过程中如果有execute immediate ‘create table..’语句,将会引发ORA-01031: insufficient privileges错误。
存储过程分为两种,即DR(Definer’s Rights ) Procedure和IR(Invoker’s Rights ) Procedure。为什么会有两种存储过程呢?其实考虑完下面的问题就清楚了。比如说用户hrch创建了删除表tar_table的存储过程drop_table(),当用户hrch调用时,即删除用户hrch下的表tar_table;如果是另一个用户scott调用呢?是删除用户scott下的tar_table表呢,还是删除用户hrch下的tar_table呢?另外,如果存储过程中包含建表语句,不管是用户hrch还是用户scott调用都会失败,因为Public没有建表权限,除非为Public grant建表权限。

10、动态sql中执行create table解决方案(10g也存在同样问题)
1)加上Authid Current_User
2)直接赋予create table to 该用户

11、匿名块的动态sql不在此限制中
SQL> conn / as sysdba
Connected.
SQL> SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE=’TEST’;

GRANTEE PRIVILEGE ADM
—————————— —————————————- —
TEST UNLIMITED TABLESPACE NO

SQL> CONN TEST/XIFENFEI
Connected.
SQL> DECLARE
2 P_SQL VARCHAR2(300);
3 BEGIN
4 P_SQL := ‘create table t_t as select * from user_tables where 1=0′;
5 EXECUTE IMMEDIATE P_SQL;
6 END;
7 /

PL/SQL procedure successfully completed.

发表在 ORA-xxxxx | 评论关闭

触发器引起ORA-04091

原因:在行级触发器中,不能查询自身表
场景重现:通过触发器实现test_count表中统计test表中行数

--创建子表
create table TEST
(id NUMBER, name varchar2(100), primary key (id));
--创建统计表
create table test_count (test_count int);
--创建触发器
CREATE OR REPLACE TRIGGER T_TEST
  AFTER INSERT OR DELETE ON TEST
  FOR EACH ROW
DECLARE
  A NUMBER;
BEGIN
  SELECT  COUNT(*) INTO A FROM TEST;
  UPDATE TEST_COUNT SET TEST_COUNT = A;
END T_TEST;

模拟错误

INSERT INTO TEST (ID,NAME)VALUES(2,'abc');
ORA-04091: table CHF.TEST is mutating, trigger/function may not see it
ORA-06512: at "CHF.T_TEST", line 2
ORA-04088: error during execution of trigger 'CHF.T_TEST'

处理方法
通过自治事务实现(修改触发器)

CREATE OR REPLACE TRIGGER T_TEST
  AFTER INSERT OR DELETE ON TEST
  FOR EACH ROW
DECLARE
  A NUMBER;
  PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  SELECT  COUNT(*) INTO A FROM TEST;
  UPDATE TEST_COUNT SET TEST_COUNT = A;
  COMMIT;
END T_TEST;

PRAGMA AUTONOMOUS_TRANSACTION
当前的触发器作为已有事务的子事务运行,子事务自治管理,子事务的commit、rollback操作不影响父事务的状态

发表在 ORA-xxxxx | 标签为 | 一条评论

WARNING: inbound connection timed out (ORA-3136)

1、现象
alert文件中
Mon Jun 27 11:12:34 2011
WARNING: inbound connection timed out (ORA-3136)

sqlnet.log文件中
Fatal NI connect error 12170.
VERSION INFORMATION:
TNS for Linux: Version 10.2.0.4.0 – Production
Oracle Bequeath NT Protocol Adapter for Linux: Version 10.2.0.4.0 – Production
TCP/IP NT Protocol Adapter for Linux: Version 10.2.0.4.0 – Production
Time: 27-JUN-2011 11:12:34
Tracing not turned on.
Tns error struct:
ns main err code: 12535
TNS-12535: TNS:operation timed out
ns secondary err code: 12606
nt main err code: 0
nt secondary err code: 0
nt OS err code: 0
Client address: (ADDRESS=(PROTOCOL=tcp)(HOST=211.155.227.20)(PORT=2104))

2、原因
Whenever default timeouts are assigned to a parameter, there may be cases where this default does not work well with a particular application. However, some type of timeout on the connection establishment is necessary to combat Denial of Service attacks on the database. In this case, SQLNET.INBOUND_CONNECT__TIMEOUT and INBOUND_CONNECT_TIMEOUT_listenername were given default values of 60 seconds in Oracle 10.2. It is these timeout values that can cause the errors described in this note.
Also note that it is possilbe the reason the database is slow to authenticate, may be due to an overloaded Oracle database or node.

3、解决
1). set INBOUND_CONNECT_TIMEOUT_listenername=0 in listener.ora
2). set SQLNET.INBOUND_CONNECT_TIMEOUT = 0 in sqlnet.ora of server.
3). stop and start both listener and database.
4). Now try to connect to DB and observe the behaviour

4、具体操作
4.1)修改INBOUND_CONNECT_TIMEOUT_listenername
4.1.1)lsnrctl命令修改
LSNRCTL> set inbound_connect_timeout 0
LSNRCTL>save_config

4.1.2)vi修改
修改listener.ora文件,加入: INBOUND_CONNECT_TIMEOUT_listenername=0

4.2)修改SQLNET.INBOUND_CONNECT__TIMEOUT
修改sqlnet.ora文件,加入: SQLNET.INBOUND_CONNECT__TIMEOUT=0

发表在 ORA-xxxxx, Oracle 监听 | 标签为 | 一条评论