Oracle--多用户控制

来源:互联网 发布:手机怎么添加mac地址 编辑:程序博客网 时间:2024/06/17 09:02

首先,数据库的用途:
- 存储数据
- 多个用户同时使用数据
控制同时发生的多个数据请求是数据库必须完成的一项非常重要的任务。这也使得数据库变得非常复杂。
- 用户希望自己是数据的唯一用户
- 数据库必须控制可能存在冲突的请求而不能影响性能
- 当应用程序增加时,所有这些特性必须继续作为请求而存在。
这样就必须支持多用户。

多用户的总体目的

  • 数据完整性:某个用户对数据的任何变化不会影响其他用户的数据,而且需要保证返回给用户稳定的数据。这需要数据库内部机制来保证(如约束);
  • 隔离:数据库必须允许在任何时候用户同其他用户隔离
  • 串行化:上述两点带来了复杂性。解决该复杂性的一个办法就是将任何用户的整个工作分割成许多小片,称为事务。数据库必须保证事务是按照逻辑顺序产生的,必须实现所有事务的串行化(有点类似分时操作系统)

事务

  • 事务(transaction)是数据库区别于文件系统的特性之一。
  • 数据库中引入事务的主要目的:事务会把数据库从一种一致状态转变为另一种一致状态。
    -在数据库中提交工作时,可以确保要么所有修改都已经保存,要么所有修改都不保存。
    -另外,事务还能保证实现了保护数据完整性的各种规则和检查。

Oracle中的事务体现了所有必要的ACID特征。ACID是以下4个词的所写:

  • 原子性(atomicity):事务中的所有动作要么都发生,要么都不发生;
  • 一致性(consistency):事务将数据库从一种一致状态转变为下一种一致状态;
  • 隔离性(isolation):一个事务的影响在该事务提交前对其他事务都不可见;
  • 持久性(durability):事务一旦提交,其结果就是永久性的。

Oracle中的事务控制语句有:

  • Commit;
  • Rollback
  • Savepoint
  • Rollback to < savepoint>
  • Set transaction

我们通过事务控制语句显示的结束当前语句,commit会结束事务并且把已修改称为永久性的保存。rollback结束事务,撤销当前正在进行的所有未提交的修改,可以和savePoint结合使用,在事务中实现部分回滚。
用户完整性问题

多名用户同时读取相同的数据会造成完整性的三个基本问题:

  • 丢失更新
  • 不可重复的读取
  • 幻影读取
    丢失更新:主要指的是多个用户同时读取数据时,一个用户覆盖了另一个用户对该数据的更新。
    不可重复读取:在一个事务的不同时间点获取的数据不同。
    幻影读取:是当用户在自己的事务中读取数据时,读取了在事务期间别的用户新增的数据(事务开始时无此数据)。
    为了解决数据完整性问题,引入了锁机制。

  • 数据库中的锁和日常生活当中的锁作用是一样的,都是用于阻止访问。
  • 数据的相互作用决定了锁的两种类型
    -共享锁,有时称为读取锁
    -专用锁,有时称为写操作锁

1.专用锁只允许单独用户对数据段进行访问,数据库无法为已经放置了共享锁的数据段发布一个专用锁
- 如果数据库在事务的中间,允许其他用户改变数据,结果既可能造成丢失更新,或者无法重复读取,以及幻影数据。
2. 这种使用方式造成了读取的冲突:
-设置了共享锁,则无法加专用锁。既读取操作阻塞了写操作;
-设置了专用锁,则无法加共享锁。既写操作阻塞了读取操作。
这种情况甚至会造成死锁。
ORACLE解决方案 — 多版本读取一致性(MVRC):

  • 无论何时任何事务在数据库中改变数据,Oracle都创建一个改变后行的新版本;
  • Oracle使用其回退缓冲区存储行的早期版本;
  • 每个行版本标记了事务的系统改变号码(SCN)。每个事务获得一个全局SCN号码,分配在事务开始的顺序中。SCN提供事务连续顺序的完全记录。

1.Oracle 自动为查询提供了读一致性,使得查询得到的全部数据来自一个的单一时间点 (statement-level read consistency,称为语句一致性).
2.Oracle 还可以针对一个事务对事务中的查询提供一致性 (transaction-level read consistency,称为事务一致性).
3.Oracle 在回滚段中(rollback segments)保存已经被修改过的数据的历史版本,并依据这些数据来提供上述两种一致性。

这样oracle通过在回滚段中保存已经被修改过的数据的历史版本来保证这些数据的语句一致性和事务一致性。

首相,Oracle中,当事务开始时,MRVC给每个用户一个特定的数据视图,因此无需使用读取锁。这样的话并不需要读取锁,每个用户想要更新数据时,不需要对数据进行保护,会直接读取数据的前一个版本。一个事务可以在任何时间获得读取锁。
但这样oracle数据库在运行时会比一般的数据库性能要高。

另一种解决方案 — 事务隔离级别

SQL标准定义了4种事务隔离级别,对于相同的事务,采用不同的隔离级别分别有不同的结果。
隔离级别根据三个现象来划定:

  • 脏读(dirty read):读取了未提交的数据;如果允许脏读将影响数据完整性、破坏外键约束,而且会忽略唯一性约束;
  • 不可重复读(non-repeatable read)
  • 幻象读(phantom read):已经读取的数据不会改变,只是可能会有更多的数据。

SQL隔离级别根据上述三个现象定义。它并没有强制采用某种特定的锁定机制,允许有多种不同的锁定/并发机制存在。

这里写图片描述

通过表格可以看到在不同的级别里面有不同的现象出现。

事务隔离级别:

  • READ COMMITTED
    –“提交读”隔离级别是指事务只能读取数据库中已经提交的数据。这里没有脏读,但是有:不可重复读,幻像读。
    – “提交读”在数据库中是最常用的隔离级别,也是oracle数据库的默认模式。
  • REPEATABLE READ
    –目标:不仅能够给出一致的正确答案,还能避免丢失更新。加共享锁
    – 在一个采用共享读锁的数据库中,该隔离级别保证不会发生丢失更新错误。
    – 最大的缺点是严重地限制并发读写,存在幻象读现象。
  • SERIALIZABLE
    – 最受限制的隔离级别,但提供了最高程度的隔离性;
    – Serializable隔离级别中的事务,在一个环境中操作时,就好像没有别的用户在修改数据库中的数据一样;
    – 读取的所有行在重新读取时都肯定一样,所执行的查询在整个事务期间也总能返回相同的结果。
    – 完全消除了“脏读”、不可重复读和幻象读现象。

    在使用时应注意:

    • 一般没有其他人修改同样的数据
    • 需要事务级读一致性
    • 事务都很短(这有助于保证第一点)
  • READ ONLY
    – Read only事务与serializable事务相似,惟一的区别是read only事务不允许修改,因此不会遭遇ora-08177错误。
    – Read only事务的目的是支持报告需求,即相对于某个时间点,报告的内容应该是一致的。
    – 其他数据库实现此功能需要使用共享锁;oracle通过read only实现,而无需在任何地方锁定数据。

oracle在解决多用户控制上提出了锁机制,但是锁机制又产生出了新的问题–死锁,为了解决这些问题,Oracle解决方案:多版本读取一致性和在三个并发现象:幻象读、不可重复读、脏读上提出了4种事务隔离级别,来解决并发读取问题。

理解比较浅,希望可以和大家一起交流。

0 1