天天看點

oracle學習筆記 鎖相關視圖及相關操作oracle學習筆記 鎖相關視圖及相關操作

oracle學習筆記 鎖相關視圖及相關操作

我們繼續研究鎖

這節課主要研究鎖的相關視圖,以及鎖的相關操作

主要是研究視圖

然後通過視圖查鎖的問題

oracle對于鎖來講我們沒有什麼太多可操作的地方

但是我們可以通過視圖找出鎖的問題

一)v$transaction視圖

第一個視圖是v$transaction

就是oracle資料庫所有活動的事務數

所有活動的事務每一個活動的事務在這裡有一行

v$transaction
    XIDUSN表示目前事務使用的復原段的編号
    XIDSLOT說明該事務在復原段頭部的事務表中對應的記錄編号(也可以叫做槽号)
    XIDSQN說明序列号
    STATUS說明該事務是否為活動的
           

這是v$transaction視圖的結構

我們去看一下,比如說去做一個實驗

在一個hr使用者的sqlplus中執行

SQL> delete from employees where rownum=;

 row deleted.
           

我删一行,開始一個事務

可以查一下

以管理者身份運作,去執行一下

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

看看有幾個事務

結果:

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

    XIDUSN    XIDSLOT     XIDSQN STATUS
---------- ---------- ---------- ----------------
         4         43        216 ACTIVE
           

一個事務在這裡面有一行

XIDUSN是事務使用的復原段的編号

XIDSLOT是哪個槽位數

XIDSQN是覆寫多少次

這三個唯一的标示一個事務的編号

STATUS是目前事務的狀态

這個事務為ACTIVE

這是v$transaction

所有的活動事務裡面都有

二)v$lock視圖

v$lock
    記錄了session已經獲得的鎖定以及正在請求的鎖定的資訊
    SID說明session的ID号
    TYPE說明鎖的類型,主要關注TX和TM
    LMODE說明已經獲得的鎖定的模式,以數字編碼表示
    REQUEST說明正在請求的鎖定的模式,以數字編碼表示
    BLOCK說明是否阻止了其他使用者獲得鎖定,大于0說明是,等于0說明否
           

v$lock這裡面

記錄了session已經獲得的鎖定以及正在請求的鎖定的資訊

就是每個會話

它已經擷取的鎖和正在申請的鎖它都會列出來

這裡面我們去查一下

上面執行了

delete from employees where rownum=1;

一個事務開始以後至少産生幾個鎖

第一個行上加鎖了

行上的鎖你是看不見的,因為它在行上

但是我們開始一個事務有一個事務鎖

同時在表上應該加了個RX鎖

應該這時候有兩個鎖

一個TX鎖事務鎖

一個是TM級别上的表級的RX鎖

去查一下,v$lock裡面應該有

使用語句

select sid,type,id1,id2,
    decode(lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,  
  decode(request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') request_mode,block
    from v$lock
    where sid=;
           

這個語句本課中用的較多,這裡把它取名為(#A)語句

最後where條件有sid

sid是會話的編号

先查一下我們會話的編号是多少

在我的實驗環境下

在hr使用者的sqlplus中

SQL> select sid from v$mystat where rownum=;
select sid from v$mystat where rownum=
                *
ERROR at line :
ORA-: table or view does not exist
           

hr使用者無權通路v$mystat

是以換個方法

使用下面的指令得到hr使用者目前的sid

SQL> select userenv('sid') from dual;

USERENV('SID')
--------------
           132
           

得到SID是132

然後用132替換前面(#A)語句where條件下的sid的值

然後在管理者使用者下查一下

因為hr使用者依然無法通路v$lock

執行結果

SQL> select sid,type,id1,id2,decode(lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
decode(request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') request_mode,block
              from v$lock
       where sid=;

       SID TY        ID1        ID2 LOCK_MODE           REQUEST_MODE             BLOCK
---------- -- ---------- ---------- ------------------- ------------------- ----------
        TM                 Row share           None                         
        TM                 Row share           None                         
        TM                 Row Exclusive       None                         
        TM                 Row share           None                         
        TM                 Row share           None                         
        TM                 Row share           None                         
        TM                 Row share           None                         
        TM                 Row share           None                         
        TX              Exclusive           None                         

 rows selected.
           

我們看一下132這個會話在很多的表上産生了TM鎖

132這個會話至少底下産生了一個TX鎖

同時132産生了TM鎖

LOCK_MODE中是Row share說明是RS鎖

是select for update産生的鎖

132這個會話産生的TM鎖的ID1列的ID數

這個TM在某個表上産生的鎖,ID1就是這個表的編号

有一個是51902

我們可以根據51902查出來

select object_name from dba_objects where object_id=51902;

查出51902是哪個表

執行結果

SQL> select object_name from dba_objects where object_id=51902;

OBJECT_NAME
-------------------------------------------------------------------------------------------------------
PRODUCT_INFORMATION
           

對象編号51902是PRODUCT_INFORMATION表

說明我們找錯了

這個表上加的鎖是Row share類型的鎖

删除操作的表應該産生Row Exclusive類型的鎖

前面delete語句删除EMPLOYEES表中行時牽涉到了PRODUCT_INFORMATION這個表

是主外鍵限制關系的原因在PRODUCT_INFORMATION表産生了RS鎖

再看剛才的結果

應該是這一行

鎖應該是RX鎖,TM級别的RX鎖

應該是51857

把語句改為

select object_name from dba_objects where object_id=51857;

改一下,執行一下,看一下

SQL> select object_name from dba_objects where object_id=51857;

OBJECT_NAME
----------------------------------------------------------------------------------------------------
EMPLOYEES
           

結果是EMPLOYEES,是對的

是以說記住

這個TM這個表級鎖在哪個表上

根據ID1對應的ID可以找出來

另外結果中TX所在的行

有ID1對應的ID和ID2列對應的ID

ID1和ID2這兩個數字标示着

這個事務用的那個復原段、事務表裡面的槽位号還有覆寫次數

我們可以通過一個sql語句查出來

将ID1拆解
select trunc(393249/power(2,16)) as undo_blk#,bitand(393249,to_number('ffff','xxxx')) + 0 as slot#
from dual;
           

剛才delete語句産生的TX鎖是這一行

132 TX 262187 216 Exclusive None 0

ID1列的值262187替換上面的語句中的值393249

得到

select trunc(262187/power(2,16)) as undo_blk#,bitand(262187,to_number(‘ffff’,’xxxx’)) + 0 as slot#

from dual;

執行一下

SQL> select trunc(/power(,)) as undo_blk#,bitand(262187,to_number('ffff','xxxx')) + 0 as slot#
        from dual;  

 UNDO_BLK#      SLOT#
---------- ----------
                  
           

看結果是4号復原段,復原段事務表中槽位号SLOT#是43

和以前查詢

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

    XIDUSN    XIDSLOT     XIDSQN STATUS
---------- ---------- ---------- ----------------
         4         43        216 ACTIVE
           

結果是一樣的

剛才這個語句XIDSQN的值216

(#A)語句結果行

直接有了

(#A)語句結果中ID2是覆寫次數

通過

select trunc(262187/power(2,16)) as undo_blk#,bitand(262187,to_number(‘ffff’,’xxxx’)) + 0 as slot#

from dual; 2

這個sql語句

找出來用的哪個復原段

槽位号是多少

然後包括覆寫次數

這三個資訊

也就是(#A)語句結果中TX這一行

ID1列和ID2列可以找到哪個事務

132 TM 51857 0 Row Exclusive None 0

是TM鎖

ID1對應的編号51857是對象的編号

這是v$lock

oracle中的表級鎖有

鎖定模式 鎖定簡稱 編碼數值
Row Exclusive RX 3
Row Shared RS 2
Share S 4
Exclusive X 6
Share Row Exclusive SRX 5
NULL N/A 0或者1

這是鎖的一些編号

v$lock視圖裡面是用編号給列出來了

如編号3對應Row Exclusive鎖模式

并且v$lock持有鎖和申請鎖的都列出來了

我們查詢以後得出的結論

SID為132的LOCK_MODE它是持有鎖的模式

(#A)結果中SID為132的行有9行

它是持有這麼多的鎖

REQUEST_MODE都是None

請求這塊是none

我們看(#A)結果中這些列

SID是session id

Type是類型

有表級鎖TM和事務鎖TX

對于ID

對TM來講ID1是哪個對象

對于TX來講ID1和ID2分别對應哪個事務

LOCK_MODE是SID會話持有的鎖

它持有這個鎖

REQUEST_MODE這個是請求什麼鎖

這裡我請求都是None

沒有請求任何鎖

同時

BLOCK這個數字是0或者1

這個0表示

比如說SID為132的會話持有LOCK_MODE為Row share的鎖

這個鎖并沒有把其它的别人鎖住,BLOCK就為0

BLOCK如果是1的話

132持有這個鎖同時還鎖住了别人

到底鎖住了誰可以去查

BLOCK是這個意思

這裡結果中block都是0

也就是對132來講

我持有這麼多的鎖

但是沒有鎖其它的任何人

也就是132持有的鎖沒有對别人造成影響

三)v$enqueue_lock視圖

v$enqueue_lock
該視圖中包含的字段以及字段含義與v$lock中的字段一模一樣。
隻不過該視圖中隻顯示那些申請鎖定,但是無法獲得鎖定的session資訊。
其中的記錄按照申請鎖定的時間先後順序排列,先申請鎖定的session排在前面,排在前面的session将會先獲得鎖定。
           

我們接着看v$enqueue_lock

v lock是把會話持有的鎖和請求的鎖全給列出來了v enqueue_lock隻是把請求鎖的都列出來了

v$enqueue_lock隻是把哪些會話它正在請求鎖

它把請求的列出來了

它持有鎖它沒列

因為對我們來講

有時候我們隻關心誰在請求鎖

因為請求鎖就有可能被鎖住

但有時候我們并不關心持有鎖

四)v$locked_object視圖

v$locked_object
記錄了目前已經被鎖定的對象的資訊
XIDUSN表示目前事務使用的復原段的編号
XIDSLOT說明該事務在復原段頭部的事務表中對應的記錄編号
XIDSQN說明序列号
OBJECT_ID說明目前被鎖定的對象的ID号,可以根據該ID号到dba_objects裡查找被鎖定的對象名稱
LOCKED_MODE說明鎖定模式的數字編碼
           

v$locked_object

記錄了目前已經被鎖定的對象的資訊

哪些對象被鎖定了

XIDUSN、XIDSLOT、XIDSQN是鎖這些對象的事務資訊

OBJECT_ID是哪個對象被鎖住了

LOCKED_MODE是鎖的模式是什麼,用什麼方式鎖了

比如某個表被鎖住的話

這裡面可以查出來

五)v$session視圖

v$session
記錄了目前session的相關資訊
SID表示session的編号
SERIAL#表示序列号
SID和SERIAL#可以認為是v$session的主鍵,它們共同唯一辨別一個session
           

記錄的是會話資訊

通過SID和SERIAL#

它倆可以唯一的标示一個會話

六)選擇hr使用者做實驗

1)hr使用者

在sqldeveloper裡面開的會話有的是用hr使用者登陸的

sqldeveloper打開後

在 連接配接 設定卡部分

選擇其中的一個連接配接

右鍵點選連接配接名

再點選右鍵菜單中的屬性

打開 建立/選擇資料庫連接配接 設定卡

将其中的 使用者名和密碼 改成你需要的使用者

我們使用hr做的測試,這裡用hr

這個sqldeveloper就是使用hr使用者

也可以在sqldeveloper中使用sys使用者

老師使用的sqlplus裡面都是用hr使用者登的

hr使用者它預設不能通路v$mystat

這個視圖要經常被使用

可以使用下面的指令

grant select on v_$mystat to hr;

以管理者身份運作,給hr使用者授權

在sys使用者裡面執行一下

SQL> grant select on v_$mystat to hr;

Grant succeeded.
           

執行以後這個hr使用者就可以通路v$mystat了

我們看一下比如這個

select sid from v$mystat where rownum=1;

看看會話的目前的SID是多少

如果grant沒有執行的話

hr使用者使用這個語句查詢它會報錯的

它會報沒有這個對象

去grant一下以後它就ok了

是以你需要用sys使用者grant一下

在sqldeveloper中

一個hr使用者建立的連接配接傳回了一個結果

SID
       134
           

目前的SID是134

我們看看第二個hr使用者建立的會話

SID
       131
           

老師執行時傳回結果慢

在sqldeveloper執行慢主要和sqldeveloper的原理有關系

當一個會話長時間不用的時候它會關掉

sqldeveloper确實非常占資源

我們現在開了三個是以非常的慢了

在sqlplus中也可以查

這個比較的快

SQL> select sid from v$mystat where rownum=1;

       SID
----------
       139
           

這個hr使用者會話的SID是139

在另一個sqlplus中查

SQL> select sid from v$mystat where rownum=1;

       SID
----------
       145
           

這個hr使用者會話的SID是145

好我們記一下

134,131

第三個sqldeveloper不用

第四個是sqlplus是139

第五個sqlplus是145

hr使用者一共建了了四個會話

SID分别是134,131,139,145

最終老師放棄了使用sqldeveloper做hr使用者的實驗

後面的實驗隻使用了前面hr會話中的139和145的兩個會話

2)v_$mystat和v$mystat

可能大家注意到了

grant語句中使用的v_$mystat和hr使用者通路的v$mystat不一樣

這裡補充說一下 v$mystat 和 v_$mystat 的差別

初始狀态下hr使用者通路v$mystat時

SQL> select sid from v$mystat where rownum=;
select sid from v$mystat where rownum=
                *
ERROR at line :
ORA-: table or view does not exist
           

提示通路的表或者視圖不存在

當sys使用者給hr使用者授權後

grant select on v_$mystat to hr;

hr使用者就可以通路了

大家注意到上面兩個語句中執行的對象并不一樣

要通路的是v$mystat,而授權的是v_$mystat

如果我們直接給v$mystat授權

SQL> grant select on v$mystat to hr;
grant select on v$mystat to hr
                *
ERROR at line :
ORA-: can only select from fixed tables/views
           

說明這裡授權的v$mystat不是固有視圖,不能直接授權

實際這裡hr通路的v$mystat是一個同義詞

sys不能給同義詞授權,隻能授權給固定的表或視圖

同義詞在oracle中可以了解為一個對象的别名

有私有和共用之分

每個使用者都可以給自己的對象建立自己的同義詞

這樣建立的同義詞隻能自己使用

建立私有同義詞文法:

Create [OR REPLACE] SYNONYM [schema.]synonym_name FOR [schema.]object_name;

預設隻有系統管理者可以建立共用同義詞

共用同義詞屬于oracle的public

public擁有了的權限,oracle所有的使用者都自動擁有了并可以使用

建立公有同義詞文法:

Create PUBLIC SYNONYM synonym_name FOR [schema.]object_name;

删除同義詞的文法:

drop [public] synonym 同義詞名稱;

私有同義詞不能和自己已有的對象同名

公用同義詞可以和建立者已有的對象同名

當一個使用者的一個對象和公有同義詞同名時

使用時自己的對象優先

私有同義詞和共用同義詞可以同名

使用時私有同義詞優先

是以這幾種對象如果有同名,語句中的使用順序是:

先使用自己的固有對象或私有同義詞,最後使用公用同義詞

根據網上得到的資料,

我也自己動手查了查V$MYSTAT同義詞的來源

查詢V$MYSTAT的說明:

SQL> select * from dict where table_name='V$MYSTAT';

TABLE_NAME
------------------------------
COMMENTS
------------------------------ 
V$MYSTAT
Synonym for V_$MYSTAT
           

V$MYSTAT是一個同義詞是V_$MYSTAT的同義詞

再在庫中的同義詞資料字典中查找這個同義詞

SQL> select * from dba_synonyms where SYNONYM_NAME='V$MYSTAT';

OWNER      SYNONYM_NAME         TABLE_OWNE TABLE_NAME           DB_LINK
---------- -------------------- ---------- -------------------- --------------------
PUBLIC     V$MYSTAT             SYS        V_$MYSTAT
           

說明V$MYSTAT是SYS使用者的V_$MYSTAT視圖的共用同義詞

查詢V_$MYSTAT視圖的定義

SQL> select OWNER,VIEW_NAME,TEXT from dba_views where view_name = 'V_$MYSTAT';

OWNER      VIEW_NAME                      TEXT
---------- ------------------------------ --------------------------------------------------------------------------------
SYS        V_$MYSTAT                      select "SID","STATISTIC#","VALUE" from v$mystat
           

TEXT字段是這個視圖的定義

select “SID”,”STATISTIC#”,”VALUE” from v$mystat

也可以通過dbms_metadata.get_ddl

查詢V_$MYSTAT視圖的定義

dbms_metadata.get_ddl傳回的是long類型的結果

long型資料為可變長字元串,最大長度限制是2GB

sqlplus處理long型資料非常困難

因為裡面存的資料一般都很長

sqlplus顯示時一般隻能顯示出來一部分

是以想顯示完整的long型資料

要先給sqlplus環境設定LONG參數

SQL> SET LONG 
SQL> select dbms_metadata.get_ddl('VIEW','V_$MYSTAT') from dual;

DBMS_METADATA.GET_DDL('VIEW','V_$MYSTAT')
--------------------------------------------------------------------------------

  CREATE OR REPLACE FORCE VIEW "SYS"."V_$MYSTAT" ("SID", "STATISTIC#", "VALUE") AS
  select "SID","STATISTIC#","VALUE" from v$mystat
           

結果和從dba_views得到的一樣

這裡又有一個v$mystat

前面的一個是同義詞,這一個看看視圖定義裡面有沒有

而視圖的定義在

v$fixed_view_definition

中有

這裡查詢V$MYSTAT的定義

SQL> select * from v$fixed_view_definition where VIEW_NAME = 'V$MYSTAT';

VIEW_NAME
------------------------------
VIEW_DEFINITION
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
V$MYSTAT
select  SID , STATISTIC# , VALUE from GV$MYSTAT where inst_id = USERENV('Instance')
           

說明有一個固定視圖也叫V$MYSTAT它來源于GV$MYSTAT

經過查找和分析

GV$MYSTAT同樣有一個同名的PUBLIC同義詞和一個固定視圖

而且也有一個關聯的GV_$MYSTAT視圖

PUBLIC同義詞GV$MYSTAT來自于GV_$MYSTAT,而GV_$MYSTAT又産生自固定視圖GV$MYSTAT

再看一下固定視圖GV$MYSTAT的定義

SQL> select * from v$fixed_view_definition where VIEW_NAME = 'GV$MYSTAT';

VIEW_NAME
------------------------------
VIEW_DEFINITION
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GV$MYSTAT
select inst_id,ksusenum,ksusestn,ksusestv from x$ksumysta where bitand(ksspaflg,1)!=0 and bitand(ksuseflg,1)!=0 and ksusestn<(select ksusgstl from x$ksusgif)
           

說明固定視圖GV$MYSTAT來自于x$ksumysta

這裡x$ksumysta表中的資訊是oracle執行個體目前會話的狀态資訊

可以從v$fixed_table繼續查到x$ksumysta和結果中出現的x$ksusgif的資訊

SQL> SELECT * FROM v$fixed_table WHERE NAME in ('X$KSUMYSTA','X$KSUSGIF');

NAME                            OBJECT_ID TYPE   TABLE_NUM
------------------------------ ---------- ----- ----------
X$KSUSGIF                       TABLE         
X$KSUMYSTA                      TABLE         
           

這是固定表,不用再繼續找了

一般使用者使用的V$MYSTAT是一個共用同義詞

它的來源管道追溯過程是:

V$MYSTAT共用同義詞 來自于 V_$MYSTAT視圖 來自于 V$MYSTAT固定視圖 來自于 GV$MYSTAT 來自于 固定表X$KSUMYSTA

是以V$MYSTAT最終來自于固定表X$KSUMYSTA

前面查詢中用到的dict實際也是個共用同義詞

SYS使用者的DICTIONARY視圖有兩個共用同義詞DICT和DICTIONARY

我們使用了DICT同義詞

DICTIONARY是一個資料字典

官方描述是:

DICTIONARY contains descriptions of data dictionary tables and views.

就是DICTIONARY是個資料字典

内容中包含oracle系統中所有資料字典,包括所有資料字典表和資料字典視圖的名稱和說明。

3)oracle中的PUBLIC角色

前面講了一個共用同義詞建立時

自動的屬于了PUBLIC

PUBLIC在oracle中比較特殊,有很多人弄不清楚它到底是什麼類型的對象

本人在參考了網上的資料後

下面是我查找的過程

查詢PUBLIC在角色中有沒有定義:

SQL> select dbms_metadata.get_ddl('ROLE','PUBLIC') from dual;

DBMS_METADATA.GET_DDL('ROLE','PUBLIC')
--------------------------------------------------------------------------------

   CREATE ROLE "PUBLIC"
           

查詢PUBLIC在使用者中有沒有定義:

SQL> select dbms_metadata.get_ddl('USER','PUBLIC') from dual;
ERROR:
ORA-: object "PUBLIC" of type USER not found in schema "SYS"
ORA-: at "SYS.DBMS_SYS_ERROR", line 
ORA-: at "SYS.DBMS_METADATA", line 
ORA-: at "SYS.DBMS_METADATA", line 
ORA-: at line 



no rows selected
           

是以PUBLIC是一個角色,不是使用者

但是在DBA_ROLES查詢

SQL> select * from DBA_ROLES;

ROLE                           PASSWORD
------------------------------ --------
CONNECT                        NO
RESOURCE                       NO
DBA                            NO
SELECT_CATALOG_ROLE            NO
EXECUTE_CATALOG_ROLE           NO
DELETE_CATALOG_ROLE            NO
EXP_FULL_DATABASE              NO
IMP_FULL_DATABASE              NO
RECOVERY_CATALOG_OWNER         NO
GATHER_SYSTEM_STATISTICS       NO
LOGSTDBY_ADMINISTRATOR         NO
AQ_ADMINISTRATOR_ROLE          NO
AQ_USER_ROLE                   NO
GLOBAL_AQ_USER_ROLE            GLOBAL
SCHEDULER_ADMIN                NO
HS_ADMIN_ROLE                  NO
AUTHENTICATEDUSER              NO
OEM_ADVISOR                    NO
OEM_MONITOR                    NO
WM_ADMIN_ROLE                  NO
JAVAUSERPRIV                   NO
JAVAIDPRIV                     NO
JAVASYSPRIV                    NO
JAVADEBUGPRIV                  NO
EJBCLIENT                      NO
JAVA_ADMIN                     NO
JAVA_DEPLOY                    NO
CTXAPP                         NO
XDBADMIN                       NO
XDBWEBSERVICES                 NO
OLAP_DBA                       NO
OLAP_USER                      NO
MGMT_USER                      NO

 rows selected.
           

并沒有PUBLIC

查詢DBA_ROLES的定義

SQL> select dbms_metadata.get_ddl('VIEW','DBA_ROLES','SYS') from dual;

DBMS_METADATA.GET_DDL('VIEW','DBA_ROLES','SYS')
--------------------------------------------------------------------------------

  CREATE OR REPLACE FORCE VIEW "SYS"."DBA_ROLES" ("ROLE", "PASSWORD_REQUIRED") AS
  select name, decode(password, null, 'NO', 'EXTERNAL', 'EXTERNAL',
                      'GLOBAL', 'GLOBAL', 'YES')
from  user$
where type# =  and name not in ('PUBLIC', '_NEXT_USER')
           

結果中有這麼一句

name not in (‘PUBLIC’, ‘_NEXT_USER’)

說明DBA_ROLES生成時過濾掉了PUBLIC

oracle中的角色是一種權限的集合

如常用的CONNECT連接配接角色,RESOURCE資源角色,DBA資料庫管理者角色是ORACLE系統的三個内置角色

可以把單個的權限再賦予角色使角色的權限增加

如:

SQL> select ROLE, PRIVILEGE from role_sys_privs where role='CONNECT';

ROLE                           PRIVILEGE
------------------------------ ----------------------------------------
CONNECT                        CREATE SESSION

SQL> grant CREATE ANY VIEW to CONNECT;

Grant succeeded.

SQL> select ROLE, PRIVILEGE from role_sys_privs where role='CONNECT';

ROLE                           PRIVILEGE
------------------------------ ----------------------------------------
CONNECT                        CREATE ANY VIEW
CONNECT                        CREATE SESSION
           

也可以回收角色的權限

SQL> revoke CREATE ANY VIEW from CONNECT;

Revoke succeeded.

SQL> select ROLE, PRIVILEGE from role_sys_privs where role='CONNECT';

ROLE                           PRIVILEGE
------------------------------ ----------------------------------------
CONNECT                        CREATE SESSION
           

但最終這些角色和單個的權限是要被賦予使用者來起作用的

檢視使用者擁有的權限

select grantee,privilege from dba_sys_privs where grantee=’HR’;

如結果:

SQL> select grantee,privilege from dba_sys_privs where grantee='HR';

GRANTEE                        PRIVILEGE
------------------------------ ----------------------------------------
HR                             CREATE VIEW
HR                             UNLIMITED TABLESPACE
HR                             CREATE DATABASE LINK
HR                             CREATE SEQUENCE
HR                             CREATE SESSION
HR                             ALTER SESSION
HR                             CREATE SYNONYM

 rows selected.
           

使用授權語句時可以把單個權限分别賦予單個使用者

也可以把權限的集合角色授予一個使用者

我們可以把權限賦予PUBLIC

SQL> grant CREATE ANY VIEW to PUBLIC;

Grant succeeded.
           

同時也可以把PUBLIC賦予使用者

SQL> grant PUBLIC to HR;

Grant succeeded.
           

如果把使用者賦予使用者是不允許的:

SQL> grant sys to HR;
grant sys to HR
      *
ERROR at line :
ORA-: role 'SYS' does not exist
           

進一步說明PUBLIC是個角色

再查HR使用者的權限

HR的系統權限

SQL> select * from dba_sys_privs where grantee = 'HR';

GRANTEE                        PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
HR                             CREATE VIEW                              NO
HR                             UNLIMITED TABLESPACE                     NO
HR                             CREATE DATABASE LINK                     NO
HR                             CREATE SEQUENCE                          NO
HR                             CREATE SESSION                           NO
HR                             ALTER SESSION                            NO
HR                             CREATE SYNONYM                           NO

 rows selected.
           

HR的角色權限

SQL> select * from dba_role_privs where grantee = 'HR';

GRANTEE                        GRANTED_ROLE                   ADM DEF
------------------------------ ------------------------------ --- ---
HR                             RESOURCE                       NO  YES
HR                             PUBLIC                         NO  YES
           

這時HR使用者我們看到在已經賦予的角色GRANTED_ROLE中有了PUBLIC角色權限,

這是我前面手動賦予了HR使用者的權限

盡管它原來就有,但在這裡顯示出來了

而HR使用者初始的角色權限是這樣的:

SQL> select * from dba_role_privs where grantee = 'HR';

GRANTEE                        GRANTED_ROLE                   ADM DEF
------------------------------ ------------------------------ --- ---
HR                             RESOURCE                       NO  YES
           

這是HR角色權限的預設狀态

是以可以确定PUBLIC是一個角色了

但這個角色比較特殊

在很多的表和視圖都給屏蔽掉了

但有的地方還是可以查到的

SQL> select * from dba_role_privs where grantee = 'PUBLIC';

GRANTEE                        GRANTED_ROLE                   ADM DEF
------------------------------ ------------------------------ --- ---
PUBLIC                         RESOURCE                       NO  YES

SQL> select * from dba_sys_privs where grantee = 'PUBLIC';

GRANTEE                        PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
PUBLIC                         UNLIMITED TABLESPACE                     NO
PUBLIC                         CREATE ANY VIEW                          NO
           

這兩個查詢列出了PUBLIC擁有的角色權限和系統權限

同樣也可以給PUBLIC添加新的權限,CREATE ANY VIEW就是我自己給它添加的

public擁有的權限,所有的使用者都自動的擁有了

也就是所有的使用者初始預設都擁有PUBLIC角色的權限

七)兩個事務間鎖争用執行個體

1)兩個事務争用鎖

我們執行一個

update employees set last_name=last_name||’a’ where department_id=60;

開始一個事務

開始實驗

在其中一個sqlplus中執行

SQL> update employees set last_name=last_name||'a' where department_id=;

 rows updated.
           

當然我們講過

這個事務一旦開始以後

伴随着一堆的鎖

執行這個語句的SID是139

我們先查一下和事務相關的

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

剛才已經開始一個事務了

使用sys使用者看一下有多少事務

因為剛開始一個事務

它是active的沒有送出

它在v$transaction裡面一定會出現

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

    XIDUSN    XIDSLOT     XIDSQN STATUS
---------- ---------- ---------- ----------------
         7         23        238 ACTIVE
           

這就是剛才我們的事務

然後我們可以去查一下

剛才在139開始的一個事務

sys使用下面的語句查一下

查詢結果

SQL> select sid,type,id1,id2,decode(lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
decode(request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') request_mode,block
              from v$lock
        where sid=;  

       SID TY        ID1        ID2 LOCK_MODE           REQUEST_MODE             BLOCK
---------- -- ---------- ---------- ------------------- ------------------- ----------
        TM                 Row Exclusive       None                         
        TX              Exclusive           None                         
           

從結果看139會話

産生了一個TM鎖和一個TX鎖

TM的ID2總是0

ID1是代表着操作所在的表

TX鎖的ID1和ID2通過語句可以找到這個事務

從LOCK_MODE看出他們都持有鎖

REQUEST_MODE看出都沒有請求鎖

從BLOCK都是0看出持有的鎖都沒有阻塞别人

再另外開一個session

同樣的去執行

update employees set last_name=last_name||’b’ where department_id=60;

在SID為145的hr會話中執行

它需要的資源被鎖住

SQL> update employees set last_name=last_name||'b' where department_id=;

           

這時的執行被卡住

我們再去查一下這裡是139和145

對(#A)語句稍作修改

得到語句

select sid,type,id1,id2,

decode(lmode,0,’None’,1,’Null’,2,’Row share’,3,’Row Exclusive’,4,’Share’,5,’Share Row Exclusive’,6,’Exclusive’) lock_mode,

decode(request,0,’None’,1,’Null’,2,’Row share’,3,’Row Exclusive’,4,’Share’,5,’Share Row Exclusive’,6,’Exclusive’) request_mode,block

from v$lock

where sid in(139,145)

order by sid;

查的是v$lock

看看這個鎖的狀況

好執行一下,結果

SQL> select sid,type,id1,id2,
decode(lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
        decode(request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') request_mode,block
from v$lock
        where sid in(,)
    order by sid;

       SID TY        ID1        ID2 LOCK_MODE           REQUEST_MODE             BLOCK
---------- -- ---------- ---------- ------------------- ------------------- ----------
        TM                 Row Exclusive       None                         
        TX              Exclusive           None                         
        TM                 Row Exclusive       None                         
        TX              None                Exclusive                    
           

139和145都出現了

139的TM和TX鎖沒變

一開始執行的139,後面執行的145

139一開始執行的,持有TX和TM鎖

145的TM鎖LOCK_MODE為Row Exclusive持有

145和139的TM鎖的ID1相同就是對象還一樣

也就是說139和145都在這個51857對象上加了RX鎖

但是145的TX鎖行的REQUEST_MODE的值是Exclusive

出現了Exclusive

也就是145被139這個事務鎖住了

記住145被139鎖住了表示這麼個意思

然後我們看139的TX這行

BLOCK的值是1

說明阻塞了别人

阻塞了145

而145 TX的REQUEST_MODE是Exclusive

它正在請求Exclusive鎖,也就是被鎖住了

通過這個我們看到一些問題

但是我們知道這個鎖出現這個問題

也不見得有問題

因為鎖住很正常

139一旦送出以後

145馬上就擷取到這個鎖了

2)關于等待鎖中的ID1和ID2

另外從結果我們可能發現一個問題

TX              Exclusive           None                         

        TX              None                Exclusive                    
           

我們看到139會話和145會話的TX鎖的ID1和ID2是相同的

這裡的145的鎖狀态的ID1和ID2并不是145會話的事務資訊

145會話的TX鎖的REQUEST_MODE為Exclusive說明它在請求一個鎖

這個例子中145自己本身的事務還沒有開始

這時查詢v$transaction并沒有145會話的事務

TX鎖REQUEST_MODE為Exclusive時

這裡的ID1和ID2的值是被請求鎖的事務資訊

這裡在請求139會話的鎖,這裡ID1和ID2的值就是139會話的資訊

當145得到鎖以後

本例中這時145會話開始了一個事務

這裡的ID1和ID2 的值會自動改變為145事務的資訊

REQUEST_MODE為Exclusive的鎖ID1和ID2的資訊始終是被請求的持有鎖的事務的資訊

有多個事務等待同一個鎖

前一個持有鎖的事務釋放鎖後

一個新事務得到了這個鎖

這時隊列中的其它事務的Exclusive狀态的鎖資訊的ID1和ID2都變為了這個新持有鎖的事務的資訊

如果145事務在請求鎖之前

145已經開始了一個事務,也就是它已經持有了事務鎖

這時的結果會把它本身的事務鎖也列出,并且ID1和ID2的值是145事務的資訊

同時也會列出它正在請求的鎖的資訊,這條資訊的ID1和ID2是被請求鎖的資訊

我自己做出了下面的一個例子的結果

SID TY        ID1        ID2 LOCK_MODE           REQUEST_MODE             BLOCK
---------- -- ---------- ---------- ------------------- ------------------- ----------
       148 TX     262165        242 None                Exclusive                    0
       148 TM      51857          0 Row Exclusive       None                         0
       148 TX     524327        303 Exclusive           None                         0
       150 TX     262165        242 Exclusive           None                         1
       150 TM      51857          0 Row Exclusive       None                         0
           

148會話本身持有一個TX鎖

這條資訊的ID1和ID2的資訊是它本身事務的資訊

148會話還請求一個TX鎖

TX              None                Exclusive                    
           

這條資訊的ID1和ID2的資訊是148正在請求的被請求鎖的事務的資訊

這裡正在請求150正在持有的鎖

是以這行的ID1和ID2列出了150事務的資訊

有一行

這行的BLOCK為1

說明150事務它持有的鎖有别的事務正在等待

正好和148正在請求鎖對應

驗證了前面的分析

八)三個事務的鎖争用

1)三個事務争同一個鎖

我們再打開一個會話

再建立一個會話

以hr使用者身份連接配接

先查一下SID

SQL> select sid from v$mystat where rownum=1;

       SID
----------
       136
           

這個新的目前會話的SID是136

接着前面的實驗

也去做同樣的一個操作

update employees set last_name=last_name||’b’ where department_id=60;

它肯定也被鎖住

執行結果

SQL> update employees set last_name=last_name||'b' where department_id=;

           

暫時無傳回值

也被鎖住

這裡是136

現在是139 145 和136操作

139應該把145和136鎖住了

再去查一個語句

select sid,type,
    decode(request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive')
    request_mode
    from v$enqueue_lock
    where sid in(,);
           

根據分析兩個被鎖住的是145和136

查的是v$enqueue_lock

這裡面它會隻是把誰被鎖住了誰給列出來

請求鎖的被列出來

執行一下

這裡通路的是v$enqueue_lock

執行結果

SQL> select sid,type,
        decode(request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive')
        request_mode
        from v$enqueue_lock
        where sid in(,);              

       SID TY REQUEST_MODE
---------- -- -------------------
        TX Exclusive
        TX Exclusive
           

我們看145和136都在

v$enqueue_lock列出的都在請求鎖

145和136都在請求事務鎖,都被别人鎖住了

其實139鎖住了145 和 136

根據語句執行的順序

145是第一個被鎖住的

136是第二個被鎖住的

這裡面如果我139釋放了的話

139把145和136同時鎖住了

這個時候

第一個獲得鎖的應該是145

再就是136

鎖是可以排隊的

我們看一個TX鎖這個鎖是139的

這個鎖把145和136同時鎖住了

145和136會到139下面去排隊

先是145,後面是136要過來排隊

139釋放以後

145第一個擷取,第一個獲得鎖

有可能獲得鎖以後145又把136鎖住了

如果它們擷取一樣的資源

145把136鎖住了

如果說139釋放以後

145擷取的資源和136擷取的資源不一樣的話

這兩個可以同時擷取到鎖

通過這個我們可以看出并記住鎖是排隊的

2)v$lock中BLOCK字段的值

我又做了一個三個事務争用相同鎖的例子

查詢v$lock視圖的結果

SQL> select sid,type,id1,id2,
decode(lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
        decode(request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') request_mode,block
    from v$lock
    where sid in(,,)
    order by sid;

       SID TY        ID1        ID2 LOCK_MODE           REQUEST_MODE             BLOCK
---------- -- ---------- ---------- ------------------- ------------------- ----------
        TM                 Row Exclusive       None                         
        TX              Exclusive           None                         
        TM                 Row Exclusive       None                         
        TX              None                Exclusive                    
        TM                 Row Exclusive       None                         
        TX              None                Exclusive                    

 rows selected.
           

這三個事務開始執行的順序是132,135,139

這時132事務的資訊是ID1:655370 ,ID2:242

135和139會話中的事務還沒有開始

執行rollback釋放第一個事務占用的鎖

然後執行相同的語句

得到的結果是:

SID TY        ID1        ID2 LOCK_MODE           REQUEST_MODE             BLOCK
---------- -- ---------- ---------- ------------------- ------------------- ----------
       135 TM      51857          0 Row Exclusive       None                         0
       135 TX     327683        338 Exclusive           None                         1
       139 TM      51857          0 Row Exclusive       None                         0
       139 TX     327683        338 None                Exclusive                    0
           

132事務釋放鎖後

第一個排隊的135得到了鎖

得到鎖後135會話中的事務就開始了

這時135會話中事務的資訊是ID1:327683,ID2:338

這時它鎖住了139,139還在等待

139會話中的事務仍然沒有開始

不管是1個事務還是2個事務在等待鎖

持有鎖的事務的資訊的BLOCK都為1

這個字段并不是說明有多少個事務在等待鎖

隻是說明有沒有事務在等待這個鎖

等待鎖的139會話

在第一次查詢時的結果

139 TX 655370 242 None Exclusive 0

在第二次查詢時的結果

139 TX 327683 338 None Exclusive 0

ID1和ID2的值變化了

但都是139它等待的目前正在持有這個鎖的事務的資訊

九)鎖的時間

我們找一個非常有意義的一個

select a.sid blocker_sid,a.serial#,a.username as blocker_username,b.type,
decode(b.lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
b.ctime as time_held,c.sid as waiter_sid,
decode(c.request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') request_mode,
c.ctime time_waited 
from   v$lock b, v$enqueue_lock c, v$session a 
where  a.sid = b.sid and    b.id1= c.id1(+) and b.id2 = c.id2(+) and c.type(+) = 'TX' and  b.type = 'TX' and  b.block   = 
order by time_held, time_waited;
           

這個sql語句是我們用的最多的一個sql語句

它做一件什麼事情呢

SQL> select a.sid blocker_sid,a.serial#,a.username as blocker_username,b.type,
decode(b.lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
        b.ctime as time_held,c.sid as waiter_sid,
    decode(c.request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') request_mode,
    c.ctime time_waited
    from   v$lock b, v$enqueue_lock c, v$session a
where  a.sid = b.sid and    b.id1= c.id1(+) and b.id2 = c.id2(+) and c.type(+) = 'TX' and  b.type = 'TX' and  b.block   = 
        order by time_held, time_waited;

BLOCKER_SID    SERIAL# BLOCKER_USERNAME               TY LOCK_MODE            TIME_HELD WAITER_SID REQUEST_MODE        TIME_WAITED
----------- ---------- ------------------------------ -- ------------------- ---------- ---------- ------------------- -----------
                HR                             TX Exclusive                          Exclusive                  
                HR                             TX Exclusive                          Exclusive                  
           

前兩個字段

BLOCKER_SID為139和SERIAL#為2746标明一個會話

這個會話使用BLOCKER_USERNAME為hr使用者登陸的

它的TY是TX鎖

它持有TIME_HELD為3909厘秒

第一行

WAITER_SID為136事務

TIME_WAITED等待了1790這麼長時間

也就是說136目前在等待139

就是136被139鎖住了

139持有鎖的時間是TIME_HELD 3909這麼長了

WAITER_SID 136等待TIME_WAITED 1790這麼長了

有了時間了就能判斷這個鎖是不是有沒有問題

還有一個

136等待了1790這麼長的時間

145等待139等待了2931這麼長時間

就說明145比136等的時間長了

過了一段時間再執行一次上面的指令

SQL> select a.sid blocker_sid,a.serial#,a.username as blocker_username,b.type,
decode(b.lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
        b.ctime as time_held,c.sid as waiter_sid,
    decode(c.request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') request_mode,
    c.ctime time_waited
from   v$lock b, v$enqueue_lock c, v$session a
        where  a.sid = b.sid and    b.id1= c.id1(+) and b.id2 = c.id2(+) and c.type(+) = 'TX' and  b.type = 'TX' and  b.block   = 
    order by time_held, time_waited;

BLOCKER_SID    SERIAL# BLOCKER_USERNAME               TY LOCK_MODE            TIME_HELD WAITER_SID REQUEST_MODE        TIME_WAITED
----------- ---------- ------------------------------ -- ------------------- ---------- ---------- ------------------- -----------
                HR                             TX Exclusive                          Exclusive                  
                HR                             TX Exclusive                          Exclusive                  
           

145等待的時間比136時間長

也就是從某種意義上來講145它排在136的前面

這個指令是有意義的

我們就看TIME_WAITED列

再看TIME_HELD

如果你持有時間太長了

也就是說明你這個事務遲遲不送出

就根據BLOCKER_SID和SERIAL#這裡是139和2746

就可以執行一個sql語句

可以用

alter system kill session ‘139,2746’;

把它kill掉

可以執行這個指令

執行它以後

它就可以把139給kill掉

kill以後它就會自動復原

系統管理者sys會話中做一下

SQL> alter system kill session '139,2746';

System altered.
           

kill以後我們看

139已經kill掉了

這時我們看145

SQL> update employees set last_name=last_name||'b' where department_id=;

 rows updated.
           

145的等待狀态解除了

update操作成功了

也就是145現在持有了鎖

136仍在等待

136還被鎖着得不到執行

因為145又把136鎖了

我們再去查

SQL> select a.sid blocker_sid,a.serial#,a.username as blocker_username,b.type,
decode(b.lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
b.ctime as time_held,c.sid as waiter_sid,
            decode(c.request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') request_mode,
    c.ctime time_waited
    from   v$lock b, v$enqueue_lock c, v$session a
where  a.sid = b.sid and    b.id1= c.id1(+) and b.id2 = c.id2(+) and c.type(+) = 'TX' and  b.type = 'TX' and  b.block   = 
        order by time_held, time_waited;

BLOCKER_SID    SERIAL# BLOCKER_USERNAME               TY LOCK_MODE            TIME_HELD WAITER_SID REQUEST_MODE        TIME_WAITED
----------- ---------- ------------------------------ -- ------------------- ---------- ---------- ------------------- -----------
                HR                             TX Exclusive                           Exclusive                   
           

現在是145持有鎖

但它阻塞了WAITER_SID 為136的會話

139會話就沒鎖了

我們把剛才的事務都復原了

在139會話中執行

SQL> rollback;
rollback
*
ERROR at line 1:
ORA-00028: your session has been killed
           

看出session 139已經被kill了

再把145的會話復原了

SQL> rollback;

Rollback complete.
           

再把136的會話復原了

SQL> update employees set last_name=last_name||'b' where department_id=;

 rows updated.

SQL> rollback;

Rollback complete.
           

136會話在145會話復原後得到了執行,最終它也得到了鎖

為了試驗把它也復原了

十)一個事務多個TM鎖

一個事務修改多行

産生一個TX鎖,可以在多個表上産生多個TM鎖

一個事務隻産生一個事務鎖TX鎖

我們在一個事務裡面多執行幾條sql語句

update employees set last_name=last_name||'a' where department_id=;
update departments set department_name='unknow' where department_id=;
update locations set city='unknown' where location_id=;
           

在一個hr會話

SQL> select sid from v$mystat where rownum=1;

       SID
----------
       132
           

先執行一條update

SQL> update employees set last_name=last_name||'a' where department_id=;

 rows updated.
           

更新了employees這個表

第二個語句

它接着更新departments

SQL> update departments set department_name='unknow' where department_id=;

 row updated.
           

都是一個事務裡面的

下面語句是更新locations

SQL> update locations set city='unknown' where location_id=;

 row updated.
           

更新了三個語句

然後我們再使用

select sid,type,id1,id2,
decode(lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
decode(request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive')request_mode,block
from v$lock
where sid=;
           

再去查132這個會話它持有鎖的情況

在sys使用者會話中執行結果

SQL> select sid,type,id1,id2,
decode(lmode,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive') lock_mode,
        decode(request,,'None',,'Null',,'Row share',,'Row Exclusive',,'Share',,'Share Row Exclusive',,'Exclusive')request_mode,block
    from v$lock
    where sid=;

       SID TY        ID1        ID2 LOCK_MODE           REQUEST_MODE             BLOCK
---------- -- ---------- ---------- ------------------- ------------------- ----------
        TM                 Row Exclusive       None                         
        TM                 Row Exclusive       None                         
        TM                 Row Exclusive       None                         
        TX              Exclusive           None                         
           

一個會話的一個事務它修改了三個表

對三個表産生TM鎖

它産生了一個TX鎖,TX鎖就隻有一個

十一)transactions和dml_locks參數

再看一個sql語句

select name,value from v$parameter where name in(‘transactions’,’dml_locks’);

可以獲得的TX鎖定的總個數由初始化參數transactions決定,而可以獲得的TM鎖定的個數則由初始化參數dml_locks決定

transactions參數表示oracle一個執行個體最多可有的事務數

dml_locks參數表示一個oracle執行個體中最多可産生的TM鎖就是表級鎖的數量

對整個資料庫來講

它能獲得的TX鎖和TM鎖的總數由’transactions’和’dml_locks’它倆限制

如果這兩個參數過小的話

有可能影響并發的事務的數量以及通路的表的數量

我們執行一下看有多大

SQL> select name,value from v$parameter where name in('transactions','dml_locks');

NAME            VALUE
--------------- ----------
dml_locks       
transactions    
           

這個有時候也會碰到一些問題

結果中一個dml_locks是748,一個transactions是187

對資料庫來講

同時可以有187個事務可以同時運作

而鎖的數量

同時修改的表可以有700多個

一般的我們把這個都修改的擡高一些

比如把transactions修改為300

比如dml_locks我們修改成1500

可以給它增加

到底該不該增加

我們有一個查詢

select resource_name as "R_N",current_utilization as "C_U",max_utilization as "M_U",initial_allocation as "I_U" 
from v$resource_limit 
where resource_name in('transactions','dml_locks');
           

這個很有用,很有幫助

有v$resource_limit這個視圖

我們大家可以查一下

裡面有好多的資訊

我們先查這一個transactions和dml_locks參數

SQL> select resource_name as "R_N",current_utilization as "C_U",max_utilization as "M_U",initial_allocation as "I_U"
from v$resource_limit
where resource_name in('transactions','dml_locks');      

R_N                                   C_U        M_U I_U
------------------------------ ---------- ---------- --------------------
dml_locks                                                
transactions                                               
           

R_N這個列是資源名字

如dml_locks是資源名

C_U是current_utilization目前已經使用的數目

目前鎖定了3個表

M_U是max_utilization最大同時使用的數目

最大鎖過48個

I_U是initial_allocation初始可配置設定的數量

最大可配置設定的748

這是dml_locks

目前C_U是3個,最大可以是I_U是748

M_U為48是曾經達到的最大值是48

隻要這個48沒達到748

說明我這個dml_locks沒出現過問題

那麼transactions

曾經最大是9個,最大可以是187

這都沒問題

v$resource_limit視圖我們查一下通路一下

裡面有很多資源

SQL> select resource_name as "R_N",current_utilization as "C_U",max_utilization as "M_U",initial_allocation as "I_U"
from v$resource_limit;  

R_N                                   C_U        M_U I_U
------------------------------ ---------- ---------- --------------------
processes                                               
sessions                                                
enqueue_locks                                          
enqueue_resources                                       
ges_procs                                                   
ges_ress                                                    
ges_locks                                                   
ges_cache_ress                                              
ges_reg_msgs                                                
ges_big_msgs                                                
ges_rsv_msgs                                                
gcs_resources                                               
gcs_shadows                                                 
dml_locks                                                
temporary_table_locks                               UNLIMITED
transactions                                              
branches                                                  
cmtcallbk                                                 
sort_segment_locks                                  UNLIMITED
max_rollback_segments                                   
max_shared_servers                                  UNLIMITED
parallel_max_servers                                       

 rows selected.
           

隻要這個M_U的值沒有跟I_U的值相等,當然不可能超過

沒有跟它相等就說明我設定的參數都沒有問題

比如

有人經常說這個processes、這個sessions是不是設小了

連不上

可以看看sessions的M_U的值有沒有超過I_U的值,有沒有等于它

等于它說明可能就有問題

記住v$resource_limit這個很有意義

這裡講了和事務相關的一些操作

十二)死鎖

1)死鎖的發生

oracle裡面還有一種鎖叫死鎖

oracle一直這麼說

oracle中隻要産生死鎖一定是你的應用寫的有問題

記住

第一個

碰到死鎖的時候一定是應用寫的有問題

第二

碰到死鎖的時候oracle自動會釋放

會殺掉一個事務

一個死鎖會産生一個trc檔案

我們來看什麼叫死鎖

一個事務要修改一個資源

A事務修改了這個資源

B事務修改了另一個資源

A事務修改了一個資源以後在這個資源上加了鎖了

B事務修改了另一個資源後也加了鎖

A想持有B正在修改的這個資源,但已被B鎖住了

A修改了一個資源但是它還想修改B正在修改的資源但已被B鎖住

A被B鎖住了

B修改了一個資源後又想去修改A正在修改的資源

B被A鎖住了

好!産生死鎖了!

這個結它解不開

因為

這時隻有A復原了以後

B才能持有A現在擁有的資源

死鎖以後會有什麼現象呢

我把原來實驗的會話都給它rollback

并在新會話中實驗

在session1裡面

我更新100

SQL> select sid from v$mystat where rownum=1;

       SID
----------
       150

SQL> update employees set last_name=last_name||'a'
where employee_id=100;  2

1 row updated.
           

我把100給鎖住了

然後在 session2裡面呢

SQL> select sid from v$mystat where rownum=1;

       SID
----------
       148

SQL> update employees set last_name=last_name||'b'
where employee_id=101;  2

1 row updated.
           

把101給鎖住了

A裡面把100鎖住了

B把101鎖住了

然後session1想去

SQL> update employees set last_name=last_name||'c' where employee_id=;

           

想去鎖B鎖住的資源

已被B鎖住了

這時A被B鎖住了

然後session2中

SQL> update employees set last_name=last_name||'d' where employee_id=;

           

也在等待鎖

B又被A鎖住了

形成一個死循環了

這時在A裡面出現

SQL> update employees set last_name=last_name||'c' where employee_id=;
update employees set last_name=last_name||'c' where employee_id=
         *
ERROR at line :
ORA-: deadlock detected while waiting for resource
           

這時候A會話馬上出一個問題

另外一個會話B中我們回車以後

這個A會話一下子檢測到死鎖,被復原了

馬上被復原了

這裡復原的不是A會話中的整個事務

隻是被復原了一條語句,就是把造成死鎖的那條語句給復原了

這個事務中前面其它語句沒有影響,并沒有復原整個的事務

如果這時查詢A會話

查詢後可以得知這條語句前執行的語句仍然有效

也就是當死鎖發生的時候

oracle馬上會檢測到

同時将其中一個事務的一條造成死鎖的語句給自動復原

這裡是復原了第一個會話造成死鎖的語句,

就是請求第二個會話占有的鎖但是未得到鎖的語句,

但這時第二個會話請求的鎖,第一個會話仍然占有

既然如此,死循環被解除了

這樣在在造成死鎖的兩個會話中解除了死鎖

我們執行rollback将其中一個會話全部復原

SQL> rollback;

Rollback complete.
           

并且這裡又把第一個會話中占用鎖的語句復原後

第二個會話中等待鎖的語句得到了執行

SQL> update employees set last_name=last_name||'d' where employee_id=;

 row updated.
           

把第二個會話也復原

SQL> rollback;

Rollback complete.
           

當死循環發生的時候會做幾件事情

第一個oracle自動的對死鎖自動的檢測

而且還能快速檢測

而且把其中一個事務給復原

但隻是復原部分sql語句

2)死鎖的資訊

同時當死鎖發生的時候

會出現一件很重要的事情

oracle會記錄下死鎖的資訊

死鎖發生的時候

[oracle@redhat4 bdump]$ pwd
/u01/app/oracle/admin/jiagulun/bdump
           

在這個目錄裡面

[[email protected] bdump]$ ls
alert_jiagulun.log       jiagulun_lgwr_13577.trc  jiagulun_mmnl_6638.trc
jiagulun_cjq0_13651.trc  jiagulun_lgwr_13643.trc  jiagulun_p000_6646.trc
jiagulun_lgwr_13460.trc  jiagulun_lgwr_6626.trc   jiagulun_p001_6648.trc
           

有alert日志alert_jiagulun.log

alert日志是資料庫的總日志

可以檢視這個alert日志

cat alert_jiagulun.log

執行結果

[oracle@redhat4 bdump]$ cat alert_jiagulun.log
Mon Apr  :: 
Starting ORACLE instance (normal)
LICENSE_MAX_SESSION = 
LICENSE_SESSIONS_WARNING = 
Shared memory segment for instance monitoring created
.
.
.
Tue Nov  :: 
MMNL absent for  secs; Foregrounds taking over
MMNL absent for  secs; Foregrounds taking over
MMNL absent for  secs; Foregrounds taking over
Tue Nov  :: 
ORA-: Deadlock detected. More info in file /u01/app/oracle/admin/jiagulun/udump/jiagulun_ora_21608.trc.
Tue Nov  :: 
ORA-: Deadlock detected. More info in file /u01/app/oracle/admin/jiagulun/udump/jiagulun_ora_21608.trc.
           

在alert日志裡面會自動把死鎖資訊給列出來

說死鎖發生了

如:

Tue Nov  :: 
ORA-: Deadlock detected. More info in file /u01/app/oracle/admin/jiagulun/udump/jiagulun_ora_21608.trc.
           

在資訊裡面可以得到死鎖對應的trc檔案

/u01/app/oracle/admin/jiagulun/udump/jiagulun_ora_21608.trc

就是死鎖的具體資訊

這個trc檔案老師以後會給大家去分析

本人自己打開看了看,就看懂了開頭的一點

主要内容老師不給講真的看不明白!

這就是關于死鎖的一些情況

死鎖有關于oracle的排錯

這裡面就不講太多了

隻是告訴大家為什麼産生死鎖

oracle怎麼處理

這就是講的oracle的鎖的一些情況

2017年12月12日

文字:韻筝