Oracle OCP筆記 18 併發與鎖

2021-06-29 01:37:26 字數 3890 閱讀 1976

一.鎖定機制

在任何多使用者資料庫應用程式中,最終免不了會出現兩個使用者希望同時使用同一行的情況。借助表和記錄的鎖定機制,可以實現併發訪問的序列化。

二.共享鎖與排他鎖(share lock, exclusive lock)

排他鎖: 

在指定記錄上請求排他鎖的第乙個會話會得到排他鎖,其他請求對該記錄進行寫訪問的會話則必須等待.雖然這行已通過鎖定會話進行了更新,但是對其進行讀訪問是被允許的(而且經常會出現這種情況),並且這些讀操作會涉及撤銷資料的使用,從而確保讀會話並不會看到任何未被提交的變化.

對於一行或乙個表上的排他鎖來說,每次只能有乙個會話可以獲得這個排他鎖,不過許多會話可以同時獲得相同物件上的共享鎖。

共享鎖在一行上設定共享鎖毫無意義,鎖定一行的唯一目的就是不允許其他會話更改它。共享鎖被置於整個表上。同時許多會話可以獲得同乙個表上的共享鎖。

在乙個表上放置共享鎖的目的是為了防止另乙個會話獲得這個表上的排他鎖(在已存在共享鎖的情況下無法再獲得排他鎖).

在表上放置排他鎖時需要執行ddl語句,如果其他人和會話已經在乙個表上放置了共享鎖,就無法修改某個物件的語句(例如刪除這個表的一列).

為了在行上執行dml語句,當前會話必須獲取待更改行上的排他鎖以及包含這些行的表上的共享鎖,如果另乙個會話已經獲取了待更改行上的排他鎖,那麼當前會話將被掛起,直至使用commit或rollback命令解除鎖定。如果另乙個會話已經獲取了表上的共享鎖以及其他行上的排他鎖,就不存在任何問題。

乙個表上的排他鎖也是允許的,但是,除非ddl語句要求這麼做,預設鎖定機制是不鎖定整個表。

所有dml語句至少都需要兩種鎖定: 受影響記錄上的排他鎖,以及包含受影響記錄的表上的共享鎖。排他鎖能夠防止其他會話干預指定的行,而共享鎖則能夠阻止其他會話使用ddl語句修改表的定義。這兩種鎖定會被自動請求。如果某條dml語句在指定記錄上無法獲取所需的排他鎖,那麼這條語句會被掛起直至獲得所需的排他鎖。

執行ddl命令需要使用所涉及物件上的排他鎖,只有在針對指定表的所有dml事務結束,且行上的排他鎖以及表上的共享鎖都被解除之後,才可以獲得執行ddl命令所需的排他鎖。任何ddl語句所需要的排他鎖都是被自動請求的。但是,如果無法獲取所需的排他鎖(通常是因為其他會話已經獲得用於dml語句的共享鎖),那麼ddl語句就會由於錯誤立即終止。

三.監視鎖定爭用.

-- 檢視鎖定的會話和鎖定物件

select s.sid,s.serial#,s.lockwait,s.status,s.schemaname,s.machine,s.terminal,s.osuser,s.program,s.module,s.action,s.logon_time,

l.oracle_username,l.os_user_name,l.locked_mode,o.owner,o.object_name,o.object_type,o.status

from v$session s,

v$locked_object l,

dba_objects o

where s.sid = l.session_id

and l.object_id = o.object_id;

-- 檢視阻塞與等待鎖的會話

select * from dba_waiters;

-- 檢視鎖定的會話和鎖定物件(阻塞的會話)

select s.sid,s.serial#,s.lockwait,s.status,s.schemaname,s.machine,s.terminal,s.osuser,s.program,s.module,s.action,s.logon_time,

l.oracle_username,l.os_user_name,l.locked_mode,o.owner,o.object_name,o.object_type,o.status,

'alter system kill session '||''''|| s.sid||','||s.serial#||''''||';' kill_session_sql   

from v$session s,

v$locked_object l,

dba_objects o

where s.sid = l.session_id

and l.object_id = o.object_id

and s.sid in (select holding_session from dba_waiters);

-- 檢視鎖定的會話和鎖定物件(阻塞的會話),rac環境

select s.sid,s.serial#,s.lockwait,s.status,s.schemaname,s.machine,s.terminal,s.osuser,s.program,s.module,s.action,s.logon_time,

l.oracle_username,l.os_user_name,l.locked_mode,o.owner,o.object_name,o.object_type,o.status,

'alter system kill session '||''''|| s.sid||','||s.serial#||''''||';' kill_session_sql   

from gv$session s,

gv$locked_object l,

dba_objects o

where s.sid = l.session_id

and l.object_id = o.object_id

and s.sid in (select holding_session from dba_waiters);

-- 檢視正在執行的sql語句(排除當前的語句)

select s.sid,s.serial#,s.lockwait,s.status,s.schemaname,s.machine,s.terminal,s.osuser,

s.program,s.module,s.action,s.logon_time,t.sql_id,t.piece,t.sql_text

from v$session s,

v$sqltext t

where s.sql_address = t.address

and s.sql_hash_value = t.hash_value

and s.status = 'active'

and s.sid <> userenv('sid') --(select sid from v$mystat where rownum = 1)

order by s.sid,t.sql_id,t.piece;

-- 檢視正在執行的sql語句(排除當前的語句)

select s.sid,s.serial#,s.lockwait,s.status,s.schemaname,s.machine,s.terminal,s.osuser,

s.program,s.module,s.action,s.logon_time,a.sql_text,a.sql_fulltext 

from v$session s,

v$sqlarea a

where s.sql_address = a.address

and s.sql_hash_value = a.hash_value

and s.status = 'active'

and s.sid <> userenv('sid') --(select sid from v$mystat where rownum = 1)

order by s.sid

-- 殺掉長期鎖定物件的會話

alter system kill session 'sid,serial#' immediate;

四.死鎖(deadlock)

兩個會話相互阻塞,這兩個會話都被掛起,每個會話都在等待另乙個會話釋放鎖定,這種場景被稱為死鎖(deadlock)。

死鎖是由不合理的程式設計導致的,發生死鎖問題的原因是程式試圖獲得鎖定物件的順序不一致導致的。資料庫系統能自動檢測到死鎖。

ORACLE OCP之管理資料併發

在oracle中,控制事務的語句稱為tcl 事務控制語句 一共有三個動作 一致性 consistency c 隔離性 isolation i 永續性 durability d 不可重複讀 nonrepeatable read 幻讀 phantom read read committed 注 有些翻譯...

Oracle OCP筆記 06 口令檔案

在資料庫未開啟時,需要登入oracle來開啟資料庫,但資料庫未開啟不能讀取資料字典,不能通過資料字典來驗證身份,這就需要通過外部口令檔案來進行身份驗證。1 作業系統和口令檔案身份驗證 口令檔案預設位置 oracle home dbs orapwsid 要啟用作業系統和口令檔案身份驗證 二者是相配的 ...

Oracle OCP筆記 12 資料庫鏈結

分布式環境中,在乙個資料庫的使用者會話中訪問另乙個資料庫時,需要資料庫鏈結.1 檢視所有的資料庫鏈結 select owner,object name from dba objects where object type database link select from dba db links ...