网站首页 > 技术文章 正文
Spring支持的事务管理类型
Spring支持两种类型的事务管理。
1、编程式事务管理
在此过程中,在编程的帮助下管理事务。它为您提供极大的灵活性,但维护起来非常困难。
2、声明式事务管理
事务管理与业务代码分离,仅使用注解或基于 XML的配置来管理事务。
更倾向用哪种事务管理类型
大多数 Spring 框架的用户选择声明式事务管理,因为它对应用代码的影响最小,因此更符合一个无侵入的轻量级容器的思想。声明式事务管理要优于编程式事务管理,虽然比编程式事务管理 (这种方式允许你通过代码控制事务)少了一点灵活性。
Spring框架的事务管理有哪些优点
1、它为不同的事务API, 如 JTA,JDBC,Hibernate,JPA 和JDO,提供一个不变的编程模式。
2、它为编程式事务管理提供了一套简单的 API 而不是一些复杂的事务 API。
3、它支持声明式事务管理。
4、它和 Spring 各种数据访问抽象层很好的集成。
事务
基本概念
事务是逻辑上的一组操作,要么都执行,要么都不执行。我们系统的每个业务方法可能包括了多个原子性的数据库操作,比如下面的 savePerson() 方法中就有两个原子性的数据库操作。这些原子性的数据库操作是有依赖的,它们要么都执行,要不都不执行。
另外需要格外注意的是:事务能否生效,数据库引擎是否支持事务是关键。比如常用的 MySQL 数据库默认使用支持事务的 innodb引擎,但是如果把数据库引擎变为 myisam,那么程序也就不再支持事务了。
特性
原子性
一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即事务不可分割、不可约简。
一致性
在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
隔离性
数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
持久性
事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
隔离级别
ISOLATION_DEFAULT
使用后端数据库默认的隔离级别,MySQL 默认采用的 REPEATABLE_READ 隔离级别,Oracle 默认采用的 READ_COMMITTED 隔离级别。
ISOLATION_READ_UNCOMMITTED(读未提交)
就是一个事务可以读取另一个未提交事务的数据。最低的隔离级别,使用这个隔离级别很少,因为它允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
ISOLATION_READ_COMMITTED(读已提交)
允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
ISOLATION_REPEATABLE_READ(可重复读)
对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
ISOLATION_SERIALIZABLE(串行化)
最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能,通常情况下也不会用到该级别。
传播行为(7个)
基本概念
事务传播行为是为了解决业务层方法之间互相调用的事务问题。当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
示例:我们在 A 类的aMethod()方法中调用了 B 类的 bMethod() 方法。这个时候就涉及到业务层方法之间互相调用的事务问题。如果我们的 bMethod()发生异常需要回滚,如何配置事务传播行为才能让 aMethod()也跟着回滚呢?这个时候就需要事务传播行为的知识了,如果你不知道的话一定要好好看一下。
PROPAGATION_REQUIRED
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中,这是最常见的选择。
使用的最多的一个事务传播行为,我们平时经常使用的@Transactional注解默认使用就是这个事务传播行为。如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务。也就是说
(1)如果外部方法没有开启事务的话,Propagation.REQUIRED修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
(2)如果外部方法开启事务并且被Propagation.REQUIRED修饰的话,所有Propagation.REQUIRED修饰的内部方法和外部方法均属于同一事务 ,只要一个方法回滚,整个事务均回滚。
举个例子:如果我们上面的aMethod()和bMethod()使用的都是PROPAGATION_REQUIRED传播行为的话,两者使用的是同一个事务,只要其中一个方法回滚,整个事务均回滚。
PROPAGATION_REQUIRES_NEW
创建一个新的事务,如果当前存在事务,则把当前事务挂起,也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
举个例子:如果我们上面的bMethod()使用PROPAGATION_REQUIRES_NEW事务传播行为修饰,aMethod还是用PROPAGATION_REQUIRED修饰的话。如果aMethod()发生异常回滚,bMethod()不会跟着回滚,因为 bMethod()开启了独立的事务。但是,如果 bMethod()抛出了未被捕获的异常并且这个异常满足事务回滚规则的话,aMethod()同样也会回滚,因为这个异常被 aMethod()的事务管理机制检测到了。
PROPAGATION_NESTED
如果当前存在事务,就在嵌套事务内执行;如果当前没有事务,就执行与
TransactionDefinition.PROPAGATION_REQUIRED类似的操作。也就是说:
(1)在外部方法开启事务的情况下,在内部开启一个新的事务,作为嵌套事务存在。
(2)如果外部方法无事务,则单独开启一个事务,与 PROPAGATION_REQUIRED 类似。
这里还是简单举个例子:如果 bMethod() 回滚的话,aMethod()也会回滚。
PROPAGATION_MANDATORY
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常(事务将不会发生回滚)。(mandatory:强制性)这个使用的很少,就不举例子来说了。
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行(事务将不会发生回滚)。这个用的很少。
PROPAGATION_NOT_SUPPORTED
以非事务方式运行,如果当前存在事务,则把当前事务挂起。这个用的很少。
PROPAGATION_NEVER
以非事务方式运行,如果当前存在事务,则抛出异常。(事务将不会发生回滚)这个用的很少。
说明
若是错误的配置以下 3 种事务传播行为,事务将不会发生回滚。
PROPAGATION_SUPPORTS
PROPAGATION_NOT_SUPPORTED
PROPAGATION_NEVER
编程式事务管理
通过 TransactionTemplate类或者TransactionManager接口手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。
使用TransactionTemplate 进行编程式事务管理的示例代码如下:
使用TransactionManager 进行编程式事务管理的示例代码如下:
声明式事务管理
推荐使用(代码侵入性最小),实际是通过 AOP 实现(基于@Transactional 的全注解方式使用最多)。使用 @Transactional注解进行事务管理的示例代码如下:
Spring事务管理接口
基本说明
Spring 框架中,事务管理相关最重要的3个接口如下:
PlatformTransactionManager:(平台)事务管理器,Spring 事务策略的核心。
TransactionDefinition:事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)。
TransactionStatus:事务运行的状态。
我们可以把
PlatformTransactionManager 接口可以被看作是事务上层的管理者,而 TransactionDefinition 和 TransactionStatus 这两个接口可以看作是事务的描述。
PlatformTransactionManager会根据 TransactionDefinition 的定义,比如事务超时时间、隔离级别、传播行为等来进行事务管理 ,而 TransactionStatus 接口则提供了一些方法来获取事务相应的状态,比如是否新事务、是否可以回滚等。
PlatformTransactionManager接口
基本概念
Spring 并不直接管理事务,而是提供了多种事务管理器 。Spring 事务管理器的接口是:
PlatformTransactionManager 。通过这个接口,Spring 为各个平台如 JDBC(
DataSourceTransactionManager)、Hibernate(
HibernateTransactionManager)、JPA(JpaTransactionManager)等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
为什么要定义或者说抽象出来
PlatformTransactionManager这个接口呢?主要是因为要将事务管理行为抽象出来,然后不同的平台去实现它,这样我们可以保证提供给外部的行为不变,方便我们扩展。
源码
具体实现
方法
TransactionStatus getTransaction(TransactionDefinition definition)
获取事务
void commit(TransactionStatus status)
提交事务
void rollback(TransactionStatus status)
回滚事务
TransactionDefinition:事务属性
基本概念
事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。事务属性包含了 5 个方面:
(1)隔离级别
(2)传播行为
(3)回滚规则
(4)是否只读
(5)事务超时
源码
方法(5个)
int getIsolationLevel();
获取隔离级别,默认值是DEFAULT
String getName();
返回事务的名称,可以是null。
int getPropagationBehavior();
获取传播行为,默认值是REQUIRED。
int getTimeout();
返回事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
boolean isReadOnly();
返回是否为只读事务,默认值为 false
TransactionStatus:事务状态
基本概念
TransactionStatus接口用来记录事务的状态,该接口定义了一组方法,用来获取或判断事务的相应状态信息。
PlatformTransactionManager.getTransaction(…)方法返回一个 TransactionStatus 对象。
源码
方法(5个)
boolean isNewTransaction();
是否是新的事务
boolean hasSavepoint();
返回此事务是否在内部带有保存点,即是否已基于保存点创建为嵌套事务。
void setRollbackOnly()
设置为只回滚
boolean isRollbackOnly();
是否为只回滚
boolean isCompleted()
是否已完成
TransactionAttribute接口
源码
方法
String getQualifier()
boolean rollbackOn(Throwable ex)
事务超时
所谓事务超时就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒,默认值为-1。
事务只读属性
对于只有读取数据查询的事务,可以指定事务类型为 readonly,即只读事务。只读事务不涉及数据的修改,数据库会提供一些优化手段,适合用在有多条数据库查询操作的方法中。MySQL 默认对每一个新建立的连接都启用了autocommit模式。在该模式下,每一个发送到 MySQL 服务器的sql语句都会在一个单独的事务中进行处理,执行结束后会自动提交事务,并开启一个新的事务。但是如果你给方法加上了Transactional注解的话,这个方法执行的所有sql会被放在一个事务中。如果声明了只读事务的话,数据库就会去优化它的执行,并不会带来其他的什么收益。如果不加Transactional,每条sql会开启一个单独的事务,中间被其它事务改了数据,都会实时读取到最新值。
如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持 SQL 执行期间的读一致性,如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询 SQL 必须保证整体的读一致性,否则在前条 SQL 查询之后,后条 SQL 查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时应该启用事务支持。
事务回滚规则
这些规则定义了哪些异常会导致事务回滚而哪些不会。默认情况下事务只有遇到运行期异常(RuntimeException 的子类)时才会回滚,Error 也会导致事务回滚,但是在遇到检查型(Checked)异常时不会回滚。
如果你想要回滚你定义的特定的异常类型的话,可以这样:
@Transactional注解使用详解
源码
作用范围
1、方法:推荐将注解使用于方法上,不过需要注意的是:该注解只能应用到 public方法上,否则不生效。
2、类:如果这个注解使用在类上的话,表明该注解对该类中所有的 public 方法都生效。
3、接口:不推荐在接口上使用。
常用的配置参数
propagation
事务的传播行为,默认值是REQUIRED。
rollbackFor
事务回滚的异常类型。
默认情况下,@Transactional 注解的 rollbackFor 属性是空的,也就是说没有指定任何异常类型。这意味着默认情况下,Spring 在发生未检查异常(继承自 RuntimeException 的异常)或 Error 时会回滚事务,而对于已检查异常(非继承自 RuntimeException 的异常),Spring 不会自动回滚事务。
rollbackFor 属性允许我们指定一个异常类或异常类数组,用于说明哪些异常发生时需要回滚事务。例如:
在上面的例子中,如果方法 someTransactionalMethod 抛出了 SQLException 或 MyCustomException 类型的异常,Spring 会回滚事务。如果抛出的异常不属于指定的回滚异常类型,事务不会回滚(除非是未检查异常或 Error)。
noRollbackFor
不会发生事务回滚的异常类型。
原理
我们知道@Transactional 的工作机制是基于 AOP 实现的,AOP 又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理,如果目标对象没有实现接口,会使用CGLIB动态代理。多提一嘴:createAopProxy() 方法决定了是使用 JDK 还是 Cglib 来做动态代理,源码如下:
如果一个类或者一个类中的 public 方法上被标注@Transactional 注解的话,Spring 容器就会在启动的时候为其创建一个代理类,在调用被@Transactional 注解的 public 方法的时候,实际调用的是TransactionInterceptor类中的 invoke()方法。这个方法的作用就是在目标方法之前开启事务,方法执行过程中如果遇到异常的时候回滚事务,方法调用完成之后提交事务。
TransactionInterceptor 类中的 invoke()方法内部实际调用的是 TransactionAspectSupport 类的invokeWithinTransaction()方法。由于新版本的 Spring 对这部分重写很大,而且用到了很多响应式编程的知识。
Spring AOP自调用问题
若同一类中的其他没有 @Transactional 注解的方法内部调用有 @Transactional 注解的方法,有@Transactional 注解的方法的事务会失效。这是由于Spring AOP代理的原因造成的,因为只有当 @Transactional 注解的方法在类以外被调用的时候,Spring事务管理才生效。MyService 类中的method1()调用method2()就会导致method2()的事务失效。
解决办法就是避免在同一类中自调用或者使用AspectJ取代Spring AOP代理。
@Transactional注解失效的情况
1、@Transactional 应用在非public 修饰的方法上
之所以会失效是因为在Spring AOP 代理时,TransactionInterceptor (事务拦截器)在目标方法执行前后进行拦截,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的 intercept 方法或 JdkDynamicAopProxy 的 invoke 方法会间接调用
AbstractFallbackTransactionAttributeSource的
computeTransactionAttribute 方法,获取Transactional 注解的事务配置信息。
此方法会检查目标方法的修饰符是否为 public,不是 public则不会获取@Transactional 的属性配置信息。
注意:protected、private 修饰的方法上使用 @Transactional 注解,虽然事务无效,但不会有任何报错,这是我们很容易犯错的一点。
2、@Transactional 注解属性propagation设置错误
3、@Transactional 注解属性rollbackFor设置错误
4、同一个类中方法调用,导致@Transactional失效
5、异常被你的 catch“吃了”导致@Transactional失效
6、数据库引擎不支持事务
使用注意事项总结
1、@Transactional 注解只有作用到 public 方法上事务才会生效,不推荐在接口上使用。
2、避免在同一个类中调用 @Transactional 注解的方法,这样会导致事务失效。
3、正确设置 @Transactional 的 rollbackFor 和 propagation 属性,否则事务可能会回滚失败。
4、被 @Transactional 注解的方法所在的类必须被Spring管理,否则不生效。
5、底层使用的数据库必须支持事务机制,否则不生效。
Spring配置定时任务
基本概念
Quartz就是来干这样的事,你给它一个触发条件的定义,它负责到了时间点,触发相应的Job起来干活。
Spring中使用Quartz的3种方法(
MethodInvokingJobDetailFactoryBean,implements Job,extends QuartzJobBean),动态启动、暂停、添加、删除定时任务,可以传参数。Quartz是一个强大的企业级任务调度框架,Spring中继承并简化了Quartz。
开发思路
(1)首先我们写一个被调度的类
(2)编写Spring配置文件quartz-config.xml文件
说明:文件名可以随便定义:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "
http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 要调用的工作类 -->
<bean id="quartzJob" class="com.kay.quartz.QuartzJob"></bean>
<!-- 定义调用对象和调用对象的方法 -->
<bean id="jobtask" class="
org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 调用的类 -->
<property name="targetObject">
<ref bean="quartzJob"/>
</property>
<!-- 调用类中的方法 -->
<property name="targetMethod">
<value>work</value>
</property>
</bean>
<!-- 定义触发时间 -->
<bean id="doTime" class="
org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="jobtask"/>
</property>
<!-- cron表达式 -->
<property name="cronExpression">
<value>10,15,20,25,30,35,40,45,50,55 * * * * ?</value>
</property>
</bean>
<!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
<bean id="startQuertz" lazy-init="false" autowire="no" class="
org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="doTime"/>
</list>
</property>
</bean>
</beans>
(3)测试程序
package com.kay.quartz;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {
public static void main(String[] args) {
System.out.println("Test start .");
ApplicationContext context = new
ClassPathXmlApplicationContext("quartz-config.xml");
//如果配置文件中将startQuertz bean的lazy-init设置为false 则不用实例化
//context.getBean("startQuertz");
System.out.print("Test end ..");
}
}
#我们需要把log4j的配置文件放入src目录下,启动main类就可以了。
关于quartz中的cron表达式
Cron表达式包括以下7个字段
1、秒
2、分
3、小时
4、月内日期
5、月
6、周内日期
7、年(可选字段)
Cron触发器利用一些列特殊字符
反斜线(/)字符表示增量值。例如,在秒字段中“5/15”代表从第 5 秒开始,每 15 秒一次。
问号(?)字符和字母 L 字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含具体值。
在月内日期字段中的字母(W)字符把执行安排在最靠近指定值的工作日。把“1W”放在月内日期字段中,表示把执行安排在当月的第一个工作日内。
井号(#)字符为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中,表示把任务安排在当月的第二个星期一。
星号(*)字符是通配字符,表示该字段可以接受任何可能的值。
字段 允许值 允许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /
#表达式意义
"0 0 12 * * ?" 每天中午12点触发
"0 15 10 ? * *" 每天上午10:15触发
"0 15 10 * * ?" 每天上午10:15触发
"0 15 10 * * ? *" 每天上午10:15触发
"0 15 10 * * ? 2005" 2005年的每天上午10:15触发
"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每月15日上午10:15触发
"0 15 10 L * ?" 每月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发
每天早上6点
0 6 * * *
每两个小时
0 */2 * * *
晚上11点到早上8点之间每两个小时,早上八点
0 23-7/2,8 * * *
每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
0 11 4 * 1-3
1月1日早上4点
0 4 1 1 *
类
QuartzJobBean
基本概念
QuartzJobBean是Spring框架提供的一个抽象类,用于简化Quartz定时任务的开发。
源码
作用
1、依赖注入
可以直接在Job类中使用@Autowired注入Spring Bean
2、属性设置
自动将JobDataMap中的数据映射到Job类的属性上
3、异常处理
提供更好的异常处理机制
基本使用
关键特性
1、自动参数映射
JobDataMap中的键值对会自动通过setter方法注入到Job实例的属性中。
2、Spring容器管理
Job实例由Spring容器创建和管理,可以享受完整的Spring特性。
3、线程安全
每次执行都会创建新的Job实例,避免了线程安全问题。
配置示例
注意事项
1、必须为需要注入的属性提供setter方法
2、Job类需要有无参构造函数
3、每次执行都会创建新实例,不要在Job中保存状态
4、适合需要Spring依赖注入的复杂定时任务场景
这样就可以很方便地在Quartz定时任务中使用Spring的各种特性了。
Java项目中Classpath路径说明
(1)src不是classpath, WEB-INF/classes,lib才是classpath,WEB-INF/ 是资源目录, 客户端不能直接访问。
(2)WEB-INF/classes目录存放src目录中Java文件编译之后的class文件,xml、properties等资源配置文件,这是一个定位资源的入口。
(3)引用classpath路径下的文件,只需在文件名前加classpath:
示例:
(4)lib和classes同属classpath,两者的访问优先级为: lib>classes。
(5)classpath 和 classpath* 区别:classpath:只会到你的class路径中查找文件,classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找。
猜你喜欢
- 2025-07-10 分布式之系统底层原理(上)(底层分布式技术)
- 2025-07-10 MySQL面试题整理:从基础到高级的全面覆盖
- 2025-07-10 MySQL从入门到实战:表设计、索引优化与高频面试解析
- 2025-07-10 一个非教条式的TDD例子(一个非一个虫)
- 2025-07-10 SQL 开发必学:深度解析 NULL 值处理的 6 大核心规则与避坑指南
- 2025-07-10 关系型数据库设计要领(值得收藏)(关系型数据库有哪些设计范式)
- 2025-07-10 Oracle数据库中判断字段不为空?(oracle数据库中判断字段不为空的函数)
- 2024-10-17 oracle数据库设计总结|三大范式 oracle数据库设计规范
- 2024-10-17 数据库(Oracle)序列(Sequence)的基本使用
- 2024-10-17 oracle日常巡检--检查数据库安全 oracle问题排查
你 发表评论:
欢迎- 07-10Oracle 与 Google Cloud 携手大幅扩展多云服务
- 07-10分享收藏的 oracle 11.2.0.4各平台的下载地址
- 07-10Oracle 和 Microsoft 推出 Oracle Exadata 数据库服务
- 07-10Oracle Database@Azure 推进到南美等新区域并增加了新服务
- 07-10Oracle宣布推出 Oracle Database@AWS 的有限预览版
- 07-10Oracle与Nextcloud合作,推出主权云上的安全协作平台
- 07-10NodeRED魔改版连接MsSql、PostgreSQL、MySQL、OracleDB存储无忧
- 07-10对于企业数据云备份,“多备份”承诺的是成本更低,管理更高效#36氪开放日深圳站#
- 600℃几个Oracle空值处理函数 oracle处理null值的函数
- 592℃Oracle分析函数之Lag和Lead()使用
- 580℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 576℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 572℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 565℃【数据统计分析】详解Oracle分组函数之CUBE
- 551℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 546℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
-
- Oracle 与 Google Cloud 携手大幅扩展多云服务
- 分享收藏的 oracle 11.2.0.4各平台的下载地址
- Oracle 和 Microsoft 推出 Oracle Exadata 数据库服务
- Oracle Database@Azure 推进到南美等新区域并增加了新服务
- Oracle宣布推出 Oracle Database@AWS 的有限预览版
- Oracle与Nextcloud合作,推出主权云上的安全协作平台
- NodeRED魔改版连接MsSql、PostgreSQL、MySQL、OracleDB存储无忧
- 对于企业数据云备份,“多备份”承诺的是成本更低,管理更高效#36氪开放日深圳站#
- 解读丨《归档文件整理规则》— 电子文件元数据存储
- Data Guard跳归档恢复的实践(dataguard failover)
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端获取当前时间 (50)
- Oracle RAC (76)
- oracle恢复 (77)
- oracle 删除表 (52)
- oracle 用户名 (80)
- oracle 工具 (55)
- oracle 内存 (55)
- oracle 导出表 (62)
- oracle约束 (54)
- oracle 中文 (51)
- oracle链接 (54)
- oracle的函数 (57)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)