Enqueue Lock介绍.ppt

4,186 views

Published on

  • Be the first to comment

Enqueue Lock介绍.ppt

  1. 1. Enqueue Lock 介绍 [email_address] http://www.dbthink.com/
  2. 2. 内容介绍 <ul><li>Enqueue Lock 基本的概念 </li></ul><ul><li>相关 Enqueue Lock 介绍 </li></ul><ul><ul><li>TM 锁 (Table Lock) </li></ul></ul><ul><ul><li>TX 锁 (Transaction Lock) </li></ul></ul><ul><ul><li>HW 锁 (High Watermark Lock) </li></ul></ul><ul><ul><li>US 锁 (Undo Segment Lock) </li></ul></ul><ul><ul><li>TO 锁 (Temporary Object Lock) </li></ul></ul><ul><ul><li>CF 锁 (Control File Lock) </li></ul></ul><ul><ul><li>JO 锁 (Job Queue Lock) </li></ul></ul><ul><ul><li>SQ 锁 (Sequence Cache) </li></ul></ul>
  3. 3. Enqueue Lock 类型 <ul><li>数据字典锁 (Data Dictionary Lock) </li></ul><ul><ul><li>行缓存锁 (Row Cache Lock) </li></ul></ul><ul><ul><li>库缓存锁 (Library Cache Lock & Library Cache Pin) </li></ul></ul><ul><li>数据处理锁 (Data Manipulation Lock) </li></ul><ul><ul><li>行锁 (Row Lock) </li></ul></ul><ul><ul><li>表锁 (Table Lock) </li></ul></ul><ul><li>内部锁以及内部闩锁 (Internal Lock and Latch) </li></ul><ul><li>分布式锁 (Distributed Lock) </li></ul><ul><li>并行缓存管理锁 (Parallel Cache Management (PCM)Lock) </li></ul>
  4. 4. 锁资源标识符 Enqueue Resource Identifier <ul><li>每个 Enqueue Lock 都有一个唯一名称 , 这个名称也被成为锁名称或资源名称 </li></ul><ul><li>标识符的格式为 <type-id1-id2> </li></ul><ul><ul><li>Type 由有两个字母组成 , 如” TM”,”TX” </li></ul></ul><ul><ul><li>Id1 与 id2 为正的数字 (4 个字节长 ) </li></ul></ul><ul><li>下面分别是一个 TX 锁与 TM 锁的例子 </li></ul><ul><ul><li>TX-393237-184 </li></ul></ul><ul><ul><li>TM-6317-0 </li></ul></ul>
  5. 5. Enqueue Lock 模式 模式 内部编号 模式值 描述 ( 以 DML 为例来说明 ) Null KSQMNull 1 Null 模式 , 不妨碍任何并发访问 , 主要用来作为 Cache Invalidate 的通知机制存在 SS KSQMSS 2 SubShare 模式 , 使用共享模式锁住一条记录 SX KSQMSX 3 SubExclusive 模式 , 使用独占模式锁住一条记录 S KSQMS 4 共享模式 SSX KSQMSSX 5 Share,SubExclusive, 对表持有共享锁 , 对其中的记录持独占模式 X KSQMX 6 Exclusive 模式 , 对全表持独占模式
  6. 6. Enqueue 模式兼容性 请求 / 占用 Null SS SX S SSX X Null Yes Yes Yes Yes Yes Yes SS Yes Yes Yes Yes Yes No SX Yes Yes Yes No No No S Yes Yes No Yes No No SSX Yes Yes No No No No X Yes No No No No No
  7. 7. Enqueue Resource & Enqueue Lock <ul><li>Enqueue 的获取 / 转换 / 释放操作都是由 Session 操作的 ( 而不是 Process) </li></ul><ul><li>当一个 Session 持有一个 Enqueue 的时候 , 同时也可能有其它 Session 在请求持有或转换 Enqueue 模式 </li></ul><ul><li>每个 Enqueue 都有一个资源结构与其对应 , 由它来管理持有者 (Owners), 等待者 (Waiters) 以及请求转换模式者 (Converter). </li></ul><ul><li>每个 Owner/waiter/Converter 都有一个对应的锁结构 </li></ul>
  8. 8. Enqueue Resource 结构
  9. 9. Enqueue Hash 与 Latch <ul><li>所有的 Enqueue Resource 都属于一个 Resource 表 (X$ksqrs,v$resource). </li></ul><ul><li>Oracle 使用 hash 来访问数据库中的 Enqueue Resource. </li></ul><ul><li>每个 Hash bucket 都包含一个资源链表 (Hash Chain) </li></ul><ul><li>每个 Hash Chain 都有一个或多个 Latch 来控制访问 . </li></ul>
  10. 10. 获取 Enqueue Lock 的步骤 <ul><li>计算 hash 值 , 确定所需访问资源所在的链表 </li></ul><ul><li>得到对应的 enqueue hash chains latch </li></ul><ul><li>定位此资源 , 如果不存在 , 则在空闲资源列表中取一个放到此处 </li></ul><ul><li>获取 enqueues latch </li></ul><ul><li>获取一个空闲的 Lock 结构 </li></ul><ul><li>将此 Enqueue Lock 对应的信息填充进去 </li></ul><ul><li>将此 Lock 结构挂到此 Enqueue Resource 结构上 </li></ul><ul><li>释放 enqueues latch </li></ul><ul><li>释放 enqueue hash chains latch </li></ul>
  11. 11. 获取 Enqueue Lock 的步骤 (2)
  12. 12. 释放 Enqueue Lock 的步骤 <ul><li>计算 hash 值 , 确定所需访问资源所在的链表 </li></ul><ul><li>得到对应的 enqueue hash chains latch </li></ul><ul><li>定位此资源 </li></ul><ul><li>获取 enqueues latch </li></ul><ul><li>将 lock 结构从 Enqueue Resource 结构上取出 </li></ul><ul><li>释放 Enqueues latch </li></ul><ul><li>通知处在等待 ( 转换 ) 队列上的进程 ( 如果有的话 ) </li></ul><ul><li>如果可能 , 释放此 Enqueue Resource, 并将其放入空闲资源列表 </li></ul><ul><li>释放 enqueue hash chains latch </li></ul>
  13. 13. 死锁的检测 (dead-lock)
  14. 14. Enqueue Lock 转储 <ul><li>alter session set events 'immediate trace name enqueues level x‘ </li></ul><ul><ul><li>Level 1 转储当前活动资源与锁的概要信息 , 资源空闲列表以及哈希表 </li></ul></ul><ul><ul><li>Level >= 2 加上资源结构 (Resource Structure) 的转储信息 </li></ul></ul><ul><ul><li>Level >= 3 加上锁结构 (Lock Structure) 的转储信息 </li></ul></ul>
  15. 15. Enqueue Lock 的事件跟踪 <ul><li>Alter session set events ‘10704 trace name context forever,level x’; </li></ul><ul><li>当打开此等待事件 , 将输出请求 Enqueue 的操作信息 , 以及请求相关的参数 </li></ul><ul><li>X 表示等待事件的级别 , 具体说明如下 </li></ul><ul><ul><li>1-4 打出 ksqlrl,ksqcmi 的基本信息 </li></ul></ul><ul><ul><li>5-9 还打出 ksqlac,ksqlop 等回调信息 </li></ul></ul><ul><ul><li>10+ 还打出每个操作对应的时间信息 </li></ul></ul>
  16. 16. 相关动态视图介绍 <ul><li>V$resource ( 来自 x$ksqrs) 所有 enqueue resource 相关信息 </li></ul><ul><li>V$enqueue_lock ( 主要来自 x$ksqeq) lock Structure 为其主要信息 , 此视图同时也将此 lock structure 对应的 session 信息与 enqueue resource 信息关联过来了 </li></ul><ul><li>V$resource_limit 查看 enqueue_lock 与 enqueue_resource 的当前使用情况 </li></ul><ul><li>V$enqueue_stat ( 来自 x$ksqst) enqueue 操作的相关统计信息 </li></ul><ul><li>V$lock 所有 enqueue lock 相关锁信息 </li></ul><ul><li>V$locked_object ( 来在 x$ktcxb,v$transaction 完全来自此视图 ) 查找当前被锁住的对象 . </li></ul>
  17. 17. 相关视图介绍 <ul><li>Lock 相关的视图信息 , 不会自动创建 , 需要执行 catblock.sql </li></ul><ul><ul><li>Dba_lock 基本锁信息 </li></ul></ul><ul><ul><li>Dba_lock_internal 包含内部锁 (library cache pin/lock) 以及 latch </li></ul></ul><ul><ul><li>Dba_dml_locks 仅显示 TM 锁信息 , 不过同时关联此锁对应的 </li></ul></ul><ul><ul><li>Dba_ddl_locks 仅显示 library cache lock 锁 , 也即基本对象做 ddl 涉及到的锁 </li></ul></ul><ul><ul><li>Dba_waiters,dba_blockers 显示持有或者被阻塞的锁信息 </li></ul></ul><ul><li>显示锁相关的等待树的脚本 </li></ul><ul><ul><li>@?/rdbms/admin/utllockt.sql </li></ul></ul><ul><ul><li>显示当前持有 / 被阻塞的锁的等待树 </li></ul></ul>
  18. 18. TM 锁 <ul><li>当对表以及表的分区进行操作时就会持有此表上的 TM 锁 . </li></ul><ul><li>相关操作包含 </li></ul><ul><ul><li>修改表中的数据 </li></ul></ul><ul><ul><li>调整表上的约束 </li></ul></ul><ul><ul><li>调整表对应的索引 </li></ul></ul><ul><ul><li>分析表上的统计信息或者 validate structure </li></ul></ul><ul><ul><li>并行 dml 操作 </li></ul></ul><ul><li>Id1 为此对象的 object_id(dml_locks>0) </li></ul><ul><li>Id2 始终为 0 </li></ul>
  19. 19. TM 锁 - 相关锁 mode 对应的操作 <ul><li>表上发生 dml 操作时 , 持有的 TM mode 为 3(SubExclusive) </li></ul><ul><li>修改表结构时持有锁 mode 为 6 </li></ul><ul><li>对表上的索引做 rebuild 或者创建索引时持有的锁 mode 为 4 </li></ul><ul><li>当对表做并行插入时需要持有的锁 mode 为 6, 此时后续的所有 dml 操作都会被阻塞 </li></ul>
  20. 20. TM 锁 -online create/rebuild index <ul><li>Rebuild 命令尝试获取一个对应表上的 Share 锁 ( 之前会获取一个 SubShare 锁 ), 接着就会因等待当前表上还未完成的事务结束 . </li></ul><ul><li>当前表上的所有事务结束 , 所有在 rebuild 命令之后的事务都被 Rebuild 持有的锁阻塞 </li></ul><ul><li>rebuild 命令获得它的锁 , 准备物化视图日志 (MV log), 开始重建过程 , 并释放之前持有的锁 </li></ul><ul><li>所有等待的事务继续执行 </li></ul><ul><li>重建过程做大量的表扫描以及排序以准备此索引 , 并将排好序的索引复制到其目标存储位置 </li></ul><ul><li>Rebuild 命令尝试再次获取一个表上的 Share 锁 , 并阻塞以等待表上当前的所有事务运行结束 </li></ul><ul><li>表上的所有当前事务运行结束 , 所有的新事务阻塞在此 Rebuild 锁之后 </li></ul><ul><li>Rebuild 命令获得它请求的锁 , 应用 Rebuild 开始到此锁获得之间的所有变更到新的索引上 , 删除物化视图日志 (MV log) 与旧的索引 , 并释放持有的锁 . </li></ul><ul><li>所有等待的事务继续执行 </li></ul>
  21. 21. TX 锁 <ul><li>当事务开始时持有此锁 , 知道事务被提交或者回滚才释放此锁 . </li></ul><ul><li>当 Pmon/Smon 需要回滚出现异常的事务时也会持有 Exclusive mode 的事务锁 </li></ul><ul><li>主要用来保护事务变更的记录不被并发修改 </li></ul><ul><li>Id1 为 undo segment number << 16 | slot </li></ul><ul><li>Id2 为此事务的 sequence </li></ul><ul><li>由 id1,id2 的值组合出事务编号 usn.slot.seq </li></ul>
  22. 22. TX-mode 6 <ul><li>普通的 dml 产生的事务锁 . </li></ul><ul><li>持有锁的事务的 lmode = 6 </li></ul><ul><li>被阻塞的事务的 request mode = 6 </li></ul><ul><li>相关实例 </li></ul><ul><li>Session 1 </li></ul><ul><ul><li>Update james_t set value = ‘test 1’ where id = 1; </li></ul></ul><ul><li>Session 2 </li></ul><ul><ul><li>Update james_t set value = ‘test 2’ where id = 1; </li></ul></ul>
  23. 23. TX 锁 -index Contention <ul><li>当两个 Session 插入的值出现主键 / 唯一键冲突的时候 </li></ul><ul><li>持有锁的 Session 的 lmode = 6 </li></ul><ul><li>被阻塞的 session 请求的 mode 为 4 </li></ul><ul><li>Session 1 </li></ul><ul><ul><li>insert into james_t (id,value) values (6000001,'test 6000001'); </li></ul></ul><ul><li>Session 2 </li></ul><ul><ul><li>insert into james_t (id,value) values (6000001,'test 6000001'); </li></ul></ul>
  24. 24. TX 锁 -itl contention <ul><li>当 block 上的活动事务槽用完 , 又没有足够的空间来扩展事务槽或者是达到 maxtrans 设定的事务槽数量时 . 此 block 上新请求的事务会等到 mode=4 的 tx lock </li></ul><ul><li>session 1 </li></ul><ul><ul><li>Update james_itl set value = ‘test 1’ where id =1; </li></ul></ul><ul><li>Session 2 </li></ul><ul><ul><li>Update james_itl set value = ‘test 2’ where id = 2; </li></ul></ul><ul><li>Session 3 </li></ul><ul><ul><li>Update james_itl set value = ‘test 3’ where id = 3; </li></ul></ul>
  25. 25. HW 锁 <ul><li>此锁主要用来控制特定对象空间分配时的并发操作 </li></ul><ul><li>Id1 为表空间的编号 ts# </li></ul><ul><li>Id2 需要分配空间的对象 segment header 的相对 DBA(Data Block Address) 位置 </li></ul><ul><li>争用主要发生在大量插入时 , 或手工对该对象 allocate/deallocate 空间时 </li></ul>
  26. 26. US- 锁 <ul><li>控制特定 Undo Segment 上的并行化操作 </li></ul><ul><li>Id1 为此 undo segment 的编号 *1 </li></ul><ul><li>Id2 始终为 1 </li></ul><ul><li>触发 US 锁的相关操作 </li></ul><ul><ul><li>CREATE ROLLBACK SEGMENT </li></ul></ul><ul><ul><li>DROP ROLLBACK SEGMENT </li></ul></ul><ul><ul><li>ALTER ROLLBACK SEGMENT ONLINE </li></ul></ul><ul><ul><li>ALTER ROLLBACK OFFLINE </li></ul></ul><ul><ul><li>ALTER ROLLBACK SEGMENT SHRINK </li></ul></ul><ul><ul><li>ALTER ROLLBACK SEGMENT STORAGE </li></ul></ul><ul><ul><li>Offlining PENDING OFFLINE RBS by SMON </li></ul></ul><ul><ul><li>SMON - abortive offline cleanup. </li></ul></ul><ul><ul><li>STARTUP. </li></ul></ul>
  27. 27. TO- 锁 <ul><li>TO 锁主要是用来防止对临时表的并发操作 </li></ul><ul><ul><li>当针对临时表做 alter,drop,create 操作时 , 会对此临时表取 TO 的 Exclusive mode 锁 </li></ul></ul><ul><ul><li>当对此临时表做 DML 时获取 SX 锁 </li></ul></ul><ul><ul><li>对此临时表的 index 做 ddl 操作时获取 S 锁 </li></ul></ul><ul><li>Id1 为此临时表的 object_id </li></ul><ul><li>Id2 始终为 1 </li></ul>
  28. 28. CF 锁 - 说明 <ul><li>与控制文件修改相关的锁 </li></ul><ul><ul><li>串行化对控制文件的修改 </li></ul></ul><ul><ul><li>任何涉及到对控制文件进行修改的进程都会持有此锁 </li></ul></ul><ul><li>Id1 始终为 0 </li></ul><ul><li>Id2 = 0 表示串行化控制文件的操作 </li></ul><ul><li>Id2= 1 表示共享信息的访问 </li></ul>
  29. 29. CF 锁 - 使用场景 <ul><li>日志文件切换 </li></ul><ul><li>新增 / 删除各种类型的文件 ( 数据文件 , 临时文件 , 日志文件 ) </li></ul><ul><li>打开 / 关闭 / 备份数据库 , 改变表空间 / 数据文件的在线状态 , 读写状态 </li></ul><ul><li>转储控制文件中的对象信息 ( 数据文件 , 日志文件 ) </li></ul><ul><li>修改数据库的 checkpoint 信息 . </li></ul>
  30. 30. JQ 锁 <ul><li>此锁是为了控制对 job 的并发访问与执行 </li></ul><ul><li>正在运行的 job 才会持有此锁 </li></ul><ul><li>Id1 始终为 0 </li></ul><ul><li>Id2 为此 job 的编号 job_no </li></ul><ul><li>Dba_jobs_running 是 Oracle 以此为基础创建的视图 , 可通过此视图确定正在运行的任务 . </li></ul><ul><li>Session 13 </li></ul><ul><ul><li>Exec dbms_job.run(3); </li></ul></ul>
  31. 31. SQ- 锁 <ul><li>使用此锁来防止多个进程同时刷新 SGA 中的 Sequence 缓存 </li></ul><ul><li>Id1 为 sequence 对应的 object_id </li></ul><ul><li>Id2 始终为 0 </li></ul><ul><li>如果 Sequence 的 cache 设置较小 ( 比如选择使用默认值 ), 就会导致系统会遭遇较多的 SQ enqueue 等待出现 (taobao 曾经因此出现过故障 ) </li></ul><ul><li>另 , 如果 sequence 使用 nocache, 系统可能会遇到较严重的 row cache lock, 而不会出现任何 SQ enqueue 等待 </li></ul>

×