Oracle锁的概念和类型
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。
Oracle在两个不同级别上提供读取一致性:语句级读取一致性和事务级读取一致性。
语句级读取一致性:Oracle总是实施语句级读取一致性,保证单个查询所返回的数据与该查询开始时保持一致。
事务级读取一致性:事务级读取一致性是指在同一个事物中的所有数据对时间点是一致的。
1锁的概念和类型
数据库的特点就是数据的集中管理和共享。在通常情况下,总是有若干个事务并发地运行,这些并行的事务并发地存取相同的数据 。若对并发操作不加控制,就可能会读取和存储不正确的数据,破坏数据库的一致性。为保证数据库数据正确地反映所有事务的更新,在一事务修改数据时,其它事务不能同时修改这个数据,数据库系统用锁来控制对数据的并发访问及数据一致性。
锁按用户和系统分可以分为自动锁和显示锁。
自动锁:当进行一项数据库操作时,缺省情况下,系统自动为此数据库操作获得所有有必要的锁。
显示锁:某些情况下,需要用户显示的锁定数据库操作要用到的数据,使数据库操作执行得更好,显示锁是用户为数据库对象设定的。
锁按操作分可以分为 DML 锁、DLL 锁和 System Locks。
DML锁:称为数据锁,用于保护数据的完整性;从封锁粒度(封锁对象的大小)的角度看,Oracle DML锁共有两个层次,即行级锁和表级锁。
DDL lock:用于保护数据库对象的结构(例如表、视图、索引的结构定义)。
System Locks:保护内部数据库结构。
.2DML锁
.2.1DML锁的简介
在Oracle中最主要的锁是DML(也可称为data locks,数据锁)锁。DML锁的目的在于保证并发情况下的数据完整性。在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。
当 Oracle 数据库执行 DML 语句时,系统自动在所要操作的表上申请 TM 类型的锁。当 TM 锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查 TX锁相容性时就不用再逐行检查锁标志,而只需检查 TM 锁模式的相容性即可,大大提高了系统的效率。
在 Oracle 数据库中,当一个事务首次发起一个 DML 语句时就获得一个 TX 锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行 DML 语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后, TX 锁被释放,其他会话才可以加锁。
当 Oracle 数据库发生 TX 锁等待时,如果不及时处理常常会引起 Oracle 数据库挂起,或导致死锁的发生。这些现象都会对实际应用产生极大的危害,如长时间未响应,会导致大量事务失败。
TM 锁用于确保在修改表的内容时,表的结构不会改变,例如防止在DML 语句执行期间相关的表被移除。当用户对表执行 DDL或DML 操作时,将获取一个此表的表级锁。当事务获得行锁后,此事务也将自动获得该行的表锁(共享锁),以防止其它事务进行 DDL 语句影响记录行的更新。事务也可以在进行过程中获得共享锁或排它锁,只有当事务显示使用 LOCK TABLE 语句显示的定义一个排它锁时,事务才会获得表上的排它锁,也可使用 LOCK TABLE 显示的定义一个表级的共享锁。
TM 锁包括了 SS、 SX、 S、 X 等多种模式,在数据库中用 0-6来表示。不同的 SQL 操作产生不同类型的 TM 锁,如图10-1所示。
图10-1TX锁的模式
TX 锁:当事务执行数据库插入、更新、删除操作时,该事务自动获得操作表中操作行的排它锁。事务发起第一个修改时会得到TX 锁(事务锁),而且会一直持有这个锁,直至事务执行提交或回滚。
对用户的数据操作, Oracle 可以自动为操纵的数据进行加锁,但如果有操纵授权,则为满足并发操纵的需要另外实施加锁。
10.2.2DML锁添加方式
DML 锁可由一个用户进程以显式的方式加锁,也可通过某些 SQL 语句隐含方式实现。
DML 锁有三种加锁方式:共享锁方式、独占锁方式、共享更新。
共享锁,独占锁用于 TM 锁,共享锁用于 TX 锁。
1)共享方式的表级锁
共享方式的表级锁是对表中的所有数据进行加锁,该锁用于保护查询数据的一致性,防止其它用户对已加锁的表进行更新。其它用户只能对该表再施加共享方式的锁,而不能再对该表施加独占方式的锁,共享更新锁可以再施加,但不允许持有共享更新封锁的进程做更新。
共享该表的所有用户只能查询表中的数据,但不能更新。
共享方式的表级锁只能由用户用 SQL 语句来设置,语句格式如下:
LOCK TABLE <表名>[,<表名>]… IN SHARE MODE [NOWAIT]
执行该语句,对一个或多个表施加共享方式的表封锁。当指定了选择项NOWAIT,若该锁暂时不能施加成功,则返回并由用户决定是进行等待,还是去执行别的语句。持有共享锁的事务,在出现如下之一的条件时,便释放其共享锁:
执行 COMMIT 或 ROLLBACK 语句。
退出数据库( LOG OFF)。
程序停止运行。
共享方式表级锁常用于一致性查询过程,即在查询数据期间表中的数据不发生改变。
2)独占方式表级锁
独占方式表级锁是用于加锁表中的所有数据,拥有该独占方式表封锁的用户,即可以查询该表,又可以更新该表,其它的用户不能再对该表施加任何加锁(包括共享、独占或共享更新封锁)。其它用户虽然不能更新该表,但可以查询该表。
独占方式的表加锁,格式如下:
LOCK TABLE <表名>[,<表名>]… IN EXCLUSIVE MODE [NOWAIT]
独占方式的表级锁也可以在用户执行 DML 语句 INSERT、UPDATE、DELETE时隐含获得。独占方式封锁通常用于更新数据,当某个更新事务涉及多个表时,可减少发生死锁.
3)共享更新加锁方式
共享更新加锁是对一个表的一行或多行进行加锁,因而也称作行级加锁。表级加锁虽然保证了数据的一致性,但却减弱了操作数据的并行性。
行级加锁确保在用户取得被更新的行到该行进行更新这段时间内不被其它用户所修改。因而行级锁即可保证数据的一致性又能提高数据操作的迸发性。
获得行级锁,格式如下:
LOCK TABLE < 表 名 >[,< 表 名 >]… IN SHARE UPDATE MODE
[NOWAIT]