精细审计

本文深入探讨了Oracle FGAC(Fine-Grained Access Control)与VPD(View-Point Dependency)机制的原理与实现,通过实例展示了如何在Oracle数据库中实施精细审计、设置FGA策略、监控特定查询语句,并通过函数实现基于用户的上下文信息对查询条件进行动态调整。同时,阐述了FGAC作为基于行的访问控制策略,以及如何利用VPD实现基于行的数据过滤与行级安全性增强。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

精细审计

精细审计FGA(Fined-Grained Aiditing)能实现比标准审计粒度更细化的审计功能,如当用户对满足指定条件的数据行或列进行了操作才进行审计。

FGA的实现通过dbms_fga包进行。审计结果放在fga_log$中,可通过系统视图dba_fga_audit_trail进行查询。

SQL> begin

 2  dbms_fga.add_policy

 3  (object_schema=>'scott',

 4  object_name=>'emp',

 5 policy_name=>'fga_rows_audit',

 6 audit_condition=>'deptno=10',

 7  enable=>true,

 8 statement_types=>'select,update');

 9  end;

 10  /

 

PL/SQL procedure successfully completed.

【设置FGA审计策略,当scott用户emp表上部门号为10的数据行被查询或修改时即记录审计信息】

 

[oracle@desktop241 ~]$ sqlplus / as sysdba

SQL> select * from dba_audit_policies;

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

SCOTT                    EMP

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

FGA_ROWS_AUDIT

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

deptno=10

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------ ------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

 

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

                                             YES YES NO  YES

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

NO DB+EXTENDED  ANY_COLUMNS

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

SQL> grant select any table to john;

 

Grant succeeded.

 

SQL> grant update any table to john;

 

Grant succeeded.

 

SQL> select timestamp,db_user,os_user,object_schema,object_name,sql_textfrom dba_fga_audit_trail;

 

no rows selected【查询FGA审计结果】

 

[oracle@desktop241 ~]$ sqlplus john/john123

SQL> select * from scott.emp wheredeptno=10;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7782 CLARK      MANAGER         7839 09-JUN-81          2450

      10

 

     7839 KING       PRESIDENT    17-NOV-81          5000

      10

 

     7934 MILLER     CLERK        7782 23-JAN-82          1300

      10

 

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

 

TIMESTAMP   DB_USER

------------ ------------------------------

OS_USER

--------------------------------------------------------------------------------

OBJECT_SCHEMA

------------------------------

OBJECT_NAME

--------------------------------------------------------------------------------

SQL_TEXT

--------------------------------------------------------------------------------

18-OCT-12   JOHN

oracle

SCOTT

 

TIMESTAMP   DB_USER

------------ ------------------------------

OS_USER

--------------------------------------------------------------------------------

OBJECT_SCHEMA

------------------------------

OBJECT_NAME

--------------------------------------------------------------------------------

SQL_TEXT

--------------------------------------------------------------------------------

EMP

select * from scott.emp where deptno=10

【再查FGA审计结果】

SQL> select * from scott.emp wheredeptno=20;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7369 SMITH      CLERK        7902 17-DEC-80           800

      20

 

     7566 JONES      MANAGER         7839 02-APR-81          2975

      20

 

     7788 SCOTT      ANALYST          7566 19-APR-87          3000

      20

 

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7876 ADAMS      CLERK       7788 23-MAY-87         1100

      20

 

     7902 FORD       ANALYST          7566 03-DEC-81          3000

      20

 

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text from dba_fga_audit_trail;

 

TIMESTAMP   DB_USER

------------ ------------------------------

OS_USER

--------------------------------------------------------------------------------

OBJECT_SCHEMA

------------------------------

OBJECT_NAME

--------------------------------------------------------------------------------

SQL_TEXT

--------------------------------------------------------------------------------

18-OCT-12   JOHN

oracle

SCOTT

 

TIMESTAMP   DB_USER

------------ ------------------------------

OS_USER

--------------------------------------------------------------------------------

OBJECT_SCHEMA

------------------------------

OBJECT_NAME

--------------------------------------------------------------------------------

SQL_TEXT

--------------------------------------------------------------------------------

EMP

select * from scott.emp where deptno=10

 

 

SQL>update scott.emp set sal=sal*1.1 where deptno=10;

 

3 rows updated.

 

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

update scott.emp set sal=sal*1.1 wheredeptno=10

 

SQL> execdbms_fga.drop_policy('scott','emp','fga_rows_audit');

 

PL/SQL procedure successfully completed.

 

SQL> truncate table fga_log$;

 

Table truncated.

SQL> begin

 2  dbms_fga.add_policy

 3  (object_schema=>'scott',

 4  object_name=>'emp',

 5 policy_name=>'fga_columns_audit',

 6  audit_column=>'sal',

 7  enable=>true,

 8  statement_types=>'select');

 9  end;

 10  /

 

PL/SQL procedure successfully completed.

【再设FGA审计策略,当scott用户emp表上sal列被查询时即记录审计信息】

测试:

SQL> select sal from scott.emp wheredeptno=10;

 

      SAL

----------

     2695

     5500

     1430

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text from dba_fga_audit_trail;

EMP

select sal from scott.emp where deptno=10

 

SQL> select ename from scott.emp wheredeptno=10;

 

ENAME

----------

CLARK

KING

MILLER

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

select sal from scott.emp where deptno=10

 

SQL> select ename from scott.emp wheredeptno=10 and sal>3000;

 

ENAME

----------

KING

 

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

 

--------------------------------------------------------------------------------

EMP

select ename from scott.emp where deptno=10and sal>3000

 

SQL> execdbms_fga.drop_policy('scott','emp','fga_columns_audit');

 

PL/SQL procedure successfully completed.

 

SQL> truncate table fga_log$;

 

Table truncated.

 

SQL> get fga.add

 1  begin

 2  dbms_fga.add_policy

 3  (object_schema=>'scott',

 4  object_name=>'emp',

 5  policy_name=>'fga_audit',

 6 audit_condition=>'deptno=10',

 7  audit_column=>'sal',

 8  enable=>true,

 9  statement_types=>'select');

 10*end;

 11  /

 

PL/SQL procedure successfully completed.

【再设FGA审计策略,当scott用户emp表上deptno为10的数据库行的sal列被查询时即记录审计信息。即当audit_condition与audit_column指定的条件都满足时将进行FGA审计记录】

测试:

SQL> select empno from scott.emp;

 

    EMPNO

----------

     7369

     7499

     7521

     7566

     7654

     7698

     7782

     7788

     7839

     7844

     7876

 

    EMPNO

----------

     7900

     7902

     7934

 

14 rows selected.

 

SQL> show user;

USER is "JOHN"

SQL> select timestamp,db_user,os_user,object_schema,object_name,sql_textfrom dba_fga_audit_trail;

 

no rows selected

SQL> select empno,sal from scott.emp;

 

    EMPNO        SAL

---------- ----------

     7369    800

     7499  1600

     7521  1250

     7566  2975

      7654  1250

     7698  2850

     7782  2695

     7788  3000

     7839  5500

     7844  1500

     7876  1100

 

    EMPNO        SAL

---------- ----------

     7900    950

     7902  3000

     7934  1430

 

14 rows selected.

 

SQL> select timestamp,db_user,os_user,object_schema,object_name,sql_textfrom dba_fga_audit_trail;

 

no rows selected

 

SQL_TEXT

--------------------------------------------------------------------------------

EMP

select empno,sal from scott.emp

SQL> select empno,sal from scott.emp;

 

    EMPNO        SAL

---------- ----------

     7369    800

     7499  1600

     7521  1250

     7566  2975

     7654  1250

     7698  2850

     7782  2450

     7788  3000

     7839  5000

     7844  1500

     7876  1100

 

    EMPNO        SAL

---------- ----------

     7900    950

     7902  3000

     7934  1300

 

14 rows selected.

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

 

SQL> show user;

USER is "SCOTT"

 

SQL_TEXT

--------------------------------------------------------------------------------

EMP

select empno,sal from scott.emp

 

SQL> execdbms_fga.drop_policy('scott','emp','fga_audit');

 

PL/SQL procedure successfully completed.

 

SQL> truncate table fga_log$;

 

Table truncated.【查自己的表记录,sys用户查不记录】

强制审计

【记录以sysdba身份登录数据库的动作,默认生效,不依赖于参数设置,在数据库关闭时也同样生效】

SQL> show parameter audit_file_dest;

 

NAME                         TYPE   VALUE

----------------------------------------------- ------------------------------

audit_file_dest              string   /u01/app/oracle/admin/ora10/ad

                                   ump

[oracle@desktop241 ~]$ sqlplus / as sysdba

[oracle@desktop241 ~]$ ps -ef | grepV$SPID;

oracle  30705 30589  0 22:56 pts/4    00:00:00 grep V

 

 

[oracle@desktop241 adump]$ vimora10_ora_30582_1.aud

Thu Oct 18 22:53:41 2012

LENGTH : '158'

ACTION :[7] 'CONNECT'

DATABASE USER:[1] '/'

PRIVILEGE :[6] 'SYSDBA'

CLIENT USER:[6] 'oracle'

CLIENT TERMINAL:[5] 'pts/1'

STATUS:[1] '0'

DBID:[9] '775040288'

 

VPD虚拟专用数据库(virtual private database)

虚拟专用数据库(VPD)提供了角色视图无法提供的行级访问控制,如实现每个销售用户登录后只能访问销售表中自己的销售中自己的销售记录。具体实现过程为:

1.   先设置应用程序上下文A(应用程序上下文是一个数据库对象,在整个session周期内保存session的各项属性如登录用户名,类似于环境变量)用来保存用户登录时的登录名;

2.   再在用户登录时由触发器C执行预设定好的程序单元B 获取用户名并保存在应用程序上下文A中;

3.   预设定好的审计规则E在监控到销售用户执行销售记录的查询语句时,由预设定好的程序单元D在用户执行的查询语句后隐式添加指定条件,如当销售用户执行select * from sales时系统自动转换为select * from sales where seller=’s001’;

建立测试环境

SQL> create table scott.sales(product_id varchar(4),price number,qtys number,seller varchar(4));

 

Table created.

 

SQL> insert into scott.sales values('0001',1000,1,'s001');

 

1 row created.

 

SQL> insert into scott.sales values('0002',2000,2,'s002');

 

1 row created.

 

SQL> create user s001 identified bys001;

 

User created.

 

SQL> create user s002 identified bys002;

 

User created.

 

SQL> create user mgr identified by mgr;

 

User created.

 

SQL> grant connect,resource,select anytable to s001;

 

Grant succeeded.

 

SQL> grant connect,resource,select anytable to s002;

 

Grant succeeded.

 

SQL> grant connect,resource,select anytable to mgr;

 

Grant succeeded.

[oracle@desktop241 ~]$ sqlplus s001/s001

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001        1000       1 s001

0002        2000       2 s002

 

SQL> connect s002/s002

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001        1000       1 s001

0002        2000       2 s002

 

SQL> connect mgr/mgr

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001        1000       1 s001

0002        2000       2 s002

【测试3个用户均能查到sales销售表中所有数据,VPD需要实现Mgr用户能查所有数据,而s001和s002只能查到自己的销售数据】

A.   B建立应用程序上下文A(保存登录用户名)和存储过程B(获取登录用户名)

SQL> connect / as sysdba

Connected.

SQL> create or replacecontext vpd_context using scott.vpd_get_username;

【建立应用程序上下文vpd_context,其中所保存的属性由存储过程scott.vpd_get_username(即存储过程B)赋予】

Context created.

 

SQL> create or replaceprocedure scott.vpd_get_username is begin

  2 dbms_session.set_context('vpd_context','seller',user);

  3  end;

  4  /

【建立存储过程,为vpd_context建立属性名seller,用来保存属性值user】

Procedure created.

SQL> grant execute on scott.vpd_get_username to public;

【将存储过程的执行权限赋给所有用户】

Grant succeeded.

C.建立触发器C(自动获取登录用户名)

SQL>create or replace trigger get_username_on_logon

  2 after logon on database

  3 begin

  4 scott.vpd_get_username;

  5  end;

  6  /

【建立触发器,用于用户登录后自动执行存储过程vpd_get_username获取用户名存入应用程序上下文vpd_context中】

Trigger created.

 

SQL> connect s001/s001

Connected.

SQL> selectsys_context('vpd_context','seller')from dual;

 

SYS_CONTEXT('VPD_CONTEXT','SELLER')

--------------------------------------------------------------------------------

S001

 

SQL> connect s002/s002

Connected.

SQL> selectsys_context('vpd_context','seller')from dual;

 

SYS_CONTEXT('VPD_CONTEXT','SELLER')

--------------------------------------------------------------------------------

S002

 

SQL> connect mgr/mgr

Connected.

SQL> selectsys_context('vpd_context','seller')from dual;

 

SYS_CONTEXT('VPD_CONTEXT','SELLER')

--------------------------------------------------------------------------------

MGR

【测试应用程序上下文vpd_context是否生效,其属性seller中是否包含用户名属性值】

D.建立函数D(在用户执行的语句后隐式添加指定条件)

SQL> create or replace function scott.vpd_add_condition

  2  (p_schema_name varchar2,p_tab_name varchar2)

  3  return varchar2 is

  4  v_namevarchar2(100):=upper(sys_context('vpd_context','seller'));

  5  v_condition varchar2(2000);

  6  begin

  7  if v_name like 's%' thenv_condition:='seller='||''''||v_name||'''';

  8                      else v_condition:=null;

 9  end if;

 10 return v_condition;

 11  end;

 12  /

 

Function created.

【建立函数D,在用户执行的查询语句后隐式添加指定条件。如当销售用户执行语句select * fromsales时系统自动转换为select *from sales where seller=’s001’;而当非销售用户mgr执行语句时,则不添加指定条件(Null),其中p_schema_name和p_tab_name两变量值为FGAC规则函数必须的两个传入参数,分别用来表示对哪个schema下的哪个table 添加FGAC规则】

FGAC即FINE_CRAINED ACCESS CONTROL,即对数据行进行过滤的VPD,即提供行级安全性的VPD,即基于行的VPD。

E.建立审计规则E(监控销售表上执行的查询语句)

 

SQL>begin dbms_rls.add_policy

  2 (object_schema=>'scott',

  3 object_name=>'sales',

  4 policy_name=>'fgac_vpd',

  5 function_schema=>'scott',

  6 policy_function=>'vpd_add_condition',

  7 statement_types=>'select',

  8 enable=>true);

  9  end;

 10  /

 

PL/SQL procedure successfully completed.

【建立审计规则E,监控到sales销售表上执行查询语句时,就调用vpd_add_condition函数进行处理】

测试结果:

 

SQL> conn S001/S001

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001         100       1 S001

 

SQL> conn scott/tiger

Connected.

SQL> select * from scott.sales;

 

no rows selected

 

SQL> conn S002/S002

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0002         200       2 S002

 

SQL> conn mgr/mgr

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001         100       1 S001

0002         200       2 S002

 

SQL> conn system/song

Connected.

SQL> select * from scott.sales;

 

no rows selected

 

SQL> conn sys/song  as sysdba

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001         100       1 S001

0002         200       2 S002

 

 

 

基于列的VPD

仅有具有权限的用户才能访问敏感列,敏感列,否则列数据被屏蔽

 

SQL> create or replace functionscott.vpd_col_condition

 2  (p_owner varchar2,p_objvarchar2)

 3  return varchar2 is

 4  v_condition varchar2(2000);

 5  begin

 6  if (p_owner=user)thenv_condition:=null;

 7                  elsev_condition:='1=2';

 8  end if;

 9  return v_condition;

 10  end;

 11  /

【建立规则函数,判断执行查询语句的用户是不是表的属主,是则不做限制,不是则添加条件1=2】

Function created.

 

SQL> begin dbms_rls.add_policy

 2  (object_schema=>'scott',

 3  object_name=>'emp',

 4  policy_name=>'fgac_col_vpd',

 5  function_schema=>'scott',

 6 policy_function=>'vpd_col_condition',

 7  statement_types=>'select',

 8  sec_relevant_cols=>'sal',

 9  sec_relevant_cols_opt=>dbms_rls.all_rows);

 10  end;

 11  /

 

PL/SQL procedure successfully completed.

【建立审计规则,监控到emp表上执行查询语句时,就调用vpd_col_condition函数判断执行查询语句的用户是不是表的属主,是则不做限制,不是则对所有记录(由参数sec_relevant_cols_opt=>dbms_rls.all_rows指定)的sal列(sec_relevant_cols=>’sal’指定)单独添加条件1=2(即隐藏该列数据)】

SQL> conn scott/tiger

Connected.

SQL> select * from scott.emp;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7369 SMITH      CLERK        7902 17-DEC-80           800

      20

 

     7499 ALLEN      SALESMAN        7698 20-FEB-81          1600    300

      30

 

     7521 WARD       SALESMAN       7698 22-FEB-81          1250    500

SQL> conn mgr/mgr

Connected.

SQL> select * from scott.emp;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7369 SMITH      CLERK        7902 17-DEC-80

      20

 

     7499 ALLEN      SALESMAN        7698 20-FEB-81                  300

      30

 

     7521 WARD       SALESMAN       7698 22-FEB-81                  500

      30

SQL> conn / as sysdba

Connected.

SQL> select * from scott.emp;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7369 SMITH      CLERK        7902 17-DEC-80           800

      20

 

     7499 ALLEN      SALESMAN        7698 20-FEB-81          1600    3

 

TDE透明数据加密(transparent database encryption)

使用VPD可对敏感信息进行保护,但无法阻止用户直接从数据文件dump出重要信息,实际工程中常在应用程序代码中调用特定加密函数对数据加密,但要求熟悉应用程序。

Oracle的TDE在数据写入磁盘前调用钱包wallet文件中的密钥自动加密数据(支持3DES168,AES128,AES192,AES256等加密算法),查询时则调用钱包wallet文件中的密钥自动解密,简化了成本和复杂性,但其只将数据在存储级别进行了加密,不能阻止用户通过查询语句查询敏感数据,故应将VPD,TDE等方法结合起来保护数据。

Sys用户的表不能被加密

SQL> host mkdir/u01/app/oracle/admin/ora10/wallet

【指定钱包默认存储路径】

SQL> alter system set encryption keyidentified by song;

【创建钱包文件并设置钱包访问口令】

System altered.

 

SQL> host ls -l$ORACLE_BASE/admin/ora10/wallet/

总计 4【查看生成的钱包文件】

-rw------- 1 oracle oinstall 1309 10-1916:19 ewallet.p12

SQL> create table scott.tde(idnumber,name char(10) encrypt using 'AES128' no salt);

【利用钱包使用AES128算法对新建表 指定列进行加密,加密时不使用随机字符串增强密码强度( salt,使得相同明文加密后密文不同,)以使能在加密列上建立索引】

Table created.

测试:

SQL> insert into scott.tde values (0001,'aaa');

 

1 row created.

 

SQL> insert into scott.tde values(0002,'bbb');

 

1 row created.

 

SQL> insert into scott.tde values(0002,'ccc');

 

1 row created.

 

SQL> select * from scott.tde;

 

      IDNAME

---------- ----------

       1 aaa

       2 bbb

       2 ccc

SQL> alter system set encryption walletclose;

 

System altered.

 

SQL> select * from scott.tde;

select * from scott.tde

                    *

ERROR at line 1:

ORA-28365: wallet is not open

 

 

SQL> select id from scott.tde;

 

      ID

----------

       1

       2

       2

 

SQL> alter system set encryption walletopen authenticated by song;

 

System altered.

 

SQL> select * from scott.tde;

 

      IDNAME

---------- ----------

       1 aaa

       2 bbb

       2 ccc

 

SQL> alter table scott.tde modify namechar(10) decrypt;

【取消列加密】

Table altered.

 

SQL> alter system set encryption walletclose;

 

System altered.

 

SQL> select * from scott.tde;

 

      IDNAME

---------- ----------

       1 aaa

       2 bbb

       2 ccc

加密备份数据

SQL> alter system set encryption walletopen authenticated by song;

 

System altered.

RMAN> connect target sys/song

 

connected to target database: ORA10(DBID=775040288)

using target database control file insteadof recovery catalog

 

RMAN> configure encryption for databaseon;

 

new RMAN configuration parameters:

CONFIGURE ENCRYPTION FOR DATABASE ON;

new RMAN configuration parameters aresuccessfully stored

 

RMAN> backup tablespace users;

 

Starting backup at 19-OCT-12

allocated channel: ORA_DISK_1

channel ORA_DISK_1: sid=143 devtype=DISK

channel ORA_DISK_1: starting full datafilebackupset

channel ORA_DISK_1: specifying datafile(s)in backupset

input datafile fno=00004name=/u01/app/oracle/oradata/ora10/users01.dbf

channel ORA_DISK_1: starting piece 1 at19-OCT-12

channel ORA_DISK_1: finished piece 1 at19-OCT-12

piece handle=/backup/backup_0pno5hvm_1_1 tag=TAG20121019T164022comment=NONE

channel ORA_DISK_1: backup set complete,elapsed time: 00:00:03

Finished backup at 19-OCT-12

 

Starting Control File and SPFILE Autobackupat 19-OCT-12

piecehandle=/u01/app/oracle/flash_recovery_area/ORA10/autobackup/2012_10_19/o1_mf_s_797100026_8824hysg_.bkpcomment=NONE

Finished Control File and SPFILE Autobackupat 19-OCT-12

【打开钱包,配置RMAN为透明加密模式,则备份数据时利用钱包进行加密,恢复时也需打开钱包才能进行,适合备份和恢复都在本地进行的备份模式

RMAN> set encryption identified by song1only;

 

executing command: SET encryption

 

RMAN> backup tablespace users;

 

Starting backup at 19-OCT-12

using channel ORA_DISK_1

channel ORA_DISK_1: starting full datafilebackupset

channel ORA_DISK_1: specifying datafile(s)in backupset

input datafile fno=00004name=/u01/app/oracle/oradata/ora10/users01.dbf

channel ORA_DISK_1: starting piece 1 at19-OCT-12

channel ORA_DISK_1: finished piece 1 at19-OCT-12

piece handle=/backup/backup_0rno5i71_1_1tag=TAG20121019T164417 comment=NONE

channel ORA_DISK_1: backup set complete,elapsed time: 00:00:02

Finished backup at 19-OCT-12

 

Starting Control File and SPFILE Autobackupat 19-OCT-12

piecehandle=/u01/app/oracle/flash_recovery_area/ORA10/autobackup/2012_10_19/o1_mf_s_797100259_8824q3st_.bkpcomment=NONE

Finished Control File and SPFILE Autobackupat 19-OCT-12

【不使用钱包,配置RMAN为密码加密模式,则恢复时必须提供备份时所指定的密码(set decryption)才能进行,适合备份在本地,恢复在异地的备份模式】

RMAN> set decryption identified bysong1;

 

executing command: SET decryption

 

RMAN> set encryption identified bysong2;

 

executing command: SET encryption

 

RMAN> backup tablespace users;

 

Starting backup at 19-OCT-12

using channel ORA_DISK_1

channel ORA_DISK_1: starting full datafilebackupset

channel ORA_DISK_1: specifying datafile(s)in backupset

input datafile fno=00004name=/u01/app/oracle/oradata/ora10/users01.dbf

channel ORA_DISK_1: starting piece 1 at19-OCT-12

channel ORA_DISK_1: finished piece 1 at19-OCT-12

piece handle=/backup/backup_0tno5iii_1_1tag=TAG20121019T165026 comment=NONE

channel ORA_DISK_1: backup set complete,elapsed time: 00:00:01

Finished backup at 19-OCT-12

 

Starting Control File and SPFILE Autobackupat 19-OCT-12

piecehandle=/u01/app/oracle/flash_recovery_area/ORA10/autobackup/2012_10_19/o1_mf_s_797100627_88252n6k_.bkpcomment=NONE

Finished Control File and SPFILE Autobackupat 19-OCT-12

 

RMAN> set decryption identified bysong2;

 

executing command: SET decryption

【使用钱包和密码,配置RMAN为混合加密模式,则恢复时打开钱包,或者提供备份时所指定的密码均可进行,适合恢复即可能在本地,也可能在异地进行的备份模式】

LOCK   &  LATCH

Lock

独占锁(X锁)与共享锁(S锁)

SQL> update t1 set id=2 where id=1;

 

1 row updated.

SQL> update t1 set id=3 where id=1;

Waiting….

【为保证数据的一致性,会话1在修改记录时在记录上加了独占锁(exclusive,简称x锁),又称排他锁,以防止事务在提交或回退前记录被其他事务同时修改。

一旦用户对某个资源添加了x锁,则其他用户都不能再对该资源添加任何类型的锁,直到该用户释放了资源上的x锁为止】

 

SQL> update t1 set id=2 where id=1;

 

1 row updated.

SQL> drop table t1;

drop table t1

          *

ERROR at line 1:

ORA-00054: resource busy and acquire withNOWAIT specified

 

【为保证数据的一致性,会话1在修改记录时同时还在表头上加了共享锁(shared ,简称s锁),以便其他删表事务执行前不用检查表中每条记录是否加了独占锁(那就不能删表),而只要检查表头是否存在共享锁就可以了

若删表事务(要对全表加独占锁)进行前,还有另一会话还进行了删除记录操作(且未提交或回退,即事务未结束),那么另一会话在被删记录上加独占锁,同时在表上再加一个共享锁,则删表事务要等到表头上所有共享锁全部取消后(即所有独占事务全部完成后),才能进行(才能对整表施加独占锁)。

一旦用户对某个资源添加了S锁,则其他用户都不能在该资源上添加X,只能添加S锁,直到该用户释放了资源上的s 锁为止】

DML事务锁

根据被保护的对象种类的不同,锁还可以分成多种类型,如因DDL引起的锁,DML事务引起的锁,分布式事务中涉及的锁等,DML事务锁应主要关注。

DML事务锁能保证当某用户正在更新表中某行数据时,其他用户不能同时更新相同的数据行,而且也不能删除或修改被更新的表,包括行锁TX表锁TM

 

前列修改记录时,在行记录上所施加的就是行(独占)锁,对于ORACLE来说,行锁只可能是独占锁;而同时在表头上所施加的就是表(共享)锁,对于ORACLE来说,表锁可能是共享锁(如删表中记录时在表头上所施加的共享锁),也可能是独占锁(如删表操作时需要在表头上所施加的独占锁)。

 

TM表锁的种类

TM表锁即可能是独占锁,也可能是共享锁,可细分为如下几类:

编号                  表锁                    含义

0/1                     无    

2                           RS                row share

3                         RX                  row exclusive

4                         S                    share

5                         SRX                    share+row  exclusive

6                            x                      exclusive

 

A.   select * from table_name不会产生锁;

B.   lock table table_name in rowshare mode 会在表上加RS锁,使用完毕后rollback即解锁。

【当执行相应语句时,系统自动在所要操作的表上申请表级RS锁(意向锁,表示某事务有意向进行锁表),当表上加RS锁后,不许其他事务对该表添加x排他锁(如drop table),但允许其他事务对该表再加除x锁之外的其他锁,如其他事务再对该表加RS锁(再执行lock table in row share mode),或其他事务再对该表加RX锁(再执行插删改DML操作),或其他事务再对该表加S锁(再执行建索引操作)等】

 

SQL> create table t4 (id number);

 

Table created.

 

SQL> insert into t4 values (1);

 

1 row created.

 

SQL> insert into t4 values(10);

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> lock table t4 in row share mode;

 

Table(s) Locked.

 

SQL> select sid from v$mystat;

 

       SID

----------

       157

SQL> select * from v$lock where sid=157;

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- -------------------- ---------- ----------

    CTIME BLOCK

---------- ----------

3FB4A54C 3FB4A564 157 TM      55335     0          2       0

      116      0

 

SQL> drop table t4;

drop table t4

          *

ERROR at line 1:

ORA-00054: resource busy and acquire withNOWAIT specified

C/D/E/F.insert/update/ delete DML语句及select * from table_name for  update句会在表上加RX(其中select for update用于在读数据过程中禁止其他事务对所读数据进行DML操作),操作完成后commit或roback解锁。

当执行相应语句时,系统自动在所要操作的表上申请表级RX锁(意向锁,表示某事务有意向要进行锁表),当表级锁获得后,系统再自动申请TX行锁(实体锁,表示该事务的具体锁动作),并将相应数据行加x锁,当表上加RX锁后,不许其他事务对该表再加X排他锁(如drop table),不允许其他事务对该表再加S锁(如建索引);但允许其他事务对该表再加RS锁(如执行lock table inrow share mode)或RX锁(如插删改记录,注意,其他事务在同一表上再加RX表锁没问题,但再加行锁时,不能再加在表内已加X锁的数据行上,而只许加在表内其他数据行上。

对表施加RX锁也可以通过手工执行Lock table table_name in rowexclusive mode进行显示加锁,执行后即对表施加了RX锁(但未对数据行申请加TX行锁),直到rollback释放。

RS与RX区别:

1.   产生条件不同。

2.   RX锁后,其他事务读不到更改后的结果。而RS对其他事务而言读是没有问题的,故称RS,虽都是指在表的层面上防止其他事务锁表,但RX是 forexclusive reading or writing,而RS是for exclusive write access.这也是RS的S(share)表现的地方。

SQL> insert into t4 values (8);

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> update t4 set id=9 where id<=3;

 

4 rows updated.

 

SQL> select * from v$mystat;

 

       SID STATISTIC#     VALUE

---------- ---------- ----------

       145       0          1

       145       1          1

 

SQL> select * from v$lock where sid=145;

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME  BLOCK

---------- ----------

3FB4A54C 3FB4A564 145 TM      55336     0           3       0

       131       0

 

3FB85DF8 3FB85E1C 145TX     458775   597           6       0

 

SQL> rollback;

 

SQL> select * from v$lock where sid=145;

 

ADDR    KADDR      SID TY       ID1   ID2       LMODE    REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME  BLOCK

---------- ----------

3FB4A54C 3FB4A564 145 TM      55336     0           3       0

       172       0

 

3FB85DF8 3FB85E1C 145 TX     458775   597           6       0

       172       0

SQL> select xidusn,xidslot,xidsqn,status from v$transaction;

 

    XIDUSN    XIDSLOT   XIDSQN STATUS

---------- ---------- ---------- ----------------

 7      23         597 ACTIVE

 

SQL> select sid,type,id1,id2,lmode,request,block from v$lockwhere sid=145;

 

       SID TY        ID1     ID2 LMODE        REQUEST     BLOCK

---------- -- ---------- ---------- ---------- ---------- ----------

       145 TM     55336       0      3        0       0

       145 TX     458775    597      6        0       0

 

SQL> select object_name from dba_objects where object_id='55336';

 

OBJECT_NAME

--------------------------------------------------------------------------------

T4

 

SQL> select trunc(458775/power(2,16)) from dual;

 

TRUNC(458775/POWER(2,16))

-------------------------

            7

 

SQL> select bitand (458775,to_number('ffff','xxxx'))+0 from dual;

 

BITAND(458775,TO_NUMBER('FFFF','XXXX'))+0

-----------------------------------------

                         23

 

SQL> show parameter transactions

 

NAME                          TYPE   VALUE

------------------------------------ -----------------------------------------

transactions                  integer 187

transactions_per_rollback_segment   integer 5

SQL> show parameter dml_locks;

 

NAME                          TYPE   VALUE

------------------------------------ -----------------------------------------

dml_locks                     integer 748

 

【TX数量和事务个数相同,并受transactions参数(默认187)限制,TM锁数量和被更新的表的个数相同,并受dml_locks参数(默认748)限制,即默认情况下可同时启动187个事务,更新748个表,平均允许每个事务同时更新4个表】

SQL> select resource_name,initial_allocation,current_utilization,max_utilizationfrom v$resource_limit where resource_name in ('transactions','dml_locks');

 

RESOURCE_NAME                 INITIAL_ALLOCATION   CURRENT_UTILIZATION

------------------------------ ---------------------------------------

MAX_UTILIZATION

---------------

dml_locks                     748                     0

     44

 

transactions                   187                     0

      9

【查看当前TX/TM锁的使用情况,包括能够分配的最大个数,当前分配的个数,及曾经分配的最大个数】

SQL> update t4 set id=10 where id<10;

 

9 rows updated.

 

SQL> update t4 set id=10 where id<=10;

 

SQL> select sid,type,id1,id2,lmode,request,block from v$lockwhere sid in (145,158) order by sid desc;

 

       SID TY        ID1     ID2 LMODE        REQUEST     BLOCK

---------- -- ---------- ---------- ---------- ---------- ----------

       158 TM     55336       0      3        0       0

       158 TX     196619    637      0        6       0

       145 TX     196619    637      6        0       1

       145 TM     55336       0      3        0       0

 

Create index on table语句会在表上加S锁,操作完成后即解锁。

创建索引时,需要读表中所有数据,且在读数据过程中数据不能由其他事务进行更新,此时需要对表加S锁,S锁用于保证在操作期间整个表上不能再由其他事务加RX锁(进行插删改操作)及X锁(不能删表),因为若在创建索引时,允许有未提交的其他插删改事务发生,而新的数据是不会被索引的,则将造成数据和索引间的不一致。因为S和RX锁是互斥的,所以当某事务在表上有未提交插删改事务时(以加RX锁),另一事务不能创建索引(无法再加S锁)。或者反之,当创建索引动作还没结束时(S锁未释放),其他事务即不可以在表上开始插删改事务(无法获得RX锁)。

当表上加S锁后,不许其他事务对该表再加X排他锁(如drop table),不允许其他事务对该表再加RX锁(如插删改记录);但允许其他事务对该表再加RS锁(如执行LOCK table inrow  share mode).

对表施加S锁也可以通过手工执行lock table table_name in share mode 进行显式加锁,执行后即对表施加了S 锁,其他事务对该表即不能进行数据插删改及删表操作,直到rollback释放。

 

SQL> update t4 set id=10 where id=10;

 

0 rows updated.

 

SQL> select * from v$lock where sid=158;

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME BLOCK

---------- ----------

3FB4A608 3FB4A620 158 TM      55336     0           3       0

      21      0

 

 

SQL> create index i4 on t4 (id);

create index i4 on t4 (id)

                   *

ERROR at line 1:

ORA-00054: resource busy and acquire with NOWAIT specified

 

SQL> select * from v$lock where sid=158;

 

no rows selected

 

SQL> create index i4 on t4 (id);

create index i4 on t4 (id)

                   *

ERROR at line 1:

ORA-00054: resource busy and acquire with NOWAIT specified

SQL> lock table t4 in share mode;

 

SQL> select * from v$lock where sid in (158,145);

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME BLOCK

---------- ----------

3FB4A54C 3FB4A564 145 TM      55336     0           3       0

      2185      0

 

3FB86364 3FB86388 145 TX     196619   637           6       0

      2185      0

 

SQL> select * from v$lock where sid in (145,158,148);

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME BLOCK

---------- ----------

3FB4A54C 3FB4A564 145 TM      55336     0           5       0

       179      1

 

3FB4A6C4 3FB4A6DC     148TM      55336     0           0       3

      60      0

 

3FB4A780 3FB4A798 158 TM      55336     0           0       3

      33      0

 

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME BLOCK

---------- ----------

3FB86364 3FB86388 145 TX     458790   575           6       0

       179      0

 

如果对一个数据库对象加SRX锁,表示对它加S锁,再加RX锁,即SRX=S+RX.例如事务对某个表加SRX锁,则表示该事务需要读表中所有数据,且在读数据过程中数据不能由其他事务进行更新(所以要对该表加S锁),同时本事务会更新个别行(所以要对该表加RX锁),注意,表上加S锁后再由本事务加RX锁是允许的,而表上加S锁后再由其他事务加RX锁是不允许的。

对表施加SRX锁也可以通过手工执行lock table table_name in share row exclusive mode 进行显式加锁,执行后即对表施加了SRX锁,其他事务对该表即不能进行数据插删改及删表操作,直到rollback释放。

 

 

执行Alter table,drop table ,drop index,truncatetable操作时,需要对表加X锁,X锁是限制级别最高的锁。对表加X锁后,不能进行其他任何锁操作。

对表施加X锁也可以通过手工执行lock table table_name in exclusive mode 进行显式加锁,执行后即对表施加了x锁,其他事务对该表即不能进行任何其他加锁操作,直到rollback释放。

死锁deadlock

精细审计

精细审计FGA(Fined-Grained Aiditing)能实现比标准审计粒度更细化的审计功能,如当用户对满足指定条件的数据行或列进行了操作才进行审计。

FGA的实现通过dbms_fga包进行。审计结果放在fga_log$中,可通过系统视图dba_fga_audit_trail进行查询。

SQL> begin

 2  dbms_fga.add_policy

 3  (object_schema=>'scott',

 4  object_name=>'emp',

 5 policy_name=>'fga_rows_audit',

 6 audit_condition=>'deptno=10',

 7  enable=>true,

 8 statement_types=>'select,update');

 9  end;

 10  /

 

PL/SQL procedure successfully completed.

【设置FGA审计策略,当scott用户emp表上部门号为10的数据行被查询或修改时即记录审计信息】

 

[oracle@desktop241 ~]$ sqlplus / as sysdba

SQL> select * from dba_audit_policies;

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

SCOTT                    EMP

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

FGA_ROWS_AUDIT

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

deptno=10

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------ ------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

 

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

                                             YES YES NO  YES

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

NO DB+EXTENDED  ANY_COLUMNS

 

OBJECT_SCHEMA                 OBJECT_NAME

------------------------------------------------------------

POLICY_NAME

------------------------------

POLICY_TEXT

--------------------------------------------------------------------------------

POLICY_COLUMN                 PF_SCHEMA

------------------------------------------------------------

PF_PACKAGE                  PF_FUNCTION                ENA SEL INS UPD

------------------------------------------------------------ --- --- --- ---

DEL AUDIT_TRAIL  POLICY_COLU

--- ------------ -----------

SQL> grant select any table to john;

 

Grant succeeded.

 

SQL> grant update any table to john;

 

Grant succeeded.

 

SQL> select timestamp,db_user,os_user,object_schema,object_name,sql_textfrom dba_fga_audit_trail;

 

no rows selected【查询FGA审计结果】

 

[oracle@desktop241 ~]$ sqlplus john/john123

SQL> select * from scott.emp wheredeptno=10;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7782 CLARK      MANAGER         7839 09-JUN-81          2450

      10

 

     7839 KING       PRESIDENT    17-NOV-81          5000

      10

 

     7934 MILLER     CLERK        7782 23-JAN-82          1300

      10

 

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

 

TIMESTAMP   DB_USER

------------ ------------------------------

OS_USER

--------------------------------------------------------------------------------

OBJECT_SCHEMA

------------------------------

OBJECT_NAME

--------------------------------------------------------------------------------

SQL_TEXT

--------------------------------------------------------------------------------

18-OCT-12   JOHN

oracle

SCOTT

 

TIMESTAMP   DB_USER

------------ ------------------------------

OS_USER

--------------------------------------------------------------------------------

OBJECT_SCHEMA

------------------------------

OBJECT_NAME

--------------------------------------------------------------------------------

SQL_TEXT

--------------------------------------------------------------------------------

EMP

select * from scott.emp where deptno=10

【再查FGA审计结果】

SQL> select * from scott.emp wheredeptno=20;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7369 SMITH      CLERK        7902 17-DEC-80           800

      20

 

     7566 JONES      MANAGER         7839 02-APR-81          2975

      20

 

     7788 SCOTT      ANALYST          7566 19-APR-87          3000

      20

 

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7876 ADAMS      CLERK       7788 23-MAY-87         1100

      20

 

     7902 FORD       ANALYST          7566 03-DEC-81          3000

      20

 

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text from dba_fga_audit_trail;

 

TIMESTAMP   DB_USER

------------ ------------------------------

OS_USER

--------------------------------------------------------------------------------

OBJECT_SCHEMA

------------------------------

OBJECT_NAME

--------------------------------------------------------------------------------

SQL_TEXT

--------------------------------------------------------------------------------

18-OCT-12   JOHN

oracle

SCOTT

 

TIMESTAMP   DB_USER

------------ ------------------------------

OS_USER

--------------------------------------------------------------------------------

OBJECT_SCHEMA

------------------------------

OBJECT_NAME

--------------------------------------------------------------------------------

SQL_TEXT

--------------------------------------------------------------------------------

EMP

select * from scott.emp where deptno=10

 

 

SQL>update scott.emp set sal=sal*1.1 where deptno=10;

 

3 rows updated.

 

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

update scott.emp set sal=sal*1.1 wheredeptno=10

 

SQL> execdbms_fga.drop_policy('scott','emp','fga_rows_audit');

 

PL/SQL procedure successfully completed.

 

SQL> truncate table fga_log$;

 

Table truncated.

SQL> begin

 2  dbms_fga.add_policy

 3  (object_schema=>'scott',

 4  object_name=>'emp',

 5 policy_name=>'fga_columns_audit',

 6  audit_column=>'sal',

 7  enable=>true,

 8  statement_types=>'select');

 9  end;

 10  /

 

PL/SQL procedure successfully completed.

【再设FGA审计策略,当scott用户emp表上sal列被查询时即记录审计信息】

测试:

SQL> select sal from scott.emp wheredeptno=10;

 

      SAL

----------

     2695

     5500

     1430

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text from dba_fga_audit_trail;

EMP

select sal from scott.emp where deptno=10

 

SQL> select ename from scott.emp wheredeptno=10;

 

ENAME

----------

CLARK

KING

MILLER

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

select sal from scott.emp where deptno=10

 

SQL> select ename from scott.emp wheredeptno=10 and sal>3000;

 

ENAME

----------

KING

 

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

 

--------------------------------------------------------------------------------

EMP

select ename from scott.emp where deptno=10and sal>3000

 

SQL> execdbms_fga.drop_policy('scott','emp','fga_columns_audit');

 

PL/SQL procedure successfully completed.

 

SQL> truncate table fga_log$;

 

Table truncated.

 

SQL> get fga.add

 1  begin

 2  dbms_fga.add_policy

 3  (object_schema=>'scott',

 4  object_name=>'emp',

 5  policy_name=>'fga_audit',

 6 audit_condition=>'deptno=10',

 7  audit_column=>'sal',

 8  enable=>true,

 9  statement_types=>'select');

 10*end;

 11  /

 

PL/SQL procedure successfully completed.

【再设FGA审计策略,当scott用户emp表上deptno为10的数据库行的sal列被查询时即记录审计信息。即当audit_condition与audit_column指定的条件都满足时将进行FGA审计记录】

测试:

SQL> select empno from scott.emp;

 

    EMPNO

----------

     7369

     7499

     7521

     7566

     7654

     7698

     7782

     7788

     7839

     7844

     7876

 

    EMPNO

----------

     7900

     7902

     7934

 

14 rows selected.

 

SQL> show user;

USER is "JOHN"

SQL> select timestamp,db_user,os_user,object_schema,object_name,sql_textfrom dba_fga_audit_trail;

 

no rows selected

SQL> select empno,sal from scott.emp;

 

    EMPNO        SAL

---------- ----------

     7369    800

     7499  1600

     7521  1250

     7566  2975

      7654  1250

     7698  2850

     7782  2695

     7788  3000

     7839  5500

     7844  1500

     7876  1100

 

    EMPNO        SAL

---------- ----------

     7900    950

     7902  3000

     7934  1430

 

14 rows selected.

 

SQL> select timestamp,db_user,os_user,object_schema,object_name,sql_textfrom dba_fga_audit_trail;

 

no rows selected

 

SQL_TEXT

--------------------------------------------------------------------------------

EMP

select empno,sal from scott.emp

SQL> select empno,sal from scott.emp;

 

    EMPNO        SAL

---------- ----------

     7369    800

     7499  1600

     7521  1250

     7566  2975

     7654  1250

     7698  2850

     7782  2450

     7788  3000

     7839  5000

     7844  1500

     7876  1100

 

    EMPNO        SAL

---------- ----------

     7900    950

     7902  3000

     7934  1300

 

14 rows selected.

SQL> selecttimestamp,db_user,os_user,object_schema,object_name,sql_text fromdba_fga_audit_trail;

 

SQL> show user;

USER is "SCOTT"

 

SQL_TEXT

--------------------------------------------------------------------------------

EMP

select empno,sal from scott.emp

 

SQL> execdbms_fga.drop_policy('scott','emp','fga_audit');

 

PL/SQL procedure successfully completed.

 

SQL> truncate table fga_log$;

 

Table truncated.【查自己的表记录,sys用户查不记录】

强制审计

【记录以sysdba身份登录数据库的动作,默认生效,不依赖于参数设置,在数据库关闭时也同样生效】

SQL> show parameter audit_file_dest;

 

NAME                         TYPE   VALUE

----------------------------------------------- ------------------------------

audit_file_dest              string   /u01/app/oracle/admin/ora10/ad

                                   ump

[oracle@desktop241 ~]$ sqlplus / as sysdba

[oracle@desktop241 ~]$ ps -ef | grepV$SPID;

oracle  30705 30589  0 22:56 pts/4    00:00:00 grep V

 

 

[oracle@desktop241 adump]$ vimora10_ora_30582_1.aud

Thu Oct 18 22:53:41 2012

LENGTH : '158'

ACTION :[7] 'CONNECT'

DATABASE USER:[1] '/'

PRIVILEGE :[6] 'SYSDBA'

CLIENT USER:[6] 'oracle'

CLIENT TERMINAL:[5] 'pts/1'

STATUS:[1] '0'

DBID:[9] '775040288'

 

VPD虚拟专用数据库(virtual private database)

虚拟专用数据库(VPD)提供了角色视图无法提供的行级访问控制,如实现每个销售用户登录后只能访问销售表中自己的销售中自己的销售记录。具体实现过程为:

1.   先设置应用程序上下文A(应用程序上下文是一个数据库对象,在整个session周期内保存session的各项属性如登录用户名,类似于环境变量)用来保存用户登录时的登录名;

2.   再在用户登录时由触发器C执行预设定好的程序单元B 获取用户名并保存在应用程序上下文A中;

3.   预设定好的审计规则E在监控到销售用户执行销售记录的查询语句时,由预设定好的程序单元D在用户执行的查询语句后隐式添加指定条件,如当销售用户执行select * from sales时系统自动转换为select * from sales where seller=’s001’;

建立测试环境

SQL> create table scott.sales(product_id varchar(4),price number,qtys number,seller varchar(4));

 

Table created.

 

SQL> insert into scott.sales values('0001',1000,1,'s001');

 

1 row created.

 

SQL> insert into scott.sales values('0002',2000,2,'s002');

 

1 row created.

 

SQL> create user s001 identified bys001;

 

User created.

 

SQL> create user s002 identified bys002;

 

User created.

 

SQL> create user mgr identified by mgr;

 

User created.

 

SQL> grant connect,resource,select anytable to s001;

 

Grant succeeded.

 

SQL> grant connect,resource,select anytable to s002;

 

Grant succeeded.

 

SQL> grant connect,resource,select anytable to mgr;

 

Grant succeeded.

[oracle@desktop241 ~]$ sqlplus s001/s001

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001        1000       1 s001

0002        2000       2 s002

 

SQL> connect s002/s002

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001        1000       1 s001

0002        2000       2 s002

 

SQL> connect mgr/mgr

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001        1000       1 s001

0002        2000       2 s002

【测试3个用户均能查到sales销售表中所有数据,VPD需要实现Mgr用户能查所有数据,而s001和s002只能查到自己的销售数据】

A.   B建立应用程序上下文A(保存登录用户名)和存储过程B(获取登录用户名)

SQL> connect / as sysdba

Connected.

SQL> create or replacecontext vpd_context using scott.vpd_get_username;

【建立应用程序上下文vpd_context,其中所保存的属性由存储过程scott.vpd_get_username(即存储过程B)赋予】

Context created.

 

SQL> create or replaceprocedure scott.vpd_get_username is begin

  2 dbms_session.set_context('vpd_context','seller',user);

  3  end;

  4  /

【建立存储过程,为vpd_context建立属性名seller,用来保存属性值user】

Procedure created.

SQL> grant execute on scott.vpd_get_username to public;

【将存储过程的执行权限赋给所有用户】

Grant succeeded.

C.建立触发器C(自动获取登录用户名)

SQL>create or replace trigger get_username_on_logon

  2 after logon on database

  3 begin

  4 scott.vpd_get_username;

  5  end;

  6  /

【建立触发器,用于用户登录后自动执行存储过程vpd_get_username获取用户名存入应用程序上下文vpd_context中】

Trigger created.

 

SQL> connect s001/s001

Connected.

SQL> selectsys_context('vpd_context','seller')from dual;

 

SYS_CONTEXT('VPD_CONTEXT','SELLER')

--------------------------------------------------------------------------------

S001

 

SQL> connect s002/s002

Connected.

SQL> selectsys_context('vpd_context','seller')from dual;

 

SYS_CONTEXT('VPD_CONTEXT','SELLER')

--------------------------------------------------------------------------------

S002

 

SQL> connect mgr/mgr

Connected.

SQL> selectsys_context('vpd_context','seller')from dual;

 

SYS_CONTEXT('VPD_CONTEXT','SELLER')

--------------------------------------------------------------------------------

MGR

【测试应用程序上下文vpd_context是否生效,其属性seller中是否包含用户名属性值】

D.建立函数D(在用户执行的语句后隐式添加指定条件)

SQL> create or replace function scott.vpd_add_condition

  2  (p_schema_name varchar2,p_tab_name varchar2)

  3  return varchar2 is

  4  v_namevarchar2(100):=upper(sys_context('vpd_context','seller'));

  5  v_condition varchar2(2000);

  6  begin

  7  if v_name like 's%' thenv_condition:='seller='||''''||v_name||'''';

  8                      else v_condition:=null;

 9  end if;

 10 return v_condition;

 11  end;

 12  /

 

Function created.

【建立函数D,在用户执行的查询语句后隐式添加指定条件。如当销售用户执行语句select * fromsales时系统自动转换为select *from sales where seller=’s001’;而当非销售用户mgr执行语句时,则不添加指定条件(Null),其中p_schema_name和p_tab_name两变量值为FGAC规则函数必须的两个传入参数,分别用来表示对哪个schema下的哪个table 添加FGAC规则】

FGAC即FINE_CRAINED ACCESS CONTROL,即对数据行进行过滤的VPD,即提供行级安全性的VPD,即基于行的VPD。

E.建立审计规则E(监控销售表上执行的查询语句)

 

SQL>begin dbms_rls.add_policy

  2 (object_schema=>'scott',

  3 object_name=>'sales',

  4 policy_name=>'fgac_vpd',

  5 function_schema=>'scott',

  6 policy_function=>'vpd_add_condition',

  7 statement_types=>'select',

  8 enable=>true);

  9  end;

 10  /

 

PL/SQL procedure successfully completed.

【建立审计规则E,监控到sales销售表上执行查询语句时,就调用vpd_add_condition函数进行处理】

测试结果:

 

SQL> conn S001/S001

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001         100       1 S001

 

SQL> conn scott/tiger

Connected.

SQL> select * from scott.sales;

 

no rows selected

 

SQL> conn S002/S002

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0002         200       2 S002

 

SQL> conn mgr/mgr

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001         100       1 S001

0002         200       2 S002

 

SQL> conn system/song

Connected.

SQL> select * from scott.sales;

 

no rows selected

 

SQL> conn sys/song  as sysdba

Connected.

SQL> select * from scott.sales;

 

PROD      PRICE      QTYS SELL

---- ---------- ---------- ----

0001         100       1 S001

0002         200       2 S002

 

 

 

基于列的VPD

仅有具有权限的用户才能访问敏感列,敏感列,否则列数据被屏蔽

 

SQL> create or replace functionscott.vpd_col_condition

 2  (p_owner varchar2,p_objvarchar2)

 3  return varchar2 is

 4  v_condition varchar2(2000);

 5  begin

 6  if (p_owner=user)thenv_condition:=null;

 7                  elsev_condition:='1=2';

 8  end if;

 9  return v_condition;

 10  end;

 11  /

【建立规则函数,判断执行查询语句的用户是不是表的属主,是则不做限制,不是则添加条件1=2】

Function created.

 

SQL> begin dbms_rls.add_policy

 2  (object_schema=>'scott',

 3  object_name=>'emp',

 4  policy_name=>'fgac_col_vpd',

 5  function_schema=>'scott',

 6 policy_function=>'vpd_col_condition',

 7  statement_types=>'select',

 8  sec_relevant_cols=>'sal',

 9  sec_relevant_cols_opt=>dbms_rls.all_rows);

 10  end;

 11  /

 

PL/SQL procedure successfully completed.

【建立审计规则,监控到emp表上执行查询语句时,就调用vpd_col_condition函数判断执行查询语句的用户是不是表的属主,是则不做限制,不是则对所有记录(由参数sec_relevant_cols_opt=>dbms_rls.all_rows指定)的sal列(sec_relevant_cols=>’sal’指定)单独添加条件1=2(即隐藏该列数据)】

SQL> conn scott/tiger

Connected.

SQL> select * from scott.emp;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7369 SMITH      CLERK        7902 17-DEC-80           800

      20

 

     7499 ALLEN      SALESMAN        7698 20-FEB-81          1600    300

      30

 

     7521 WARD       SALESMAN       7698 22-FEB-81          1250    500

SQL> conn mgr/mgr

Connected.

SQL> select * from scott.emp;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7369 SMITH      CLERK        7902 17-DEC-80

      20

 

     7499 ALLEN      SALESMAN        7698 20-FEB-81                  300

      30

 

     7521 WARD       SALESMAN       7698 22-FEB-81                  500

      30

SQL> conn / as sysdba

Connected.

SQL> select * from scott.emp;

 

    EMPNO ENAME      JOB          MGR HIREDATE          SAL  COMM

---------- ---------- --------- ---------------------- ---------- ----------

   DEPTNO

----------

     7369 SMITH      CLERK        7902 17-DEC-80           800

      20

 

     7499 ALLEN      SALESMAN        7698 20-FEB-81          1600    3

 

TDE透明数据加密(transparent database encryption)

使用VPD可对敏感信息进行保护,但无法阻止用户直接从数据文件dump出重要信息,实际工程中常在应用程序代码中调用特定加密函数对数据加密,但要求熟悉应用程序。

Oracle的TDE在数据写入磁盘前调用钱包wallet文件中的密钥自动加密数据(支持3DES168,AES128,AES192,AES256等加密算法),查询时则调用钱包wallet文件中的密钥自动解密,简化了成本和复杂性,但其只将数据在存储级别进行了加密,不能阻止用户通过查询语句查询敏感数据,故应将VPD,TDE等方法结合起来保护数据。

Sys用户的表不能被加密

SQL> host mkdir/u01/app/oracle/admin/ora10/wallet

【指定钱包默认存储路径】

SQL> alter system set encryption keyidentified by song;

【创建钱包文件并设置钱包访问口令】

System altered.

 

SQL> host ls -l$ORACLE_BASE/admin/ora10/wallet/

总计 4【查看生成的钱包文件】

-rw------- 1 oracle oinstall 1309 10-1916:19 ewallet.p12

SQL> create table scott.tde(idnumber,name char(10) encrypt using 'AES128' no salt);

【利用钱包使用AES128算法对新建表 指定列进行加密,加密时不使用随机字符串增强密码强度( salt,使得相同明文加密后密文不同,)以使能在加密列上建立索引】

Table created.

测试:

SQL> insert into scott.tde values (0001,'aaa');

 

1 row created.

 

SQL> insert into scott.tde values(0002,'bbb');

 

1 row created.

 

SQL> insert into scott.tde values(0002,'ccc');

 

1 row created.

 

SQL> select * from scott.tde;

 

      IDNAME

---------- ----------

       1 aaa

       2 bbb

       2 ccc

SQL> alter system set encryption walletclose;

 

System altered.

 

SQL> select * from scott.tde;

select * from scott.tde

                    *

ERROR at line 1:

ORA-28365: wallet is not open

 

 

SQL> select id from scott.tde;

 

      ID

----------

       1

       2

       2

 

SQL> alter system set encryption walletopen authenticated by song;

 

System altered.

 

SQL> select * from scott.tde;

 

      IDNAME

---------- ----------

       1 aaa

       2 bbb

       2 ccc

 

SQL> alter table scott.tde modify namechar(10) decrypt;

【取消列加密】

Table altered.

 

SQL> alter system set encryption walletclose;

 

System altered.

 

SQL> select * from scott.tde;

 

      IDNAME

---------- ----------

       1 aaa

       2 bbb

       2 ccc

加密备份数据

SQL> alter system set encryption walletopen authenticated by song;

 

System altered.

RMAN> connect target sys/song

 

connected to target database: ORA10(DBID=775040288)

using target database control file insteadof recovery catalog

 

RMAN> configure encryption for databaseon;

 

new RMAN configuration parameters:

CONFIGURE ENCRYPTION FOR DATABASE ON;

new RMAN configuration parameters aresuccessfully stored

 

RMAN> backup tablespace users;

 

Starting backup at 19-OCT-12

allocated channel: ORA_DISK_1

channel ORA_DISK_1: sid=143 devtype=DISK

channel ORA_DISK_1: starting full datafilebackupset

channel ORA_DISK_1: specifying datafile(s)in backupset

input datafile fno=00004name=/u01/app/oracle/oradata/ora10/users01.dbf

channel ORA_DISK_1: starting piece 1 at19-OCT-12

channel ORA_DISK_1: finished piece 1 at19-OCT-12

piece handle=/backup/backup_0pno5hvm_1_1 tag=TAG20121019T164022comment=NONE

channel ORA_DISK_1: backup set complete,elapsed time: 00:00:03

Finished backup at 19-OCT-12

 

Starting Control File and SPFILE Autobackupat 19-OCT-12

piecehandle=/u01/app/oracle/flash_recovery_area/ORA10/autobackup/2012_10_19/o1_mf_s_797100026_8824hysg_.bkpcomment=NONE

Finished Control File and SPFILE Autobackupat 19-OCT-12

【打开钱包,配置RMAN为透明加密模式,则备份数据时利用钱包进行加密,恢复时也需打开钱包才能进行,适合备份和恢复都在本地进行的备份模式

RMAN> set encryption identified by song1only;

 

executing command: SET encryption

 

RMAN> backup tablespace users;

 

Starting backup at 19-OCT-12

using channel ORA_DISK_1

channel ORA_DISK_1: starting full datafilebackupset

channel ORA_DISK_1: specifying datafile(s)in backupset

input datafile fno=00004name=/u01/app/oracle/oradata/ora10/users01.dbf

channel ORA_DISK_1: starting piece 1 at19-OCT-12

channel ORA_DISK_1: finished piece 1 at19-OCT-12

piece handle=/backup/backup_0rno5i71_1_1tag=TAG20121019T164417 comment=NONE

channel ORA_DISK_1: backup set complete,elapsed time: 00:00:02

Finished backup at 19-OCT-12

 

Starting Control File and SPFILE Autobackupat 19-OCT-12

piecehandle=/u01/app/oracle/flash_recovery_area/ORA10/autobackup/2012_10_19/o1_mf_s_797100259_8824q3st_.bkpcomment=NONE

Finished Control File and SPFILE Autobackupat 19-OCT-12

【不使用钱包,配置RMAN为密码加密模式,则恢复时必须提供备份时所指定的密码(set decryption)才能进行,适合备份在本地,恢复在异地的备份模式】

RMAN> set decryption identified bysong1;

 

executing command: SET decryption

 

RMAN> set encryption identified bysong2;

 

executing command: SET encryption

 

RMAN> backup tablespace users;

 

Starting backup at 19-OCT-12

using channel ORA_DISK_1

channel ORA_DISK_1: starting full datafilebackupset

channel ORA_DISK_1: specifying datafile(s)in backupset

input datafile fno=00004name=/u01/app/oracle/oradata/ora10/users01.dbf

channel ORA_DISK_1: starting piece 1 at19-OCT-12

channel ORA_DISK_1: finished piece 1 at19-OCT-12

piece handle=/backup/backup_0tno5iii_1_1tag=TAG20121019T165026 comment=NONE

channel ORA_DISK_1: backup set complete,elapsed time: 00:00:01

Finished backup at 19-OCT-12

 

Starting Control File and SPFILE Autobackupat 19-OCT-12

piecehandle=/u01/app/oracle/flash_recovery_area/ORA10/autobackup/2012_10_19/o1_mf_s_797100627_88252n6k_.bkpcomment=NONE

Finished Control File and SPFILE Autobackupat 19-OCT-12

 

RMAN> set decryption identified bysong2;

 

executing command: SET decryption

【使用钱包和密码,配置RMAN为混合加密模式,则恢复时打开钱包,或者提供备份时所指定的密码均可进行,适合恢复即可能在本地,也可能在异地进行的备份模式】

LOCK   &  LATCH

Lock

独占锁(X锁)与共享锁(S锁)

SQL> update t1 set id=2 where id=1;

 

1 row updated.

SQL> update t1 set id=3 where id=1;

Waiting….

【为保证数据的一致性,会话1在修改记录时在记录上加了独占锁(exclusive,简称x锁),又称排他锁,以防止事务在提交或回退前记录被其他事务同时修改。

一旦用户对某个资源添加了x锁,则其他用户都不能再对该资源添加任何类型的锁,直到该用户释放了资源上的x锁为止】

 

SQL> update t1 set id=2 where id=1;

 

1 row updated.

SQL> drop table t1;

drop table t1

          *

ERROR at line 1:

ORA-00054: resource busy and acquire withNOWAIT specified

 

【为保证数据的一致性,会话1在修改记录时同时还在表头上加了共享锁(shared ,简称s锁),以便其他删表事务执行前不用检查表中每条记录是否加了独占锁(那就不能删表),而只要检查表头是否存在共享锁就可以了

若删表事务(要对全表加独占锁)进行前,还有另一会话还进行了删除记录操作(且未提交或回退,即事务未结束),那么另一会话在被删记录上加独占锁,同时在表上再加一个共享锁,则删表事务要等到表头上所有共享锁全部取消后(即所有独占事务全部完成后),才能进行(才能对整表施加独占锁)。

一旦用户对某个资源添加了S锁,则其他用户都不能在该资源上添加X,只能添加S锁,直到该用户释放了资源上的s 锁为止】

DML事务锁

根据被保护的对象种类的不同,锁还可以分成多种类型,如因DDL引起的锁,DML事务引起的锁,分布式事务中涉及的锁等,DML事务锁应主要关注。

DML事务锁能保证当某用户正在更新表中某行数据时,其他用户不能同时更新相同的数据行,而且也不能删除或修改被更新的表,包括行锁TX表锁TM

 

前列修改记录时,在行记录上所施加的就是行(独占)锁,对于ORACLE来说,行锁只可能是独占锁;而同时在表头上所施加的就是表(共享)锁,对于ORACLE来说,表锁可能是共享锁(如删表中记录时在表头上所施加的共享锁),也可能是独占锁(如删表操作时需要在表头上所施加的独占锁)。

 

TM表锁的种类

TM表锁即可能是独占锁,也可能是共享锁,可细分为如下几类:

编号                  表锁                    含义

0/1                     无    

2                           RS                row share

3                         RX                  row exclusive

4                         S                    share

5                         SRX                    share+row  exclusive

6                            x                      exclusive

 

A.   select * from table_name不会产生锁;

B.   lock table table_name in rowshare mode 会在表上加RS锁,使用完毕后rollback即解锁。

【当执行相应语句时,系统自动在所要操作的表上申请表级RS锁(意向锁,表示某事务有意向进行锁表),当表上加RS锁后,不许其他事务对该表添加x排他锁(如drop table),但允许其他事务对该表再加除x锁之外的其他锁,如其他事务再对该表加RS锁(再执行lock table in row share mode),或其他事务再对该表加RX锁(再执行插删改DML操作),或其他事务再对该表加S锁(再执行建索引操作)等】

 

SQL> create table t4 (id number);

 

Table created.

 

SQL> insert into t4 values (1);

 

1 row created.

 

SQL> insert into t4 values(10);

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> lock table t4 in row share mode;

 

Table(s) Locked.

 

SQL> select sid from v$mystat;

 

       SID

----------

       157

SQL> select * from v$lock where sid=157;

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- -------------------- ---------- ----------

    CTIME BLOCK

---------- ----------

3FB4A54C 3FB4A564 157 TM      55335     0          2       0

      116      0

 

SQL> drop table t4;

drop table t4

          *

ERROR at line 1:

ORA-00054: resource busy and acquire withNOWAIT specified

C/D/E/F.insert/update/ delete DML语句及select * from table_name for  update句会在表上加RX(其中select for update用于在读数据过程中禁止其他事务对所读数据进行DML操作),操作完成后commit或roback解锁。

当执行相应语句时,系统自动在所要操作的表上申请表级RX锁(意向锁,表示某事务有意向要进行锁表),当表级锁获得后,系统再自动申请TX行锁(实体锁,表示该事务的具体锁动作),并将相应数据行加x锁,当表上加RX锁后,不许其他事务对该表再加X排他锁(如drop table),不允许其他事务对该表再加S锁(如建索引);但允许其他事务对该表再加RS锁(如执行lock table inrow share mode)或RX锁(如插删改记录,注意,其他事务在同一表上再加RX表锁没问题,但再加行锁时,不能再加在表内已加X锁的数据行上,而只许加在表内其他数据行上。

对表施加RX锁也可以通过手工执行Lock table table_name in rowexclusive mode进行显示加锁,执行后即对表施加了RX锁(但未对数据行申请加TX行锁),直到rollback释放。

RS与RX区别:

1.   产生条件不同。

2.   RX锁后,其他事务读不到更改后的结果。而RS对其他事务而言读是没有问题的,故称RS,虽都是指在表的层面上防止其他事务锁表,但RX是 forexclusive reading or writing,而RS是for exclusive write access.这也是RS的S(share)表现的地方。

SQL> insert into t4 values (8);

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> update t4 set id=9 where id<=3;

 

4 rows updated.

 

SQL> select * from v$mystat;

 

       SID STATISTIC#     VALUE

---------- ---------- ----------

       145       0          1

       145       1          1

 

SQL> select * from v$lock where sid=145;

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME  BLOCK

---------- ----------

3FB4A54C 3FB4A564 145 TM      55336     0           3       0

       131       0

 

3FB85DF8 3FB85E1C 145TX     458775   597           6       0

 

SQL> rollback;

 

SQL> select * from v$lock where sid=145;

 

ADDR    KADDR      SID TY       ID1   ID2       LMODE    REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME  BLOCK

---------- ----------

3FB4A54C 3FB4A564 145 TM      55336     0           3       0

       172       0

 

3FB85DF8 3FB85E1C 145 TX     458775   597           6       0

       172       0

SQL> select xidusn,xidslot,xidsqn,status from v$transaction;

 

    XIDUSN    XIDSLOT   XIDSQN STATUS

---------- ---------- ---------- ----------------

 7      23         597 ACTIVE

 

SQL> select sid,type,id1,id2,lmode,request,block from v$lockwhere sid=145;

 

       SID TY        ID1     ID2 LMODE        REQUEST     BLOCK

---------- -- ---------- ---------- ---------- ---------- ----------

       145 TM     55336       0      3        0       0

       145 TX     458775    597      6        0       0

 

SQL> select object_name from dba_objects where object_id='55336';

 

OBJECT_NAME

--------------------------------------------------------------------------------

T4

 

SQL> select trunc(458775/power(2,16)) from dual;

 

TRUNC(458775/POWER(2,16))

-------------------------

            7

 

SQL> select bitand (458775,to_number('ffff','xxxx'))+0 from dual;

 

BITAND(458775,TO_NUMBER('FFFF','XXXX'))+0

-----------------------------------------

                         23

 

SQL> show parameter transactions

 

NAME                          TYPE   VALUE

------------------------------------ -----------------------------------------

transactions                  integer 187

transactions_per_rollback_segment   integer 5

SQL> show parameter dml_locks;

 

NAME                          TYPE   VALUE

------------------------------------ -----------------------------------------

dml_locks                     integer 748

 

【TX数量和事务个数相同,并受transactions参数(默认187)限制,TM锁数量和被更新的表的个数相同,并受dml_locks参数(默认748)限制,即默认情况下可同时启动187个事务,更新748个表,平均允许每个事务同时更新4个表】

SQL> select resource_name,initial_allocation,current_utilization,max_utilizationfrom v$resource_limit where resource_name in ('transactions','dml_locks');

 

RESOURCE_NAME                 INITIAL_ALLOCATION   CURRENT_UTILIZATION

------------------------------ ---------------------------------------

MAX_UTILIZATION

---------------

dml_locks                     748                     0

     44

 

transactions                   187                     0

      9

【查看当前TX/TM锁的使用情况,包括能够分配的最大个数,当前分配的个数,及曾经分配的最大个数】

SQL> update t4 set id=10 where id<10;

 

9 rows updated.

 

SQL> update t4 set id=10 where id<=10;

 

SQL> select sid,type,id1,id2,lmode,request,block from v$lockwhere sid in (145,158) order by sid desc;

 

       SID TY        ID1     ID2 LMODE        REQUEST     BLOCK

---------- -- ---------- ---------- ---------- ---------- ----------

       158 TM     55336       0      3        0       0

       158 TX     196619    637      0        6       0

       145 TX     196619    637      6        0       1

       145 TM     55336       0      3        0       0

 

Create index on table语句会在表上加S锁,操作完成后即解锁。

创建索引时,需要读表中所有数据,且在读数据过程中数据不能由其他事务进行更新,此时需要对表加S锁,S锁用于保证在操作期间整个表上不能再由其他事务加RX锁(进行插删改操作)及X锁(不能删表),因为若在创建索引时,允许有未提交的其他插删改事务发生,而新的数据是不会被索引的,则将造成数据和索引间的不一致。因为S和RX锁是互斥的,所以当某事务在表上有未提交插删改事务时(以加RX锁),另一事务不能创建索引(无法再加S锁)。或者反之,当创建索引动作还没结束时(S锁未释放),其他事务即不可以在表上开始插删改事务(无法获得RX锁)。

当表上加S锁后,不许其他事务对该表再加X排他锁(如drop table),不允许其他事务对该表再加RX锁(如插删改记录);但允许其他事务对该表再加RS锁(如执行LOCK table inrow  share mode).

对表施加S锁也可以通过手工执行lock table table_name in share mode 进行显式加锁,执行后即对表施加了S 锁,其他事务对该表即不能进行数据插删改及删表操作,直到rollback释放。

 

SQL> update t4 set id=10 where id=10;

 

0 rows updated.

 

SQL> select * from v$lock where sid=158;

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME BLOCK

---------- ----------

3FB4A608 3FB4A620 158 TM      55336     0           3       0

      21      0

 

 

SQL> create index i4 on t4 (id);

create index i4 on t4 (id)

                   *

ERROR at line 1:

ORA-00054: resource busy and acquire with NOWAIT specified

 

SQL> select * from v$lock where sid=158;

 

no rows selected

 

SQL> create index i4 on t4 (id);

create index i4 on t4 (id)

                   *

ERROR at line 1:

ORA-00054: resource busy and acquire with NOWAIT specified

SQL> lock table t4 in share mode;

 

SQL> select * from v$lock where sid in (158,145);

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME BLOCK

---------- ----------

3FB4A54C 3FB4A564 145 TM      55336     0           3       0

      2185      0

 

3FB86364 3FB86388 145 TX     196619   637           6       0

      2185      0

 

SQL> select * from v$lock where sid in (145,158,148);

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME BLOCK

---------- ----------

3FB4A54C 3FB4A564 145 TM      55336     0           5       0

       179      1

 

3FB4A6C4 3FB4A6DC     148TM      55336     0           0       3

      60      0

 

3FB4A780 3FB4A798 158 TM      55336     0           0       3

      33      0

 

 

ADDR    KADDR      SID TY        ID1   ID2       LMODE   REQUEST

-------- -------- ---------- -- ---------- ---------- --------------------

     CTIME BLOCK

---------- ----------

3FB86364 3FB86388 145 TX     458790   575           6       0

       179      0

 

如果对一个数据库对象加SRX锁,表示对它加S锁,再加RX锁,即SRX=S+RX.例如事务对某个表加SRX锁,则表示该事务需要读表中所有数据,且在读数据过程中数据不能由其他事务进行更新(所以要对该表加S锁),同时本事务会更新个别行(所以要对该表加RX锁),注意,表上加S锁后再由本事务加RX锁是允许的,而表上加S锁后再由其他事务加RX锁是不允许的。

对表施加SRX锁也可以通过手工执行lock table table_name in share row exclusive mode 进行显式加锁,执行后即对表施加了SRX锁,其他事务对该表即不能进行数据插删改及删表操作,直到rollback释放。

 

 

执行Alter table,drop table ,drop index,truncatetable操作时,需要对表加X锁,X锁是限制级别最高的锁。对表加X锁后,不能进行其他任何锁操作。

对表施加X锁也可以通过手工执行lock table table_name in exclusive mode 进行显式加锁,执行后即对表施加了x锁,其他事务对该表即不能进行任何其他加锁操作,直到rollback释放。

死锁deadlock

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值