若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性,加锁是实现数据库并发控制的一个非常重要的技术,需要的朋友可以了解下数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。
在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。
Oracle数据库的锁类型
根据保护的对象不同,Oracle数据库锁可以分为以下几大类:
1、DML锁(data locks,数据锁),用于保护数据的完整性;
2、DDL锁(dictionary locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;
3、内部锁和闩(internal locks and latches),保护 数据库的内部结构。
DML锁的目的在于保证并发情况下的数据完整性。在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。
当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。
oracle 锁机制锁问题的详细分析(处理锁定),以及死锁的解决方案
在任何多用户数据库应用中,最终必然会出现两个用户希望同时处理相同记录的情况.这种情况在逻辑上是不可能的,并且数据库必须确保其在物理上也是不可能的.事务隔离性原则要求数据库保证:在 ,这个会话无法影响另一个会话,并且后者也无法看到前者.为了实现这个要求,数据库创行话并发的数据访问,甚至在多个会话请求访问相同的记录时,数据库也必须确保这些会话排队依次进行. 借助于记录和表锁定机制,我们可以实现并发的串行化.oracle数据库中的锁定是完全自动的.一般而言,只有在试图结合软件与自动锁定机制是或者编程人员编写的代码太糟糕时才会引发某些问题
oracle数据库中锁定的标准级别保证了最大可能的并发级别也就是说,如果某个会话正在更新一条记录,那么只有这条记录会被锁定.此外,锁定这条记录是为了防止其他会话对其进行更新,其他会话可以随时执行读取操作.只有在使用commit或rollback命令结束事务之后,锁定才会被解除.这种锁定是一个”排他锁”:在指定记录上请求排他锁的第一个会话会得到这个锁定,其他请求对该记录进行写访问的会话则必须等待.虽然这条记录已通过锁定会话进行了更新,但是对其进行读访问你是被允许的(而且经常会出现这种情况),并且这些读操作会涉及撤销数据的使用,从而确保都会回并不会看到任何未被提交的变化 。
对于一条记录或一个完整表上的一个排他锁来说,每次只能有一个会话可以获得这个排他锁,不过许多会话可以同时获得相同对象上的”共享锁”.在一条记录上设置共享锁毫无意义,其原因在于锁定一条记录的唯一目的就是不允许其他会话更改它.共享锁被置于整个表上,同时许多会话可以获得同一个表上的共享锁.在一个表上放置共享锁的目的是为了防止另一个会话获得这个表上的排他锁(在已存在共享锁的情况下无法再获得排他锁).在表上防止排他锁是需要执行DDL语句.如果其他任何会话已经在一个表上放置了共享锁,那么我们就无法执行修改某个对象的语句(例如删除这个表的某一列).
为了在记录上执行DML语句,当前会话必须获取待更新记录上的排他锁以及包含这些记录的表上的共享锁.如果另一个会话已经获取了待更新记录上的排他锁,那么当前会话将被挂起,直至使用COMMIT或ROLLBACK命令解除这些锁定,如果另一个会话已经获取了待修改记录的表上的共享锁以及其他记录上的排他锁,那么就不存在任何问题.一个表上的排他锁会锁定这个表,但是,如果不需要执行DDL语句,那么我们就可以不锁定整个表的默认锁定机制.
提示:
只有在特别请求并且编程人员具有充分理由的情况下,才可以要求在整个表上放置排他锁.
1、DML锁与DDL锁
所有DML语句都至少需要两种锁定:受影响记录上的排他锁,以及包含受影响记录的表上的共享锁.排他锁能够防止其他会话干预指定的记录,而共享锁则能够阻止其他会话使用DDL语句修改表的定义.这两种锁定会被自动请求.如果某条DML语句在指定记录上无法获取所需的排他锁,那么这条语句会被挂起直至获得所需的排他锁.
执行DDL命令需要使用所涉及对象上的排他锁.只有在针对指定表的所有DML事务结束,并且记录上的排他锁以及表上的共享锁都被解除之后,我们才可以获得执行DDL命令所需的排他锁,任何DDL语句所需的排他锁都是被自动请求的.但是,如果无法获取所需的排他锁(通常是因为其他会话已经获得用于DML语句的共享锁),那么DDL语句就会由于错误立即终止.
为了更好的说明锁机制,我们还是看一个实际的例子吧:
1.使用SQL*PLUS,作为用户SYSTEM连接数据库.
2.创建一个表,并且在这个表中插入一条记录.
create table t1(c1 number);
insert into t1 values(1);
commit;
3.再次使用SQL*PLUS并作为用户SYSTEM进行连接,从而打开另一个会话.
4.在第一个会话中执行一个DML命令,这个命令会在插入的记录上放置一个排他锁,同时还会在创建的表上放置一个共享锁.
update t1 set c1=2 where c1=1;
5.如下所示,在第二个会话中执行第一条针对新建表的DDL语句.
alter table t1 add(c2 date);
出现以下错误
error at line 1:
ora-00054:resource busy and acquire with nowait specified
因为DDL语句需要表上的排他锁,而这与DML语句已在表上放置了共享锁相冲突,所以试图在表中插入一个列的这条DDL语句会失败.需要注意的是:在类似情况下,DML语句会等待并不断进行尝试,直至获得其所需的锁(换句话说就是挂起);而DDL语句则会由于错误立即终止.
6.在第一个会话中,提交当前事务
commit;
7.在第二个会话中,重新执行步骤5.此时,因为不纯在与DDL排他锁相冲突的DML共享锁,因此DDL语句将成功的执行.
8.在第一个会话中 ,锁定整个表.
lock table t1 in exclusive mode;
9.在第二个会话中,插入一条记录.此时,这个会话将被挂起.
insert into t1 values (1,sysdate);
10.在第一个会话中,通过执行COMMIT命令解除整个表上的锁定.需要注意的是,ROLLBACK命令也可以实现相同的目的.
commit;
11.第二个会话会释放并且现在会完成插入操作.随后,执行COMMIT命令,终止当前事务斌且解除该记录上的排他锁.
2、关于如何解决死锁的问题.
最近遇到这样一个问题,操作一个表,发现被人锁定了,于是查询谁锁定的表,发现多人锁定,安全起见,不能全部kill,于是用一下语句判定,谁锁定,谁等待。
SELECT /*+ rule */
lpad(' ', decode(l.xidusn, 0, 3, 0)) || l.oracle_username User_name,
o.owner,
o.object_name,
o.object_type,
s.sid,
s.serial#
FROM v$locked_object l, dba_objects o, v$session s
WHERE l.object_id = o.object_id
AND l.session_id = s.sid
ORDER BY o.object_id, xidusn DESC;
如果发生了锁等待,我们可能更想知道是谁锁了表而引起谁的等待
以上的语句可以查询到谁锁了表,而谁在等待。 以上查询结果是一个树状结构,如果有子节点,则表示有等待发生。 如果想知道锁用了哪个回滚段,还可以关联到V$rollname,其中xidusn就是回滚段的USN
找出谁锁定的记录,kill掉就行了。 --ALTER SYSTEM KILL SESSION '查出的SID,查出的SERIAL#';
alter system kill session '11,973' ;
--以下几个为相关表 SELECT * FROM v$lock; SELECT * FROM v$sqlarea; SELECT * FROM v$session; SELECT * FROM v$process ; SELECT * FROM v$locked_object; SELECT * FROM all_objects; SELECT * FROM v$session_wait; --1.查出锁定object的session的信息以及被锁定的object名
SELECT l.session_id sid, s.serial#, l.locked_mode,l.oracle_username,
l.os_user_name,s.machine, s.terminal, o.object_name, s.logon_time
FROM v$locked_object l, all_objects o, v$session s
WHERE l.object_id = o.object_id
AND l.session_id = s.sid
ORDER BY sid, s.serial# ;
--2.查出锁定表的session的sid, serial#,os_user_name, machine name, terminal和执行的语句
--比上面那段多出sql_text和action
SELECT l.session_id sid, s.serial#, l.locked_mode, l.oracle_username, s.user#,
l.os_user_name,s.machine, s.terminal,a.sql_text, a.action
FROM v$sqlarea a,v$session s, v$locked_object l
WHERE l.session_id = s.sid
AND s.prev_sql_addr = a.address
ORDER BY sid, s.serial#;
--3.查出锁定表的sid, serial#,os_user_name, machine_name, terminal,锁的type,mode
SELECT s.sid, s.serial#, s.username, s.schemaname, s.osuser, s.process, s.machine,
s.terminal, s.logon_time, l.type
FROM v$session s, v$lock l
WHERE s.sid = l.sid
AND s.username IS NOT NULL
ORDER BY sid;
行级锁
行级锁只对用户正在访问的行进行锁定。如果该用户正在修改某行,那么其他用户就可以更新同一表中该行之外的数据。例如:如果用户1正在更新Jobs 表中的第一行,则用户2可以同时修改该表中的第二行。也就是说除了该表中的第一行,其他用户可以修改任意行,但是第一行的数据其他用户只能select。
行级锁是一种排他锁,防止其他事务修改此行,但是不会阻止读取此行的操作。在使用INSERT、UPDATE、DELETE 和SELECT„FOR UPDATE 等 语句时,Oracle 会自动应用行级锁锁定。SELECT...FOR UPDATE 语句允许用户每次选择多行记录进行更新,这些记录会被锁定,且只能由发起查询的用户进行编辑。只有在回滚或提交事务之后,锁定才会释放,其他用户才可以编辑这些记录。 SELECT...FOR UPDATE 语句的语法如下:
SELECT ... FOR UPDATE [OF column_list][WAIT n|NOWAIT];
其中:
OF 子句用于指定即将更新的列,即锁定行上的特定列。
WAIT 子句指定等待其他用户释放锁的秒数,防止无限期的等待。 “使用FOR UPDATE WAIT”子句的优点如下:
⒈防止无限期地等待被锁定的行;
⒉允许应用程序中对锁的等待时间进行更多的控制。
⒊对于交互式应用程序非常有用,因为这些用户不能等待不确定 举例:比如一个用户在SQL PLUS下输入这条语句:SQL>SELECT * FROM order_master WHERE vencode='V002' FOR UPDATE;
此时再开启一个SQL PLUS,以相同的用户登陆,执行下面的命令。
SQL<> SELECT * FROM order_master WHERE vencode='V02' FOR UPDATE WAIT 5; 由于要更新的行已经被锁定,上述命令在等待5秒钟之后返回,并给出如下的错误信息:
ERROR 位于第1行;
ORA-30006;资源已被占用;执行操作时出现WAIT超时。
PS:再开启的SQL PLUS 是以相同用户登陆的,用其他用户登陆更是不可能。
表级锁
表级锁被锁定的表,暂时放在内存中,不提交不进去数据库,也就是说,多个用户在同一时间,同时修改同一个表的同一行时,同时点提交,但是还是按随机的先后被提交进数据库,而不是同时被提交,而是先随机存储后,被再次提交的覆盖。
表级锁将保护表数据,在事务处理过程中,表级锁会限制对整个表的访问。可以使用LOCK TABLE 语句显示地锁定表。表级锁用来限制对表执行添加、更新和删除等修改操作。锁定表的语法如下:
LOCK TABLE <table_name> IN <lock_mode> MODE [NOWAIT]; 其中:
lock_mode 是锁定的模式。
NOWAIT 关键字用于防止无限期的等待其他用户释放锁。 表级锁的模式包括以下内容:
行共享 (ROW SHARE, RS): 允许其他用户访问和锁定该表,但是禁止排他锁定整个表。行共享锁锁定后,在同一时刻,不同用户可以对同一个表中的被行共享锁锁定后的该行,具备增、删、改、查的功能。
行排他(ROW EXCLUSIVE, RX):与行共享模式相同,同时禁止其他用户在此表上使用共享锁。使用SELECT...FOR UPDATE 语句会在表上自动应用排他锁。被行排他后,其他用户不能同时修改该行,但是可以插入行,可以查询该行,其他用户也不能再在该表上对此行进行排他。
共 享(SHARE, S):共享锁将锁定表,仅允许其他用户查询表中的行,但不允许插入、更新或删除行。多个用户可以同时在同一个表中放置共享锁,即允许资源共享,因此得名 “共享锁”。例如,如果用户每天都需要在结帐时更新日销售表,则可以在更改该表时使用共享锁以确保数据的一致性。也就是说该表只能查,其他用户想修改表中行的数据,只需要对该表进行共享锁。
共享行排他(SHARE ROW EXCLUSIVE , SPX):执行比共享表更多的限制。防止其他事务在表上应用共享锁、共享行排他锁以及排他锁。共享行排他是除了该行以外的其他行也不能增、删、改。只能在此表中加低级表。要是想在该表中更改其他行的数据,就只有其他用户对该行进行共享行排他锁,也仅仅只能修改被这个用户锁定的行,而其他的行也修改不了。
排他(EXCLUSIVE,E):对表执行最大限制。除了允许其他用户查询该表的记录,排他锁防止其他事务对表做任何更改或在表上应用任何类型的锁。这个锁应该叫锁中之王,他锁住了的话,其他用户就只有查询的功能了,就别想在该表中干别的事了。
BTW:在能加很多锁的表中,如果第一个用户对该表锁定时,没有使用“NOWAIT”语句,是需要第一个用户对该表COMMIT或ROLLBACK 命令释放锁定后,其他用户才能对该表进行锁定。如果其他用户违反了该条,就会无期限的等待。。。。 SQL> LOCK TABLE order_mater IN SHARE MODE; 而使用下面的语句就可以很少的预防这种情况的存在: SQL> LOCK TBALE order_mater IN SHARE MODE NOWAIT;
下面对行级锁和表级锁来个总结,行级锁锁定的只是行,而表级锁是对表的锁定,但是在表级锁锁定表后,还可以在该表中使用行级锁。
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一致。
select * from v$db_object_cache where owner='OCP' and locks<>0
select * from v$access a where a.object=upper('对象')
select * from v$session where sid=3279
alter system kill session '3279,48861'
select * from v$process where addr='9CE3E048'
相关推荐
Oracle数据库通过内部机制自动管理锁的获取和释放,但在高并发环境下,了解锁的行为和避免死锁对于优化应用程序性能至关重要。 #### 结论 理解Oracle数据库中的锁机制对于设计高性能、高可用性的应用系统至关重要...
### Oracle的锁表与解锁:深入理解与操作 在Oracle数据库管理中,锁是一个至关重要的概念,用于控制多个用户或进程对数据的并发访问,确保数据的一致性和完整性。锁可以分为行级锁(Row Level Lock)和表级锁...
Oracle锁是数据库并发控制的关键机制,它确保了在多用户环境下数据的一致性和完整性。当多个用户并发地访问和操作数据库中的数据时,...了解并掌握Oracle锁的原理和应用,对于优化数据库性能和解决并发问题至关重要。
本文深入探讨了Oracle数据库的锁机制,主要关注锁的种类、异常情况以及解决策略。 Oracle数据库中的锁主要分为两大类型:排它锁(X锁)和共享锁(S锁)。X锁不允许其他事务读取或修改被锁定的数据,而S锁允许其他...
在深入讨论Oracle解锁和死锁之前,我们首先需要了解Oracle数据库中的锁机制。 1. **共享锁(S)**:允许多个用户读取行,但不允许修改。 2. **排他锁(X)**:允许单个用户修改行,其他用户只能等待。 3. **共享更新锁...
本文将深入探讨Oracle数据库中的锁类型,尤其是DML锁,以及它们是如何在并发环境中维护数据完整性的。 #### 二、Oracle数据库锁类型概览 Oracle数据库的锁类型大致可以分为三类:DML锁、DDL锁和内部锁与闩锁。DML...
理解并熟练掌握Oracle数据库中的锁机制对于数据库管理员来说至关重要。它不仅能帮助解决并发控制问题,还能提高数据库的整体性能。当遇到由于长时间运行的事务导致的锁等待时,能够快速识别并解锁相关会话,对于保持...
深入理解Oracle RAC 12c,需要掌握以下几个核心知识点: 1. 集群架构:了解Oracle RAC集群的架构是基础。Oracle RAC使用集群件(Clusterware)来协调集群节点间的关系,使用全局资源管理来控制数据访问和维护数据...
总结,Oracle锁机制是数据库并发控制的核心,理解并熟练掌握锁的使用和管理对于优化数据库性能、避免并发问题至关重要。通过使用适当的工具和技巧,我们可以有效地监控和解决锁相关问题,从而提高系统的稳定性和响应...
了解锁的兼容性对于避免死锁至关重要。 #### 六、总结 Oracle数据库中的锁机制是实现数据一致性和并发控制的关键。通过合理选择不同类型的锁,可以有效提高系统的并发性能和数据安全性。开发者在设计应用程序时应...
Oracle数据库是全球广泛使用的大型企业级关系型数据库管理系统,它提供了高效、稳定的数据存储和管理解决方案。...读者可以通过这个文件深入理解Oracle数据库的各个方面,提升数据库管理和开发技能。
在Oracle数据库管理中,...通过深入学习Oracle的锁机制和监控工具,数据库管理员可以更有效地管理锁,提高系统的稳定性和性能。同时,定期审查和调整数据库的锁策略,能够帮助企业避免因锁问题导致的生产环境故障。
因此,理解和掌握Oracle数据库锁机制是非常重要的。只有通过深入了解锁机制的工作原理和使用方法,才能避免锁表问题的出现,并提高数据库应用的性能。 Oracle数据库锁机制的分类: 1.null空锁 2.Row-S共享锁 3....
Oracle数据库系统中,锁和表分区是两...了解并熟练掌握锁和表分区的概念及其应用,对于优化Oracle数据库的性能和确保数据一致性至关重要。在实际操作中,根据业务需求合理使用这些机制,能够显著提升数据库的运行效率。
在Oracle数据库管理与优化领域,深入理解逻辑读写机制对于提升数据库性能至关重要。本文将围绕“Oracle逻辑读写深入分析”这一主题,结合描述及部分示例内容,全面解析Oracle数据库中逻辑读的概念、分类及其统计方法...