OCP认证考试指南(9):操纵数据库数据(1)

1、数据库事务

1.1、原子性(A)

原子性(Atomicity)原则规定一个事务的各个部分都必须完成,否则整个事务都不会完成。数据库必须保证两个更新操作都能完成或者都不完成。

1.2、一致性(C)

一致性(Consistency)的原则规定查询的结果必须与数据库在查询开始时的状态一致。例如:查询整个表要数分钟,在查询期间,其他用户更新记录,那查询出来的应该还新值还是旧值?通过使用摊销段,在查询成功的前提下,查询结果是一致的,如果撤消段没有正确配置,查询可能不成功会引发常见的Oracle错误“ORA-1555 snapshot too old(快照过旧)”。

1.3、隔离性(I)

隔离性(Isolation)的原则规定对于其他部分来说,未完成的事务必须不可视。就是说只有执行该事务的一个会话看见所做变化,其他所有会话看见的都是没有变化的数据(而不是更改后的新值)。这点也是通过撤销段来保证的。

1.4、持久性(D)

持久性(Durability)原则规定一旦使用COMMIT命令结束某个事务,就必须保证数据库不丢失这个事务。隔离性是要求除指定会话外的任何用户看不到当前所做变化,事务一旦完成,所有用户都必须能立即看到所做的变化,同时数据库必须保证这些变化绝不会丢失。这点通过日志文件来满足。

2、执行SQL语句

2.1、执行SELECT语句

SELECT语句分阶段执行。服务器进程首先查看包含所需数据的数据块是否已经位于内存和数据库高速缓存区中。如果条件成立,执行就会立即进行。如果条件不成立,服务器必须在磁盘上定位相应的数据块,并将这些数据块复制至数据库高速缓存区,进一步的处理(如排序或聚集)就在指定会话的PGA中完成,执行完成后,结果集返回至用户进程。

如果查询遇到在查询开始之后被改变的数据块,那么服务器进程会进入保护这个变化的撤销段,从而定位原有数据和回滚该变化。这样,在查询开始之后启动的任何变化都不可视。

2.2、执行UPDATE语句

对于DML操作,必须同时处理数据块和撤销块,并且还会生成重做。ACID测试的A、C和I要求生成撤销,D则要求生成重做。

“撤销”不是“重做”的逆过程!对于表段、索引段或撤销段的数据块的变化来说,重做可以保护所有的数据块变化。就重做而言,撤销段只是一个段,对这个段所做的任何变化都必须是持久的。

执行DML语句的第一个步骤与执行SELECT语句第一个步骤相同:必须在内存中查找到所需的数据块或者将所需的数据块从磁盘复制至内存。这个步骤中,二者唯一的不同是执行DML语句还需要某个撤销段的一个空数据块(或过期数据块)。之后,必须在DML操作影响的所有记录以及关联索引键上放置锁定。接下来会生成重做,此时服务器进程在日志缓冲区中写入即将应用于指定数据块的变化。这个重做生成操作应用于数据块的变化和撤销块的变化。如果要更新某个列,这个列的新值(应用于表数据块的变化)以及旧值(应用于撤销块的变化)都会被写入日志缓冲区。如果这个列是某个索引键的一部分,应用于该索引的变化以及保护索引变化的撤销块变化也会被写入日志缓冲区。

生成重做后,就可以在数据库高速缓存区完成下列更新操作:使用变化后的列更新表数据块,未变化的列则被写入撤销段数据块。从这一时刻到提交更新操作的时候,与发生变化的记录相关的其他会话中的所有查询都会被重定向至撤销数据。只有执行更新操作的会话才可以在表数据块中看见更新后的记录。所有关联的索引变化同样也会应用上述原则。

例如:

SQL> update emp set sal = sal * 1.1 where empno = 7934;

为执行这条语句,包含员工号为7934记录的表数据块会被复制至数据库高速缓存区,某个撤销段的数据块也会被复制至数据库的高速缓存区。接下来,服务器进程将未变化的sal列(应用于撤销块的变化)和变化后的sal列(应用于表数据块的变化)都写入日志缓存区。最后,这些数据块会被更新。

2.3、执行INSERT与DELETE语句

INSERT和DELETE语句与UPDATE具有相同的管理方式。其中,重做生成操作完全相同,对数据块和撤销块进行的所有变化都会首先被写入日志缓存区。二者的差异在于所生成的撤销数据量不同。插入一条记录时,生成撤销的操作只涉及为撤销块写下新的rowid。这是由于回滚INSERT语句时,只需要rowid信息。

对于DELETE语句来说,因为整条记录都被写入摊销块,所以在必要时通过在表中插回整条记录就可以回滚这个删除操作。

2.4、执行ROLLBACK命令

出现任何错误,后台进程都会完全自动地回滚正在进行的事务。发出ROLLBACK命令时,用户可以执行手动的回滚操作。无论何种方式回滚,机制都相同。回滚UPDATE,未被更新的列会从撤销块复制回表数据块。回滚INSERT,从撤销块中检索插入记录的rowid,并将其用作在表上进行删除的键。回滚DELETE,根据撤销块中的数据构造一条完整的插入语句。因此,实现ROLLBACK命令时会使用撤销数据来构造和执行反转第一条语句执行结果的另一条语句。

2.5、执行COMMIT命令

执行COMMIT命令时发生的所有物理操作是LGWR进程将日志缓冲区的内容写入磁盘。DBWn进程完全没有执行任何操作。基于这个,某个事务涉及若干分钟或若干小时的更新操作,但这事务可以在不到一秒时间内被提交。因为LGWR进程写入操作接近于实时完成。

DBWn进程与提交处理没有关系,不过最终这个进程会将变化的或“脏的”数据块写入磁盘。在正常运行期间,DBWn进程只将某些脏缓冲区写入磁盘。在需要某个检查点时,DBWn进程会将所有的脏缓冲区写入磁盘。

2.6、DDL与事务控制

COMMIT和ROLLBACK只应用于DML,所以无法回滚DDL语句。DDL语句一旦被执行就会立即具有持久化状态。

例如:如果查看CREATE TABLE命令源代码,其原因就会知道,创建表时,都执行了用于保护数据字典的COMMIT命令。

2.7、所谓的“自动提交”

执行DDL语句就是一种情况,退出用户进程则是另一种情况。

Windows终端上使用SQL*Plus并执行一条DML语句,再执行“退出”,事务就会被提交,这是因为“退出”命令嵌入了一条COMMIT语句。但点击窗口右上角则发现,事务会回滚,因为关闭窗口代码中嵌入一条ROLLBACK语句。全用X Windows形式的SQL*Plus,那么关闭窗口会提交事务。

3、DML与完整性约束

如果多语句事务中的一条语句违反了某个约束,那么只有这条语句被回滚,该事务的其余语句保持完整和未提交状态。

4、练习

练习一下,实践出真知啊!!!

这次我们要开启两个会话:

######################################
# 第一个会话
######################################
SQL> create table t1 as select * from all_users;
 
Table created.
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
        20
 
######################################
# 第二个会话
######################################
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
        20
 
#################################################################
# 两个会话中执行的结果相同
#################################################################
 
######################################
# 第一个会话
######################################
SQL> delete from t1;
 
20 rows deleted.
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
         0
 
######################################
# 第二个会话
######################################
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
        20
 
#################################################################
# 因为隔离原则,所以两个会话执行结果不同
#################################################################
 
######################################
# 第一个会话
######################################
SQL> rollback;
 
Rollback complete.
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
        20
 
######################################
# 第二个会话
######################################
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
        20
 
#################################################################
# 两个会话中执行的结果相同
#################################################################
 
######################################
# 第一个会话
######################################
SQL> delete from t1;
 
20 rows deleted.
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
         0
 
######################################
# 第二个会话
######################################
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
        20
 
######################################
# 第一个会话
######################################
SQL> create view v1 as select * from t1;
 
View created.
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
         0
 
######################################
# 第二个会话
######################################
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
         0
 
######################################
# 第一个会话
######################################
SQL> rollback;
 
Rollback complete.
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
         0
 
######################################
# 第二个会话
######################################
 
SQL> select count(*) from t1;
 
  COUNT(*)
----------
         0
 
#################################################################
# 由于DDL语句提交了事务,因此无法回滚
#################################################################
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值