oracle的各种锁的类型

oracle-数据库的各种-锁-详解

简介

数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。

如果是单用户的系统,那完全没有必要这个锁,就是因为有多用户并发操作,我们为了确保资源的安全性(也就是Oracle的数据完整性和一致性)才引申出这个锁出来。Oracle 利用其锁机制来实现事务间的数据并发访问及数据一致性。

加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

Oracle的锁机制是一种轻量级的锁定机制,不是通过构建锁列表来进行数据的锁定管理,而是直接将锁作为数据块的属性,存储在数据块首部。

在 Oracle 数据库中,它并不是对某个表加上锁或者某几行加上锁, 锁是以数据块的一个属性存在的。 也就是说, 每个数据块本身就存储着自己数据块中数据的信息,这个地方叫 ITL( Interested Transaction List), 凡是在这个数据块上有活动的事务,它的信息就会记录在这里面供后续的操作查询,一保证事务的一致性。

在oracle数据库中,不存在真正意义上属于某个对象或数据的锁。oracle锁的信息是数据块的一个物理属性,而不是逻辑上属于某个表或某个行。

分类

按用户和系统分可以分为自动锁和显示锁

自动锁( Automatic Locks)

当进行一项数据库操作时,缺省情况下,系统自动为此数据库操作获得所有有必要的锁。
自动锁分为三种:

  • DML 锁
  • DDL 锁
  • systemlocks。

显示锁( Manual Data Locks)

某些情况下,需要用户显示的锁定数据库操作要用到的数据,才能使数据库操作执行得更好,显示锁是用户为数据库对象设定的。

按锁级别分可以分为排它锁和共享锁

排他锁(exclusive lock,即X锁)和共享锁(share lock,即S锁)

排他锁(exclusive lock,即X锁)

事务设置排它锁后,该事务单独获得此资源,另一事务不能在此事务提交之前获得相同对象的共享锁或排它锁。

共享锁(share lock,即S锁)

共享锁使一个事务对特定数据库资源进行共享访问——另一事务也可对此资源进行访问或获得相同共享锁。
共享锁为事务提供高并发性,但如拙劣的事务设计+共享锁容易造成死锁或数据更新丢失。

按操作分可以分为DML锁、DLL锁和System Locks

DML锁

DML 锁用于控制并发事务中的数据操纵,保证数据的一致性和完整性。
DML锁主要用于保护并发情况下的数据完整性。
DML 语句能够自动地获得所需的表级锁(TM)与行级(事务)锁(TX)。

它又分为:
( 1) TM 锁(表级锁)
( 2) TX 锁( 事务锁或行级锁)

当 Oracle 执行 DML 语句时,系统自动在所要操作的表上申请 TM 类型的锁。当 TM 锁获得后,系统再自动申请 TX 类型的锁,并将实际锁定的数据行的锁标志位进行置位。
这样在事务加锁前检查 TX锁相容性时就不用再逐行检查锁标志,而只需检查 TM 锁模式的相容性即可,大大提高了系统的效率。

在数据行上只有 X 锁(排他锁)。
在 Oracle 数据库中,当一个事务首次发起一个 DML 语句时就获得一个 TX 锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行 DML 语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后, TX 锁被释放,其他会话才可以加锁。

当 Oracle 数据库发生 TX 锁等待时,如果不及时处理常常会引起 Oracle 数据库挂起,或导致死锁的发生,产生ORA-600 的错误。这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。

DML 锁有如下三种加锁方式:

  • 共享锁方式( SHARE)
  • 独占锁方式( EXCLUSIVE)
  • 共享更新锁( SHARE UPDATE)
    其中:
    SHARE, EXCLUSIVE 用于 TM 锁(表级锁)
    SHARE UPDATE 用于 TX 锁( 行级锁)

TM 锁(表级锁)

TM 锁用于确保在修改表的内容时,表的结构不会改变,例如防止在 DML 语句执行期间相关的表被移除。当用户对表执行 DDL 或 DML 操作时,将获取一个此表的表级锁。

当事务获得行锁后,此事务也将自动获得该行的表锁(共享锁),以防止其它事务进行 DDL 语句影响记录行的更新。

事务也可以在进行过程中获得共享锁或排它锁,只有当事务显示使用 LOCK TABLE 语句显示的定义一个排它锁时,事务才会获得表上的排它锁,也可使用 LOCK TABLE 显示的定义一个表级的共享锁。

TM 锁包括了 SS、 SX、 S、 X 等多种模式,在数据库中用 0-6 来表示。不同的 SQL 操作产生不同类型的 TM 锁.

TM 锁类型表
TM锁

TX 锁( 事务锁或行级锁)

当事务执行数据库插入、更新、删除操作时,该事务自动获得操作表中操作行的排它锁。

事务发起第一个修改时会得到TX 锁(事务锁),而且会一直持有这个锁,直至事务执行提交(COMMIT)或回滚(ROLLBACK)。

对用户的数据操纵, Oracle 可以自动为操纵的数据进行加锁,但如果有操纵授权,则为满足并发操纵的需要另外实施加锁。

DML 锁可由一个用户进程以显式的方式加锁,也可通过某些 SQL 语句隐含方式实现。 这部分属于 Manual Data Locks。

原理:
一个事务要修改块中的数据,必须获得该块中的一个itl,通过itl和undo segment header中的transaction table,可以知道事务是否处于活动阶段。事务在修改块时(其实就是在修改行)会检查行中row header中的标志位,如果该标志位为0(该行没有被活动的事务锁住),就把该标志位修改为事务在该块获得的itl的序号,这样当前事务就获得了对记录的锁定,然后就可以修改行数据了,这也就是oracle行锁实现的原理。

共享方式的表级锁( Share)
共享方式的表级锁是对表中的所有数据进行加锁,该锁用于保护查询数据的一致性,防止其它用户对已加锁的表进行更新。

其它用户只能对该表再施加共享方式的锁,而不能再对该表施加独占方式的锁,共享更新锁可以再施加,但不允许持有共享更新封锁的进程做更新。

共享该表的所有用户只能查询表中的数据,但不能更新。

共享方式的表级锁只能由用户用 SQL 语句来设置.

语句格式如下:

LOCK TABLE <表名>[,<表名>]... IN SHARE MODE [NOWAIT]

执行该语句,对一个或多个表施加共享方式的表封锁。
当指定了选择项NOWAIT,若该锁暂时不能施加成功,则返回并由用户决定是进行等待,还是先去执行别的语句。
持有共享锁的事务,在出现如下之一的条件时,便释放其共享锁:

A、执行 COMMIT 或 ROLLBACK 语句。
B、退出数据库( LOG OFF)。
C、程序停止运行。

共享方式表级锁常用于一致性查询过程,即在查询数据期间表中的数据不发生改变。

posted @ 2023-06-21 15:54  数据库小白(专注)  阅读(301)  评论(0编辑  收藏  举报