Oracle
数据库锁机制
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。
在数据库中有两种基本的锁类型:排它锁(
Exclusive Locks
,即
X
锁)和共享锁(
Share Locks
,即
S
锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。
在实际应用中经常会遇到的与锁相关的异常情况,如由于等待锁事务被挂起、死锁等现象,如果不能及时地解决,将严重影响应用的正常执行,而目前对于该类问题的解决缺乏系统化研究和指导,本文在总结实际经验的基础上,提出了相应的解决方法和具体的分析过程。
Oracle
数据库的锁类型
根据保护的对象不同,
Oracle
数据库锁可以分为以下几大类:
DML
锁(
data locks
,数据锁),用于保护数据的完整性;
DDL
锁(
dictionary locks
,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;内部锁和闩(
internal locks and latches
),保护数据库的内部结构。
DML
锁的目的在于保证并发情况下的数据完整性,本文主要讨论
DML
锁。在
Oracle
数据库中,
DML
锁主要包括
TM
锁和
TX
锁,其中
TM
锁称为表级锁,
TX
锁称为事务锁或行级锁。
当
Oracle
执行
DML
语句时,系统自动在所要操作的表上申请
TM
类型的锁。当
TM
锁获得后,系统再自动申请
TX
类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查
TX
锁相容性时就不用再逐行检查锁标志,而只需检查
TM
锁模式的相容性即可,大大提高了系统的效率。
TM
锁包括了
SS
、
SX
、
S
、
X
等多种模式,在数据库中用
0
-
6
来表示。不同的
SQL
操作产生不同类型的
TM
锁。如表
1
所示。
在数据行上只有
X
锁(排他锁)。在
Oracle
数据库中,当一个事务首次发起一个
DML
语句时就获得一个
TX
锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行
DML
语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后,
TX
锁被释放,其他会话才可以加锁。
当
Oracle
数据库发生
TX
锁等待时,如果不及时处理常常会引起
Oracle
数据库挂起,或导致死锁的发生,产生
ORA-60
的错误。这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。
TX
锁等待的分析
在介绍了有关地
Oracle
数据库锁的种类后,下面讨论如何有效地监控和解决锁等待现象,及在产生死锁时如何定位死锁的原因。
监控锁的相关视图
数据字典是
Oracle
数据库的重要组成部分,用户可以通过查询数据字典视图来获得数据库的信息。和锁相关的数据字典视图如表
2
所示。
TX
锁等待的监控和解决在日常工作中,如果发现在执行某条
SQL
时数据库长时间没有响应,很可能是产生了
TX
锁等待的现象。为解决这个问题,首先应该找出持锁的事务,然后再进行相关的处理,如提交事务或强行中断事务。
死锁的监控和解决在数据库中,当两个或多个会话请求同一个资源时会产生死锁的现象。死锁的常见类型是行级锁死锁和页级锁死锁,
Oracle
数据库中一般使用行级锁。下面主要讨论行级锁的死锁现象。
当
Oracle
检测到死锁产生时,中断并回滚死锁相关语句的执行,报
ORA-00060
的错误并记录在数据库的日志文件
alertSID.log
中。同时在
user_dump_dest
下产生了一个跟踪文件,详细描述死锁的相关信息。
在日常工作中,如果发现在日志文件中记录了
ora-00060
的错误信息,则表明产生了死锁。这时需要找到对应的跟踪文件,根据跟踪文件的信息定位产生的原因。
如果查询结果表明,死锁是由于
bitmap
索引引起的,将
IND_T_PRODUCT_HIS_STATE
索引改为
normal
索引后,即可解决死锁的问题。
表
1 Oracle
的
TM
锁类型
| |||
锁模式
|
锁描述
|
解释
|
SQL
操作
|
0
|
none
|
|
|
1
|
NULL
|
空
|
Select
|
2
|
SS(Row-S)
|
行级共享锁,其他对象只能查询这些数据行
|
Select for update
、
Lock for update
、
Lock row share
|
3
|
SX(Row-X)
|
行级排它锁,在提交前不允许做
DML
操作
|
Insert
、
Update
、
Delete
、
Lock row share
|
4
|
S(Share)
|
共享锁
|
Create index
、
Lock share
|
5
|
SSX(S/Row-X)
|
共享行级排它锁
|
Lock share row exclusive
|
6
|
X(Exclusive)
|
排它锁
|
Alter table
、
Drop able
、
Drop index
、
Truncate table
、
Lock exclusive
|
表
2
数据字典视图说明
| ||
视图名
|
描述
|
主要字段说明
|
v$session
|
查询会话的信息和锁的信息。
|
sid,serial#
:表示会话信息。
program
:表示会话的应用程序信息。
row_wait_obj#
:表示等待的对象。
和
dba_objects
中的
object_id
相对应。
|
v$session_wait
|
查询等待的会话信息。
|
sid
:表示持有锁的会话信息。
Seconds_in_wait
:表示等待持续的时间信息
Event
:表示会话等待的事件。
|
v$lock
|
列出系统中的所有的锁。
|
Sid
:表示持有锁的会话信息。
Type
:表示锁的类型。值包括
TM
和
TX
等。
ID1
:表示锁的对象标识。
lmode,request
:表示会话等待的锁模式的信
息。用数字
0
-
6
表示,和表
1
相对应。
|
dba_locks
|
对
v$lock
的格式化视图。
|
Session_id
:和
v$lock
中的
Sid
对应。
Lock_type
:和
v$lock
中的
type
对应。
Lock_ID1
:
和
v$lock
中的
ID1
对应。
Mode_held,mode_requested
:和
v$lock
中
的
lmode,request
相对应。
|
v$locked_object
|
只包含
DML
的锁信息,包括回滚段和会话信息。
|
Xidusn,xidslot,xidsqn
:表示回滚段信息。和
v$transaction
相关联。
Object_id
:表示被锁对象标识。
Session_id
:表示持有锁的会话信息。
Locked_mode
:表示会话等待的锁模式的信
息,和
v$lock
中的
lmode
一致。
|