《Oracle数据库管理与维护实战》——2.9 锁

简介:

本节书摘来自异步社区出版社《Oracle数据库管理与维护实战》一书中的第2章,第2.9节,作者: 何伟娜 , 常建功,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.9 锁

Oracle数据库管理与维护实战
为阻止并发事务对数据的一致性破坏,Oracle在系统中锁定不同的数据库资源。数据库锁防止影响另外一些人使用数据库。

锁可分为自动锁和显示锁,当进行数据库操作时,缺省情况下,一个事务会自动获得所有数据库资源所需要的锁。例如,假设开始一项新事务,要更新一个客户的地址,在更新需要的记录行之前,Oracle进行检查,确定有没有其他事务锁定这行记录。如果有其他事务锁定这条记录,Oracle则等待,直到其他事务释放了该记录的锁;如果没有其他记录锁定该记录,则自动为该记录上锁,到该事务提交或回滚这个事务时才释放该锁。

Oracle的缺省锁机制对大多数应用而言已经足够。但也有一些情况下,事务需要显示的锁定数据库操作需要用到的数据。例如,如果要对表中大多数记录行进行更新,而表又很大,那么对整个表锁定比对一行记录锁定更有效。而且,对表进行锁定可以保证对表更新一次完成,中间不需要有锁等待。

Oracle的锁根据对象的级别可以分为表级锁、行级锁等。

2.9.1 锁级别

通常,Oracle有两种锁锁定数据资源:共享锁和排他锁。图2-30显示了共享锁和排他锁的使用。

1.共享锁
数据库资源的共享锁给予一个事务对特定锁资源的共享访问,同时另一事务也可以获得同一资源的共享锁。例如图2-30中,两个事务都具有同一表的共享锁,这就允许不同事务在同一时间更新同一表中不同的记录行。

共享锁允许事务高度并发性,又称共享锁为写锁。然而,事务不能总是为所有类型的资源与操作获得共享锁。例如,图2-30中虽然每个事务都可以同时获得同一个表的共享锁,但该事务对它所更新的行获得排他锁,使其他事务不能更新相同的行,以保护数据安全。

image

2.排他锁
排他锁不同于共享锁的是,排他锁在锁定了某资源后,不允许其他事务获取该资源,例如图2-30中,事务1获得第1行与第2行的排他锁后,另一事务2不可以在事务1提交或回滚前获得相同行的共享锁或排他锁。

排他锁显然比共享锁更严格,排他锁又叫写锁,并发性程度更低。因而,Oracle不自动获取数据库资源的排他锁,除非个别需要使用,如需阻止其他并发事件的破坏性交互。

2.9.2 DML锁

当事务进行DML操作(INSERT、UPDATE、DELETE)时,Oracle自动获得数据库中表与索引的锁。为提高并发性并且防止破坏数据,在DML执行过程中,Oracle可以同时获得行级锁和表级锁。

1.行级锁
当事务插入、更新、删除行时,该事务自动获得该特定行的排他锁。在行级锁锁数据行期间,其他事务不可以对该行更新、删除或修改。举一个例子,当事务中含有以下语句时,Oracle将自动锁定CUSTOMERS表中的行。

SQL>UPDATE sales.customers
SET….
WHERE last_name=’Ellison’ AND first_name = ‘Lawrence’;

如果其他事务在以上事务提交或回滚之前,想更新CUSTOMERS表中的Larry Ellison的记录,Oracle发现该行已被锁定,就会让后来的事务处于等待状态。

在更新记录之前,事务可以使用SELECT…FOR UPDATE语句先行锁定要更新的记录。例如,以下语句将所有的zipcode为95000的记录锁定。

SQL>SELECT * FROM sales.customers
WHERE zipcode=95000
FOR UPDATE
NOWAIT;

当执行以上语句时,如果不能锁定所有满足条件的记录,Oracle会返回控制。如果没有NOWAIT关键字,SELECT…FOR UPDATE语句就会一直处于等待状态,直到获得所有的记录行。

2.表级锁
当事务获得一条记录上的锁时,事务自动获得含该行的表的锁。当事务更新表中一行或多行时,可以使用表级锁,以防止其他DDL操作破坏表更新。

例如,要更新CUSTOMERS表中的一行时,事务获得更新行的排他锁,同时也获得CUSTOMERS的表级锁,将表锁定以防止其他事务修改或删除表。

事务可以在事务进行过程中获得表上的共享锁或排他锁。当事务执行一条基本的DML操作,如INSERT、UPDATE或DELETE时,事务通常给共享锁,但也可以使用排他锁。这时需要用LOCK TABLE在表中显示的指定。例如以下语句就用LOCK TABLE语句获得CUSTOMERS的排他锁。

SQL>LOCK TABLE customers
IN EXCLUSIVE MODE
NOWAIT;

如果Oracle不能立即获得所需要的表级锁,NOWAIT会将控制返回,告知不能立即获得表级锁。如果没有NOWAIT,事务将一直处于等待状态,直到获得表级锁。

Oracle实际上还有几种不同级别的表级锁,这里不再详细介绍,包括行共享、行排他、共享行排他以及排他级别,每个表级锁都比前一个严格。

3.死锁
死锁是Oracle系统应当尽量避免的情形,它是因为资源共享而引起的。产生的原因是两个或多个事务等待需要的某个资源,而又不释放现有的资源。图2-31示意的是死锁发生的 过程。
image
图2-31中,事务1在表的Row #1有一个排他锁并等待事务2释放#2的排他锁,但同时#2具有#1需要的排他锁并且在等待#1释放锁。因而两个事务一直僵持,如果没有外来干预,两个事务将永远僵持下去。

死锁的发生是因为不合理的设计。例如,以下两个事务,每个事务含有对PARTS表的多个更新,结果处于死锁状态,因为它们各自锁定了另一个事务需要的行,如表2-7所示。
image

上述事务的设计容易引起死锁,当事务1和事务2同时执行时,事务1需要锁定id=2的行,而事务2将id=2的行已先行锁定,事务1只能等待事务2释放锁;而事务2又在等待事务1的锁,两个事务进入死循环。我们可以对表2-7加以改进,避免死锁,如表2-8所示。

image

上述表对事务设计进行了改进,在每一个UPDATE语句后面都加COMMIT语句,以及时提交并释放行级锁,这样避免了死锁。Oracle在运行过程中会自动检测死锁,并回滚产生死锁的语句以消除死锁。

2.9.3 DDL锁

前面解释了Oracle自动用于保护DML操作的锁。但在使用CREATE、ALTER与DROP语句时,Oracle也会自动锁定数据。每个DDL操作在它自己的事务中完成,只有在进行DDL操作期间才会使用DDL锁。

1.排他DDL锁
创建、修改或删除数据库对象的DDL语句需要对目标对象使用排他锁。例如,当执行一个ALTER TABLE语句时,要给表増加完整性约束,事务会自动给表加排他锁。在ALTER语句前,其他用户不能修改或删除该表。

2.共享DDL锁
一些DDL语句可以获得数据库对象的共享DDL锁,在数据库对象之间建立相互依赖关系的DDL语句通常需要共享DDL锁。例如,创建包时,包的过程与函数引用许多不同的数据库表:当创建这个包时,事务获得这个包上的排他DDL锁,同时获得所引用锁的共享DDL锁,这个共享DDL锁阻止另一个事务获得所引用表的排他锁,而且防止Oracle在完成包编译前修改或删除包所引用的表。和DML共享锁一样,DDL共享锁不妨碍另一个事务获得同一表的共享DDL锁。

相关文章
|
8月前
|
SQL 存储 关系型数据库
数据库的行级锁与表锁?
表锁: 不会出现死锁,发生锁的冲突几率高,并发性低。 存储引擎在进行SQL数据读写请求前,会对涉及到的表进行加锁。 其中锁分为共享读锁和独占写锁:读锁会阻塞写,写锁会阻塞读和写。 行级锁: 会出现死锁,发生锁的冲突几率低,并发性高。 InnoDB引擎支持行锁,与Oracle不同,MySQL的行锁是通过索引加载的,也就是说,行锁是加在索引响应的行上的,要是对应的SQL语句没有走索引,则会全表扫描,行锁则无法实现,取而代之的是表锁,此时其它事务无法对当前表进行更新或插入操作。 行级锁注意事项: 行级锁必须有索引才能实现,否则会自动锁全表,那就不是行锁了。 两个事务不能锁同一个索引。 in
|
9月前
|
关系型数据库 MySQL 网络安全
如何排查和解决PHP连接数据库MYSQL失败写锁的问题
通过本文的介绍,您可以系统地了解如何排查和解决PHP连接MySQL数据库失败及写锁问题。通过检查配置、确保服务启动、调整防火墙设置和用户权限,以及识别和解决长时间运行的事务和死锁问题,可以有效地保障应用的稳定运行。
349 25
|
SQL 关系型数据库 MySQL
|
运维 Oracle 容灾
Oracle dataguard 容灾技术实战(笔记),教你一种更清晰的Linux运维架构
Oracle dataguard 容灾技术实战(笔记),教你一种更清晰的Linux运维架构
|
11月前
|
SQL 存储 关系型数据库
数据库的行级锁与表锁?
表锁:存储引擎在SQL数据读写请求前对涉及的表加锁,分共享读锁和独占写锁,读锁阻塞写,写锁阻塞读写,易发锁冲突,并发性低。行级锁:InnoDB支持,通过索引加锁,提高并发性,但可能引起死锁,需注意索引使用,适用于避免不可重复读场景。
172 21
|
监控 数据库 索引
避免锁等待超时对数据库性能的影响
【10月更文挑战第16天】避免锁等待超时对数据库性能的影响需要综合考虑多个方面,通过不断地优化和改进,来提高数据库的并发处理能力和稳定性。
201 1
|
存储 关系型数据库 MySQL
MySQL数据库锁:共享锁和独占锁
本文详细介绍了`InnoDB`存储引擎中的两种行级别锁:共享锁(S锁)与排他锁(X锁)。通过具体示例展示了这两种锁的工作机制及其在`InnoDB`与`MyISAM`引擎中的表现差异。文章还提供了锁的兼容性矩阵,帮助读者更好地理解锁之间的互斥关系。最后总结了两种锁的特点及适用场景。适合希望深入了解`MySQL`并发控制机制的读者阅读。
446 1
|
SQL 存储 关系型数据库
"MySQL增列必锁表?揭秘InnoDB在线DDL,让你的数据库操作飞一般,性能无忧!"
【8月更文挑战第11天】在数据库领域,MySQL凭借其稳定高效的表现深受开发者喜爱。对于是否会在给数据表添加列时锁表的问题,MySQL的行为受版本、存储引擎等因素影响。从5.6版起,InnoDB支持在线DDL,可在改动表结构时保持表的可访问性,避免长时间锁表。而MyISAM等则需锁表完成操作。例如,在使用InnoDB的表上运行`ALTER TABLE users ADD COLUMN email VARCHAR(255);`时,通常不会完全锁表。虽然在线DDL提高了灵活性,但复杂操作或大表变更仍可能暂时影响性能。因此,进行结构变更前应评估其影响并择机执行。
258 6
|
SQL 数据库
无法获得数据库 'model' 上的排他锁。请稍后重试该操作
无法获得数据库 'model' 上的排他锁。请稍后重试该操作
316 0
|
SQL Oracle 前端开发
Oracle效率分析,Github标星25K+超火的前端实战项目
Oracle效率分析,Github标星25K+超火的前端实战项目

热门文章

最新文章

推荐镜像

更多