一、锁的认识
加锁是实现数据库并发控制的一个非常重要的技术。Oracle 利用其锁机制来实现事务间的数据并发访问,以确保数据并发性、数据完整性和语句级读取一致性。
二、锁的分类
1、按系统划分,分为显式锁和隐式锁
(1)显式锁(Manual Data Locking)
Oracle数据库总是自动执行锁定,如果应用程序在事务期间需要数据保存一致,不反映其他事务的更改,可以通过显示锁定的方式重写默认锁定来实现。可以使用以下方式实现显式锁定:
- SET TRANSACTION ISOLATION LEVEL
通过设置事务隔离级别来实现显式锁,具体语法如下
SET TRANSACTION [ READ ONLY | READ WRITE ]
[ ISOLATION LEVEL [ SERIALIZE | READ COMMITED ]
[ USE ROLLBACK SEGMENT 'segment_name' ]
[ NAME 'transaction_name' ];
例如设置名字为lu_example的事务隔离级别为读写
SET TRANSACTION READ WRITE NAME 'lu_example';
- LOCK TABLE
--当表被锁后,所有的行都被锁定,其他用户不能修改表
LOCK TABLE employees, departments IN EXCLUSIVE MODE NOWAIT;
LOCK TABLE departments IN SHARE MODE;
--行锁定允许并发访问被锁定的表,但是不允许锁定整个表
LOCK TABLE employees IN ROW SHARE MODE NOWAIT;
LOCK TABLE employees IN ROW EXCLUSIVE MODE NOWAIT;
LOCK TABLE employees IN SHARE UPDATE MODE;
LOCK TABLE employees IN SHARE ROW EXCLUSIVE MODE;
- SELECT … FOR UPDATE
通过锁定查询返回的行,控制表中这些行的并发访问。当其他事务试图访问这些行,必须等待锁定这些行的事务完成。
注:显式锁都是表级锁
(2)隐式锁(Automatic Locks)
当进行某项数据库操作时,系统会自动为该数据库操作获得锁。根据操作不同可分为以下三种类型的锁,它们控制不同对象的并发访问。
- DML 锁
- DDL 锁
- systemlocks
2、按保护对象划分,分为数据锁(DML lock)、字典锁(DDL lock)和System Locks
(1)DML 锁
DML锁,又称为数据锁,目的是在多个用户并发访问时保证数据的一致性。Oracle 19c官方文档描述多个客户从网上书店购买最后一本书的例子介绍了DML锁,可点击标题超链接查看Oracle官方文档内容。
当执行DML操作时,系统自动获得行级或表级的锁。因此,从封锁粒度来看,数据锁又可分为行级锁(TX锁)和表级锁(TM锁)。
(2)DDL 锁
DDL锁,又称为数据字典锁,目的是保护数据库对象的定义,例如用户创建一个存储过程,为避免存储过程在执行过程中对象被删除或更改,系统会自动为存储过程中使用到的对象获得DDL锁。在进行DDL操作时,整个schema对象会被锁定,用户不能显式地获得DDL锁。DDL锁分为以下三种类型:
- 排他DDL锁(Exclusive DDL Locks)
该锁会阻断其他会话获得DDL锁或DML锁。例如,当正在进行alter table 操作时,是不允许删除表的。 - 共享DDL锁(Share DDL Locks)
该锁可以阻断冲突的DDL操作,防止对象在被引用时遭到破坏性干扰。例如创建一个包,在包执行期间会为包中引用的表对象获得共享锁,避免其他事务执行冲突性干扰,其他事务不能对这些表对象加排他DDL锁,但同时加上共享DDL锁引用这些表对象。 - 可破坏的解析锁(Breakable Parse Locks)
在SQL语句的解析阶段,可在共享池中获得解析锁。每个schema对象会为其持有的SQL语句或PL/SQL程序块获得解析锁,以便在数据库对象被修改或删除时,其持有的SQL块可以失效。在下次引用该SQL块时,系统需要重新编译。解析锁是可破坏的,允许任何DDL操作。
(3)systemlocks
包括internal locks、latches、mutex、pin,保护内部数据库结构
3、按封锁粒度划分,分为行级锁(TX锁)和表级锁(TM锁)
(1)行级锁(TX锁)
行级锁,又称为TX锁,当执行INSERT, UPDATE, DELETE, MERGE, and SELECT … FOR UPDATE语句时,事务会为每一行获得TX锁,直到事务提交或回滚后锁才被释放。
(2)表级锁(TM锁)
当事务获取行的TX锁时,系统还自动获取该行所在表的TM锁,防止冲突的DDL操作覆盖当前事务中的数据更改,也可以使用lock table语句显式获取表锁。表锁包括以下五种类型:
- 行共享锁(RS)
- 行排他锁(RX)
- 共享表锁(S)
- 共享行独占表锁(SRX)
- 排他表锁(X)
4、按锁级别划分,分为排他锁(X锁)和共享锁(S锁)
(1)排他锁(X锁)
排他锁,又称为写锁,如果一个事务给某个数据加了排它锁,其它事务就不能对它再加任何锁,直到事务提交或回滚,排它锁释放。
(2)共享锁(S锁)
共享锁,又称为读锁,加了共享锁的数据,只能共享读,不能再加排它锁进行写的操作。
三、死锁
1、死锁的产生
死锁是两个或多个事务在执行过程中,因为资源争用而互相等待的现象。死锁问题,oracle默认会解决,这里的锁问题主要指的是由于数据库锁机制而导致的阻塞现象,或者由于不正当操作或者程序中的bug,当程序卡住造成的锁表现象,或者是事物进行回滚或者提交时发生了异常,没有回滚成功或者提交成功,导致锁表。
2、查询锁表
查找到数据库中所有的DML语句产生的锁
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;
3、处理锁表
杀掉进程 sid,serial#
alter system kill session'110,11555';
参考文章:
https://docs.oracle.com/search/?q=lock&category=database&product=en%2Fdatabase%2Foracle%2Foracle-database%2F19
https://cloud.tencent.com/developer/article/1451003
https://www.cnblogs.com/leohahah/p/7039907.html
https://www.w3cschool.cn/oraclejc/oraclejc-1xpv2r2k.html
https://blog.youkuaiyun.com/bobozhanghb/article/details/17298489