数据库锁概述
oracle在事务执行会自动对操作资源进行锁定,防止其它事务对同一个资源做破坏性存取。数据库自动根据操作资源类型不同,对资源加上各种类型的锁。 oracle根据操作资源的类型,把锁分为如下分类
DML锁:保护数据,例如表锁锁定这个表,行级锁锁定选择的行
DDL锁:保护对象的定义,例如表和视图的数据字典
系统锁:保护内部数据库的结构,例如数据文件,latch,mutexes和内部锁定,这些都是自动实现的
相关阅读 oracle数据库事务transaction隔离级别isolation level的选择依据
dml锁
一个DML锁,又叫做数据锁,用来保证多个用户并发事务执行时的数据完整性。 例如:一个DML锁可以防止两个用户在在线商店购买最后一本书。DML语句自动获取如下类型的锁:行级锁TX和表锁TM 示例 SQL> update t_test set a=1; 2 rows updated. 可见 产生事务会 在原有基础上添加2种锁,一为表锁tm,其锁模式为行级排它锁,二为行锁tx,其锁模式为排它锁 SQL> / SID TY ID1 ID2 LMODE REQUEST ---------- -- ---------- ---------- ---------- ---------- 25 AE 133 0 4 0 25 TX 65566 1359 6 0 dml锁 25 TM 76989 0 3 0 dml锁 SQL> desc dba_dml_locks; Name Null? Type ----------------------------------------- -------- ---------------------------- SESSION_ID NUMBER OWNER NOT NULL VARCHAR2(128) NAME NOT NULL VARCHAR2(128) MODE_HELD VARCHAR2(13) MODE_REQUESTED VARCHAR2(13) LAST_CONVERT NUMBER BLOCKING_OTHERS VARCHAR2(40) SQL> select session_id,owner,name,mode_held,mode_requested,last_convert,blocking_others from dba_dml_locks SESSION_ID OWNER NAME MODE_HELD MODE_REQUESTE LAST_CONVERT BLOCKING_OTHERS ---------- -------------------- -------------------- ------------- ------------- ------------ ---------------------------------------- 25 USER_DDL T_TEST Row-X (SX) None 1052 Not Blocking oracle在锁定行所在的数据块(事务需要修改的数据块)中存储锁的相关信息。数据库使用队列机制获取行级锁,如果事务需要一个未锁定行的锁,那么事务在数据块中在放一个锁,事务修改的每一行都会指向数据块头部(ITL)中的事务ID。当事务结束时,事务ID仍然留在数据块头部的ITL中。如果不同的事务想要修改一行数据,数据库会使用ITL中原来事务的ID,通过查询相关动态视图判断事务是否还存在,及锁是否存在,如果锁仍然是活动的,那么会话排队等待事务结束后的通知,如果锁不活动了,那么,事务得到锁,并更新ITL表 小结
oracle会在数据块中记录锁的信息及事务的信息
oracle会话如需要获取表记录的锁,先查找表记录所属数据块是否已存在锁,在数据块中存储事务及锁的数据结构叫itl
itl在数据块的头块
oracle会话发现修改数据块有活动事务,即持锁,它会等待
oracle dml锁是采用排队机制实现即先到先到,后到后等算法
oracle的在获取到数据块进行修改时,需要在数据块头部的itl修改数据块的事务状态,表明数据块正被修改
tm锁即表锁,会有5种不同的锁模式,之前文章讲过,不再复述
ddl锁
当DDL操作或者关联操作某对象时,DDL锁保护对象的定义。只有在DDL语句中修改或者引用的对象才被锁定,数据库不会锁定整个数据字典。oracle数据库代表DDL事务自动实现DDL锁。 用户不能显式获得DDL锁。例如,一个用户创建一个存储过程,数据库自动获得存储过程中引入的对象的DDL锁。DDL锁阻止存储过程编译过程中这些对象的修改和删除 小结
ddl锁保存数据定义的数据结构
ddl锁只有在修改数据定义的数据结构或引用数据定义的数据结构,才会持有ddl锁
修改数据定义的数据结构操作,比如:create table,alter table类似的语句
引用数据定义的数据结构操作,比如:基于源表创建存储过程或调用执行存储过程(因为必须保证在执行存储过程期间依赖基表的完整性)
ddl锁由oracle自身控制,人为无法控制,无法显式获取ddl锁
ddl锁一般看不到,因为ddl操作极快
ddl锁底层是通过锁定数据字典实现
SQL> desc dba_ddl_locks; Name Null? Type ----------------------------------------- -------- ---------------------------- SESSION_ID NUMBER OWNER VARCHAR2(128) NAME VARCHAR2(1000) TYPE VARCHAR2(40) MODE_HELD VARCHAR2(9) MODE_REQUESTED VARCHAR2(9) 即使没有执行数据库事务,仍存在ddl锁,下述ddl锁就是保护各种对象类型的定义结构不被破坏 SQL> select session_id,owner,name,type,mode_held,mode_requested from dba_ddl_locks; SESSION_ID OWNER NAME TYPE MODE_HELD MODE_REQU ---------- -------------------- -------------------- ---------------------------------------- --------- --------- 32 SYS KUPU$UTILITIES Table/Procedure/Type Null None 32 SYS STANDARD Table/Procedure/Type Null None 32 SYS STANDARD Table/Procedure/Type Null None 32 SYS DBMS_PRVT_TRACE Table/Procedure/Type Null None 74 SYSTEM SYSTEM 18 Null None 76 SYSTEM SYSTEM 18 Null None 75 SYSTEM SYSTEM 18 Null None 74 SYS DBMS_OUTPUT Body Null No SQL> grant execute on dbms_lock to system; Grant succeeded. create or replace procedure proc_t_test as v_cnt int; begin dbms_lock.sleep(300); select count(a) into v_cnt from t_test; end; / --未执行相关与DDL前2个测试会话各为25及74的运行信息 SQL> select session_id,owner,name,type,mode_held,mode_requested from dba_ddl_locks where session_id in (25,74) SESSION_ID OWNER NAME TYPE MODE_HELD MODE_REQU ---------- --------------- -------------------------------------------------- ---------------------------------------- --------- --------- 25 SYSTEM SYSTEM 18 Null None 74 SYSTEM SYSTEM 18 Null None 74 SYS DBMS_OUTPUT Body Null None 25 SYS DBMS_LOCK Body Null None 74 SYS DBMS_OUTPUT Table/Procedure/Type Null None 25 LBACSYS LBAC_EVENTS Body Null None 25 LBACSYS LBAC_EVENTS Table/Procedure/Type Null None 25 SYS DBMS_APPLICATION_INFO Body Null None 74 SYS DBMS_APPLICATION_INFO Body Null None 25 SYS DBMS_STANDARD Table/Procedure/Type Null None 74 SYS PLITBLM Table/Procedure/Type Null None SESSION_ID OWNER NAME TYPE MODE_HELD MODE_REQU ---------- --------------- -------------------------------------------------- ---------------------------------------- --------- --------- 74 SYSTEM 73 Share None 25 SYSTEM 73 Share None 25 SYS DBMS_APPLICATION_INFO Table/Procedure/Type Null None 74 SYS DBMS_APPLICATION_INFO Table/Procedure/Type Null None 25 MDSYS GETMDSYSEVENT Table/Procedure/Type Null None 25 SYS DBMS_LOCK Table/Procedure/Type Null None 25 SYS DATABASE 18 Null None 74 SYS DATABASE 18 Null None 19 rows selected. ---会话25 执行存储过程 SQL> exec proc_t_test; ---会话74 正在执行存储过程期间删除存储过程 卡住 SQL> drop procedure proc_t_test; SQL> select session_id,owner,name,type,mode_held,mode_requested from dba_ddl_locks where session_id in (25,74) and mode_held='Exclusive' or mode_requested='Exclusive' SESSION_ID OWNER NAME TYPE MODE_HELD MODE_REQU ---------- ------------------------------ -------------------------------------------------- -------------------- --------- --------- 74 SYSTEM PROC_T_TEST Table/Procedure/Type Exclusive None SQL> / SESSION_ID OWNER NAME TYPE MODE_HELD MODE_REQU ---------- ------------------------------ -------------------------------------------------- -------------------- 25 SYSTEM PROC_T_TEST Table/Procedure/Type Null None 持锁会话(持锁模式为null) 74 SYSTEM PROC_T_TEST Table/Procedure/Type Exclusive None 等待会话 (请求持锁模式为排它模式) SQL> select distinct type from dba_ddl_locks; TYPE -------------------- 73 Table/Procedure/Type 18 10 Body 23 6 rows selected. ---可见产生ddl锁,不会体现在v$lock中 SQL> select sid,type,id1,id2,lmode,request from v$lock where sid in (25,74); SID TY ID1 ID2 LMODE REQUEST ---------- -- ---------- ---------- ---------- ---------- 74 AE 133 0 4 0 25 AE 133 0 4 0 --可见产生ddl锁,持ddl锁的会话等待事件为library cache pin SID STATUS BLOCKING_SESSION EVENT ---------- -------- ---------------- ---------------------------------------------------------------- 25 ACTIVE PL/SQL lock timer 74 ACTIVE 25 library cache pin --等待事件对应如下的library cache pin,library cache pin对sga的library cache内存数据结构的一种保存机制 SQL> col type for a50 SQL> col name for a35 SQL> col id1_tag for a30 SQL> col id2_tag for a30 SQL> col description for a50 SQL> select type,name,id1_tag,id2_tag,is_user,description from v$lock_type where lower(description) like '%library%'; TYPE NAME ID1_TAG ID2_TAG IS_ DESCRIPTION ---------- ----------------------------------- -------------------- ------------------------- --- ---------------------------------------------------------------------------------------------------- V Library Cache Lock 3 hash value hash value NO Synchronizes accesses to library cache objects E Library Cache Lock 2 hash value hash value NO Synchronizes accesses to library cache objects L Library Cache Lock 1 hash value hash value NO Synchronizes accesses to library cache objects Y Library Cache Pin 3 hash value hash value NO Synchronizes accesses to the contents of library cache objects G Library Cache Pin 2 hash value hash value NO Synchronizes accesses to the contents of library cache objects N Library Cache Pin 1 hash value hash value NO Synchronizes accesses to the contents of library cache objects IV Library Cache Invalidation object # time stamp NO Synchronizes library cache object invalidations across instances 7 rows selected. ddl锁又分为几种类型:
排它ddl锁
排它DDL锁阻止其他会话获得DDL和DML锁。例如删除一个表的操作会阻止同时在表中添加一列的DDL操作,反之亦然。排它的DDL锁在整个DDL操作时有效,执行结束会自动提交
共享ddl锁
共享DDL锁防止其它冲突的DDL操作,但是允许类似的DDL操作并发执行。例如当执行DDL操作时,会对引用的所有表加DDL共享锁,其它事务可以建存储过程时加共享DDL锁,但 是不允许加排它DDL锁
易碎解析锁
sql或者pl/sql会持有应用对象的解析锁。解析锁被用来实现当引用的对象被修改或者删除时,共享sql区域会失效。解析锁之所以易碎,是因为它不允许DDL操作,当DDL冲突 时,会被打碎 小结 上述的ddl锁和dml锁不太一样,不好理解。后续会有专门文章分享。
系统锁
oracle使用系统锁保护内部的数据库和内存结构,用户不能操作这些内部锁,它由数据库自己控制。 系统锁分为 latch,mutexes,内部锁internal lock
闩latch
latch是为了保护sga内存数据结构的一致,实现的一种底级锁机制 SQL> select count(*) from v$latchname; COUNT(*) ---------- 902 SQL> select distinct type from v$latchname; TYPE ---- SGA OSP SQL> SQL> select name,hash,type from v$latchname where lower(name) like '%library%'; NAME HASH TYPE ---------------------------------------------------------------- ---------- ---- library cache load lock 2952162927 SGA
mutex
mutex不同上于上述的latch,latch保护一组对象,而mutex更低级,它仅保护一个对象,它是代码层面的,相当底层 SQL> select mutex_type from v$mutex_sleep; MUTEX_TYPE -------------------------------- Row Cache Library Cache Cursor Pin
内部锁
它是高级别,比latch和mutex更复制,用于其它用途。数据库具有一些类型的内部锁:
数据字典缓存锁
这种锁时间短,当数据字典实体被修改时,用来保护相关内容。这种锁确保语句解析期间,能够看到对象的一致性视图。数据 字典锁是共享和排它的。解析结束时,共享锁被释放,DDL操作结束时,排它锁被释放
文件和日志管理锁
这种锁保护各种文件,例如,内部锁保护控制文件,确保一个时间点只有一个进程能够修改。另外的锁能协调归档和在线日志。当 多实例共享模式挂载数据库或者单实例排它挂载时会对数据文件加锁。由于文件锁标识着文件的状态,这些锁持续的时间一般都比较长
表空间和undo段锁
用来保护表空间和undo段,例如所有实例必须对表空间是否在线达成一致
联系方式
