- 浏览: 495597 次
- 性别:
- 来自: OnePiece
文章分类
- 全部博客 (196)
- --------- 基础----------- (0)
- java 碎碎念 (12)
- java 并行编程 (11)
- java I/O (6)
- java Charset & Encoding (2)
- spring学习笔记 (8)
- 正则表达式 (5)
- web前端-javascript (11)
- web前端-jQuery (7)
- web前端-碎碎念 (1)
- mybatis (0)
- 数据库-通用 (8)
- 数据库-oracle (20)
- nosql-redis (11)
- nosql-mongoDB (1)
- xml (2)
- log4j (2)
- uml (3)
- web services: soap/wsdl (6)
- soa-tuscany (2)
- linux (6)
- ----------修养----------- (0)
- 深入理解java虚拟机 (7)
- java 设计模式 (9)
- 数据结构和算法 (2)
- 读书笔记--代码整洁之道 (2)
- 计算机基础 (1)
- -----------践行---------- (0)
- 重构(refactor) (7)
- jvm-诊断 (4)
- 数据库-让oracle跑得更快 (7)
- Nginx (6)
- ehcache (2)
- 短信开发 (1)
- Servlet+Filter+Listener (2)
- 运维 (6)
- 问题记录 (38)
- 杂七杂八 (12)
最新评论
-
zhanggang807:
第二种方法比较好
<spring> 定时任务每次都执行两次的问题,慎用new ClassPathXmlApplicationContext() -
assasszt:
谢谢分享,很清楚的讲明了原理。
字符集与字符编码简介 -
su0nils000:
难得的笔记
<进阶-2> 打造高效正则表达式 -
足至迹留:
mini188 写道用MD5来解决碰撞是不是也是可行的呢?个人 ...
Hash简介 -
mini188:
用MD5来解决碰撞是不是也是可行的呢?
Hash简介
事务(transaction)是数据库区别于文件系统的特性之一。在文件系统中,如果你正把文件写到一半,操作系统就崩溃了,这个文件就很可能会被破坏。这正是数据库中引入事务的主要目的,事务会把数据库从一种一致状态转变为另一种一致状态。在数据库中提交工作时,可以确保要么所有修改都已经保存,要么所有修改都不保存。
Oracle中的事务体现了所有必要的ACID特征。
原子性(Atomicity):事务中的所有动作要么都发生,要么都不发生。
一致性(Consistency):事务将数据库从一种一致状态变为下一种一致状态。
隔离性(Isolation):一个事务的影响在该事务提交前对其他事务都不可见。
持久性(Durability):事务一旦提交,其结果就是永久性的。
7.1 事务控制语句
Oracle中不需要专门的语句来“开始事务”。事务会在修改数据的第一条语句处隐式开始(也就是得到TX锁的第一条语句)。也可以使用set transaction或DBMS_TRANSACTION包来显式地开始一个事务,但是这一步并不是必要的,这与其他的许多数据库不同,因为那些数据库中都必须显式开始事务。如果发出commit或rollback语句(注意rollback to savepoint不会结束事务),就会显式地结束一个事务。
如果正常退出sql*plus会话,而没有提交或回滚事务,sql*plus会自动完成提交。不要过分依赖这些隐式行为,一定要显式提交或回滚。
Oracle中的事务是原子性的,这说明无非两种情况:构成事务的每条语句都会提交(成为永久)或者所有语句都回滚。注意这里的“所有”,也就是当成了一个整体。
我们可以了解到控制事务的语句只有:commit,rollback, savepoint, rollback to <savepoint>,set transaction五种。
7.2 原子性
前面对事务控制语句做了一个简要的概述后,下面可以看看语句原子性、过程原子性和事务原子性的含义。
7.2.1 语句级原子性
考虑以下语句:
insert into t values(1);
如果该语句由于一个约束冲突而失败,这一行就不会插入。不过再考虑下面的例子,表T上的一个insert或delete会触发一个触发器,它将适当地调整t2表上的列:
T2: create table t2 (cnt int);
T: create table t (x int check (x > 0));
创建触发器:
这种情况下往T表插入数据,会发生什么就不那么显而易见了。如果触发器触发之后出现了错误,触发器的影响是否还存在?也就是如果触发器被触发,并且更新了t2,但是这一行没有插入到T中,结果会怎样?期望的结果是,如果并没有真正在T中插入一行,我们就不希望T2中的cnt列增加。幸运的是,在oracle中,客户最初发出的语句(在这里就是insert into t)会完全成功或完全失败。这个语句是原子性的,同时insert into T的任何连带效果都被认为是该语句的一部分,这里就是触发器。
为了得到这种语句级原子性,oracle悄悄地在每个数据库调用外面包了一个savepoint。前面的insert 语句实际处理如下:
在Sybase或sqlserver中刚好相反。这些系统中的触发器会独立于触发语句执行。如果触发器遇到一个错误,它必须显式地回滚自己的工作,然后产生另外一个错误来回滚触发语句。
7.2.2 过程级原子性
有意思的是,oracle把pl/sql匿名块也当做是语句。比如以下存储过程:
继续沿用上节的check约束,在这个过程中,第二个insert总会失败。这时候我们调用这个存储过程会发现表t里总是空的。也就是整体没有插入数据。但是如果我们调用p的时候自己捕获了错误,那第一句插入就会成功。因为oracle没有捕获到异常发生,当做事务成功,就会提交。
7.2.3 事务级原子性
事务的总目标是把数据库从一种一致状态转变为另一种一致状态。为了实现这个目标,事务也是原子性的,事务完成的所有工作要么完全提交称为永久性的,要么回滚并撤销。
7.2.4 DDL与原子性
需要指出,oracle中有一类语句具有原子性,不过只是在语句级保证原子性。DDL(数据定义语言, Data Definition Language, DDL)语句采用了一种特定的实现方式,可以完成如下工作:
(1) 提交当前所有未完成的工作,结束当前已有的所有事务。
(2) 完成DDL操作,如create table.
(3) 如果DDL操作成功则提交,否则回滚DDL操作。
7.3 持久性
通常情况下,一个事务提交时,它的改变就是永久性的。即使数据库在提交完成之后随即崩溃,你也完全可以相信这些改变确实已经永久存储在数据库中。不过,下述两种情况例外:
(1) 使用commit语句新增的write扩展(这是oracle database 10g release2及以上版本中新增的特性)。
(2) 在非分布式(只访问一个数据库,而不是多个数据库连接)pl/sql代码块中执行commit.
7.3.1 commit的write扩展
在oracle 10g release2及以上版本中,可以为commit语句增加一个write子句。这个write子句允许等到生成的redo写至磁盘之后再提交(wait,这是默认选项),或者不等写redo就直接提交(nowait)。
通常情况下,commit是一个同步过程,应用首先调用commit,然后等待整个commit处理完成。在oracle 10g release2之前,所有oracle版本支持的都是这种commit行为,这也是oracle 10g release2及以上版本的默认行为。
Oracle的当前版本中,并不需要等待提交完成(这需要一定的时间,因为提交涉及一个物理IO操作,要向存储在磁盘上的redo日志文件完成物理写操作),可以在后台完成提交。这会带来一个副作用:提交不能保证持久性。也就是说,应用可能会从该数据库得到一个响应,指出已经收到你的异步提交,而且其他会话能够看到你做出的改变,不过后来却发现你原以为已经提交的事务实际上并未真正提交。这种情况很少见,往往涉及严重的硬件或软件故障。要让一个异步提交不具有持久性,数据库必须异常关闭,这意味着数据库实例或运行这个数据库实例的计算机必须完全失效。
那么,既然事务要保证持久性,这种可能导致非持久性的特性又有什么用呢?答案在于性能。在应用中发出一个commit时,会请求LGWR进程得到生成的redo,并确保将生成的这些redo写至在线redo日志文件。完成物理IO操作的速度相当慢,所以,commit甚至比事务中DML语句本身耗时还要长。如果异步完成commit,就不再需要等待客户应用中的物理IO,这会让客户应用速度更快,特别是如果有大量commit,异步提交会让速度大大提高。
既然如此,为什么不总是使用commit write nowait呢?记住,正确性永远位于首位。只有3种特殊情况才需要使用nowait:
(1) 定制的数据加载程序。
(2) 处理某种实时数据,这些数据对时间敏感,即使失败也可能会被覆盖或丢弃。
(3) 应用实现了自己的“排队”机制。
你会注意到这3种应用个都是后台的非交互式应用,他们不会与人直接交互。如果应用需要与人交互,向用户报告“提交完成”,就应当使用同步提交。对于面向客户的在线应用,不能把异步提交作为改善性能的手段。异步提交只适应于面向批处理的应用。因此除了这3类批处理应用外,其他应用中都不该使用这个新功能—commit write nowait。
7.3.2 非分布式pl/sql代码块中的commit
从oracle6引入pl/sql以来,pl/sql一直都透明地使用异步提交。这种做法是可行的,因为从某种意义来说所有pl/sql都类似于批处理程序,即在pl/sql过程完全执行完之前,最终用户无法知道过程的结果。也正是因为这个原因,这种异步提交只能用于非分布式的pl/sql代码块;如果涉及到多个数据库,会有两个对象(两个数据库)依赖于提交的持久性。倘若两个数据库都依赖于提交的持久性,就必须采用同步协议,否则可能在一个数据库中改变已经提交,而在另一个数据库中未提交。
7.4 完整性约束和事务
默认情况下,完整性约束会在整个sql语句得到处理之后才进行检查。也有一些可延迟的约束允许将完整性约束的验证延迟到应用请求时(发出一个set constraints all immediate命令)才完成,或者延迟到发出commit时再检查。
7.4.1 immediate约束
在讨论的前一部分,我们假设约束都是immediate模式,这也是一般情况。在这种情况下,完整性约束会在整个sql语句得到处理之后立即检查。注意,这里用的是“sql语句”而不是“语句”。如果一个pl/sql存储过程中有多条sql语句,那么在每条sql语句执行之后都会立即验证其完整性约束,而不是在这个存储过程完成后才检查它。比如update语句会影响多条语句,则会在所有需要更新的语句更新完后才检查一次,而不是每变化一行数据就检查一次。
7.4.2 deferrable约束和级联更新
从oracle8开始,我们还能够延迟约束检查,对于许多操作来说,这很有好处。首先能想到的是可能需要将一个主键的update级联到子键。在以前的版本中,确实也可以完成cascade udpate,但是为此需要做大量的工作,而且存在某些限制。有了可延迟约束后,这就变得易如反掌了。
7.5 不好的事务习惯
许多开发人员在事务方面都有一些不好的习惯。例如在Informix、sybase和sqlserver中,必须显式地begin一个事务;否则,每条单个的语句本身就是一个事务。Oracle在具体的语句外包了一个savepoint,采用类似的方式,哪些数据库则在各条语句外报了一个begin work/commit或rollback。这是因为,在这些数据库中,锁是稀有资源,另外读取器会阻塞写入器,反之,写入器也会阻塞读取器。为了提高并发性,这些数据库希望你的事务越小越好,有时甚至会以数据完整性为代价来做到这一点。
Oracle则采用了完全不同的方法。事务总是隐式的,没有办法“自动提交”事务,除非应用专门实现。在oracle中,每个事务都应该只在必要时才提交。事务的大小要根据需要而定。锁、阻塞等问题并不是决定事务大小的关键,数据完整性才是确定事务大小的根本。
7.5.1 在循环中提交
如果交给你一个任务,要求更新多行,大多数程序员都会力图找出一种过程性方法,通过循环来完成这个任务,这样就能提交多行。通常这样做的两个主要原因是:
(1) 频繁地提交大量小失误比处理和提交一个大事务快;
(2) 没有足够的undo空间。
这两个原因都存在误导性。另外,如果提交地太过频繁,很容易陷入危险,倘若更新做到一半时失败了,就会使你的数据库处于一种未知的状态。到目前为止,最好的办法是按业务过程的要求以适当的频度提交,并且相应地设置undo段的大小。
7.5.2 使用自动提交
关于不好的事务习惯,最后要说的是由于使用流行的编程api(odbc或jdbc)所带来的问题。这些api会默认“自动提交”(autocommit)。使用jdbc的一个好习惯是获取连接后,设置setAutocommit(false);
但是设置之后,使用更加要小心,不仅要手动commit,在失败的地方还要手动rollback,否则如果是使用了连接池,那就不会释放锁,导致锁表。还可以参考:
http://ygsilence.iteye.com/blog/1297762
7.6 分布式事务
Oracle有很多很好的特性,其中之一就是能够透明的处理分布式事务。在一个事务的范围内,可以更新多个不同数据库的数据。提交时,要么提交所有实例的更新,要么一个都不提交(它们都会回滚)。为此,我们不需要另外编写任何代码,只是提交就行了。
Oracle中分布式事务的关键是数据库链接(database link)。数据库链接是一个数据库对象,描述了如果从你的实例登陆到另一个实例。一旦建立了一个数据库链接,访问远程对象就很简单了,如下:
Select * from T@another_database;
这会从数据库链接another_database所定义数据库实例的表T中选择。一般地,你会创建表T的一个视图(或一个同义词)来隐藏T是一个远程表的事实。比如:create synonym T for T@another_database;
现在执行一个分布式事务与执行一个本地事务没什么两样:
Update local_table set x=5;
Update remote_table@another_database set y=10;
Commit;
Oracle会完成所有数据库中的提交,或都不提交。它使用了一个2PC(two-phase commit protocol,二段提交协议)来做到这一点。2PC是一个分布式协议,如果一个修改影响到多个不同的数据库,2PC允许原子性地提交这个修改。
对于分布式事务中能做的事情,还存在一些限制,这些限制是合理的:
(1) 不能在数据库链接上发出commit。也就是说,不能发出commit@remote_site,只能从发起事务的那个站点提交。
(2) 不能在数据库链接上完成DDL,因为DDL会提交,违反上面那条限制。
(3) 不能在数据库连接上发出savepoint.
Oracle中的事务体现了所有必要的ACID特征。
原子性(Atomicity):事务中的所有动作要么都发生,要么都不发生。
一致性(Consistency):事务将数据库从一种一致状态变为下一种一致状态。
隔离性(Isolation):一个事务的影响在该事务提交前对其他事务都不可见。
持久性(Durability):事务一旦提交,其结果就是永久性的。
7.1 事务控制语句
Oracle中不需要专门的语句来“开始事务”。事务会在修改数据的第一条语句处隐式开始(也就是得到TX锁的第一条语句)。也可以使用set transaction或DBMS_TRANSACTION包来显式地开始一个事务,但是这一步并不是必要的,这与其他的许多数据库不同,因为那些数据库中都必须显式开始事务。如果发出commit或rollback语句(注意rollback to savepoint不会结束事务),就会显式地结束一个事务。
如果正常退出sql*plus会话,而没有提交或回滚事务,sql*plus会自动完成提交。不要过分依赖这些隐式行为,一定要显式提交或回滚。
Oracle中的事务是原子性的,这说明无非两种情况:构成事务的每条语句都会提交(成为永久)或者所有语句都回滚。注意这里的“所有”,也就是当成了一个整体。
我们可以了解到控制事务的语句只有:commit,rollback, savepoint, rollback to <savepoint>,set transaction五种。
7.2 原子性
前面对事务控制语句做了一个简要的概述后,下面可以看看语句原子性、过程原子性和事务原子性的含义。
7.2.1 语句级原子性
考虑以下语句:
insert into t values(1);
如果该语句由于一个约束冲突而失败,这一行就不会插入。不过再考虑下面的例子,表T上的一个insert或delete会触发一个触发器,它将适当地调整t2表上的列:
T2: create table t2 (cnt int);
T: create table t (x int check (x > 0));
创建触发器:
create trigger t_trigger before insert or delete on t for each row begin if (inserting) then Update t2 set cnt = cnt + 1; else update t2 set cnt = cnt – 1; end if; dbms_output.put_line(‘I fired and updated’ || sql%rowcount || ‘ rows’); end; /
这种情况下往T表插入数据,会发生什么就不那么显而易见了。如果触发器触发之后出现了错误,触发器的影响是否还存在?也就是如果触发器被触发,并且更新了t2,但是这一行没有插入到T中,结果会怎样?期望的结果是,如果并没有真正在T中插入一行,我们就不希望T2中的cnt列增加。幸运的是,在oracle中,客户最初发出的语句(在这里就是insert into t)会完全成功或完全失败。这个语句是原子性的,同时insert into T的任何连带效果都被认为是该语句的一部分,这里就是触发器。
为了得到这种语句级原子性,oracle悄悄地在每个数据库调用外面包了一个savepoint。前面的insert 语句实际处理如下:
savepoint statement1; Insert into t values (1); If error then rollback to statement1; savepoint statement2; Insert into t values (-1); if error then rollback to statement2;
在Sybase或sqlserver中刚好相反。这些系统中的触发器会独立于触发语句执行。如果触发器遇到一个错误,它必须显式地回滚自己的工作,然后产生另外一个错误来回滚触发语句。
7.2.2 过程级原子性
有意思的是,oracle把pl/sql匿名块也当做是语句。比如以下存储过程:
Create or replace procedure p as Begin Insert into t values (1); Insert into t values (-1); End; /
继续沿用上节的check约束,在这个过程中,第二个insert总会失败。这时候我们调用这个存储过程会发现表t里总是空的。也就是整体没有插入数据。但是如果我们调用p的时候自己捕获了错误,那第一句插入就会成功。因为oracle没有捕获到异常发生,当做事务成功,就会提交。
7.2.3 事务级原子性
事务的总目标是把数据库从一种一致状态转变为另一种一致状态。为了实现这个目标,事务也是原子性的,事务完成的所有工作要么完全提交称为永久性的,要么回滚并撤销。
7.2.4 DDL与原子性
需要指出,oracle中有一类语句具有原子性,不过只是在语句级保证原子性。DDL(数据定义语言, Data Definition Language, DDL)语句采用了一种特定的实现方式,可以完成如下工作:
(1) 提交当前所有未完成的工作,结束当前已有的所有事务。
(2) 完成DDL操作,如create table.
(3) 如果DDL操作成功则提交,否则回滚DDL操作。
7.3 持久性
通常情况下,一个事务提交时,它的改变就是永久性的。即使数据库在提交完成之后随即崩溃,你也完全可以相信这些改变确实已经永久存储在数据库中。不过,下述两种情况例外:
(1) 使用commit语句新增的write扩展(这是oracle database 10g release2及以上版本中新增的特性)。
(2) 在非分布式(只访问一个数据库,而不是多个数据库连接)pl/sql代码块中执行commit.
7.3.1 commit的write扩展
在oracle 10g release2及以上版本中,可以为commit语句增加一个write子句。这个write子句允许等到生成的redo写至磁盘之后再提交(wait,这是默认选项),或者不等写redo就直接提交(nowait)。
通常情况下,commit是一个同步过程,应用首先调用commit,然后等待整个commit处理完成。在oracle 10g release2之前,所有oracle版本支持的都是这种commit行为,这也是oracle 10g release2及以上版本的默认行为。
Oracle的当前版本中,并不需要等待提交完成(这需要一定的时间,因为提交涉及一个物理IO操作,要向存储在磁盘上的redo日志文件完成物理写操作),可以在后台完成提交。这会带来一个副作用:提交不能保证持久性。也就是说,应用可能会从该数据库得到一个响应,指出已经收到你的异步提交,而且其他会话能够看到你做出的改变,不过后来却发现你原以为已经提交的事务实际上并未真正提交。这种情况很少见,往往涉及严重的硬件或软件故障。要让一个异步提交不具有持久性,数据库必须异常关闭,这意味着数据库实例或运行这个数据库实例的计算机必须完全失效。
那么,既然事务要保证持久性,这种可能导致非持久性的特性又有什么用呢?答案在于性能。在应用中发出一个commit时,会请求LGWR进程得到生成的redo,并确保将生成的这些redo写至在线redo日志文件。完成物理IO操作的速度相当慢,所以,commit甚至比事务中DML语句本身耗时还要长。如果异步完成commit,就不再需要等待客户应用中的物理IO,这会让客户应用速度更快,特别是如果有大量commit,异步提交会让速度大大提高。
既然如此,为什么不总是使用commit write nowait呢?记住,正确性永远位于首位。只有3种特殊情况才需要使用nowait:
(1) 定制的数据加载程序。
(2) 处理某种实时数据,这些数据对时间敏感,即使失败也可能会被覆盖或丢弃。
(3) 应用实现了自己的“排队”机制。
你会注意到这3种应用个都是后台的非交互式应用,他们不会与人直接交互。如果应用需要与人交互,向用户报告“提交完成”,就应当使用同步提交。对于面向客户的在线应用,不能把异步提交作为改善性能的手段。异步提交只适应于面向批处理的应用。因此除了这3类批处理应用外,其他应用中都不该使用这个新功能—commit write nowait。
7.3.2 非分布式pl/sql代码块中的commit
从oracle6引入pl/sql以来,pl/sql一直都透明地使用异步提交。这种做法是可行的,因为从某种意义来说所有pl/sql都类似于批处理程序,即在pl/sql过程完全执行完之前,最终用户无法知道过程的结果。也正是因为这个原因,这种异步提交只能用于非分布式的pl/sql代码块;如果涉及到多个数据库,会有两个对象(两个数据库)依赖于提交的持久性。倘若两个数据库都依赖于提交的持久性,就必须采用同步协议,否则可能在一个数据库中改变已经提交,而在另一个数据库中未提交。
7.4 完整性约束和事务
默认情况下,完整性约束会在整个sql语句得到处理之后才进行检查。也有一些可延迟的约束允许将完整性约束的验证延迟到应用请求时(发出一个set constraints all immediate命令)才完成,或者延迟到发出commit时再检查。
7.4.1 immediate约束
在讨论的前一部分,我们假设约束都是immediate模式,这也是一般情况。在这种情况下,完整性约束会在整个sql语句得到处理之后立即检查。注意,这里用的是“sql语句”而不是“语句”。如果一个pl/sql存储过程中有多条sql语句,那么在每条sql语句执行之后都会立即验证其完整性约束,而不是在这个存储过程完成后才检查它。比如update语句会影响多条语句,则会在所有需要更新的语句更新完后才检查一次,而不是每变化一行数据就检查一次。
7.4.2 deferrable约束和级联更新
从oracle8开始,我们还能够延迟约束检查,对于许多操作来说,这很有好处。首先能想到的是可能需要将一个主键的update级联到子键。在以前的版本中,确实也可以完成cascade udpate,但是为此需要做大量的工作,而且存在某些限制。有了可延迟约束后,这就变得易如反掌了。
7.5 不好的事务习惯
许多开发人员在事务方面都有一些不好的习惯。例如在Informix、sybase和sqlserver中,必须显式地begin一个事务;否则,每条单个的语句本身就是一个事务。Oracle在具体的语句外包了一个savepoint,采用类似的方式,哪些数据库则在各条语句外报了一个begin work/commit或rollback。这是因为,在这些数据库中,锁是稀有资源,另外读取器会阻塞写入器,反之,写入器也会阻塞读取器。为了提高并发性,这些数据库希望你的事务越小越好,有时甚至会以数据完整性为代价来做到这一点。
Oracle则采用了完全不同的方法。事务总是隐式的,没有办法“自动提交”事务,除非应用专门实现。在oracle中,每个事务都应该只在必要时才提交。事务的大小要根据需要而定。锁、阻塞等问题并不是决定事务大小的关键,数据完整性才是确定事务大小的根本。
7.5.1 在循环中提交
如果交给你一个任务,要求更新多行,大多数程序员都会力图找出一种过程性方法,通过循环来完成这个任务,这样就能提交多行。通常这样做的两个主要原因是:
(1) 频繁地提交大量小失误比处理和提交一个大事务快;
(2) 没有足够的undo空间。
这两个原因都存在误导性。另外,如果提交地太过频繁,很容易陷入危险,倘若更新做到一半时失败了,就会使你的数据库处于一种未知的状态。到目前为止,最好的办法是按业务过程的要求以适当的频度提交,并且相应地设置undo段的大小。
7.5.2 使用自动提交
关于不好的事务习惯,最后要说的是由于使用流行的编程api(odbc或jdbc)所带来的问题。这些api会默认“自动提交”(autocommit)。使用jdbc的一个好习惯是获取连接后,设置setAutocommit(false);
但是设置之后,使用更加要小心,不仅要手动commit,在失败的地方还要手动rollback,否则如果是使用了连接池,那就不会释放锁,导致锁表。还可以参考:
http://ygsilence.iteye.com/blog/1297762
7.6 分布式事务
Oracle有很多很好的特性,其中之一就是能够透明的处理分布式事务。在一个事务的范围内,可以更新多个不同数据库的数据。提交时,要么提交所有实例的更新,要么一个都不提交(它们都会回滚)。为此,我们不需要另外编写任何代码,只是提交就行了。
Oracle中分布式事务的关键是数据库链接(database link)。数据库链接是一个数据库对象,描述了如果从你的实例登陆到另一个实例。一旦建立了一个数据库链接,访问远程对象就很简单了,如下:
Select * from T@another_database;
这会从数据库链接another_database所定义数据库实例的表T中选择。一般地,你会创建表T的一个视图(或一个同义词)来隐藏T是一个远程表的事实。比如:create synonym T for T@another_database;
现在执行一个分布式事务与执行一个本地事务没什么两样:
Update local_table set x=5;
Update remote_table@another_database set y=10;
Commit;
Oracle会完成所有数据库中的提交,或都不提交。它使用了一个2PC(two-phase commit protocol,二段提交协议)来做到这一点。2PC是一个分布式协议,如果一个修改影响到多个不同的数据库,2PC允许原子性地提交这个修改。
对于分布式事务中能做的事情,还存在一些限制,这些限制是合理的:
(1) 不能在数据库链接上发出commit。也就是说,不能发出commit@remote_site,只能从发起事务的那个站点提交。
(2) 不能在数据库链接上完成DDL,因为DDL会提交,违反上面那条限制。
(3) 不能在数据库连接上发出savepoint.
发表评论
-
<让oracle跑得更快-7> AWR性能报告
2015-03-01 22:45 2132AWR是oracle 10g下提供的一 ... -
<让oracle跑得更快-6> 绑定变量
2015-02-28 21:52 1249变量绑定是OLTP系统中一 ... -
<让oracle跑得更快-5> 执行计划
2015-02-28 21:48 1291如果要分析某条(不是整体性能,后面还会讲到awr报告,会再次说 ... -
<让oracle跑得更快-4> 优化器(optimizer)
2015-02-27 21:27 2056Oracle数据库中优化器(o ... -
<让oracle跑得更快-3> latch和等待
2015-02-27 21:18 1170经常有人把latch造成的 ... -
<让oracle跑得更快-2> 锁和阻塞
2015-02-26 22:24 11672.1 锁和阻塞 首先,注意区别并发(concurrency) ... -
<让oracle跑得更快-1> 引起数据库性能问题的因素
2015-02-26 22:04 1544此《让oracle跑得更快》 ... -
OLTP(联机事务处理)和OLAP(联机分析处理) 【转】
2015-02-12 14:13 1248做数据库优化时,一定要先了解数据库支撑的应用特点,不同类型的应 ... -
<oracle优化>(url收藏)
2015-02-11 22:18 8231. CBO & RBO Rule Based Opt ... -
<oracle-11> 数据类型
2015-02-08 20:06 2555选择一个正确的数据类 ... -
<oracle-10> 索引
2015-02-01 21:19 2036索引是应用设计和开发的一个重要方面。如果有太多的索引,修改(插 ... -
<oracle-9> 数据库表
2015-01-30 15:44 13209.1 表类型 Oracle主要有 ... -
<oracle-8> redo和undo
2015-01-26 22:23 1654本章介绍oracle数据库中 ... -
<oracle-6> 并发多版本控制
2015-01-12 21:17 14656.1 什么是并发控制 并 ... -
<oracle-5> 锁(lock)和闩(latch)
2015-01-07 21:11 2765开发多用户、数据库驱动的应用时,最大的难点之一是:一方面要力争 ... -
<oracle-4> oracle进程
2015-01-06 23:02 1403Oracle中的各个进程要完成某个特定的任务或一组任务,每个进 ... -
<oracle-3> 内存结构
2015-01-05 22:20 1554这一篇主要讨论oracle的3 ... -
<oracle-2> oracle文件
2014-12-22 20:57 1139与oracle实例相关的文件只有下面几种: 参数文件(para ... -
<Oracle-1> oracle体系结构概述
2014-12-21 22:02 1221本系列主要参考《Oracle ...
相关推荐
《Oracle数据库》是由赵明渊主编的一本深入探讨Oracle数据库系统的专业教材,它涵盖了Oracle数据库的基础知识、管理和优化等多个方面。这本书是学习Oracle数据库的重要参考资料,同时也为将Oracle数据库知识迁移到...
你需要在`<Context>`标签内添加以下代码来定义一个名为`jdbc/myoracle`的数据源,使用`thin`驱动连接到本地的Oracle数据库,用户为`scott`,密码为`tiger`,数据库服务标识符(SID)为`mysid`: ```xml <Resource...
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> ...
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/> <!-- 配置数据库URL --> <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:orcl"/> <!-- 配置数据库用户名 --> ...
- `<local-tx-datasource>`:指定本地事务数据源。 - `<jndi-name>`:设置JNDI名称,本例中为`jdbc/oracle`。 - `<connection-url>`:配置数据库连接URL,例如`jdbc:oracle:thin:@localhost:1521:jj`。 - `...
<property name="connection.driver_class">Oracle.ManagedDataAccess.Client.OracleDriver</property> <property name="connection.connection_string">Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=...
<driver-class>oracle.jdbc.OracleDriver</driver-class> <driver>oracle</driver> <security> <user-name>your_username</user-name> <password>your_password</password> </security> <validation> <valid...
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class> <user-name>username</user-name> <password>password</password> ... </local-tx-datasource> </datasources> ``` 其中,`jndi-name`是数据...
接着,使用`<tx:advice>`和`<tx:attributes>`定义事务策略,例如,将所有以`insert*`、`update*`和`delete*`开头的方法设置为`REQUIRED`传播属性,意味着这些方法必须在事务中执行。最后,使用`<aop:config>`配置...
<groupId>com.oracle.ojdbc</groupId> <artifactId>ojdbc8</artifactId> <version>19.7.0.0</version> </dependency> <!-- DB2 --> <dependency> <groupId>com.ibm.db2</groupId> <artifactId>jcc</artifactId...
<property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:ORCL</property> <property name=...
<connection-url>jdbc:oracle:oci8:@<database></connection-url> <driver-class>oracle.jdbc.driver.OracleDriver</driver-class> <user-name>sa</user-name> <password></password> </local-tx-datasource> ...
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> ...
- OCI Thin Type 4: `jdbc:oracle:thin:@<host>:<port>:<database>` - OCI XA Type 2: `jdbc:oracle:thin:@<host>:<port>:<database>` - `<host>`: Oracle所在计算机的主机名。 - `<port>`: Oracle数据库的...
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class> <user-name>zsyd</user-name> <password>j2yd</password> <min-pool-size>5</min-pool-size> <max-pool-size>10</max-pool-size> <exception-...
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/> <property name="jdbcUrl" value="jdbc:oracle:thin:@10.142.252.132:1521:mestest"/> <property name="maxPoolSize" value="10...
<driver-class>oracle.jdbc.OracleDriver</driver-class> <url>jdbc:oracle:thin:@hostname:port/service_name</url> <username>your_username</username> <password>your_password</password> </data-source> ...
<attribute name="DriverClass">oracle.jdbc.driver.OracleDriver</attribute> <attribute name="URL">jdbc:oracle:thin:@localhost:1521:ORCL</attribute> <attribute name="User">your_username</attribute> ...