锁和闩

锁(lock)用于管理对共享资源的并发访问。

在必要时才提交,不要提前。

锁的问题:

1.丢失更新

session1 session2
(1)查询一行数据 (2)查询同一行数据
(3)update该行并提交  
  (4)update该行并提交
这个过程被称为丢失更新 因为(3)所做的所有修改都会丢失

2.锁定策略:悲观锁(pessimistic)乐观锁(optimistic)

悲观锁
这种方式在用户修改数值之前就开始生效了
乐观锁
所有锁定动作都延迟到即将执行更新之前才进行
     实现方法:使用版本列的乐观锁,使用用户总和校验的乐观锁

3.阻塞

阻塞的Insert
     带主键或唯一约束
     引用完整性约束
阻塞的Merger、update和delete

4.死锁

5.锁升级

锁的类型

DML锁
      select、insert、update、merge、delete
      可能是行级锁也可能是表级锁
   1.TX锁
      事务发起第一个修改时会得到TX锁
      Oracle没有使用锁管理器,Oracle锁定过程如下:
         (1)找到想锁定的那一行地址
         (2)到达那一行
         (3)就地锁住这一行,就在行的位置上(如果这一行已经被锁住,就等待锁住他的事务结束,除非指定nowait)
DDL锁
      create和alter语句等,可以保护对象结构定义
内部锁和闩latch
      保护内部数据结构

SQL> create table dept
  2  as select * from scott.dept;

Table created.

SQL> create table emp
  2  as select * from scott.emp;

Table created.
SQL> alter table dept
  2  add constraint dept_pk
  3  primary key(deptno);

Table altered.
SQL> alter table emp
  2  add constraint emp_pk
  3  primary key(empno);

Table altered.

SQL> alter table emp
  2  add constraint emp_fk_dept
  3  foreign key(deptno)
  4  references dept(deptno);

Table altered.

SQL> create index emp_deptno_idx
  2  on emp(deptno);

Index created.

启动一个事务:

SQL> update dept
  2  set dname=initcap(dname);

4 rows updated.


查看:

SELECT username,
       v$lock.sid,
       TRUNC (id1 / POWER (2, 16)) rbs,
       BITAND (id1, TO_NUMBER (‘ffff‘, ‘xxxx‘)) + 0 slot,
       id2 seq,
       lmode,
       request
  FROM v$lock, v$session
WHERE     v$lock.TYPE = ‘TX‘
       AND v$lock.sid = v$session.sid
       AND v$session.username = USER;

USERNAME                  SID        RBS       SLOT        SEQ    LMODE     REQUEST
--------------------------- ---------- ---------- ---------- ---------- ---------- ----------
EODA                               341       7         17        158        6           0

SQL> select XIDUSN,XIDSLOT,XIDSQN from v$transaction;

XIDUSN  XIDSLOT XIDSQN
---------- ---------- ----------
         7       17         158
这里有几点很有意思

v$lock表的LMODE为6,REQUEST为0.查看Oracle Database Reference得到LMODE=6是一个排他锁。请求REQUEST=0则意味着你没有发出请求,也就是说你拥有这个锁。

这个v$lock表只有一行。Oracle不会在任何地方存储行级锁的列表。要查看某一行是否锁定,必须直接找到这一行。

RBS、SLOT和SEQ值与v$transaction匹配,这就是我的事务ID

开启另外一个会话

SQL> update emp set ename=upper(ename);

14 rows updated.

SQL> update dept set deptno=deptno-10;

现在这个会话被阻塞

回到原来会话

SELECT username,
       v$lock.sid,
       TRUNC (id1 / POWER (2, 16)) rbs,
       BITAND (id1, TO_NUMBER (‘ffff‘, ‘xxxx‘)) + 0 slot,
       id2 seq,
       lmode,
       request
  FROM v$lock, v$session
WHERE     v$lock.TYPE = ‘TX‘
       AND v$lock.sid = v$session.sid
11         AND v$session.username = USER;

USERNAME         SID        RBS       SLOT      SEQ      LMODE     REQUEST
------------------- ---------- ---------- ---------- ---------- ---------- ----------
EODA                      311      10          3       7727        6           0
EODA                      311       7         17        158        0           6
EODA                      341       7         17        158        6           0

SQL> select XIDUSN,XIDSLOT,XIDSQN from v$transaction;

XIDUSN    XIDSLOT      XIDSQN
---------- ---------- ----------
    10        3        7727
     7       17         158
可以看到开始了一个新事务,事务ID是(10,3,7727),这一次,这个新会话(SID=311)在v$lock有两行。其中一行表示他拥有的锁(LMODE=6)。另外还有一行,显示了一个值为6的REQUEST。这是一个队排他锁的请求。有意思的是,这个请求行的RBS/SLOT/SEQ的值正是锁持有者的事务ID。SID=341的事务阻塞了sid=311的事务。从v$lock的自连查询可以看出:

SELECT (SELECT username
          FROM v$session
         WHERE sid = a.sid)
          blocker,
       a.sid,
       ‘ is blocking ‘,
       (SELECT username
          FROM v$session
         WHERE sid = b.sid)
          blockee,
       b.sid
  FROM v$lock a, v$lock b
13   WHERE a.BLOCK = 1 AND b.REQUEST > 0 AND a.ID1 = b.ID1 AND a.id2 = b.id2;

BLOCKER                   SID ‘ISBLOCKING‘    BLOCKEE                   SID
------------------------------ ---------- ------------- ------------------------------ ----------
EODA                      341  is blocking    EODA                      311
现在,提交原来的事务(SID=341),再次查询,可以看到请求行不见了

SQL> commit;

Commit complete.

SELECT username,
       v$lock.sid,
       TRUNC (id1 / POWER (2, 16)) rbs,
       BITAND (id1, TO_NUMBER (‘ffff‘, ‘xxxx‘)) + 0 slot,
       id2 seq,
       lmode,
       request
  FROM v$lock, v$session
WHERE     v$lock.TYPE = ‘TX‘
       AND v$lock.sid = v$session.sid
11         AND v$session.username = USER;

USERNAME                  SID     RBS       SLOT        SEQ    LMODE     REQUEST
------------------------------ ---------- ---------- ---------- ---------- ---------- ----------
EODA                      311      10          3       7727        6           0

再另外一个会话也可以看到更新完成,结束了被阻塞状态。

SQL> update emp set ename=upper(ename);

14 rows updated.

SQL> update dept set deptno=deptno-10;

4 rows updated.

时间: 2024-10-06 00:29:33

锁和闩的相关文章

读书摘要:第七章 闩Suan锁和自旋锁

摘要: 1.闩锁就像是内存上的锁,随着越来越多的线程参与进来,他们争相访问同一块内存,导致堵塞.2.自旋锁就是闩锁,不同之处是如果访问的内存不可用,它将继续检查轮询一段时间.3.拴锁和自旋锁是我们无法控制的,由sqlserver自动维护,但是我们应积极寻找避免他们发生堵塞的方法.4.id作为聚集索引时,当数据量增加时最后一个数据页将成为热点,征用就会发生.避免有经常行数据插入操作的表使用自增ID,改为guid.5.队列操作的数据表也应该避免ID的聚集索引问题.6.无论何时将数据插入到没有聚集索引

SQL Server里的闩锁介绍

在今天的文章里我想谈下SQL Server使用的更高级的,轻量级的同步对象:闩锁(Latch).闩锁是SQL Server存储引擎使用轻量级同步对象,用来保护多线程访问内存内结构.文章的第1部分我会介绍SQL Server里为什么需要闩锁,在第2部分我会给你介绍各个闩锁类型,还有你如何能对它们进行故障排除. 为什么我们需要闩锁? 闩锁首次在SQL Server 7.0里引入,同时微软首次引入了行级别锁(row-level locking).对于行级别锁引入闩锁的概念是非常重要的,不然的话在内存中

Oracle Buffer Pool内部闩锁机制

本文中根块,枝块,叶块,表块分别是索引根块,索引枝块,索引叶块,数据表块的简称. 此外本文大多数观点来自于大师吕海波<Oracle内核技术揭秘>一书,本博文为个人感想. 首先需要明确4点关于CBC LATCH和BUFFER PIN的知识点: 1. 对于根块和枝块,CBC LATCH都是以S模式获取的,无BUFFER PIN 2. 对于叶块,CBC LATCH是以X模式获取的,BUFFER PIN是以S模式获取的 3. 对于表块,CBC LATCH是以X模式获取的,SELECT语句的BUFFER

【锁】Oracle锁系列

[锁]Oracle锁系列 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 锁的概念.分类.及其模拟 ② 查询锁的视图及视图之间的关联 ③ 锁的参数(DML_LOCKS.DDL_LOCK_TIMEOUT) ④ FOR UPDATE及FOR UPDATE OF系列 ⑤ 带ONLINE和不带ONLINE创建索引的锁情况(是否阻塞DML操作) ⑥ 包或存过不能编译的解决方法

无锁数据结构(Lock-Free Data Structures)

原文:无锁数据结构(Lock-Free Data Structures) 一个星期前,我写了关于SQL Server里闩锁(Latches)和自旋锁(Spinlocks)的文章.2个同步原语(synchronization primitives)是用来保护SQL Server里的共享数据结构,例如缓存池里的页(通过闩锁(Latches)),锁管理器哈希表里的锁(通过自旋锁(Spinlock)).接下里你会看到越来越多的全新同步原语(synchronization primitives),即所谓的

oracle锁一些知识

表级锁共具有五种模式,如下所示. 行级排他锁(Row Exclusive,简称RX锁) 当我们进行DML时会自动在被更新的表上添加RX锁,或者也可以通过执行lock命令显式的在表上添加RX锁.在该锁定模式下,允许其他的事务通过DML语句修改相同表里的其他数据行,或通过lock命令对相同表添加RX锁定,但是不允许其他事务对相同的表添加排他锁(X锁). 行级共享锁(Row Shared,简称RS锁) 通常是通过select … from for update语句添加的,同时该方法也是我们用来手工锁定

oracle 锁

问题如下: SQL> conn scott/[email protected]_databaseConnected to Oracle Database 11g Enterprise Edition Release 11.1.0.6.0Connected as scott ...... SQL> drop table student2; drop table student2 ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效================

oracle 死锁和锁等待的区别

所谓的锁等待:就是一个事务a对一个数据表进行ddl或是dml操作时,系统就会对该表加上表级的排它锁,此时其他的事务对该表进行操作的时候会等待a提交或是回滚后,才可以继续b的操作 所谓的死锁:当两个或多个用户相互等待锁定的数据时就会发生死锁,这时这些用户被卡在不能继续处理业务,oracle可以自动检测死锁并解决他们,通过回滚一个死锁中的语句,释放锁定的数据,回滚的话会遇到ora-00060 deadlock detected while waiting for resource 模拟锁等待: 两个

ORACLE的TM锁和TX锁

根据保护的数据不同,ORACLE的数据库锁分为以下几大类: 1.DML锁(data locks数据锁),用于保护数据的完整性: 2.DDL锁(dictionary locks字典锁),用于保护数据库对象的结构,例如表.索引的结构定义: 3.内部锁或闩(internal locks or latches),用于保护内部结构 在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁. 当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的