共计 3424 个字符,预计需要花费 9 分钟才能阅读完成。
这篇文章主要讲解了“ORACLE 锁的机制介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“ORACLE 锁的机制介绍”吧!
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。
在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即 X 锁)和共享锁(Share
Locks,即 S 锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。
Oracle 数据库的锁类型
根据保护的对象不同,Oracle 数据库锁可以分为以下几大类:DML 锁(data
locks,数据锁),用于保护数据的完整性;DDL 锁(dictionary
locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;内部锁和闩(internal locks and latches),保护
数据库的内部结构。
DML 锁的目的在于保证并发情况下的数据完整性。在 Oracle 数据库中,DML 锁主要包括 TM 锁和 TX 锁,其中 TM 锁称为表级锁,TX 锁称为事务锁或行级锁。
当 Oracle 执行 DML 语句时,系统自动在所要操作的表上申请 TM 类型的锁。当 TM 锁获得后,系统再自动申请 TX 类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查 TX 锁相容性时就不用再逐行检查锁标志,而只需检查 TM 锁模式的相容性即可,大大提高了系统的效率。TM 锁包括了 SS、SX、S、X
等多种模式,在数据库中用 0-6 来表示。不同的 SQL 操作产生不同类型的 TM 锁。
在数据行上只有 X 锁(排他锁)。在 Oracle 数据库中,当一个事务首次发起一个 DML 语句时就获得一个 TX 锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行
DML 语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后,TX 锁被释放,其他会话才可以加锁。
当 Oracle 数据库发生 TX 锁等待时,如果不及时处理常常会引起 Oracle 数据库挂起,或导致死锁的发生,产生 ORA-60 的错误。这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。
一、悲观封锁
锁在用户修改之前就发挥作用:
Select ..for update(nowait)
Select * from tab1 for update
用户发出这条命令之后,oracle 将会对返回集中的数据建立行级封锁,以防止其他用户的修改。
如果此时其他用户对上面返回结果集的数据进行 dml 或 ddl 操作都会返回一个错误信息或发生阻塞。
1:对返回结果集进行 update 或 delete 操作会发生阻塞。
2:对该表进行 ddl 操作将会报:Ora-00054:resource busy and acquire with nowait specified.
原因分析
此时 Oracle 已经对返回的结果集上加了排它的行级锁,所有其他对这些数据进行的修改或删除操作都必须等待这个锁的释放,产生的外在现象就是其他的操作将发生阻塞,这个操作 commit 或 rollback.
同样这个查询的事务将会对该表加表级锁,不允许对该表的任何 ddl 操作,否则将会报出 ora-00054 错误::resource busy and acquire with nowait specified.
二、乐观封锁
乐观的认为数据在 select 出来到 update 进取并提交的这段时间数据不会被更改。这里面有一种潜在的危险就是由于被选出的结果集并没有被锁定,是存在一种可能被其他用户更改的可能。因此 Oracle 仍然建议是用悲观封锁,因为这样会更安全。
阻塞:
当一个会话保持另一个会话正在请求的资源上的锁定时,就会发生阻塞。被阻塞的会话将一直挂起,直到持有锁的会话放弃锁定的资源为止。4 个常见的 dml 语句会产生阻塞
INSERT
UPDATE
DELETE
SELECT…FOR UPDATE
INSERT:
Insert 发生阻塞的唯一情况就是用户拥有一个建有主键约束的表。当 2 个的会话同时试图向表中插入相同的数据时,其中的一个会话将被阻塞,直到另外一个会话提交或会滚。一个会话提交时,另一个会话将收到主键重复的错误。回滚时,被阻塞的会话将继续执行。
UPDATE 和 DELETE 当执行 Update 和 delete 操作的数据行已经被另外的会话锁定时,将会发生阻塞,直到另一个会话提交或会滚。
Select …for update
当一个用户发出 select..for
update 的操作准备对返回的结果集进行修改时,如果结果集已经被另一个会话锁定,就是发生阻塞。需要等另一个会话结束之后才可继续执行。可以通过发出
select… for update
nowait 的语句来避免发生阻塞,如果资源已经被另一个会话锁定,则会返回以下错误:Ora-00054:resource busy and
acquire with nowait specified.
三、死锁 -deadlock
定义: 当两个用户希望持有对方的资源时就会发生死锁.
即两个用户互相等待对方释放资源时,oracle 认定为产生了死锁, 在这种情况下, 将以牺牲一个用户作为代价, 另一个用户继续执行, 牺牲的用户的事务将回滚.
例子:
1:用户 1 对 A 表进行 Update,没有提交。
2:用户 2 对 B 表进行 Update,没有提交。
此时双反不存在资源共享的问题。
3:如果用户 2 此时对 A 表作 update, 则会发生阻塞,需要等到用户一的事物结束。
4:如果此时用户 1 又对 B 表作 update,则产生死锁。此时 Oracle 会选择其中一个用户进行会滚,使另一个用户继续执行操作。
起因:
Oracle 的死锁问题实际上很少见,如果发生,基本上都是不正确的程序设计造成的,经过调整后,基本上都会避免死锁的发生。
四、DML 锁分类表
五、oracle
锁问题的解决
1. 查看哪些 session 锁:
SQL 语句:
select alter system kill session || sid || , || serial# ||
from v$session
where sid in (select sid from v$lock where block = 1);
2. 查看 session 锁.
sql 语句:
select s.sid, q.sql_text
from v$sqltext q, v$session s
where q.address = s.sql_address
and s.sid = sid
order by piece;
3. kill 锁的进程.
SQL 语句:alter system kill session sid,serial# immediate;
4. 查看谁锁了谁。
select s1.username || email = @ @ / email || s1.machine || (SID= || s1.sid ||) is blocking || s2.username || email = @ @ / email || s2.machine || (SID= || s2.sid ||) AS blocking_status
from v$lock l1, v$session s1, v$lock l2, v$session s2
where s1.sid = l1.sid
and s2.sid = l2.sid
and l1.BLOCK = 1
and l2.request 0
and l1.id1 = l2.id1
and l2.id2 = l2.id2;
注:
: 重定向输出,将文件的标准输出重新定向输出到文件,或将数据文件作为另一程序的标准输入内容。
| :UNIX 管道:将一文件的输出作为另一文件的输入.
感谢各位的阅读,以上就是“ORACLE 锁的机制介绍”的内容了,经过本文的学习后,相信大家对 ORACLE 锁的机制介绍这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!