精細審計
精細審計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釋放。