笔记系列-------oracle事务和锁

1.什么是事务

必须具备以下四个属性   ACID属性:

  • 原子性:事务操作是完整的。各步操作不可分,要么都执行,要么都不执行
  • 一致性:一个查询结果必须与数据库在查询开始时的状态保持一致(读不等待写,写不等待读) 构造cr块,老值可找到;若是找不到,则查询失败(selection too old)
  • 隔离性:对于其他会话来说,未完成的事务必须不可见(未commit则其他会话不可见
  • 持久性:事务一旦完成提交。数据库就不可以丢失这个事务的结果,数据库通过日志保持事务的持久性

有事务必有锁和undo

2.事务的开始和结束

2.1事务采用隐性方式,起始于session的第一条DML语句

2.2事务结束于:

  • 1)commit或rollback
  • 2)ddl语句被执行(提交)
  • 3)dcl语句被执行(提交)
  • 4)用户退出sqlplus(正常退出则提交,非正常退出则回滚)
  • 5)服务器故障或系统崩溃(回滚)
  • 6)shutdown immediate(回滚)

注:在一个事务中,若是某dml语句失败,之前任何dml语句将保持完好,且不会提交

一个session只有一个事务,它可以在一个事务结束后产生第二个事务,但是不会同时存在2个事务

3.oracle的事务保存点功能

savepoint功能允许事务进行中设置一个标记(保存点),这个标记可控制rollback的效果,即在一个事务中回滚掉最近的部分dml语句,保留下保存点之前的dml语句,并使事物本身继续执行。即回滚到保存点这个操作并不使事务结束。

savepoint sp1;
delete from emp1 where empno=7900;
savepoint sp2;
update emp1 set ename='timran' where empno=7788;
select * from emp1;
rollback to sp2;
select * from emp1;
rollback to sp1;

//rollback to XXXX不会使事务结束,只有rollback可以使事务结束

此时去sys下检查

SQL> select count(*) from v$transaction;

  COUNT(*)
----------
         1
表明事务还可以继续操作

4.scn的概念

scn全称:system change number

它是一个不断增长整数,相当于oracle内部的一个时钟,只要数据库有变更,这个scn就会+1,oracle通过scn记录数据库事务的一致性。scn涉及实例恢复介质恢复的核心概念。控制文件、数据文件,日志文件都有scn,block上也有scn

实现一致性:背后是物理层面的block读,oracke会依据select命令,记录此刻的scn值,然后以scn值同所读的每个block上的scn作比较,若读到的快上的scn大于select发出时记录的scn,则需要利用undo段,在内存中构造CR块。

得到当前scn的方法:

sys:select current_scn from v$database;

select dbms_flashback.get_system_change_number from dual;

5.共享锁与排他锁的基本原理

有事务才有锁的概念(对事务上锁?)。oracle锁分类如下:

DML锁(data locks,数据锁),用于保护数据完整性

DDL锁(dictionary locks ,数据字典所),用于保护数据库对象的结构,如表、索引等的结构定义,做drop alter时上锁

system锁(internal locks and latches(内存中)),保护数据库的内部结构

注:

  • 当一个用户对某表做dml操作时,也会加ddl锁,这样在事务结束前,可防止另外一个用户对该表做ddl操作。初始化参数ddl_block_timeout可以设定了ddl锁的等待时间。事件过后若事务仍未结束,则显示资源正忙。
  • 当用户对某表做ddl操作时,也会增加dml锁(exlusive),可防止另外一个用户对该表做dml操作

数据锁/dml锁:TM锁 TX锁

  • TM面向对象,表示锁定了系统中一对象,在锁定期间不允许其他人对这个对象做ddl操作。tm锁首先产生,为实施ddl保护
  • TX:面向事务,表示锁定系统中一事务,是否有事务产生,是根据是否使用undo段来评判的

例:一个update语句,有表级锁(tm)和行锁(tx),oracle先申请表级锁tm(其中的rx锁),后系统再自动申请行锁(tx),并将实际锁定的数据行的锁标定位置(即指向其中的tx锁)

对dml操作

tx行锁只有一种

tm表锁有5中,分别rs 2,rx 3,s 4。srx 5,x 6。

6.5种TM锁的含义

row share 行共享(rs),允许其他用户同时更新其他行,允许其他用户同时增加共享锁,不允许独占(排他性质)的锁

row exclusive 行排他(rx),允许其他用户同时更新其他行,只允许其他用户同时加行共享锁或者行排他锁

share共享(s),不允许其他用户同时更新任何其他行,只允许用户同时加共享锁胡总和行共享锁

share row exclusive(srx)共享排他行、,不允许其他用户同时更新其他行,只允许其他行用户同时加共享锁

exclusive (x)排他,其他用户禁止更新任何行,禁止用户同时加任何排他锁

sql语句

加锁模式 许可其他用户加锁模式
select * from table_name rs,rx,s,srx,x

insert,update,delete (dml操作)

rx rs,rx
select * from table_name for update rx rs,rx
lock table table_name in row share mode rs rs,rx,x,srx
lock table table_name in row exclusive mode rs
lock table table_name in share mode
lock table table_name in share row exclusive mode
lock table table_name in exclusive mode

7.加锁模式

7.1 自动加锁

做dml操作时,如insert,update,delete,以及select 。。。for update由oracle自动完成加锁

select * 不产生事务,但是select * ... for update会产生事务,因为有事务才有锁,而此语句有锁。

执行:

select * from emp where deptno=10 for update; //会产生锁将select * from emp where deptno=10 得结果锁住,便于后续操作。

若是另外一个session再次执行select * from emp where job='clerk';该会话会被停掉不走;

此时可在select * from emp where job='clerk'添加以下三种参数:

  • nowait
  • wait 3
  • skip locked(emp表中有4条符合条件记录,此语句将会跳过已经被锁住得那条记录,只展现剩下3条记录;此时,共有4条clerk记录被锁住)

若有4条clerk记录被锁住,而执行者不在,管理员只能做如下操作:

  • select * from v$lock; 查sid
  • select sid,serial#,sql_text from v$session where sid=上面得sid;
  • 接下来会对serial#进行kill操作,(因为sid会重复使用,无法准确定位)
  • alter system kill session 'sid,serial#'(上面查的数字)

而kill session动作是rollback,而非commit;ddl操作是commit,因为commit命令被ddl嵌入了

7.2人工方式加锁,用lock命令以显式的方式加锁

lock table table_name in share mode

观察锁的静态和动态视图:

select * from v$lock;

select * from dba_locks where session_id=149;

8.死锁和解锁

8.1oracle自动侦测死锁,自动解决锁征用

session1:

update ... id=2000 where id=2;

session 2:

update ... id=1000 where id=1;

session1:

update ... id=1000 where id=1;   //此时session被锁住

session 2:

update ... id=1000 where id=1;   //此时形成死锁,oracle会检测到结果并自动弹开,此时若是结束session 2 得事务,session1 得内容会得以继续

8.2管理员如何解锁

定位

select * from v$lock where type in ('TM','TX');

select a.sid,a.serial#,b.sql_text from v$session a,v$sql b where a.prev_sql_id=b.sql_id and a.sid=127;

select sid,serial#,blocking_session,username,event from v$session where blocking_session_status='VALID';    //或者根据v$lock视图的block和request确定session阻塞关系,确定无误后再杀掉这个session

更多视图:v$session,v$process,v$sql,v$locked,v$sqlarea等等

你可能感兴趣的:(oracle,oracle,sql)