oracle学习day3

一。oracle事务

  • 事务四大特性:都支持
  • 支持的隔离级别:支持读已提交、串行化、只读,默认为读已提交
  • 读已提交会出现不可重读与幻读,串行化则都不会出现。因为串行化采用了事务级一致性读,事务内查询使用的数据都是事务开始时间点以前的,或者是事务内本次查询上次增删改后的数据。
  • 只读级别不能有增删改语句,串行化可以有,二者都是事务级一致性读。读已提交是语句级一致性读,这也是默认的一致性读级别。

1.只读和读已提交与其他数据库都一致,但是串行化不一致。
oralce的串行化应该叫做并发读,串行写,且事务之间读不阻塞写
串行读适合用在下面三种情况:
a.大型数据库中大多是小数据集的DML短事务
b.修改同一行的几率非常低的系统.
c.长运行事务主要是只读的系统
2.实现并发读的基础叫做事务级一致性读
3.当一个串行化事务试图更新或删除数据,而这些数据在此事务开始后被其他事
务修改并进行了提交,Oracle 将报错:无法进行串行化访问为了实现上述判断,Oracle 在数据块(data block)内存储了相关的控制信息,用于记录此块内数据行中所包含的数据是已提交或未提交的。即数据块内记录了近期对本数据块内数据行进行了修改的所有事务及事务的状态。在一个数据块内能够保留多少这样的记录是由 CREATE TABLE 或 ALTER TABLE 语句中的INITRANS 参数设定的。所以可以加大该参数的值以保证数据块有足够的空间记录事务对其的访问信息。
4.总结:串行化在事务开始的点开始,就会独占当前事务里所涉及的所有更新操作,拒绝其他事务来对独占的数据进行更新。如何保证这点呢,分两种:首先,事务在开始的时候回判断是否存在未提交的更新(可能会出现判断遗漏),如果没有才会继续,其次,举例,一个事务已经执行了一半,一种是当前事务已经执行的更新操作,由于没有提交,其他事务肯定只能等待,不能修改,另外一种是当前事务还没有执行的更新操作,在等到执行这段更新代码的时候,会去查看其他事务是否在当前事务开始后执行了提交(针对上面判断遗漏的情况),如果有,那么将抛出错误。串行执行并不是说,当前数据库中的所有事务都会串行排队,而只是针对事务中所涉及的更新数据,不会与其他事务并行修改。同时用事务级一致性读隔离各事务使用的数据

1.在已提交读取隔离模式(read committed)及串行化隔离模式(serializable)
下执行的事务都采用行级锁(row-level locking)技术,也即写锁–oracle没有读锁,他们在更新被未提交的并发事务修改的数据行时都会发生等待–等待未提交的并发事务提交或撤销,并释放锁。如果未提交的并发事务进行了回滚,那么无论发生等待的事务
运行在何种隔离模式下,都能修改之前被锁住的数据行,如同未提交的并发事
务不存在一样。
2.当导致阻塞的事务(blocking transaction)[前文中提到的未提交的并发事务]
提交并释放了锁后,运行在已提交读写模式下的等待事务就能够继续执行其中的更新操作。而运行在串行化模式下的等待事务将出现无法进行串行化访问(Cannot serialize access)错误,因为阻塞事务在串行化等待事务开始后更新了后者所存取的数据。
3.而也是由于oracle事务之间不会读写互斥,所以即使是串行化也不能保证在应用层的数据最终一致性,在查询时可以使用select for update来锁住查询的数据块保证不会被其他事务需修改。

  • 事务流程:

oracle没有显示开始事务的语句,一次事务从某个会话开始执行DML语句(增删改查)开始
oracle也不会自动提交事务,事务开始后可以执行任意数量的sql语句,也可以使用savepoint指定保存点,但不支持嵌套事务。
直到出现了用户执行了commit/rollback语句、执行DDL/DCL语句、会话关闭、系统崩溃、退出sql编辑工具等情形时,事务就会被结束。通常在退出某些sql编辑工具时,内嵌的commit/rollback语句就会被执行

一致性读

1.在oracle中,一致性读分为语句级一致性读和事务级一致性读
2.想实现一致性读,借助的是undo数据块与SCN机制。语句级一致性读记录的是本次语句开始时的SCN号,而事务级一致性读记录的是事务开始时的SCN号。
3.SCN机制指的是oracle内部的类似时间戳一样的机制,每当对一个数据块执行DML操作时,都会将最新(最大)的SCN号存在数据段的ITL槽中。数据库使用一个事务表,也称感兴趣事务列表 (ITL) ,来确定当数据库开始修改块时是否某个事务还未提交。每个段块的块头包含一个事务表。事务表中的条目描述了哪些事务有被锁定的行,以及块中的哪些行包含提交和未提交的更改。事务表指向undo段,提供对数据库所做的更改的时间相关信息。
4. 在进行DML操作时,insert、update、delete操作时,undo段记录本次事务操作之前的原数据(反向操作)并且redo日志也记录undo段的操作,既redo保护undo段的信息。当实例关闭或意外崩溃后,再次open时实例需要对没有commit的事务进行回滚,完成事务的恢复。
5.而undo段不止记录本次事务操作之前的原数据(反向操作),还记录了操作之前该数据块的ITL槽数据。如果当前undo块的SCN号仍比记录的大,则根据该undo块的ITL槽中记录的上个undo块的地址找到上个undo块,再比对上个undo块的ITL槽记录的SCN号,可以不断的通过比对SCN号->根据记录的地址找undo块,直到找到满足一致性读的SCN号,则把对应的undo块取出,与当前数据库合并,构造出当时的数据块(CR块)返回
6.假设现有一次select操作,开始时的SCN号是1000。如果扫描到某个要使用的数据块,发现该块的SCN号小于1000,则取出数据。扫描到下一个数据块,发现SCN号大于1000,则按上述步骤向前查找该块SCN号小于1000的undo块,找到就构造CR块,如果找到最后一个undo块发现SCN号还是比1000大,则报快照过旧错误。
7.不过注意,即使当前undo块的SCN号小于1000,但是如果该unod块的状态为活动,那么表示有个还未提交/回滚的事务还在操作该undo块,那么必须继续向前查找。

undo块的四种状态

  1. freed:表示该undo块内容是空的,从来没有被使用过
  2. active:表示正在使用该undo的事务还没有Commit / Rollback
  3. inactive:表示该undo上没有活动的事务,可以被其他事务覆盖。如果undo表空间太小,或者事务提交过于频繁,会导致inacvice状态的undo块被覆盖数据(有可能最小的SCN号就被覆盖成最新的了),导致某次查询无法向前找到更小的SCN号,快照过旧错误
  4. expired:在oracle 10g开始引入undo_retention参数,该参数是一个时间值。说明当还原段中的事务在提交后继续保留的时间。如果指定了该参数,那么一个undo块保持inactive状态超过该参数的值后就会被标记为expired状态,可被覆盖

二。锁

  1. 在oracle中,锁首先分为行锁TX和表锁TX
  2. 在日常使用时,表锁TX一般不会显示添加,而是通过执行语句,在申请对应的行锁时,先申请对应级别的表锁来防止DDL语句修改表,再申请对应的行锁

行锁

  1. 没有锁,select语句就是这种情况
  2. 行级排他锁-X,其他事务不能对添加了行级排他锁的记录执行DML语句中的增删改语句

表锁
在oracle中,可以在需要行锁的时候由oracle隐式的添加对应级别的表锁,也可以自己手动申请表锁,所有级别均可手动申请,但能够隐式申请的只有RS和RX级别。所有的表级锁均不允许其他事务再添加表级排他锁-X,下述级别说明中不再重复该点

  1. RS锁,一般由select … from xxx update语句引发,锁定表中某些数据行不允许其他事务对该行执行DML语句中的增删改语句,强行保证事务间的数据一致性。

该级别允许其他事务继续添加RS、SRX、RX、S锁
因为只是一个查询语句,所以允许其他事务接着将表设置为行排他、表只读等级别
手动添加:lock table in row share mode

  1. RX锁,一般就是DML中的增删改语句引发,如果事务不提交或回滚来释放RX锁,会导致死锁。

该级别允许其他事务继续添加RS、RX锁
手动添加:lock table in row exclusive mode

  1. S锁,只读锁,只能手动设置,设置后,即使是设置该锁的事务都不能对表进行DML中的增删改操作了。

该级别允许其他事务继续添加S、RS锁,因为都是读锁,所以不影响
手动添加:lock table in share mode

  1. SRX锁,与S锁没关系,是RX锁的升级版

该事务只允许其他事务添加RS锁,锁定数据行,自己还是可以执行对表进行DML中的增删改操作的,当然也就不允许其他事务添加S只读锁了。
手动添加:lock table in share row exclusive mode

  1. X锁,直接锁定整张表,不允许继续添加所有级别的表锁,只能对该表执行普通select语句

手动添加:lock table in exclusive mode

三。死锁

原因
1.行级死锁:执行会产生排他类型锁的语句后不提交或者回滚事务来释放锁,导致其他事务想对该锁范围内的记录执行排他操作时,无限等待
2.ITL死锁:数据块的ITL槽被高并发操作快速用完,然后这些槽内记录的事务信息因为没有提交或者回滚导致无法覆盖继续使用,所以也会无限等待,就会导致死锁。一个数据块默认有两个ITL槽,如果有空闲空间可以继续分配,但是还是预先设置足够多的个数比较好。
行级死锁类型

  1. 主键死锁,因为主键默认唯一,如果两个事务插入不同值后不提交,然后交换插入的值,因为对应位置已经被行锁锁定了,就会产生死锁。
  2. 外键死锁:外键未加索引很容易导致死锁。如果外键没有索引,更新或者删除父表的主键,都会导致对其子表加一个全表锁。如果父表存在删除记录或者更改外键列的情形,那么就需要在子表上为外键列创建索引。
  3. 位图索引死锁:表上的位图索引遭到并发更新也很容易产生死锁。在有位图索引存在的表上面,其实很容易就引发阻塞与死锁。这个阻塞不是发生在表上面,而是发生在索引上。因为位图索引锁定的范围远远比普通的b-tree索引锁定的范围大。因为位图索引的特性,一个值的"位图"是所有行是否存在该值的结果形成的数字串,所以更新一个值时会锁住所有行。
  4. 不同事务之间的死锁:如果你有两个会话,每个会话都持有另一个会话想要的资源,此时就会出现死锁(deadlock)。例如,如果我的数据库中有两个表A和B,每个表中都只有一行,就可以很容易地展示什么是死锁。我要做的只是打开两个会话(例如,两个SQL*Plus会话)。在会话A中更新表A,并在会话B中更新表B。现在,如果我想在会话B中更新表A,就会阻塞。会话A已经锁定了这一行。这不是死锁;只是阻塞而已。因为会话A还有机会提交或回滚,这样会话B就能继续。如果我再回到会话A,试图更新表B,这就会导致一个死锁。要在这两个会话中选择一个作为“牺牲品”,让它的语句回滚。 想要更新表B的会话A还阻塞着,Oracle不会回滚整个事务。只会回滚与死锁有关的某条语句。会话B仍然锁定着表B中的行,而会话A还在耐心地等待这一行可用。收到死锁消息后,会话B必须决定将表B上未执行的工作提交还是回滚,或者继续走另一条路,以后再提交。一旦这个会话执行提交或回滚,另一个阻塞的会话就会继续,好像什么也没有发生过一样。
  5. 自治事务死锁:存储过程INSERT表A,然后INSERT表B;其中INSERT表A触发TRIGGER T,T也INSERT表B,T是自治事务(AT),AT试图获取对B的锁,结果B已经被主事务所HOLD,这里会报出来ORA-00060 – 等待资源时检查到死锁

四。数据字典

数据字典

  • 数据字典是Oracle数据库中的一系列只读的参考表和视图。它与数据库内的其他数据相同,也是以标及视图的形式组织的。一个数据库的全部数据字典表与数据字典视图都物理地存储在该数据库的SYSTEM表空间内。它由两个部分组成:数据字典基本表(也叫基表base table)、数据字典视图(也叫用户访问视图)。
  • 数据字典是整个Oracle数据库的核心之一,描述了数据库自身的信息,以及数据库里记录对象的信息。比如说我们要对一个数据库中的一个表进行一个添加记录的操作。则需要定位到这个表位于哪个数据文件里,这个表的结构是什么等等才能够完成我们操作。数据字典就是记录着这样的信息(是以表的形式记录的)。
  • 数据字典基本表就是给Oracle看的,而数据字典视图是为了方便用户而将基本表简化出来的

数据字典表
基表存储的是一些与数据库相关的信息。只有Oracle才可以读写这些表。用户很少直接访问它们 。因为它们都是规范化的,而且大部分数据都是用一种保护的格式存储的。(只有Oracle才看得 懂,用户是无法看懂里面的信息的)
数据字典视图
视图是对存储在数据字典的基表中的数据的总结与展示。通过用连接和where字句去简化信息 的方法,把这些视图将基表中的数据编码成有用的信息(所谓有用,就是用户可以看懂,理解的 形式),比如用户,表名等,而这种将数据编码是通过用连接和where字句与简化信息。很多用户都被赋予了访问视图的权限,而没有访问基表的权限。

五。链接

常用函数、PL/SQL(重点):Oracle必备知识
视图:Oracle视图详解
临时表空间:临时表空间概念
默认表空间:Oracle 默认表空间(default permanent tablespace) 说明
临时表:Oracle 临时表详解(temporary table)
pctfree和pctused:Oracle pctfree和pctused详解
ITL构造讲的挺好:【锁】Oracle死锁(DeadLock)的分类及其模拟
高水位线:oracle 高水位线详解(删除大量数据后续处理)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值