oracle事務和鎖


數據庫事務概括

1. 說明

  一組SQL,一個邏輯工作單位,執行時整體修改或者整體回退。

 

2.事務相關概念

  1)事務的提交和回滾:COMMIT/ROLLBACK

  2)事務的開始和結束

    開始事務:連接到數據庫,執行DML、DCL、DDL語句

    結束事務: 1. 執行DDL(例如CREATE TABLE),DCL(例如GRANT),系統自動執行COMMIT語句

          2. 執行COMMIT/ROLLBACK

          3. 退出/斷開數據庫的連接自動執行COMMIT語句

          4. 進程意外終止,事務自動rollback

          5. 事務COMMIT時會生成一個唯一的系統變化號(SCN)保存到事務表

  3)保存點(savepoint): 可以在事務的任何地方設置保存點,以便ROLLBACK

  4)事務的四個特性ACID :

    1. Atomicity(原子性): 事務中sql語句不可分割,要么都做,要么都不做

    2. Consistency(一致性) : 指事務操作前后,數據庫中數據是一致的,數據滿足業務規則約束(例如賬戶金額的轉出和轉入),與原子性對應。

    3. Isolation(隔離性):多個並發事務可以獨立運行,而不能相互干擾,一個事務修改數據未提交前,其他事務看不到它所做的更改。

    4. Durability(持久性):事務提交后,數據的修改是永久的。

  5) 死鎖:當兩個事務相互等待對方釋放資源時,就會形成死鎖,下面章節詳細分析

 

oracle事務隔離級別

 

1 .兩個事務並發訪問數據庫數據時可能存在的問題

  1. 幻想讀:

    事務T1讀取一條指定where條件的語句,返回結果集。此時事務T2插入一行新記錄並commit,恰好滿足T1的where條件。然后T1使用相同的條件再次查詢,結果集中可以看到T2插入的記錄,這條新紀錄就是幻想。

  2. 不可重復讀取:

    事務T1讀取一行記錄,緊接着事務T2修改了T1剛剛讀取的記錄並commit,然后T1再次查詢,發現與第一次讀取的記錄不同,這稱為不可重復讀。

  3. 臟讀:

    事務T1更新了一行記錄,還未提交所做的修改,這個T2讀取了更新后的數據,然后T1執行回滾操作,取消剛才的修改,所以T2所讀取的行就無效,也就是臟數據。

 

2.oracle事務隔離級別

oracle支持的隔離級別:(不支持臟讀)

READ COMMITTED--不允許臟讀,允許幻想讀和不可重復讀


SERIALIZABLE--以上三種都不允許

sql標准還支持READ UNCOMMITTED (三種都允許)和 REPEATABLE READ(不允許不可重復讀和臟讀,只允許幻想讀)

以上區別在下面章節事務建立,隔離級別分析中說明

 

事務相關語句

 

1. 事務相關語句概括

SET TRANSACTION----設置事務屬性
SET CONSTRAINT -----設置約束
SAVEPOINT ------------建立存儲點
RELEASE SAVEPOINT --釋放存儲點
ROLLBACK---------------回滾
COMMIT------------------提交

 

2. 建立事務、隔離級別分析

1)建立事務

SET TRANSACTION READ ONLY--事務中不能有任何修改數據庫中數據的操作語句,這包括 insert、update、delete、create語句

SET TRANSACTION READ WRITE--默認設置,該選項表示在事務中可以有訪問語句、修改語句

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE--serialzable可以執行DML操作

注意:這些語句是互斥的,不能夠同時設置兩個或者兩個以上的選項

 

2)read only

eg:

set transaction read only;
select * from student;

結果:

執行:

update student set name='小丸子' where id='ccc';

結果:

在行 3 上開始執行命令時出錯:
update student set name='小丸子' where id='ccc'
錯誤報告:
SQL 錯誤: ORA-01456: 不能在 READ ONLY 事務處理中執行插入/刪除/更新操作
01456. 00000 -  "may not perform insert/delete/update operation inside a READ ONLY transaction"
*Cause:    A non-DDL insert/delete/update or select for update operation
           was attempted
*Action:   commit (or rollback) transaction, and re-execute

 

 

3) read write

eg:

set transaction read write;
select * from student;

update student set name='小丸子' where id='ccc';
select * from student;

結果:

transaction READ 成功。
1 行已更新。

結論:允許讀寫

 

 

4)isolation level read committed(可幻讀和重復讀)

  1.建立兩個事務如下:

事務1:

set transaction  read write;
select * from student;

事務2:

set transaction isolation level read committed;
select * from student;

 

 2. 在事務1中修改某行數據並commit

update student set score=88 where id='fff';
commit;

 3. 在事務2中查詢結果如下:

select * from student;

結果:

結論:事務2的隔離級別為 isolation level read committed, 支持不可重復讀

  4. 在事務1中插入一行數據,並提交

insert into student values('iii','小夢','1',3,4,10);

  5. 在事務2中查看:

select * from student;

結論:事務2隔離級別為 isolation level read committed, 允許幻想讀

 

 

5) isolation level  serializable

1.建立兩個事務如下:

事務1:

set transaction  read write;
select * from student;

事務2:

set transaction isolation level serializable;
select * from student;

 

 2. 在事務1中修改某行數據並commit

update student set score=88 where id='fff';
commit;

 3. 在事務2中查詢結果如下:

select * from student;

結果:

結論:事務2的隔離級別為 isolation level serializable, 不支持不可重復讀

  4. 在事務1中插入一行數據,並提交

insert into student values('iii','小夢','1',3,4,10);

  5. 在事務2中查看:

select * from student;

結論:事務2的隔離級別為 isolation level serializable, 不支持幻想讀

 

ORACLE鎖機制

1.  概括

  1)說明

    鎖是一種機制,多個事務同時訪問一個數據庫對象時,該機制可以實現對並發的控制

   2) oracle中鎖的類別

    1.DDL鎖: oracle自動的施加和釋放

    2.DML鎖:事務開始時施加,使用Commit后者Rollback被釋放、

    3.內部鎖: 由oracle自己管理以保護內部數據庫結構

  3)oracle鎖的粒度

    1. 行級鎖(TX):阻止該行上的DML操作,直到Commit或者Rollback

    2. 表級鎖(TM):

    3. 數據庫級鎖: eg: 將數據庫鎖定為只讀模式 alter database open read only;

           eg: 將數據庫設置為限制模式(導入導出數據庫時使用):alter system enable restricted session;

 

2.鎖的模式

  1)概括

  說明:

    1. 數字越大,級別越高

  2)eg:

lock table student in row share mode;

lock table student in row exclusive mode;  --用於行的修改

lock table student in share mode;   --阻止其他DML操作

lock table student in share row exclusive mode;  --阻止其他事務操作

lock table student in exclusive mode;  --獨立訪問使用

 

3.鎖查看

1)概括

SELECT * FROM V$SESSION;--查看會話和鎖的信息

SELECT * FROM V$SESSION_WAIT;--查看等待的會話信息

SELECT * FROM V$LOCK;--系統中所有鎖

SELECT * FROM V$LOCKED_OBJECT;--系統中DML鎖

2)eg:

set transaction read write;
insert into student values ('jjj','小欣','1',3,4,90);
SELECT * FROM V$LOCked_object;

分析:1. locked_mode:3  ,因為我們執行的是insert, 因而是行級排他鎖 row exclusive mode

  

死鎖

 

1. 說明

  1. 當兩個用戶希望持有對方的資源時就會發生死鎖。即兩個用戶互相等待對方釋放資源,oracle認定為產生了死鎖,在這種情況下,將以犧牲一個用戶作為代價,另一個用戶繼續執行,犧牲的用戶的事務將回滾。
  2. lORA-00060的錯誤並記錄在數據庫的日志文件alertSID.log中。同時在user_dump_dest下產生了一個跟蹤文件,詳細描述死鎖的相關信息。 
 

2.死鎖產生條件

  1. Mutual exclusion(互斥):資源不能被共享,只能由一個進程使用。
  2. Hold and wait(請求並保持):已經得到資源的進程可以再次申請新的資源。
  3. No pre-emption(不可剝奪):已經分配的資源不能從相應的進程中被強制地剝奪。
  4. Circular wait(循環等待條件):系統中若干進程組成環路,該環路中每個進程都在等待相鄰進程正占用的資源。

 

3.死鎖模擬

  student table如下

  1. 開兩個進程(此處使用sqldeveloper模擬)建立兩個事務

事務1:

set transaction read write;

事務2:

set transaction read write;

 

 

  2. t1 時刻 事務1和事務2中分別執行如下語句

事務1:

update student set classno=8 where id='iii';

事務2:

update student set score=score+10 where id='jjj';

 結果如下:

1行已更新
1行已更新

 

 

 3. t2時刻事務1和事務2中分別執行如下語句

事務1:

update student set score=score+20 where id='jjj';

事務2:

update student set classno=9 where id='iii';

結果如下:

錯誤報告:
SQL 錯誤: ORA-00060: 等待資源時檢測到死鎖
00060. 00000 -  "deadlock detected while waiting for resource"
*Cause:    Transactions deadlocked one another while waiting for resources.
*Action:   Look at the trace file to see the transactions and resources
           involved. Retry if necessary.

注意:ScriptRunner處紅色的叉,出於等待狀態

 

  4. commit 事務2,事務1結果如下:

 

 

注意:用時38.048s, 事務2commit前等待的時間

 

 4.解決死鎖沖突

1)執行commit或者rollback結束事務

2)終止會話

還是借用3中死鎖的例子

在等待資源時執行,查找阻塞會話

select sid,serial#,username from v$session where sid in (select blocking_session from v$session);

執行:

alter system kill session '423,896';

結果:

在行 10 上開始執行命令時出錯:
alter system kill session '423,896'
錯誤報告:
SQL 錯誤: ORA-00027: 無法終止當前會話
00027. 00000 -  "cannot kill current session"
*Cause:    Attempted to use ALTER SYSTEM KILL SESSION to kill the current
           session.
*Action:   None.

解決方法:另起一個session,關閉當前session(If it is necessary to kill the current session, do so from another session.

另起線程執行上面的語句:

alter system kill session '423,896';

結果如下:(session kill成功,死鎖解除,事務1更新成功)

 

 

5. 事務和死鎖預防總結

  1. 避免應用不運行長事務。
  2. 經常提交以避免長時間鎖定行。
  3. 避免使用LOCK命令鎖定表。
  4. 在非高峰期間執行DDL操作,在非高峰期間執行長時間運行的查詢或事務。
 
   另外需注意,需監測系統中死鎖,調查為什么這些鎖正被保持,頻率;當死鎖發生通過回滾事務rollback或者終止會話來解決它。

  

 

 

 

 

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM