公司建设网站的可行性分析,5118数据分析平台,中国排名前十的广告公司,建设网站专业公司哪家好本文主要研究锁的相关视图#xff0c;以及锁的相关操作#xff0c;通过视图查锁的问题。 一、v$transaction视图第一个视图是v$transaction#xff0c;就是Oracle数据库所有活动的事务数#xff0c;所有活动的事务每一个活动的事务在这里有一行。v$transactionXIDUSN表示当…本文主要研究锁的相关视图以及锁的相关操作通过视图查锁的问题。 一、v$transaction视图第一个视图是v$transaction就是Oracle数据库所有活动的事务数所有活动的事务每一个活动的事务在这里有一行。v$transactionXIDUSN表示当前事务使用的回滚段的编号XIDSLOT说明该事务在回滚段头部的事务表中对应的记录编号也可以叫做槽号XIDSQN说明序列号STATUS说明该事务是否为活动的这是v$transaction视图的结构这里做一个实验在一个hr用户的sqlplus中执行SQL delete from employees where rownum1;1 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 rownum1;一个事务开始以后至少产生几个锁第一个行上加锁了行上的锁你是看不见的因为它在行上但是我们开始一个事务有一个事务锁同时在表上应该加了个RX锁应该这时候有两个锁一个TX锁事务锁一个是TM级别上的表级的RX锁。使用语句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 sid129;这里把它取名为(#A)语句最后where条件有sidsid是会话的编号先查一下我们会话的编号是多少在我的实验环境下在hr用户的sqlplus中SQL select sid from v$mystat where rownum1;select sid from v$mystat where rownum1 *ERROR at line 1:ORA-00942: table or view does not existhr用户无权访问v$mystat所以换个方法使用下面的命令得到hr用户当前的sidSQL 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,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 2 3 from v$lock 4 where sid132; SID TY ID1 ID2 LOCK_MODE REQUEST_MODE BLOCK---------- -- ---------- ---------- ------------------- ------------------- ---------- 132 TM 51852 0 Row share None 0 132 TM 51855 0 Row share None 0 132 TM 51857 0 Row Exclusive None 0 132 TM 51864 0 Row share None 0 132 TM 51871 0 Row share None 0 132 TM 51889 0 Row share None 0 132 TM 51894 0 Row share None 0 132 TM 51902 0 Row share None 0 132 TX 262187 216 Exclusive None 09 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_id51902;查出51902是哪个表执行结果SQL select object_name from dba_objects where object_id51902;OBJECT_NAME-------------------------------------------------------------------------------------------------------PRODUCT_INFORMATION对象编号51902是PRODUCT_INFORMATION表说明我们找错了这个表上加的锁是Row share类型的锁删除操作的表应该产生Row Exclusive类型的锁前面delete语句删除EMPLOYEES表中行时牵涉到了PRODUCT_INFORMATION这个表是主外键约束关系的原因在PRODUCT_INFORMATION表产生了RS锁。再看刚才的结果132 TM 51857 0 Row Exclusive None 0锁应该是RX锁TM级别的RX锁是51857把语句改为select object_name from dba_objects where object_id51857;改一下执行一下看一下SQL select object_name from dba_objects where object_id51857;OBJECT_NAME----------------------------------------------------------------------------------------------------EMPLOYEES结果是EMPLOYEES是对的。所以这个TM这个表级锁在哪个表上根据ID1对应的ID可以找出来另外结果中TX所在的行有ID1对应的ID和ID2列对应的IDID1和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 0ID1列的值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(262187/power(2,16)) as undo_blk#,bitand(262187,to_number(ffff,xxxx)) 0 as slot# from dual; 2 UNDO_BLK# SLOT#---------- ---------- 4 43看结果是4号回滚段回滚段事务表中槽位号SLOT#是43和以前查询结果是一样的SQL select xidusn,xidslot,xidsqn,status from v$transaction; XIDUSN XIDSLOT XIDSQN STATUS---------- ---------- ---------- ---------------- 4 43 216 ACTIVE刚才这个语句XIDSQN的值216(#A)语句结果行132 TX 262187 216 Exclusive None 0直接有了(#A)语句结果中ID2是覆盖次数通过这个sql语句select trunc(262187/power(2,16)) as undo_blk#,bitand(262187,to_number(‘ffff’,’xxxx’)) 0 as slot#from dual; 2找出来用的哪个回滚段、槽位号是多少、覆盖次数这三个信息也就是(#A)语句结果中TX这一行ID1列和ID2列可以找到哪个事务行是TM锁132 TM 51857 0 Row Exclusive None 0ID1对应的编号51857是对象的编号这是v$lockOracle中的表级锁有锁定模式 锁定简称 编码数值Row Exclusive RX 3Row Shared RS 2Share S 4Exclusive X 6Share Row Exclusive SRX 5NULL 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 idType是类型有表级锁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就为0BLOCK如果是1的话132持有这个锁同时还锁住了别人到底锁住了谁可以去查。BLOCK是这个意思这里结果中block都是0也就是对132来讲我持有这么多的锁但是没有锁其它的任何人也就是132持有的锁没有对别人造成影响。三、v$enqueue_lock视图v$enqueue_lock该视图中包含的字段以及字段含义与v$lock中的字段一模一样。只不过该视图中只显示那些申请锁定但是无法获得锁定的session信息。其中的记录按照申请锁定的时间先后顺序排列先申请锁定的session排在前面排在前面的session将会先获得锁定。我们接着看v$enqueue_lockvlock是把会话持有的锁和请求的锁全给列出来了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用户做实验1hr用户在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 rownum1;看看会话的当前的SID是多少如果grant没有执行的话hr用户使用这个语句查询它会报错的它会报没有这个对象去grant一下以后它就ok了所以你需要用sys用户grant一下在sqldeveloper中一个hr用户建立的连接返回了一个结果 SID 134当前的SID是134我们看看第二个hr用户建立的会话 SID131执行时返回结果慢在sqldeveloper执行慢主要和sqldeveloper的原理有关系当一个会话长时间不用的时候它会关掉sqldeveloper确实非常占资源我们现在开了三个所以非常的慢了。在sqlplus中也可以查这个比较的快SQL select sid from v$mystat where rownum1; SID---------- 139这个hr用户会话的SID是139在另一个sqlplus中查SQL select sid from v$mystat where rownum1; SID---------- 145这个hr用户会话的SID是145简单记录一下134,131第三个sqldeveloper不用第四个是sqlplus是139第五个sqlplus是145hr用户一共建了了四个会话SID分别是134,131,139,145最终放弃了使用sqldeveloper做hr用户的实验后面的实验只使用了前面hr会话中的139和145的两个会话2v_$mystat和v$mystat可能大家注意到了grant语句中使用的v_$mystat和hr用户访问的v$mystat不一样这里补充说一下 v$mystat 和 v_$mystat 的区别。初始状态下hr用户访问v$mystat时SQL select sid from v$mystat where rownum1;select sid from v$mystat where rownum1 *ERROR at line 1:ORA-00942: 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 1:ORA-02030: 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的publicpublic拥有了的权限Oracle所有的用户都自动拥有了并可以使用创建公有同义词语法Create PUBLIC SYNONYM synonym_name FOR [schema.]object_name;删除同义词的语法drop [public] synonym 同义词名称;私有同义词不能和自己已有的对象同名公用同义词可以和创建者已有的对象同名当一个用户的一个对象和公有同义词同名时使用时自己的对象优先私有同义词和共用同义词可以同名使用时私有同义词优先。所以这几种对象如果有同名语句中的使用顺序是先使用自己的固有对象或私有同义词最后使用公用同义词。查询V$MYSTAT的说明SQL select * from dict where table_nameV$MYSTAT;TABLE_NAME------------------------------COMMENTS------------------------------ V$MYSTATSynonym for V_$MYSTATV$MYSTAT是一个同义词是V_$MYSTAT的同义词再在库中的同义词数据字典中查找这个同义词SQL select * from dba_synonyms where SYNONYM_NAMEV$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$mystatTEXT字段是这个视图的定义select “SID”,”STATISTIC#”,”VALUE” from v$mystat也可以通过dbms_metadata.get_ddl查询V_$MYSTAT视图的定义dbms_metadata.get_ddl返回的是long类型的结果long型数据为可变长字符串最大长度限制是2GBsqlplus处理long型数据非常困难因为里面存的数据一般都很长sqlplus显示时一般只能显示出来一部分所以想显示完整的long型数据要先给sqlplus环境设置LONG参数SQL SET LONG 9999SQL 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$MYSTATselect SID , STATISTIC# , VALUE from GV$MYSTAT where inst_id USERENV(Instance)说明有一个固定视图也叫V$MYSTAT它来源于GV$MYSTAT经过查找和分析GV$MYSTAT同样有一个同名的PUBLIC同义词和一个固定视图而且也有一个关联的GV_$MYSTAT视图PUBLIC同义词V$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$MYSTATselect 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 4294951930 TABLE 33X$KSUMYSTA 4294951106 TABLE 35这是固定表不用再继续找了一般用户使用的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系统中所有数据字典包括所有数据字典表和数据字典视图的名称和说明。3Oracle中的PUBLIC角色前面讲了一个共用同义词创建时自动的属于了PUBLICPUBLIC在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-31603: object PUBLIC of type USER not found in schema SYSORA-06512: at SYS.DBMS_SYS_ERROR, line 105ORA-06512: at SYS.DBMS_METADATA, line 2805ORA-06512: at SYS.DBMS_METADATA, line 4333ORA-06512: at line 1no rows selected所以PUBLIC是一个角色不是用户但是在DBA_ROLES查询SQL select * from DBA_ROLES;ROLE PASSWORD------------------------------ --------CONNECT NORESOURCE NODBA NOSELECT_CATALOG_ROLE NOEXECUTE_CATALOG_ROLE NODELETE_CATALOG_ROLE NOEXP_FULL_DATABASE NOIMP_FULL_DATABASE NORECOVERY_CATALOG_OWNER NOGATHER_SYSTEM_STATISTICS NOLOGSTDBY_ADMINISTRATOR NOAQ_ADMINISTRATOR_ROLE NOAQ_USER_ROLE NOGLOBAL_AQ_USER_ROLE GLOBALSCHEDULER_ADMIN NOHS_ADMIN_ROLE NOAUTHENTICATEDUSER NOOEM_ADVISOR NOOEM_MONITOR NOWM_ADMIN_ROLE NOJAVAUSERPRIV NOJAVAIDPRIV NOJAVASYSPRIV NOJAVADEBUGPRIV NOEJBCLIENT NOJAVA_ADMIN NOJAVA_DEPLOY NOCTXAPP NOXDBADMIN NOXDBWEBSERVICES NOOLAP_DBA NOOLAP_USER NOMGMT_USER NO33 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# 0 and name not in (PUBLIC, _NEXT_USER)结果中有这么一句name not in (‘PUBLIC’, ‘_NEXT_USER’)说明DBA_ROLES生成时过滤掉了PUBLICOracle中的角色是一种权限的集合如常用的CONNECT连接角色RESOURCE资源角色DBA数据库管理员角色是ORACLE系统的三个内置角色可以把单个的权限再赋予角色使角色的权限增加如SQL select ROLE, PRIVILEGE from role_sys_privs where roleCONNECT;ROLE PRIVILEGE------------------------------ ----------------------------------------CONNECT CREATE SESSIONSQL grant CREATE ANY VIEW to CONNECT;Grant succeeded.SQL select ROLE, PRIVILEGE from role_sys_privs where roleCONNECT;ROLE PRIVILEGE------------------------------ ----------------------------------------CONNECT CREATE ANY VIEWCONNECT CREATE SESSION也可以回收角色的权限SQL revoke CREATE ANY VIEW from CONNECT;Revoke succeeded.SQL select ROLE, PRIVILEGE from role_sys_privs where roleCONNECT;ROLE PRIVILEGE------------------------------ ----------------------------------------CONNECT CREATE SESSION但最终这些角色和单个的权限是要被赋予用户来起作用的查看用户拥有的权限select grantee,privilege from dba_sys_privs where grantee’HR’;如结果SQL select grantee,privilege from dba_sys_privs where granteeHR;GRANTEE PRIVILEGE------------------------------ ----------------------------------------HR CREATE VIEWHR UNLIMITED TABLESPACEHR CREATE DATABASE LINKHR CREATE SEQUENCEHR CREATE SESSIONHR ALTER SESSIONHR CREATE SYNONYM7 rows selected.使用授权语句时可以把单个权限分别赋予单个用户也可以把权限的集合角色授予一个用户我们可以把权限赋予PUBLICSQL 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 1:ORA-01919: role SYS does not exist进一步说明PUBLIC是个角色再查HR用户的权限HR的系统权限SQL select * from dba_sys_privs where grantee HR;GRANTEE PRIVILEGE ADM------------------------------ ---------------------------------------- ---HR CREATE VIEW NOHR UNLIMITED TABLESPACE NOHR CREATE DATABASE LINK NOHR CREATE SEQUENCE NOHR CREATE SESSION NOHR ALTER SESSION NOHR CREATE SYNONYM NO7 rows selected.HR的角色权限SQL select * from dba_role_privs where grantee HR;GRANTEE GRANTED_ROLE ADM DEF------------------------------ ------------------------------ --- ---HR RESOURCE NO YESHR 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 YESSQL select * from dba_sys_privs where grantee PUBLIC;GRANTEE PRIVILEGE ADM------------------------------ ---------------------------------------- ---PUBLIC UNLIMITED TABLESPACE NOPUBLIC CREATE ANY VIEW NO这两个查询列出了PUBLIC拥有的角色权限和系统权限同样也可以给PUBLIC添加新的权限CREATE ANY VIEW就是我自己给它添加的public拥有的权限所有的用户都自动的拥有了也就是所有的用户初始默认都拥有PUBLIC角色的权限。七、两个事务间锁争用实例1两个事务争用锁我们执行一个update employees set last_namelast_name||’a’ where department_id60;开始一个事务开始实验在其中一个sqlplus中执行SQL update employees set last_namelast_name||a where department_id60;5 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,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 2 3 from v$lock where sid139; 4 SID TY ID1 ID2 LOCK_MODE REQUEST_MODE BLOCK---------- -- ---------- ---------- ------------------- ------------------- ---------- 139 TM 51857 0 Row Exclusive None 0 139 TX 458775 238 Exclusive None 0从结果看139会话产生了一个TM锁和一个TX锁。TM的ID2总是0ID1是代表着操作所在的表TX锁的ID1和ID2通过语句可以找到这个事务从LOCK_MODE看出他们都持有锁REQUEST_MODE看出都没有请求锁从BLOCK都是0看出持有的锁都没有阻塞别人再另外开一个session同样的去执行update employees set last_namelast_name||’b’ where department_id60;在SID为145的hr会话中执行它需要的资源被锁住SQL update employees set last_namelast_name||b where department_id60;这时的执行被卡住我们再去查一下这里是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,blockfrom v$lockwhere sid in(139,145)order by sid;查的是v$lock看看这个锁的状况好执行一下结果SQL 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, 2 3 decode(request,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) request_mode,blockfrom v$lock 4 5 where sid in(139,145) 6 order by sid; SID TY ID1 ID2 LOCK_MODE REQUEST_MODE BLOCK---------- -- ---------- ---------- ------------------- ------------------- ---------- 139 TM 51857 0 Row Exclusive None 0 139 TX 458775 238 Exclusive None 1 145 TM 51857 0 Row Exclusive None 0 145 TX 458775 238 None Exclusive 0139和145都出现了139的TM和TX锁没变一开始执行的139后面执行的145139一开始执行的持有TX和TM锁145的TM锁LOCK_MODE为Row Exclusive持有145和139的TM锁的ID1相同就是对象还一样也就是说139和145都在这个51857对象上加了RX锁但是145的TX锁行的REQUEST_MODE的值是Exclusive出现了Exclusive也就是145被139这个事务锁住了。然后我们看139的TX这行BLOCK的值是1说明阻塞了别人阻塞了145而145 TX的REQUEST_MODE是Exclusive它正在请求Exclusive锁也就是被锁住了通过这个我们看到一些问题但是我们知道这个锁出现这个问题也不见得有问题因为锁住很正常139一旦提交以后145马上就获取到这个锁了2关于等待锁中的ID1和ID2另外从结果我们可能发现一个问题 139 TX 458775 238 Exclusive None 1 145 TX 458775 238 None Exclusive 0我们看到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 0148会话本身持有一个TX锁148 TX 524327 303 Exclusive None 0这条信息的ID1和ID2的信息是它本身事务的信息148会话还请求一个TX锁148 TX 262165 242 None Exclusive 0这条信息的ID1和ID2的信息是148正在请求的被请求锁的事务的信息这里正在请求150正在持有的锁所以这行的ID1和ID2列出了150事务的信息有一行150 TX 262165 242 Exclusive None 1这行的BLOCK为1说明150事务它持有的锁有别的事务正在等待正好和148正在请求锁对应验证了前面的分析八、三个事务的锁争用1三个事务争同一个锁我们再打开一个会话再新建一个会话以hr用户身份连接先查一下SIDSQL select sid from v$mystat where rownum1; SID---------- 136这个新的当前会话的SID是136接着前面的实验也去做同样的一个操作update employees set last_namelast_name||’b’ where department_id60;它肯定也被锁住执行结果SQL update employees set last_namelast_name||b where department_id60;暂时无返回值也被锁住这里是136现在是139 145 和136操作139应该把145和136锁住了再去查一个语句select sid,type, decode(request,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) request_mode from v$enqueue_lock where sid in(145,136);根据分析两个被锁住的是145和136查的是v$enqueue_lock这里面它会只是把谁被锁住了谁给列出来请求锁的被列出来执行一下这里访问的是v$enqueue_lock执行结果SQL select sid,type, decode(request,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) request_mode from v$enqueue_lock where sid in(145,136); 2 3 4 5 SID TY REQUEST_MODE---------- -- ------------------- 145 TX Exclusive 136 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获取的资源不一样的话这两个可以同时获取到锁。通过这个我们可以看出并记住锁是排队的。2v$lock中BLOCK字段的值举一个三个事务争用相同锁的例子查询v$lock视图的结果SQL 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, 2 3 decode(request,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) request_mode,block 4 from v$lock 5 where sid in(132,135,139) 6 order by sid; SID TY ID1 ID2 LOCK_MODE REQUEST_MODE BLOCK---------- -- ---------- ---------- ------------------- ------------------- ---------- 132 TM 51857 0 Row Exclusive None 0 132 TX 655370 242 Exclusive None 1 135 TM 51857 0 Row Exclusive None 0 135 TX 655370 242 None Exclusive 0 139 TM 51857 0 Row Exclusive None 0 139 TX 655370 242 None Exclusive 06 rows selected.这三个事务开始执行的顺序是132,135,139这时132事务的信息是ID1655370 ID2242135和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 0132事务释放锁后第一个排队的135得到了锁得到锁后135会话中的事务就开始了这时135会话中事务的信息是ID1327683ID2338这时它锁住了139139还在等待39会话中的事务仍然没有开始不管是1个事务还是2个事务在等待锁持有锁的事务的信息的BLOCK都为1这个字段并不是说明有多少个事务在等待锁只是说明有没有事务在等待这个锁等待锁的139会话在第一次查询时的结果139 TX 655370 242 None Exclusive 0在第二次查询时的结果139 TX 327683 338 None Exclusive 0ID1和ID2的值变化了但都是139它等待的当前正在持有这个锁的事务的信息九、锁的时间我们找一个非常有意义的一个select a.sid blocker_sid,a.serial#,a.username as blocker_username,b.type,decode(b.lmode,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) lock_mode,b.ctime as time_held,c.sid as waiter_sid,decode(c.request,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,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 1order 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,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) lock_mode, 2 3 b.ctime as time_held,c.sid as waiter_sid, 4 decode(c.request,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) request_mode, 5 c.ctime time_waited 6 from v$lock b, v$enqueue_lock c, v$session awhere 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 1 7 8 order by time_held, time_waited;BLOCKER_SID SERIAL# BLOCKER_USERNAME TY LOCK_MODE TIME_HELD WAITER_SID REQUEST_MODE TIME_WAITED----------- ---------- ------------------------------ -- ------------------- ---------- ---------- ------------------- ----------- 139 2746 HR TX Exclusive 3909 136 Exclusive 1790 139 2746 HR TX Exclusive 3909 145 Exclusive 2931前两个字段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,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) lock_mode, 2 3 b.ctime as time_held,c.sid as waiter_sid, 4 decode(c.request,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) request_mode, 5 c.ctime time_waitedfrom v$lock b, v$enqueue_lock c, v$session a 6 7 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 1 8 order by time_held, time_waited;BLOCKER_SID SERIAL# BLOCKER_USERNAME TY LOCK_MODE TIME_HELD WAITER_SID REQUEST_MODE TIME_WAITED----------- ---------- ------------------------------ -- ------------------- ---------- ---------- ------------------- ----------- 139 2746 HR TX Exclusive 6334 136 Exclusive 4215 139 2746 HR TX Exclusive 6334 145 Exclusive 5356145等待的时间比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掉了这时我们看145SQL update employees set last_namelast_name||b where department_id60;5 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,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) lock_mode,b.ctime as time_held,c.sid as waiter_sid, 2 3 4 decode(c.request,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive) request_mode, 5 c.ctime time_waited 6 from v$lock b, v$enqueue_lock c, v$session awhere 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 1 7 8 order by time_held, time_waited;BLOCKER_SID SERIAL# BLOCKER_USERNAME TY LOCK_MODE TIME_HELD WAITER_SID REQUEST_MODE TIME_WAITED----------- ---------- ------------------------------ -- ------------------- ---------- ---------- ------------------- ----------- 145 1015 HR TX Exclusive 221 136 Exclusive 221现在是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_namelast_name||b where department_id60;5 rows updated.SQL rollback;Rollback complete.136会话在145会话回滚后得到了执行最终它也得到了锁为了试验把它也回滚了十、一个事务多个TM锁一个事务修改多行产生一个TX锁可以在多个表上产生多个TM锁一个事务只产生一个事务锁TX锁我们在一个事务里面多执行几条sql语句update employees set last_namelast_name||a where department_id60;update departments set department_nameunknow where department_id10;update locations set cityunknown where location_id1100;在一个hr会话SQL select sid from v$mystat where rownum1; SID--------- 132先执行一条updateSQL update employees set last_namelast_name||a where department_id60;5 rows updated.更新了employees这个表第二个语句它接着更新departmentsSQL update departments set department_nameunknow where department_id10;1 row updated.都是一个事务里面的下面语句是更新locationsSQL update locations set cityunknown where location_id1100;1 row updated.更新了三个语句然后我们再使用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,blockfrom v$lockwhere sid132;再去查132这个会话它持有锁的情况在sys用户会话中执行结果SQL 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, 2 3 decode(request,0,None,1,Null,2,Row share,3,Row Exclusive,4,Share,5,Share Row Exclusive,6,Exclusive)request_mode,block 4 from v$lock 5 where sid132; SID TY ID1 ID2 LOCK_MODE REQUEST_MODE BLOCK---------- -- ---------- ---------- ------------------- ------------------- ---------- 132 TM 51857 0 Row Exclusive None 0 132 TM 51852 0 Row Exclusive None 0 132 TM 51847 0 Row Exclusive None 0 132 TX 589860 329 Exclusive None 0一个会话的一个事务它修改了三个表对三个表产生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 748transactions 187这个有时候也会碰到一些问题结果中一个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_Ufrom v$resource_limitwhere resource_name in(transactions,dml_locks); 2 3R_N C_U M_U I_U------------------------------ ---------- ---------- --------------------dml_locks 3 48 748transactions 2 9 187 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是748M_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_Ufrom v$resource_limit; 2R_N C_U M_U I_U------------------------------ ---------- ---------- --------------------processes 27 37 150sessions 31 42 170enqueue_locks 13 22 2300enqueue_resources 17 38 968ges_procs 0 0 0ges_ress 0 0 0ges_locks 0 0 0ges_cache_ress 0 0 0ges_reg_msgs 0 0 0ges_big_msgs 0 0 0ges_rsv_msgs 0 0 0gcs_resources 0 0 0gcs_shadows 0 0 0dml_locks 3 48 748temporary_table_locks 0 0 UNLIMITEDtransactions 2 9 187branches 0 0 187cmtcallbk 0 2 187sort_segment_locks 0 1 UNLIMITEDmax_rollback_segments 11 11 187max_shared_servers 1 1 UNLIMITEDparallel_max_servers 0 2 4022 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事务修改了一个资源以后在这个资源上加了锁了事务修改了另一个资源后也加了锁。A想持有B正在修改的这个资源但已被B锁住了A修改了一个资源但是它还想修改B正在修改的资源但已被B锁住A被B锁住了B修改了一个资源后又想去修改A正在修改的资源B被A锁住了产生死锁并且这个结它解不开因为这时只有A回滚了以后B才能持有A现在拥有的资源死锁以后会有什么现象呢我把原来实验的会话都给它rollback并在新会话中实验在session1里面我更新100SQL select sid from v$mystat where rownum1; SID---------- 150 SQL update employees set last_namelast_name||awhere employee_id100; 21 row updated.我把100给锁住了然后在 session2里面呢SQL select sid from v$mystat where rownum1; SID---------- 148 SQL update employees set last_namelast_name||bwhere employee_id101; 21 row updated.把101给锁住了A里面把100锁住了B把101锁住了然后session1想去SQL update employees set last_namelast_name||c where employee_id101;想去锁B锁住的资源已被B锁住了这时A被B锁住了然后session2中SQL update employees set last_namelast_name||d where employee_id100;也在等待锁B又被A锁住了形成一个死循环了这时在A里面出现SQL update employees set last_namelast_name||c where employee_id101;update employees set last_namelast_name||c where employee_id101 *ERROR at line 1:ORA-00060: deadlock detected while waiting for resource这时候A会话马上出一个问题另外一个会话B中我们回车以后这个A会话一下子检测到死锁被回滚了马上被回滚了这里回滚的不是A会话中的整个事务只是被回滚了一条语句就是把造成死锁的那条语句给回滚了这个事务中前面其它语句没有影响并没有回滚整个的事务如果这时查询A会话查询后可以得知这条语句前执行的语句仍然有效也就是当死锁发生的时候Oracle马上会检测同时将其中一个事务的一条造成死锁的语句给自动回滚这里是回滚了第一个会话造成死锁的语句就是请求第二个会话占有的锁但是未得到锁的语句但这时第二个会话请求的锁第一个会话仍然占有既然如此死循环被解除了这样在在造成死锁的两个会话中解除了死锁。我们执行rollback将其中一个会话全部回滚SQL rollback;Rollback complete.并且这里又把第一个会话中占用锁的语句回滚后第二个会话中等待锁的语句得到了执行SQL update employees set last_namelast_name||d where employee_id100;1 row updated.把第二个会话也回滚SQL rollback;Rollback complete.当死循环发生的时候会做几件事情第一个Oracle自动的对死锁自动的检测而且还能快速检测而且把其中一个事务给回滚但只是回滚部分sql语句2死锁的信息同时当死锁发生的时候会出现一件很重要的事情Oracle会记录下死锁的信息死锁发生的时候[oracleredhat4 bdump]$ pwd/u01/app/oracle/admin/jiagulun/bdump在这个目录里面[oracleredhat4 bdump]$ lsalert_jiagulun.log jiagulun_lgwr_13577.trc jiagulun_mmnl_6638.trcjiagulun_cjq0_13651.trc jiagulun_lgwr_13643.trc jiagulun_p000_6646.trcjiagulun_lgwr_13460.trc jiagulun_lgwr_6626.trc jiagulun_p001_6648.trc有alert日志alert_jiagulun.logalert日志是数据库的总日志可以查看这个alert日志cat alert_jiagulun.log执行结果[oracleredhat4 bdump]$ cat alert_jiagulun.logMon Apr 11 13:38:53 2016Starting ORACLE instance (normal)LICENSE_MAX_SESSION 0LICENSE_SESSIONS_WARNING 0Shared memory segment for instance monitoring createdTue Nov 21 06:45:15 2017MMNL absent for 63369 secs; Foregrounds taking overMMNL absent for 63369 secs; Foregrounds taking overMMNL absent for 63369 secs; Foregrounds taking overTue Nov 21 08:14:17 2017ORA-00060: Deadlock detected. More info in file /u01/app/oracle/admin/jiagulun/udump/jiagulun_ora_21608.trc.Tue Nov 21 08:25:31 2017ORA-00060: Deadlock detected. More info in file /u01/app/oracle/admin/jiagulun/udump/jiagulun_ora_21608.trc.在alert日志里面会自动把死锁信息给列出来说死锁发生了如Tue Nov 21 08:25:31 2017ORA-00060: 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