oracle记录被锁

本文详细介绍了数据库并发控制的重要技术——加锁机制,特别是Oracle数据库中的锁类型及其应用。主要内容包括数据库作为多用户共享资源的特点、锁的基本概念、锁的分类(如DML锁、DDL锁、内部锁等)、锁的模式(如SS、SX、S、X等)以及如何通过SQL语句(如FOR UPDATE、NOWAIT等)控制锁。此外,文章还提供了诊断数据库锁、找出和杀死占用锁的会话的方法,旨在帮助开发者理解和解决并发操作中的锁冲突问题。

今天上班有家伙说记录被锁!!其实原因就是多个用户直接通过pl/sql对数据库数据进行操作导致。

 

 数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。

加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。

根据保护的对象不同,Oracle数据库锁可以分为以下几大类:
DML锁(data locks,数据锁),用于保护数据的完整性;
DDL锁(dictionary locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;
内部锁和闩(internal locks and latches),保护数据库的内部结构,应用于SGA;

在我们实际应用开发中涉及较多的是DML锁,其他两种的话DBA会更加关心点;
DML锁的目的在于保证并发情况下的数据完整性,主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。

当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。TM锁包括了SS、SX、S、X等多种模式,在数据库中用0-6来表示。不同的SQL操作产生不同类型的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 TABLE、DROP INDEX、
TRUNCATE TABLE、LOCK EXCLUSIVE

在数据行上只有X锁(排他锁)。在 Oracle数据库中,当一个事务首次发起一个DML语句时就获得一个TX锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行 DML语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后,TX锁被释放,其他会话才可以加锁。

在大概了解oracle的锁机制之后,我们来解决几个基本的问题:
1.UPDATE/DELETE操作会将RS锁定,直至操作被COMMIT或者ROLLBACK;
若操作未COMMIT之前其他session对同样的RS做变更操作,则操作会被hold,直至前session的UPDATE/DELETE操作被COMMIT;

2.session内外SELECT的RS范围
前提:INSERT、UPDATE操作未COMMIT之前进行SELECT;
若在同一session内,SELECT出来的RS会包括之前INSERT、UPDATE影响的记录;
若不在同一session内,SELECT出来的RS不会包括未被COMMIT的记录;

3.SELECT.... FOR UPDATE [OF cols] [NOWAIT/WAIT] [SKIP LOCKED]
OF cols:只锁定指定字段所在表的RS,而没有指定的表则不会锁定,只会在多表联合查询时出现;
NOWAIT:语句不会hold,而是直接返回错误ORA-00054: resource busy and acquire with NOWAIT specified;
WAIT N:语句被hold N秒,之后返回错误ORA-30006: resource busy; acquire with WAIT timeout expired;
SKIP LOCKED:不提示错误,而是直接返回no rows selected;
以上几个选项可以联合使用的,比较推荐的有:
SELECT.... FOR UPDATE NOWAIT:对同一RS执行该SQL时,直接返回错误;
SELECT.... FOR UPDATE NOWAIT SKIP LOCKED:对同一RS执行该SQL时,直接返回空行;
PS:当RS被LOCK住之后,只对同样请求LOCK的语句有效,对无需LOCK的SELECT语句并没有任何影响;

1、查看数据库锁,诊断锁的来源及类型:

Sql代码  收藏代码
  1. select object_id,session_id,locked_mode from v$locked_object;   

 或者用以下命令:

Sql代码  收藏代码
  1. select b.owner,b.object_name,l.session_id,l.locked_mode  
  2. from v$locked_object l, dba_objects b  
  3. where b.object_id=l.object_id  
  4.   
  5. SELECT lpad(' ',decode(l.xidusn ,0,3,0))||l.oracle_username User_name,  
  6. o.owner,o.object_name,o.object_type,s.sid,s.serial#  
  7. FROM v$locked_object l,dba_objects o,v$session s  
  8. WHERE l.object_id=o.object_id  
  9. AND l.session_id=s.sid  
  10. ORDER BY o.object_id,xidusn DESC   

 2、找出数据库的serial#,以备杀死:

Sql代码  收藏代码
  1. select t2.username,t2.sid,t2.serial#,t2.logon_time  
  2. from v$locked_object t1,v$session t2  
  3. where t1.session_id=t2.sid order by t2.logon_time;   

 3、杀死该session

Sql代码  收藏代码
  1. alter system kill session 'sid,serial#'   

 用步骤2中查出来的记录,对应进该语句删除

<think>好的,我现在需要处理用户关于Oracle数据库记录锁定的问题。首先,用户提到他们遇到了“记录被另一个用户锁定”的错误,想要了解原因及解决方法。我需要先回顾已有的知识,确保回答准确。 首先,用户提供的引用[1]已经说明了原因:某个事务修改了数据但未提交或回滚,导致记录锁定。解决方法包括找出锁定会话并终止,或者让相关用户提交/回滚。不过,我需要更详细地展开这些步骤,可能还需要补充其他可能的解决方案,比如设置超时或优化事务设计。 接下来,我需要确保回答结构清晰,分点说明原因和解决方法。可能的原因有几个方面,比如未提交的事务、长时间运行的事务、程序逻辑错误等。解决方法部分需要包括查询锁定会话的方法,使用ALTER SYSTEM KILL SESSION终止会话,以及预防措施,比如事务管理和索引优化。 另外,用户可能对如何查询被锁定的对象和会话不太清楚,所以需要提供具体的SQL语句示例。例如,使用DBA_BLOCKERS、DBA_WAITERS视图,或者v$lock和v$session动态性能视图。这部分要确保语法正确,可能需要检查Oracle的文档或可靠来源,避免给出错误的查询语句。 还要注意用户提到的系统级指令,比如使用中文回答,数学公式用$...$,但这个问题可能不涉及数学公式,所以可能不需要。但生成的相关问题需要符合要求,比如关于死、监控的方法、行与表的区别等。 最后,需要生成相关问题,确保覆盖用户可能进一步询问的方向,比如死处理、监控工具、级别差异等。同时,引用部分要正确标注,虽然用户给的引用是关于锁定记录的解决方法,但可能需要确认是否有其他相关引用,但根据用户提示,引用仅供参考,主要依赖用户当前的问题和之前的回答。 在组织内容时,要分步骤说明解决方法,比如查询锁定会话、终止会话、预防措施等。每个步骤给出具体的SQL命令,并解释其作用。同时,提醒用户谨慎终止生产环境的会话,避免数据不一致。 总结一下,我需要: 1. 分点列出锁定原因。 2. 提供详细的解决步骤,包括查询和终止会话的SQL。 3. 给出预防措施,如事务优化和索引使用。 4. 生成相关问题,引导用户深入探讨。 5. 确保引用正确,回答结构清晰,语言准确。 现在需要检查是否有遗漏的点,比如Oracle的自动行机制、死检测等。可能还需要提到死的情况,但用户的问题主要是锁定而非死,不过生成的问题中可以包括死处理。确保所有信息准确无误,必要时参考官方文档或可靠资源。</think>### Oracle 数据库记录锁定原因及解决方法 #### 一、记录锁定的原因 1. **未提交的事务** 用户对数据执行了更新(`UPDATE`/`DELETE`)操作但未提交(`COMMIT`)或回滚(`ROLLBACK`),Oracle 会通过事务锁定相关记录[^1]。 2. **长时间运行的事务** 若事务包含大量操作或未合理设计,可能导致持有时间过长,阻塞其他会话。 3. **程序逻辑错误** 例如代码中开启事务后未正确关闭,或异常处理未触发回滚。 4. **升级冲突** 行可能因资源竞争升级为表(如未正确使用索引导致全表扫描)。 --- #### 二、解决方法 ##### 步骤1:定位锁定会话 通过以下 SQL 查询锁定对象及会话信息: ```sql -- 查询阻塞会话与被阻塞会话 SELECT blocker.sid AS blocking_sid, waiter.sid AS waiting_sid FROM dba_blockers blocker, dba_waiters waiter WHERE blocker.hold_leg = waiter.req_leg; -- 查询具体信息(需DBA权限) SELECT l.sid, s.username, s.machine, l.type, o.object_name FROM v$lock l JOIN v$session s ON l.sid = s.sid JOIN dba_objects o ON l.id1 = o.object_id WHERE l.type = 'TM' AND o.object_name = 'YOUR_TABLE_NAME'; ``` ##### 步骤2:终止锁定会话 ```sql -- 终止会话(替换SID和SERIAL#) ALTER SYSTEM KILL SESSION 'sid,serial#'; ``` ##### 步骤3:优化事务设计(预防措施) 1. **缩短事务时间** 将大事务拆分为小操作,避免长时间占用。 2. **显式提交/回滚** 确保程序逻辑中每个事务明确提交或回滚。 3. **使用索引优化查询** 为 WHERE 条件字段添加索引,减少全表扫描导致的升级。 --- #### 三、特殊情况处理 - **死**:Oracle 会自动检测死并回滚其中一个事务,可通过 `v$deadlock_history` 分析原因。 - **行与表**:行(`TX`)针对数据行,表(`TM`)需谨慎处理,避免并发性能下降。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值