Oracle里查询数据会不会锁表

qroom 2010-05-13 01:53:49
一般什么情况下会锁表?
...全文
5919 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
csharpfan 2010-05-17
  • 打赏
  • 举报
回复
xieyuooo与我只是对脏数据的理解不一样,你上面举的例子中提到的"脏数据",应不是数据库定义的脏数据,读取其他事务修改但未提交的数据是脏数据,具体定义你查一下资料好了.oracle应该也没有像MS SQL SERVER那样可以读取脏数据的.
BZW,关于ORACLle查询会不会锁表,我个人认为要从控制并发的锁机制和事务隔离级别上去考虑,他们是相互关联的.不管MS SQL SERVER还是ORACLE,只要是缺省的隔离级别,且不人工加上锁,查询是不会锁其他表,其他表的操作也不会阻塞查询操作的(最多会产生不可重复读和幻读),反之,就可能不是查询操作阻塞其他操作,就是其他操作阻塞本查询.
xieyu_zy 2010-05-17
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 csharpfan 的回复:]
xieyuooo与我只是对脏数据的理解不一样,你上面举的例子中提到的"脏数据",应不是数据库定义的脏数据,读取其他事务修改但未提交的数据是脏数据,具体定义你查一下资料好了.oracle应该也没有像MS SQL SERVER那样可以读取脏数据的.
BZW,关于ORACLle查询会不会锁表,我个人认为要从控制并发的锁机制和事务隔离级别上去考虑,他们是相互关联的.不管MS SQL SERVER还是OR……
[/Quote]

理解。TKS。。。脏数据这个概念的确是我自己弄错了,呵呵。。。
xieyu_zy 2010-05-16
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 csharpfan 的回复:]
13L说法中有一点错误,一般查询是不会读脏数据的,sql server和oracle 缺省的事务隔离级别都是read committed,如果出错那SQL-92标准就定义错了.下面是SQL-92事务隔离级别及并发可能带来的副作用的关系
Read uncommitted:
Possible(Dirty Read)
Possible(NonRepeatable Read)
Possibl……
[/Quote]

可能我对于脏数据的理解有点问题吧,不过在曾经的几个试验中以及参考相关资料得到相应信息,如以下两个实验:

1、模拟银行转账+查询账户,这里当然模拟极限情况,转账需要做两个动作就是分别UPDATE,并最后COMMIT,那么为了模拟,可以再两个UPDATE之间做一个dbms_lock.sleep(10)休息十秒钟,在这里开启另一个SESSION你可以用SELECT读一下表,肯定是修改前的数据,这个至少我认为是脏数据,因为即使数据在修改中,但是毕竟修改了。。。。

2、做一个过程或者统计,不过做过程更容易模拟,这个过程用断点去走,可以模拟一个SQL,也可以模拟一个游标,在过程的断点走掉中间的时候还未结束,开启另一个会话对游标查询的表进行增、删、改、查操作,并使用COMMIT,你看下你游标遍历出来的数据是什么,肯定是另一个会话对表修改前的数据,因为任何执行语句都会带上时间戳并对应其SCN号码,数据若发现SCN号码和带入的SCN号码不一致,则到回滚段中查找数据,若回滚段中没有了,执行语句会报错。。。。。

另外还有强制通过版本号或者时间戳查询历史修改数据的(可以存放多少是和回滚段大小有关系,存放时间还除和大小有关系还和系统经常发生的业务频繁操作量也有关系),也就是强制到回滚段中查询的。
huangyunzeng2008 2010-05-15
  • 打赏
  • 举报
回复
楼上说的挺对,读不会加锁,除非你手动加锁
Adebayor 2010-05-15
  • 打赏
  • 举报
回复
[Quote=引用楼主 qroom 的回复:]
一般什么情况下会锁表?
[/Quote]
select不会锁表
select ...for update会锁表
不过多年前使用toad好像会有锁表的情况 记不得了
如果有 就是bug
kingstarer 2010-05-15
  • 打赏
  • 举报
回复
select * from dual for update; 锁表
select * from dual; 不锁表
yinmoz 2010-05-15
  • 打赏
  • 举报
回复
原来如此...学习了.
csharpfan 2010-05-15
  • 打赏
  • 举报
回复
13L说法中有一点错误,一般查询是不会读脏数据的,sql server和oracle 缺省的事务隔离级别都是read committed,如果出错那SQL-92标准就定义错了.下面是SQL-92事务隔离级别及并发可能带来的副作用的关系
Read uncommitted:
Possible(Dirty Read)
Possible(NonRepeatable Read)
Possible(Phantom Read)

Read committed:
Not possible(Dirty Read)
Possible(NonRepeatable Read)
Possible(Phantom Read)

Repeatable read:
Not possible(Dirty Read)
Not possible(NonRepeatable Read)
Possible(Phantom Read)

Serializable:
Not possible(Dirty Read)
Not possible(NonRepeatable Read)
Not possible(Phantom Read)

可见,正常情况下select只会发生NonRepeatable Read和Phantom Read现象.
SQL四种隔离级别都有,oracle是支持read committed和serializable,但提供read-only
xieyu_zy 2010-05-15
  • 打赏
  • 举报
回复
首先,我建议LZ去看一下ORACLE的锁机制。

常规操作对于对象级别只有行级锁(另外有latch征用和DDL锁,你问的常规操作,这就不说了):
常规操作什么时候加锁:
UPDATE 为WHERE条件部分的行加锁
DELETE 为WHERE条件部分加锁
INSERT INSERT部分加锁(粒度很小),几乎不造成阻塞
SELECT FOR UPDATE 对WHERE条件的行加锁。

上述行级锁会相互阻塞。。。。

对于同对象的加锁,ORACLE会进行序列化过程(因为加锁也是一行一行加的,如果你要锁1000行,在锁住999行的时候,另外一个事务将那行锁住了,就死掉了),对于多个对象交叉锁ORACLE已经可以监控到。。。。

普通的SELECT语句不会阻塞,也不会受到阻塞(不过这个阻塞只是锁方面的阻塞,不是指由于海量数据返回中造成的网络阻塞),可以通过两个会话进行测试,一个语句使用SELECT FOR UPDATE并不关闭,另一个开启普通SELECT可以照常查询,不过不能保证运行中不读出脏数据,对于脏数据读要求不要的系统没必要那么精确,因为很影响性能。。。

当上述锁长期锁住的时候,通过视图v$locked_object可以查看到,并可以定位是那个SESSION_ID和对象ID,通过SESSION_ID到视图v$session可以找到对应的SID和SERIAL#字段,可以强制删除掉这个SESSION,而通过对象ID可以到USER_OBJECTS或DBA_OBJECTS视图中查看到那个对象被锁住了,几个视图可以关联起来查询。。。。
csharpfan 2010-05-14
  • 打赏
  • 举报
回复
在ORACLE和SQL SERVER中的事务隔离级别缺省都是提交读(read committed),如果你没特别设置是不回锁表的
aaaa_007 2010-05-13
  • 打赏
  • 举报
回复
for update 是会对表进行锁定的,其他情况不会,你看pl/sql里面不是有个跟前进路标一样的按钮,亮了表示对表锁定了,好像是这样的
huangdh12 2010-05-13
  • 打赏
  • 举报
回复
查询数据不会锁表,for update 是查询出来准备修改这条记录,这种情况下当然会锁表(但他好像不单单是查询了吧)
tangren 2010-05-13
  • 打赏
  • 举报
回复
oracle写不会阻塞读,读更不会阻塞读。
qroom 2010-05-13
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 zjwssg 的回复:]
查询不会锁表。
oracle的锁机制很棒,你平常根本不用考虑锁这个问题,可以当它是透明的。

2楼说的是oracle的:select * from table for update;
[/Quote]

我只是把Oracle的部分数据导到MySQL里,程序自己写
qroom 2010-05-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 mg_chen 的回复:]
只有一个TRANSACTION可以LOCK相应的行,也就是说如果一个ROW已经LOCKED了,那就不能被其他TRANSACTION所LOCK了。
LOCK由statement产生但却由TRANSACTION结尾(commit,rollback),也就是说一个SQL完成后LOCK还会存在,只有在COMMIT/ROLLBACK后才会RELEASE。xsb注:同样的道理,如果一个游标使用了for up……
[/Quote]
我只是从一些oracle数据库里取一些数据复制到mysql里,用普通的select,不会涉及到锁表吧
zjwssg 2010-05-13
  • 打赏
  • 举报
回复
查询不会锁表。
oracle的锁机制很棒,你平常根本不用考虑锁这个问题,可以当它是透明的。

2楼说的是oracle的:select * from table for update;
ojuju10 2010-05-13
  • 打赏
  • 举报
回复
一般的查询不会锁表
mg_chen 2010-05-13
  • 打赏
  • 举报
回复

只有一个TRANSACTION可以LOCK相应的行,也就是说如果一个ROW已经LOCKED了,那就不能被其他TRANSACTION所LOCK了。
LOCK由statement产生但却由TRANSACTION结尾(commit,rollback),也就是说一个SQL完成后LOCK还会存在,只有在COMMIT/ROLLBACK后才会RELEASE。xsb注:同样的道理,如果一个游标使用了for update打开后,虽然关闭了游标,但这个lock也仍是存在的,直到transaction结束!
SELECT.... FOR UPDATE [OF cols] [NOWAIT];

SELECT cols FROM tables [WHERE...] FOR UPDATE [OF cols] [NOWAIT];
transaction A运行
select a.c1,a.c2 from t1 a,t2 b
2 where b.c3=1 and a.c1=b.c1
3* for update of a.c2
此时transaction B可以对b表t2的相应行进行DML操作,但不能对a表t1相应行进行DML操作.
再看:
transaction A运行
select a.c1,a.c2 from t1 a,t2 b
2 where b.c3=1 and a.c1=b.c1
3* for update of b.c2
此时transaction B可以对a表t1的相应行进行DML操作,但不能对b表t2相应的行进行DML操作.
也就是说LOCK的仍然是行,只是如果不加OF的话会对所有涉及的表LOCK,加了OF后只会LOCK OF 字句所在的TABLE.
NOWAIT(如果一定要用FOR UPDATE,可以加上NOWAIT)
当有LOCK冲突时会提示错误并结束STATEMENT,返回错误是"ORA-00054: resource busy and acquire with NOWAIT specified",否则就会在那里等待。
另外如下用法也值得推荐,应该酌情考虑使用。
FOR UPDATE WAIT 5
5秒后会提示ORA-30006: resource busy; acquire with WAIT timeout expired
FOR UPDATE NOWAIT SKIP LOCKED;
会提示no rows selected
TABLE LOCKS
LOCK TABLE table(s) IN EXCLUSIVE MODE [NOWAIT];
同样也是在transaction结束时才会释放lock。
DEADLOCK
transaction a lock rowA , then transaction b lock rowB
then transaction a tries to lock rowB, and transaction b tries to lock rowA
也就是说两个transaction都相互试图去lock对方已经lock的ROW,都在等待对方释放自己的lock,这样就使死锁。deadlock也会有600提示。
qroom 2010-05-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 mg_chen 的回复:]
for update会锁表
[/Quote]
什么意思,能详细点吗,举个SQL语句的例子?
mg_chen 2010-05-13
  • 打赏
  • 举报
回复
for update会锁表

17,377

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 基础和管理
社区管理员
  • 基础和管理社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧