Spring事务的传播行为分析
前言
最近项目有涉及到Spring事务,所以工作之余,想认真了解学习下Spring事务,查阅了若干资料,做了一个demo(PS:参考了大牛的)。
现分享总结如下:
1、Spring 事务的简介
理解事务之前,
先讲一个你日常生活中最常干的事:取钱。
比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱;然后ATM出1000元钱。这两个步骤必须是要么都执行要么都不执行。如果银行卡扣除了1000块但是ATM出钱失败的话,你将会损失1000元;如果银行卡扣钱失败但是ATM却出了1000块,那么银行将损失1000元。所以,如果一个步骤成功另一个步骤失败对双方都不是好事,如果不管哪一个步骤失败了以后,整个取钱过程都能回滚,也就是完全取消所有操作的话,这对双方都是极好的。
事务就是用来解决类似问题的。事务是一系列的动作,它们综合在一起才是一个完整的工作单元,这些动作必须全部完成,如果有一个失败的话,那么事务就会回滚到最开始的状态,仿佛什么都没发生过一样。
在企业级应用程序开发中,事务管理必不可少的技术,用来确保数据的完整性和一致性。
事务有四个特性:ACID
- 原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
- 一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。
- 隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
- 持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。
具体可以参考:http://www.mamicode.com/info-detail-1248286.html
2、事务的传播行为
事务的第一个方面是传播行为(propagation behavior)。当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。Spring定义了七种传播行为:
1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
下面我们来看下代码:
3、demo分析
事先插入一条记录
@Override
public void before() {
jdbcTemplate.update("INSERT INTO USER (name,password) VALUES (?,?)","xiang","11111112");
}
3.1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
@Override
public void txRollbackInnerTxRollbackPropagationRequires() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("INSERT INTO USER (name,password) VALUES (?,?)","Huang","1111231");
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user name, password) values (?, ?)",
"Huang", "1111112");
//内部事务设置了 setRollbackOnly
transactionStatus.setRollbackOnly();
}
});
}
});
}
测试结果:
/**
* PROPAGATION_REQUIRES:内部事务设置了 {@link org.springframework.transaction.TransactionStatus#setRollbackOnly()} 来触发回滚,
* 外部事务接受到了一个 {@link UnexpectedRollbackException} 也被回滚
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationRequires() throws Exception {
try {
springTxService.txRollbackInnerTxRollbackPropagationRequires();
} catch (UnexpectedRollbackException e) { }finally {
Assert.assertEquals(1,springTxService.mysqlConnection());
}
}
3.2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
@Override
public void txRollbackInnerTxRollbackPropagationSupports() {
supportsTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
throw new CustomRuntimeException();
}
});
} @Override
public void txRollbackInnerTxRollbackPropagationSupports2() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
supportsTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
status.setRollbackOnly();
}
});
}
});
}
测试用例:
/**
* PROPAGATION_SUPPORTS:如果当前事务上下文中没有事务,
* 那么就按照没有事务的方式执行代码
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationSupports() throws Exception {
try {
springTxService.txRollbackInnerTxRollbackPropagationSupports();
} catch (CustomRuntimeException e) {
e.printStackTrace();
}finally {
Assert.assertEquals(2, springTxService.mysqlConnection()); } }
/**
* PROPAGATION_SUPPORTS:如果当前事务上下文中存在事务,
* 那么合并到当前上下文的事务中去,
* 表现地和 {@link org.springframework.transaction.TransactionDefinition#PROPAGATION_REQUIRED} 一样
*/
@Test(expected = UnexpectedRollbackException.class)
public void testTxRollbackInnerTxRollbackPropagationSupports2() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationSupports2();
}
3.3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
@Override
public void txRollbackInnerTxRollbackPropagationMandatory() {
mandatoryTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
}
});
} @Override
public void txRollbackInnerTxRollbackPropagationMandatory2() {
nestedTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
mandatoryTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
//内部事务回滚了,外部事务也跟着回滚
transactionStatus.setRollbackOnly();
}
});
}
});
}
测试用例:
/**
* PROPAGATION_MANDATORY:强制性的事务,当前的事务上下文中不存在事务的话,会抛出 {@link IllegalTransactionStateException}
*/
@Test(expected = IllegalTransactionStateException.class)
public void testTxRollbackInnerTxRollbackPropagationMandatory() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationMandatory(); }
/**
* PROPAGATION_MANDATORY:强制性的事务,内部的事务发生回滚,
* 那么外部的事务也会发生回滚,表现地和 {@link org.springframework.transaction.TransactionDefinition#PROPAGATION_REQUIRED}
* 一样,也会抛出 {@link UnexpectedRollbackException}
*/
@Test(expected = UnexpectedRollbackException.class)
public void testTxRollbackInnerTxRollbackPropagationMandatory2() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationMandatory2();
}
3.4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
@Override
public void txRollbackInnerTxRollbackPropagationRequiresNew() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
requiresNewTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
}
});
//外部事务发生回滚,内部事务应该不受影响还是能够提交
throw new RuntimeException();
}
});
} @Override
public void txRollbackInnerTxRollbackPropagationRequiresNew2() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
requiresNewTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
// 内部事务发生回滚,但是外部事务不应该发生回滚
transactionStatus.setRollbackOnly();
}
});
}
});
} @Override
public void txRollbackInnerTxRollbackPropagationRequiresNew3() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
requiresNewTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
// 内部事务抛出 RuntimeException,外部事务接收到异常,依旧会发生回滚
throw new RuntimeException();
}
});
}
});
}
测试用例:
/**
* PROPAGATION_REQUIRES_NEW:外部事务发生回滚,内部事务继续提交,不受影响
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationRequiresNew() throws Exception {
try {
springTxService.txRollbackInnerTxRollbackPropagationRequiresNew();
} catch (Exception e) {
e.printStackTrace();
}finally {
Assert.assertEquals(2,springTxService.mysqlConnection());
}
}
/**
* PROPAGATION_REQUIRES_NEW:内部事务通过设置 {@link org.springframework.transaction.TransactionStatus#setRollbackOnly()} 来触发回滚,
* 外部事务依旧可以不受影响,正常提交
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationRequiresNew2() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationRequiresNew2();
Assert.assertEquals(2,springTxService.mysqlConnection());
}
/**
* PROPAGATION_REQUIRES_NEW:内部事务抛出了 {@link RuntimeException} 异常发生了回滚,外部事务接收到这个异常也会发生回滚
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationRequiresNew3() throws Exception {
try {
springTxService.txRollbackInnerTxRollbackPropagationRequiresNew3();
} catch (RuntimeException e) {
e.printStackTrace();
}finally {
Assert.assertEquals(1,springTxService.mysqlConnection()); }
}
3.5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
@Override
public void txRollbackInnerTxRollbackPropagationNotSupport() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
notSupportedTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
}
});
// 外部事务回滚,不会把内部的也连着回滚
transactionStatus.setRollbackOnly();
}
});
} @Override
public void txRollbackInnerTxRollbackPropagationNotSupport2() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
notSupportedTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
throw new CustomRuntimeException();
}
});
} catch (CustomRuntimeException e) {
}
}
});
}
测试用例:
/**
* PROPAGATION_NOT_SUPPORTED:不支持事务,
* 外围的事务回滚不会导致它包含的内容回滚
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationNotSupport() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationNotSupport();
Assert.assertEquals(2,springTxService.mysqlConnection()); }
/**
* PROPAGATION_NOT_SUPPORTED:不支持事务,内部发生异常,外部捕获,都不会发生回滚
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationNotSupport2() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationNotSupport2();
Assert.assertEquals(3,springTxService.mysqlConnection());
}
3.6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
@Override
public void txRollbackInnerTxRollbackPropagationNever() {
neverTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
}
});
} @Override
public void txRollbackInnerTxRollbackPropagationNever2() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
neverTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
}
});
}
});
} @Override
public void txRollbackInnerTxRollbackPropagationNever3() {
neverTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
neverTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
}
});
}
});
}
测试代码:
/**
* PROPAGATION_NEVER:不允许当前事务上下文中存在事务,如果没有,就正常执行
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationNever() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationNever();
Assert.assertEquals(2,springTxService.mysqlConnection());
}
/**
* PROPAGATION_NEVER:不允许当前事务上下文中存在事务,
* 如果有,则抛出 {@link IllegalTransactionStateException}
*/
@Test(expected = IllegalTransactionStateException.class)
public void testTxRollbackInnerTxRollbackPropagationNever2() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationNever2();
}
/**
* PROPAGATION_NEVER:不允许当前事务上下文中存在事务,
* 当两个 NEVER 的嵌套在一起的时候,应该也是能够执行成功的。
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationNever3() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationNever3();
Assert.assertEquals(3,springTxService.mysqlConnection());
}
3.7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
@Override
public void txRollbackInnerTxRollbackPropagationNested() {
nestedTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
nestedTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
// 内部事务设置了 rollbackOnly,外部事务应该不受影响,可以继续提交
transactionStatus.setRollbackOnly();
}
});
}
});
} @Override
public void txRollbackInnerTxRollbackPropagationNested2() {
nestedTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)", "Huang",
"1111112");
nestedTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into user (name, password) values (?, ?)",
"Huang", "1111112");
}
});
// 外部事务设置了 rollbackOnly,内部事务应该也被回滚掉
transactionStatus.setRollbackOnly();
}
});
}
测试代码:
/**
* PROPAGATION_NESTED:内部事务通过设置 {@link org.springframework.transaction.TransactionStatus#setRollbackOnly()} 来触发回滚,
* 外部事务依旧可以不受影响,正常提交
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationNested() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationNested();
Assert.assertEquals(2, springTxService.mysqlConnection()); }
/**
* PROPAGATION_NESTED:外部事务通过设置 {@link org.springframework.transaction.TransactionStatus#setRollbackOnly()} 来触发回滚,由于
* savepoint 在外部事务的开头,所以内部事务应该也会被一起回滚掉
*/
@Test
public void testTxRollbackInnerTxRollbackPropagationNested2() throws Exception {
springTxService.txRollbackInnerTxRollbackPropagationNested2();
Assert.assertEquals(1, springTxService.mysqlConnection()); }
Spring事务的传播行为分析的更多相关文章
- Spring事务的传播行为 @Transactional(转)
Spring事务的传播行为 在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例 ...
- Spring事务的传播行为 @Transactional
Spring事务的传播行为http://blog.csdn.net/cuker919/article/details/5957209 在service类前加上@Transactional,声明这个se ...
- Spring事务管理源码分析
Spring事务管理方式 依据Spring.xsd文件可以发现,Spring提供了advice,annotation-driven,jta-transaction-manager3种事务管理方式.详情 ...
- Spring事务之传播机制
Spring事务传播机制:Spring在TransactionDefinition接口中规定了种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套时事务如何进行传播.即协调已经有事务标识的方法之 ...
- Spring事务的传播特性和隔离级别
事务的几种传播特性1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务.如果没有事务则开启2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务 ...
- Spring事务的传播行为
本文主要介绍下Spring事务中的传播行为. 事务传播行为介绍 Spring中的7个事务传播行为: |事务行为|说明 | |:--|:--| |PROPAGATION_REQUIRED | 支持当 ...
- Spring事务的传播:PROPAGATION_REQUIRED
PROPAGATION_REQUIRED-- 支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. ServiceA { void methodA() { ServiceB.method ...
- 关于事务,事务的特性,spring事务的传播特性
1.什么是事务: 事务是程序中一系列严密的操作,所有操作执行必须成功完成,否则在每个操作所做的更改将会被撤销,这也是事务的原子性(要么成功,要么失败). 2.事务特性: 事务特性分为四个:原子性(At ...
- 数据库的特性与隔离级别和spring事务的传播机制和隔离级别
首先数据库的特性就是 ACID: Atomicity 原子性:所有事务是一个整体,要么全部成功,要么失败 Consistency 一致性:在事务开始和结束前,要保持一致性状态 Isolation 隔离 ...
随机推荐
- android 添加一个按键键值【转】
本文转载自:http://blog.csdn.net/u012719256/article/details/52526046 1.frameworks/base/data/keyboards/Gene ...
- UESTC--758--P酱的冒险旅途(模拟)
P酱的冒险旅途 Time Limit: 1000MS Memory Limit: 65535KB 64bit IO Format: %lld & %llu Submit Status ...
- hdoj--1518--Square(dfs)
Square Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...
- 关于类和对象的进一步讨论之析构函数 C++
析构函数也是一个特殊的成员函数.它的作用与构造函数相反.它的名字是在类名的前面加一个“~”符号.在C++中“~”是位取反运算符.当对象的生命结束时,会自动执行解析函数.以下几种情况会执行析构函数: 1 ...
- IPv6系列-初学者的10个常见困扰
本文是<IPv6系列>文章的第二篇<常见困扰>,紧接<入门指南>,用于解答IPv6的10个常见困扰. 小慢哥的原创文章,欢迎转载 目录 ▪ 本文缘由 ▪ 困扰1. ...
- Redis(四)-配置
Redis 配置 Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf. 你可以通过 CONFIG 命令查看或设置配置项. 语法 Redis CONFIG 命令格式如下: ...
- MySql-Connector for NET 连接驱动选择
尝试在Visual Studio2010, 2012环境下链接Mysql, 为啥不直接在App.config里面写字符串, 当然是可以,但是当你想用EF 的时候,必须要有个数据源, 首先在[服务资源管 ...
- python--3、 可迭代对象、迭代器、生成器
可迭代对象 iterable 可直接作用于for循环的对象统称为可迭代对象. 有 list. dict.tuple.set.str等数据类型,还有 generator(包括生成器和带yield的gen ...
- android黑科技系列——分析某直播App的协议加密原理以及调用加密方法进行协议参数构造
一.前言 随着直播技术火爆之后,各家都出了直播app,早期直播app的各种请求协议的参数信息都没有做任何加密措施,但是慢慢的有人开始利用这个后门开始弄刷粉关注工具,可以让一个新生的小花旦分分钟变成网红 ...
- 【Oracle】数据迁移工具(2):Data Dump
Data Dump 使用命令行IMPDP/EXPDP实现导入导出表.schema.表空间及数据库.IMPDP/EXPDP命令行中可以加入以下选项,来实现更细粒度的导入导出. IMPDP/EXPDP和I ...