• Oracle数据库锁机制


    Lock是一种机制,可以防止事务对共享数据的不正确的更新和不正确的修改数据结构,在维护数据的一致性和并发性中,它扮演了一个很重要的角色。

    Lock行为概述

    根据获得的锁的操作,数据库维护几种不同类型的锁。通常,数据库使用两种类型的锁:排它锁(exclusive locks)和共享锁(share locks)。在诸如行或表之类的资源上,只能获得一个排它锁,但是可以在单个资源上获得多个共享锁。

    锁会影响读和写的交互。读是查询资源,而写是修改资源。下面总结了Oracle数据库读和写的锁行为:

    • 当语句修改一行时,事务仅获得改行的锁,通过在行级别锁定表数据,数据库最小化对同样数据的争用;
    • 如果一个事务正在修改一行,那么行锁会阻止其他事务同时对改行的修改;
    • 读操作从不阻塞写操作,除了select…for update语句;
    • 写操作从不阻塞读操作,当行正被写操作修改时,数据库使用undo数据来给读操作提供行的一致性视图;

    Lock用途

    在单用户数据库中,不需要锁,因为只有一个用户修改信息,然而,当多个用户访问和修改数据时,数据库必须提供一种方法来防止对相同数据的并发修改。Locks实现了下面的需求:

    • 一致性(Consistency):会话正在查看和修改的数据不会被其他会话更改,直到该会话完成;
    • 完整性(Integrity):数据和结构必须以正确的顺序反映对它们的所有更改;

    Oracle数据库通过锁机制在事务中提供了数据的并发性、一致性和完整性,锁自动执行,不需要用户参与;

    当执行SQL语句时,Oracle数据库自动获得必要的锁,例如,在会话修改数据前,会话必须锁定数据,该锁为会话提供了对数据的独占控制,以便其他事务在锁释放之前不会修改锁定的数据。

    由于Oracle数据库的锁机制和事务控制密切相关,应用程序设计人员只需正确的定义事务,Oracle数据库会自动管理锁,用户不需显式的锁定任何资源,尽管Oracle数据库也能使用户手动锁定数据。

    Lock模式

    Oracle数据库自动使用最低限制适用级别,以提供最高程度的数据并发性,同时也提供了数据完整性。限制级别越低,数据越容易被其他用户访问,反之,限制级别越多,其他事务可获得的锁类型越受限。

    Oracle数据库在多用户数据库中使用两种锁模式:

    • 排他锁模式(Exclusive lock mode):该模式防止相关的资源共享,当事务修改数据时,将会获得排它锁。第一个单独锁定资源的事务是唯一可以改变该资源的事务,直到排它锁被释放;
    • 共享锁模式(Share lock mode):该模式根据涉及的操作,相关的资源可以共享。读取数据的多个用户可以共享数据,持有共享锁可以防止需要排它锁的写操作并发访问,一些事务可以在同一资源上获得共享锁。

    假想一个事务使用select … for update选择了单个表行,该事物获取了exclusive row lock和row share table lock,row lock允许其他会话修改除了已锁定行之外的任何行,而table lock则防止会话修改表的结构,因此,数据库允许尽可能多的语句执行。

    Lock转换和升级

    Oracle数据库在必要时执行锁转换。在锁转换中,数据库自动将较低限制的表锁转换为更高限制的。

    例如:假设一个事务使用select … for update选择了单个行,然后更新锁定的行,在这种情况下,数据库自动将row share table lock转为row exclusive table lock,在该事务,它对已插入、修改和删除的所有行持有exclusive row locks,因为行锁是在最高限制程度下获得的,因此不需要或执行锁转换。

    锁转换不同于锁升级,当多个锁在一个粒度级别(比如行)或数据库将锁提升到更高的粒度级别(比如表)时,就会发生锁升级。如果用户锁定表中许多行,那么一些数据库就会自动将row lock升级到单个表。锁的数量减少了,但是锁定的限制增加了。

    Oracle数据库从不升级锁,锁升级容易引发死锁。

    Lock持续时间

    当事务不再需要资源时,Oracle数据库会自动释放锁。在大多数情况下,数据库持有在事务期间语句获得的锁,这些锁可以防止诸如脏读、丢失更新和来自并发事务的破坏性DDL等破坏性干扰。

    当语句commit或rollback时,Oracle数据库会释放事务中语句获得的所有锁,当回滚到savepoint时,也会释放savepoint后获得的锁。然而,只有不等待之前已锁定资源的事务才能获取当前可用资源上的锁,正在等待的事务继续等待,直到所有之前的事务完全提交或回滚。

    Locks和Deadlocks

    死锁是指两个或多个用户在等待彼此锁定的数据,它阻止事务继续工作。

    Oracle数据库自动探测死锁,并通过回滚包含在死锁中的语句来解决它们,释放一组冲突的行锁。数据库返回一个执行statement-level rollback的事务对应的消息。回滚的语句属于探测死锁的事务。通常,发出信号的事务应该被显式回滚,但它可以在等待后重试回滚语句。

    当事务显式覆盖Oracle数据库的默认锁定时,最常发生死锁。由于Oracle数据库不会升级锁,也不使用read locks来查询,而是使用row-level的锁,死锁很少发生。

    死锁演示:

    会话1
    会话2
    说明
    SQL> update emp set sal=1000
      2 where empno=7369;

    1 row updated.
    SQL> update emp set sal=2000
      2 where empno=7499;

    1 row updated.
    会话1和2都拥有一个行级锁;
    SQL> update emp set sal=2500
      2 where empno=7499;
    SQL> update emp set sal=1500
      2 where empno=7369;
    会话彼此修改对方刚修改过的值,因资源互相被对方占用,故都出现等待;
    SQL> update emp set sal=2500
      2 where empno=7499;

    update emp set sal=2500
           *
    ERROR at line 1:
    ORA-00060: deadlock detected while waiting for resource

    事务1检测到死锁,回滚并返回错误;
    SQL> select empno,ename,sal from emp
      2 where empno in(7369,7499);

         EMPNO ENAME SAL
    ———- ———- ———-
          7369 SMITH 1000
          7499 ALLEN 1600

    只回滚上一个事务;
    SQL> commit;

    Commit complete.

    事务1提交,并结束事务;

    1 row updated.
    事务2显示已更新一行;

    SQL> commit;

    Commit complete.

    SQL> select empno,ename,sal from emp
      2 where empno in(7369,7499);

         EMPNO ENAME SAL
    ———- ———- ———-
          7369 SMITH 1500
          7499 ALLEN 2000
    事务2提交,并结束事务;

    参考:官方文档

  • 相关阅读:
    释放下一代网络应用的能量[转载]
    帮助创建未来的 .NET 客户端开发
    ASP.NET Ajax替代品AjaxWidgets
    Microsoft Surface
    有意思的《致招商银行的公开信》行动!
    Applying DomainDriven Design and Patterns(ADDDP) With examples in C# and .NET
    Silverlight ASP.NET control
    StructureMap 轻量IOC框架
    DDay.iCal an iCalendar class library
    Mono ASP.NET 上几个性能调优技巧
  • 原文地址:https://www.cnblogs.com/alen-liu-sz/p/12975701.html
Copyright © 2020-2023  润新知