
此文章主要是对Oracle数据库锁机制的详细研究 首先我们要介绍的是Oracle数据库锁的类型 同时也阐述 在实际应用中我们经常会遇到的与锁相关的异常情况 特别对经常遇到的由于等待锁而使事务被挂起的问题进行了定位及解决 并对死锁这一比较严重的现象 提出了相应的解决方法和具体的分析过程
数据库是一个多用户使用的共享资源 当多个用户并发地存取数据时 在数据库中就会产生多个事务同时存取同一数据的情况 若对并发 *** 作不加控制就可能会读取和存储不正确的数据 破坏数据库的一致性
加锁是实现数据库并发控制的一个非常重要的技术 当事务在对某个数据对象进行 *** 作前 先向系统发出请求 对其加锁 加锁后事务就对该数据对象有了一定的控制 在该事务释放锁之前 其他的事务不能对此数据对象进行更新 *** 作
在数据库中有两种基本的锁类型 排它锁(Exclusive Locks 即X锁)和共享锁(Share Locks 即S锁) 当数据对象被加上排它锁时 其他的事务不能对它读取和修改 加了共享锁的数据对象可以被其他事务读取 但不能修改 数据库利用这两种基本的锁类型来对Oracle数据库的事务进行并发控制
在实际应用中经常会遇到的与锁相关的异常情况 如由于等待锁事务被挂起 死锁等现象 如果不能及时地解决 将严重影响应用的正常执行 而目前对于该类问题的解决缺乏系统化研究和指导 本文在总结实际经验的基础上 提出了相应的解决方法和具体的分析过程
Oracle数据库的锁类型
根据保护的对象不同 Oracle数据库锁可以分为以下几大类 DML锁(data locks 数据锁) 用于保护数据的完整性 DDL锁(dictionary locks 字典锁) 用于保护数据库对象的结构 如表 索引等的结构定义 内部锁和闩(internal locks and latches) 保护数据库的内部结构
DML锁的目的在于保证并 *** 况下的数据完整性 本文主要讨论DML锁 在Oracle数据库中 DML锁主要包括TM锁和TX锁 其中TM锁称为表级锁 TX锁称为事务锁或行级锁
当Oracle执行DML语句时 系统自动在所要 *** 作的表上申请TM类型的锁 当TM锁获得后 系统再自动申请TX类型的锁 并将实际锁定的数据行的锁标志位进行置位 这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志 而只需检查TM锁模式的相容性即可 大大提高了系统的效率
TM锁包括了SS SX S X等多种模式 在Oracle数据库中用 - 来表示 不同的SQL *** 作产生不同类型的TM锁 如表 所示
在数据行上只有X锁(排他锁) 在 Oracle数据库中 当一个事务首次发起一个DML语句时就获得一个TX锁 该锁保持到事务被提交或回滚 当两个或多个会话在表的同一条记录上执行DML语句时 第一个会话在该条记录上加锁 其他的会话处于等待状态 当第一个会话提交后 TX锁被释放 其他会话才可以加锁
当Oracle数据库发生TX锁等待时 如果不及时处理常常会引起Oracle数据库挂起 或导致死锁的发生 产生ORA 的错误 这些现象都会对实际应用产生极大的危害 如长时间未响应 大量事务失败等
TX锁等待的分析
在介绍了有关地Oracle数据库锁的种类后 下面讨论如何有效地监控和解决锁等待现象 及在产生死锁时如何定位死锁的原因
监控锁的相关视图 数据字典是Oracle数据库的重要组成部分 用户可以通过查询数据字典视图来获得数据库的信息 和锁相关的数据字典视图如表 所示
TX锁等待的监控和解决在日常工作中 如果发现在执行某条SQL时数据库长时间没有响应 很可能是产生了TX锁等待的现象 为解决这个问题 首先应该找出持锁的事务 然后再进行相关的处理 如提交事务或强行中断事务
死锁的监控和解决在数据库中 当两个或多个会话请求同一个资源时会产生死锁的现象 死锁的常见类型是行级锁死锁和页级锁死锁 Oracle数据库中一般使用行级锁 下面主要讨论行级锁的死锁现象
当Oracle检测到死锁产生时 中断并回滚死锁相关语句的执行 报ORA 的错误并记录在Oracle数据库的日志文件alertSID log中 同时在user_dump_dest下产生了一个跟踪文件 详细描述死锁的相关信息
在日常工作中 如果发现在日志文件中记录了ora 的错误信息 则表明产生了死锁 这时需要找到对应的跟踪文件 根据跟踪文件的信息定位产生的原因
如果查询结果表明 死锁是由于bitmap索引引起的 将IND_T_PRODUCT_HIS_STATE索引改为normal索引后 即可解决死锁的问题
表 Oracle的TM锁类型
锁模式 锁描述 解释 SQL *** 作
none
NULL 空 Select
SS(Row S) 行级共享锁 其他对象只能查询这些数据行 Select for update Lock for update Lock row share
SX(Row X) 行级排它锁 在提交前不允许做DML *** 作 Insert Update Delete Lock row share
S(Share) 共享锁 Create index Lock share
SSX(S/Row X) 共享行级排它锁 Lock share row exclusive
lishixinzhi/Article/program/Oracle/201311/18509
并发控制。
封锁机制是并发控制的主要手段。封锁是使事务对它要 *** 作的数据有一定的控制能力。封锁具有3个环节:第一个环节是申请加锁,即事务在 *** 作前要对它欲使用的数据提出加锁请求;第二个环节是获得锁,即当条件成熟时,系统允许事务对数据加锁,从而事务获得数据的控制权;第三个环节是释放锁,即完成 *** 作后事务放弃数据的控制权。为了达到封锁的目的,在使用时事务应选择合适的锁,并要遵从一定的封锁协议。
基本的封锁类型有两种:排它锁(Exclusive Locks,简称X锁)和共享锁(Share Locks,简称S锁)。
(1)排它锁
排它锁也称为独占锁或写锁。一旦事务T对数据对象A加上排它锁(X锁),则只允许T读取和修改A,其他任何事务既不能读取和修改A,也不能再对A加任何类型的锁,直到T释放A上的锁为止。
(2)共享锁
共享锁又称读锁。如果事务T对数据对象A加上共享锁(S锁),其他事务对A只能再加S锁,不能加X锁,直到事务T释放A上的S锁为止。
简单地对数据加X锁和S锁并不能保证数据库的一致性。在对数据对象加锁时,还需要约定一些规则。例如,何时申请X锁或S锁、持锁时间、何时释放等。这些规则称为封锁协议(Locking Protocol)。对封锁方式规定不同的规则,就形成了各种不同的封锁协议。封锁协议分三级,各级封锁协议对并发 *** 作带来的丢失修改、不可重复读取和读“脏”数据等不一致问题,可以在不同程度上予以解决。
怎么知道数据库表已经锁表了先回答你的问题:
select *from v$locked_object
可以获得被锁的对象的object_id及产生锁的会话sid。
通过查询结果中的object_id,可以查询到具体被锁的对象
再给你看看我查到的一些关于锁的资料:
锁有以下几种模式:
0:none
1:null 空
2:Row-S 行共享(RS):共享表锁
3:Row-X 行专用(RX):用于行的修改
4:Share 共享锁(S):阻止其他DML *** 作
5:S/Row-X 共享行专用(SRX):阻止其他事务 *** 作
6:exclusive 专用(X):独立访问使用
数字越大锁级别越高, 影响的 *** 作越多。
一般的查询语句如select ... from ... 是小于2的锁, 有时会在v$locked_object出现。
select ... from ... for update是2的锁。
当对话使用for update子串打开一个游标时,
所有返回集中的数据行都将处于行级(Row-X)独占式锁定,
其他对象只能查询这些数据行,不能进行update、delete或select...for update *** 作。
insert / update / delete ... 是3的锁。
没有mit之前插入同样的一条记录会没有反应,
因为后一个3的锁会一直等待上一个3的锁, 我们必须释放掉上一个才能继续工作。
创建索引的时候也会产生3,4级别的锁。
locked_mode为2,3,4不影响DML(insert,delete,update,select) *** 作,
但DDL(alter,drop等) *** 作会提示ora-00054错误。
有主外键约束时 update / delete ... 可能会产生4,5的锁。
DDL语句时是6的锁。
以DBA角色, 查看当前数据库里锁的情况可以用如下SQL语句:
select object_id,session_id,locked_mode from v$locked_object
select t2.username,t2.sid,t2.serial#,t2.logon_time
from v$locked_object t1,v$session t2
where t1.session_id=t2.sid order by t2.logon_time
如果有长期出现的一列,可能是没有释放的锁。
我们可以用下面SQL语句杀掉长期没有释放非正常的锁:
alter system kill session 'sid,serial#'
如果出现了锁的问题, 某个DML *** 作可能等待很久没有反应。
当你采用的是直接连接数据库的方式,
也不要用OS系统命令 $kill process_num 或者 $kill -9 process_num来终止用户连接,
因为一个用户进程可能产生一个以上的锁, 杀OS进程并不能彻底清除锁的问题。
记得在数据库级别用alter system kill session 'sid,serial#'杀掉不正常的锁。
这里还讲了一些:
......>>
查看oracle是否锁表
Oracle数据库 *** 作中,我们有时会用到锁表查询以及解锁和kill进程等 *** 作,那么这些 *** 作是怎么实现的呢?本文我们主要就介绍一下这部分内容。
(1)锁表查询的代码有以下的形式:
select count(*) from v$locked_object
select * from v$locked_object
(2)查看哪个表被锁
select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects b where b.object_id = a.object_id
(3)查看是哪个session引起的
select b.username,b.sid,b.serial#,logon_time from v$locked_object a,v$session b where a.session_id = b.sid order by b.logon_time
(4)杀掉对应进程
执行命令:alter system kill session'1025,41'
其中1025为sid,41为serial#.
怎么查看 sql server 数据库有没有锁表
--查看被锁表: select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName from sys.dm_tran_locks where resource_type='OBJECT' --spid 锁表进程 --tableName 被锁表名 -- 解锁: declare @spid int Set @spid = 57 --锁表进程 declare @sql varchar(1000) set @sql='kill '+cast(@spid as varchar) exec(@sql)
MYSQL数据库怎么查看 哪些表被锁了
用navicate工具可以轻松查看
里面lock的就是被锁的
查询oracle 数据库里有哪些表锁死
查锁,
SELECT /*+ rule */ s.username,
decode(l.type,'TM','TABLE LOCK',
'TX','ROW LOCK',
NULL) LOCK_LEVEL,
o.owner,o.object_name,o.object_type,
s.sid,s.serial#,s.terminal,s.machine,s.program,s.osuser
FROM v$session s,v$lock l,dba_objects o
WHERE l.sid = s.sid
AND l.id1 = o.object_id(+)
AND s.username is NOT NULL
杀锁
alter system kill session '25,7357'
如何查询mysql数据库表是否被锁 csdn
show OPEN TABLES where In_use >0
如何查看mysql中表的锁定情况
1 show processlist
SHOW PROCESSLIST显示哪些线程正在运行。您也可以使用mysqladmin processlist语句得到此信息。如果您有SUPER权限,您可以看到所有线程。否则,您只能看到您自己的线程(也就是,与您正在使用的MySQL账户相关的线程)。如果有线程在update或者insert 某个表,此时进程的status为updating 或者 sending data。
如果您得到“too many connections”错误信息,并且想要了解正在发生的情况,本语句是非常有用的。MySQL保留一个额外的连接,让拥有SUPER权限的账户使用,以确保管理员能够随时连接和检查系统(假设您没有把此权限给予所有的用户)。
Status
含义
Checking table
正在检查数据表(这是自动的)。
Closing tables
正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的 *** 作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。
Connect Out
复制从服务器正在连接主服务器。
Copying to tmp table on disk
由于临时结果集大于tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。
Creating tmp table
正在创建临时表以存放部分查询结果。
deleting from main table
服务器正在执行多表删除中的第一部分,刚删除第一个表。
deleting from reference tables
服务器正在执行多表删除中的第二部分,正在删除其他表的记录。
Flushing tables
正在执行FLUSH TABLES,等待其他线程关闭数据表。
Killed
发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。
Locked
被其他查询锁住了。
Sending data
正在处理SELECT查询的记录,同时正在把结果发送给客户端。
Sorting for group
正在为GROUP BY做排序。
Sorting for order
正在为ORDER BY做排序。
Opening tables
这个过程应该会很快,除非受到其他因素的干扰。例如,在执ALTER TABLE或LOCK TABLE语句行完以前,数据表无法被其他线程打开。正尝试打开一个表。
Removing duplicates
正在执行一个SELECT DISTINCT方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。
Reopen table
获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。
Repair by sorting
修复指令正在排序以创建索引。
Repair with keycache
修复指令正在利用索引缓存一个一个地创建新索引。它会比Repair by ......>>
如何查看SQL数据有没有锁表
后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工鼎中使用该功能,并着手修改当前还在使用该功能的应用程序。若要获取有关 SQL Server 数据库引擎中的锁的信息,请使用 sys.dm_tran_locks 动态管理视图。
USE master
GO
EXEC sp_lock 53
GO
查看Oracle中是否有锁表的sql
查锁,
SELECT /*+ rule */ s.username,
decode(l.type,'TM','TABLE LOCK',
'TX','ROW LOCK',
NULL) LOCK_LEVEL,
o.owner,o.object_name,o.object_type,
s.sid,s.serial#,s.terminal,s.machine,s.program,s.osuser
FROM v$session s,v$lock l,dba_objects o
WHERE l.sid = s.sid
AND l.id1 = o.object_id(+)
AND s.username is NOT NULL
杀锁
alter system kill session '25,7357'
如何查询mysql中是否表被锁
show OPEN TABLES where In_use >0
show global status like 'table_locks%'
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)