Oracle中的锁机制1

玩技站长 科技常识评论70字数 3795阅读模式
摘要最佳答案:由于数据库锁的误用而出现性能问题,alert中都是死锁的信息,以确保用户访问同一数据库对象时的准确性(无遗失修改,可重新读取,无读取)一般要求在修改数据之前对该数据加锁,...

有一些性能问题是由于对数据库锁的错误使用造成的。记得之前有个客户,alert中全是死锁的信息,最后发现原因是外键没有建立索引导致的。

1.基本概念文章源自玩技e族-https://www.playezu.com/749062.html

为了确保用户在存取同一数据库对象时的正确性(无丢失修改、可重复读、不读“脏”数据等),数据库引入了锁机制。基本的锁类型有两种:排它锁 X锁和共享锁 S锁。文章源自玩技e族-https://www.playezu.com/749062.html

若事务T对数据D加X锁,则其他任何事务都不能再对D加任何类型的锁,直至T释放D上的X锁;一般要求在修改数据前向该数据加排它锁,所以排它锁有成为写锁。一个资源,比如一行或者一个表只能加一个排它锁,但是可以加多个共享锁。文章源自玩技e族-https://www.playezu.com/749062.html

共享锁文章源自玩技e族-https://www.playezu.com/749062.html

若事务T对数据D加S锁,则其他事务只能对D加S锁,而不能加X锁,直至T释放D上的S锁;一般要求读取数据前向该数据加共享锁,所以共享锁又称为读锁。文章源自玩技e族-https://www.playezu.com/749062.html

2.锁行为文章源自玩技e族-https://www.playezu.com/749062.html

锁作用于读取和写入的交互。读是对资源的查询,写是对资源的修改。以下列出了Oracle数据库对读和写的锁规则:文章源自玩技e族-https://www.playezu.com/749062.html

A row is locked only when modified by a writer.文章源自玩技e族-https://www.playezu.com/749062.html

行只有被写更改的时候锁定。
含义:当一个语句更新一行的时候,会话仅获得该行的锁。通过在行级别锁定数据,数据库最大程度的减少了对相同数据的争用。正常情况下,数据库不会把行锁升级为表锁。文章源自玩技e族-https://www.playezu.com/749062.html

A writer of a row blocks a concurrent writer of the same row.文章源自玩技e族-https://www.playezu.com/749062.html

对于行级别的修改阻止对相同行的并发修改。
含义:如果一个事务正在修改一行,行锁阻止其它的事务同时修改同一行。

A reader never blocks a writer.

读操作从来不会阻止写操作。
含义:因为读不会锁定,所以可以对该行做修改。除了SELECT … FOR UPDATE这个特殊的select语句。

A writer never blocks a reader.

写操作不会阻止读操作。
含义:当一行数据正在被修改,数据库使用UNDO提供给读一个该行的一致性视图。
pending distributed transactions
一个特殊情况就是挂起的分布式事务中,读操作可能需要等待对于相同数据块的写完成。

3.锁转换、锁升级、锁定时间

锁转换:Oracle根据需要执行锁转换。例如在SELECT … FOR UPDATE中,Oracle数据库自动将行共享锁转换为行排它锁。
锁升级:Oracle不会升级锁。例如Oracle不会将行锁升级为表锁。
锁定时间:Oracle在事务rollback或者commit或者rollback savepoint等之后,都会释放相应语句获得的锁,也就是在事务执行期间。但是有个特例就是:由于在外键没有建立索引子表的锁不是在事务期间,而是在语句执行期间。

4.死锁

死锁是两个或者多个用户等待彼此锁定的数据的一种情况。Oracle数据库自动检测死锁,并通过回滚死锁涉及的一条语句,释放一组冲突的行锁来解决死锁。数据库向进行语句级回滚的事务返回相应的消息,通常,此语句应该显式回滚。
记得有次电话面试,让我口头模拟一个死锁,知道是互相等待,两个会话就够了,但是最后说错了,回想起来,除了紧张,可能还是理解不够。
模拟两个会话产生死锁:

Tsession1session2
t0UPDATE employees set salary=salary*1.1 where employee_id=100; 1 row updatedUPDATE employees set salary=salary*1.1 where employee_id=200; 1 row updated
t1UPDATE employees set salary=salary*1.1 where employee_id=200; no returnUPDATE employees set salary=salary*1.1 where employee_id=100; no return
t2ORA-00060: deadlock detected while waiting for resource
t3commit;
t41 row updated.
t5commit; Commit complete.

5.自动锁

Oracle数据库根据资源和要执行的操作自动获取不同类型的锁。

LockDescription
DML LocksProtect data. For example, table locks lock entire tables, while row locks lock selected rows.
DDL LocksProtect the structure of schema objects—for example, the dictionary definitions of tables and views.
System LocksProtect internal database structures such as data files. Latches, mutexes, and internal locks are entirely automatic.

DML锁,也称为数据锁,保证多个用户并发访问的数据的完整性。DML语句自动获取TX锁和TM锁,即行锁与表锁。

5.1.DML–ROW Locks(TX)

行锁,也称为TX锁。事务为每一行请求行锁,当执行insert、update、delete、merge、select … for update,直至会话commit或者rollback之后行锁释放。
有一些锁,如果我们不知道具体含义的话,可以通过数据字典查看,之前记得碰到TO锁,第一时间也是不知道啥含义。

SQL> set serveroutput onSQL> exec print_table('select * from v$lock_type where type=''TX''');TYPE : TXNAME : TransactionID1_TAG : usn<<16 | slotID2_TAG : sequenceIS_USER : YESDESCRIPTION : Lock held by a transaction to allow othertransactions to wait for it-----------------PL/SQL procedure successfully completed.SQL>SQL> exec print_table('select * from v$lock_type where type=''TO''');TYPE : TONAME : Temp ObjectID1_TAG : object #ID2_TAG : 1IS_USER : NODESCRIPTION : Synchronizes DDL and DML operations on a tempobject-----------------PL/SQL procedure successfully completed--以上pring_table引用了一个脚本,是《Oracle性能优化与诊断案例精选》里面看到的create or replace procedure print_table( p_query in varchar2 )AUTHID CURRENT_USERisl_theCursor integer default dbms_SQL.open_cursor;l_columnValue varchar2(4000);l_status integer;l_descTbl dbms_SQL.desc_tab;l_colCnt number;beginexecute immediate'alter session setnls_date_format=''dd-mon-yyyy hh24:mi:ss'' ';dbms_SQL.parse( l_theCursor, p_query, dbms_SQL.native );dbms_SQL.describe_columns( l_theCursor, l_colCnt, l_descTbl );for i in 1 .. l_colCnt loopdbms_SQL.define_column(l_theCursor, i, l_columnValue, 4000);end loop;l_status := dbms_SQL.execute(l_theCursor);while ( dbms_SQL.fetch_rows(l_theCursor) > 0 ) loopfor i in 1 .. l_colCnt loopdbms_SQL.column_value( l_theCursor, i, l_columnValue );dbms_output.put_line( rpad( l_descTbl(i).col_name, 30 )|| ': ' ||l_columnValue );end loop;dbms_output.put_line( '-----------------' );end loop;execute immediate'alter session set nls_date_format=''dd-MON-rr'' ';exceptionwhen others thenexecute immediate'alter session set nls_date_format=''dd-MON-rr'' ';raise;end;/

那TX锁我们怎么查呢,参考这里

-------------------------------小节分割线-----------------------------------

玩技站长微信
添加好友自动发送入群邀请
weinxin
rainbow-shownow
玩技官方公众号
官方微信公众号
weinxin
PLAYEZU
 
  • 版权提示:本站仅供存储任何法律责任由作者承担▷诈骗举报◁▷新闻不符◁▷我要投稿◁
    风险通知:非原创文章均为网络投稿真实性无法判断,侵权联系2523030730
    免责声明:内容来自用户上传发布或新闻客户端自媒体,切勿!切勿!切勿!添加联系方式以免受骗。
  • 原创转载:https://www.playezu.com/749062.html
    转载说明: 点我前往阅读>>>
匿名

发表评论

匿名网友
确定