Spring事务管理的底层逻辑—源码解析

简介: 首先进入CglibAopProxy.class的intercept方法打上一个Debug断点调试,或者在JdkDynamicAopProxy.class的invoke方法(如果目标方法是继承接口方式实现),根据不同实现方法类型选择不同的动态代理类

著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

本文代码为spring 5.1.2

spring是如何控制事务的提交和回滚

加上@Transactional注解之后,Spring可以启到事务控制的功能,在正式执行方法前它会做一系列的操作,我们来看看在这之中它到底都做了些什么?

首先进入CglibAopProxy.classintercept方法打上一个Debug断点调试,或者在JdkDynamicAopProxy.classinvoke方法(如果目标方法是继承接口方式实现),根据不同实现方法类型选择不同的动态代理类。不了解的同学可以查看我的另一篇文章《通过Spring Aop 了解动态代理》

CglibAopProxy.class

  Class<?> targetClass=target!=null?target.getClass():null; targetClass: "class com.examp ble.threadtransaction.service.UserService"  
  List<Object>chain=this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClas ss);chain:size=1advised:"org.springframework.aop.frame  
  Object retVal;  
if(chain.isEmpty()&& Modifier.isPublic(method.getModifiers())){ 
Object[]argsToUse=AopProxyUtils.adaptArgumentsIfNecessary(method,args); 
retVal = methodProxy.invoke(target,argsToUse);  
retVal=(newCglibAopProxy.CglibMethodInvocation(proxy, target, method, ,args,targetClass chain, methodproxy  .proceed()  proxy:"com.example.threadtro  
  retVal=CglibAopProxy.processReturnType(proxy, target, method, retVal);  
  var16 = retVal;   } finally{  if(target != null && !targetSource.isStatic()){ 

JdkDynamicAopProxy.class

}
target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass(): null;
List<0bject>chain=this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass): if(chain.isEmpty()){
Object[]argsToUse=AopProxyUtils.adaptArgumentsIfNecessary(method,args); retVal=AopUtils.invokeJoinpointUsingReflection(target, method,argsToUse);} else {
MethodInvocationinvocation=newReflectiveMethodInvocation(proxy, target, method, args, targetClass,chain);
retVal  invocation.proceed(); 
}
Class<?> returnType = method.getReturnType(); 

此处动态代理具体是指代的目标对象和目标方法,通过下图debug Evaluate看出

Expression:
(newCglibAopProxy.CglibMethodInvocation(proxy,target,method,  args, targetClass, chain, methodProxy)) 
Result:
beresult={CalibAopProxy$CalibMethodInvocation@8563}"ReflectiveMethodInvocation:public void com.example.threadtransaction.service.UserSer
methodProxy={MethodProxy@6547) publicMethod = true
fproxv=UserService$$EnhancerBvSprinaCGLIB$$34ea1d76@65111"com.examole.threadtransaction.service,UserService@7a5829b8
target ={UserService@6578)
method=(Method@6545}"public void com.example.threadtransaction.service.UserService.insert30) throws java.sql.SQLException' arguments ={Object[0]@8565}
targetClass={Class@5043}"casscom.example.threadtransaction.service.UserService".… Navigate userAttributes = null
interceptorsAndDynamicMethodMatchers={ArrayList@6592}size=1 currentinterceptorlndex=-1

进去之后来到ReflectiveMethodInvocation.class然后一直往下走来到invoke方法

  public final Object[l getArguments() { return this.arguments; } 
public void setArguments(0bject... arguments){ this.arguments = arguments; l  
x
@Nullable   public Object proceed() throws Throwable f  
  if(this.currentInterceptorIndex==this.interceptorsAndDynamicMethodMatchers.size()-1){ 
return this.invokeJoinpoint();1 else (
Object interceptorOrInterceptionAdvice=this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);interceptor0rInterceptionAdvice: Tr if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher){
  InterceptorAndDynamicMethodMatcherdm=(InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice: 
Class<?>targetClass= this.targetClass!= null?this.targetClass :this.method.getDeclaringClass();argetClass: "class com.example.threadtransaction return dm.methodMatcher.matches(this.method, targetClass,this.arguments)?dm.interceptor.invoke( methodinvocation: this): this.proceed(); method: “pul
} else {
return((MethodInterceptor)interceptorOrInterceptionAdvice)  .invoke(( methodlnvocation: this) interceptor0rInterceptionAdvice:TransactionInterceptor@8643 

进入invoke方法来到 TransactionInterceptor.class

this . setTransactionAttributes ( attributes );
 public TransactionInterceptor (P1atformTransactionManager ptm , TransactionAttributeSource tas )(
 this . setlransactionManager ( ptm );
 this . setTransactionAttributeSource ( tas );
@ Nullable 
 public Object invoke ( MethodInvocation invocation ) throws Throwable {
 Class <?> targetClass invocation . getThis () I = null ? AopUtils . getTargetClass ( invocation .getThis0):nun1;
 Method Var10001= invocation . gete tn00())
 invocation getlass ():
 return this . invokeWithinTransak tion (var10001, targetClass , invocation :: proceed );
 private void writeObject ( ObjectOutputStream oos ) throws IOException { 
005,0e1aUtWiteobiect():

继续往下,进入invokeWithinTransaction()方法,来到 TransactionAspectSupport.classinvokeWithinTransaction()方法,

@param targetClass the target class that we're invoking the method on
@param invocation the callback to use for proceeding with the target invocation invocation: TransactionInterceptor$lamb@return the return value of the method, if any
@throws Throwable propagated from the target invocation*/
@Nullable
protected 0bject invokeWithinTransaction(Method method: @Nullable Class<?> targetClass, method: "public void com.example.t
finalInvocationCallbackinvocation)throwsThrowable{invocation:TransactionInterceptor$Lambda@8705
事务基本信息
// If the transaction attribute is null. the method is non-transactional.
TransactionAttributeSourcetas=getTransactionAttributeSource();tas:AnnotationTransactionAttributeSource@865 finalTransactionAttributetxAttr=(tas!=null?tas.getTransactionAttribute(method, targetClass):null); tx4 finalPlatformTransactionManagertm=determineTransactionManager(txAttr);tm:DataSourceTransactionManager@8674 final StringjoinpointIdentification=methodIdentification(method,targetClass, txAttr);joinpointIdentificatio
"col
if(txAttr== null|!(tm instanceof CallbackPreferringPlatformTransactionManager)){/Standard transaction demarcation with getTransaction and commit/rollback calls如果有需要,则创建事务
TransactionInfo txInfo  createTransactionIfNecessary(tm, txAttr,joinpointIdentification); txInfo:"PROPAGATION_R 
hiact na+e7
tSupportSTransactioninfo8734 "PROPAGATION REQUIRED,ISOLATION DEFAULT" 事务信息隔窝级别  
//This is an around advice: Invoke the next interceptor in the chain.// This will normally result in a target object being invoked. retVal=invocation.proceedWithInvocation();调用业务方法
catch(Throwable ex){
// target invocation exception
completeTransactionAfterThrowing(txInfo,ex);  捕获异常rollback  
throw ex;}
finally {
cleanupTransactionInfo(txInfo);
commitTransactionAfterReturning(txInfo);  commit  
return retVal;}
else {  final ThrowableHolder throwableHolder = new ThrowableHolder();  

进入createTransactionIfNecessary(tm, txAttr, joinpointIdentifcation)方法,如图

* ereturn a Iransactionlnfo object , whether or not d 
* The [@ code hasTransaction ()} method on TransactionInfo can be used to 
* tell if there was a transaction created .
@ see # getTransactionAttributeSource ()/ serial /
 protected TransactionInfo CreateTransactionIfNecessary (@ Nullable PlatformTransactionManager tm ,
@ Nullable TransactionAttribute txAttr , final String joinpointIdentification ) t 
 ta 。 JdkDynamicAopProxy . class x 
 transaction was created .
// If no name specified , apply method identification as transaction name . if ( txAttr != null && txAttr . getName ()== null ){
 txAttr = new DelegatingTransactionAttribute ( txAttr ){
@0verride
 public String getName (){ return joinpointIdentification ;
 TransactionStatus status - null ;
 if ( txAttr != null )
 if ( tm != null )
 status - tm . getTransaction ( txAttr ); 創建事務的
 else {
 if ( logger . isDebugEnabled ()){
 logger . debug ( o :“ Skipping transactional joinpoint [”+ joinpointIdentification -
"] because no transaction manager has been configured ");
 return prepareTransactionInfo ( tm , txAttr , joinpointIdentification , status );

出现异常时进入completeTransactionAfterThrowing()方法,可以看到其中调用了rollback()回滚

protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if(txInfo != null && txInfo.getTransactionStatus() != null){
if(logger.isTraceEnabled()){
logger.trace(o:"Completing transaction for ["+txInfo.getJoinpointIdentification()+
"] after exception: "+ ex);
}
if(txInfo.transactionAttribute!= null &&txInfo.transactionAttribute.rollbackOn(ex)){
try
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
catch(TransactionSystemException ex2){
logger.error( o:"Application exception overridden by rollback exception", ex); ex2.initApplicationException(ex); throw ex2;}
catch(RuntimeException| Error ex2){
logger.error(0:"Application exception overridden by rollback exception", ex); throw ex2;
else {
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true. try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}
catch(TransactionSystemException ex2){
logger.error(o:"Application exception overridden by commit exception", ex); ex2.initApplicationException(ex); throw ex2;}
catch(RuntimeException|Error ex2){
logger.error(0:"Application exception overridden by commit exception", ex); throw ex2;
} } }
}

没有异常则继续往下执行commitTransactionAfterReturning()

/**
*Execute after successful completion ofcall, but not after an exception was handled.* Do nothing if we didn't create a transaction.
@param txInfo information about the current transaction
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo){
if(txInfo!= null && txInfo.getTransactionStatus()!= null){
if(logger.isTraceEnabled()){
logger.trace( o:"Completing transaction for「"+txInfo.getJoinpointIdentification() + "l");
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}

以上只是解读了大致的处理流程,由于没有画流程图,可能有的读者光看文章会觉得脑回路不清晰,建议大家在阅读文本之后也去自己的项目当中浏览一下,理清逻辑顺序,如果有小伙伴想提供本文流程图,欢迎你!

@Transactional 事务注解是如何产生作用的?

如上所说,事务最开始是先进入CglibAopProxy.classintercept()方法或者JdkDynamicAopProxy.classinvoke()方法,可以看出这2个类都是AOP增强类,所以@Transactional 事务注解才可以产生作用。

来到TransactionAspectSupport.classcreateTransactionIfNecessary()方法

@see :#getTransactionAttributeSourceC
/serial/  
protected TransactionInfocreateTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
  @NullableTransactionAttribute txAttr, final String joinpointIdentification){  
// If no name specified, apply method identification as transaction name.
if(txAttr!= null &&txAttr.getName()== null){TransactionAspectSupport.createTransactionIfNece  
txAttr = new DelegatingTransactionAttribute(txAttr){
  @Override 
public String getName() { return joinpointIdentification;}
  };  
}
TransactionStatus status = null;  
if(txAttr != null) {
  if(tm != nul1){ 
status =tm.getTransaction(txAttr);  获取事务  
else {  
>>
if(logger.isDebugEnabled()){
  logger.debug(o:"Skipping transactional joinpoint ["+ joinpointIdentification +  
"] because no transaction manager has been configured");
return prepareTransactionInfo(tm,txAttr,joinpointIdentification,status);
/serial/
protected TransactionInfocreateTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification){
//If no name specified, apply method identification as transaction name.
if(txAttr!=null&&txAttr.getName()== null){TransactionAspectSupport.createTransactionIfNecess
txAttr = new DelegatingTransactionAttribute(txAttr){
@Override
public String getName() { return joinpointIdentification; }};
有默认值,其实这个值的来源就是业务方法的@Transactional注解
TransactionStatus status = null; if(txAttr != null){
if(tm !=null){
status =tm.getTransaction(txAttr);
1
+(RuleBasedTransactionAttribute@8710  "PROPAGATION REQUIRED,ISOLATION DEFAULT"  
if(logger.isDebugEnabled()){
logger.debug(o:"Skipping transactional joinpoint ["+ joinpointIdentification +
"] because no transaction manager has been configured");
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

进入tm.getTransaction(txAttr); 来到AbstractPlatformTransactionManager.class

338 @see  #doBegin  
339 340 */  @Override 获取事务环境  
341 0 publicfinal TransactionStatus getTransaction(@NullableTransactionDefinition definition) throws TransactionException { 
342 Object transaction = doGetTransaction();  获取当前事务的环境 
343
344 // Cache debug flag to avoid repeated checks. 
345 boolean debugEnabled = logger.isDebugEnabled(); 
346
347 if(definition == null){ 
348 // Use defaults if no transaction definition given. 
definition = new DefaultTransactionDefinition();
349
350 } 
351
352 if(isExistingTransaction(transaction)){ 如果存在事务信息  
353 // Existing transaction found->check propagation behavior to find out how to behave 
354 returnhandleExistingTransaction(definition, transaction, debugEnabled): 
355 } 
356
357 // Check definition settings for new transaction. 
358 if(definition.getTimeout()<TransactionDefinition.TIMEOUT DEFAULT){  
359 throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());  
36日 } 
361
362 // No existing transaction found -> check propagation behavior to 如果事务信息属于这个则抛出异常 
363 if(definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION_MANDATORY){ 
364 throw new IllegalTransactionStateException( 
365 "No existing transaction found for transaction marked with propagation 'mandatory'"); 
366
367 else  (definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION REOUIRED II 
368
definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION REOUIRES NEW I
369 definition.getPropagationBehavior()==TransactionDefinition.PROPAGATION NESTED) {  
370 SuspendedResourcesHolder suspendedResources =suspend( transaction: null)  
371 if(debugEnabled){ 这三种情况创建事务 
372 logger.debug(o:"Creating new transaction with name ["+ definition.getName() +"]:"+ definition); 
373
}
374 try { 
375 boolean newSynchronization=(getTransactionSynchronization()!= SYNCHRONIZATION_NEVER); 
376 DefaultTransactionStatus status = newTransactionStatus( 
377 definition,transaction, newTransaction:true,newSynchronization, debugEnabled,suspendedResources); 
378 doBegin(transaction,definition);  
379 prepareSynchronization(status,definition);  
380 return status;  
381 382 } 
catch(RuntimeException|Error ex){
383 resume( transaction: null, suspendedResources); 
384 throw ex; 
385
2
386
387 else{其他情况不使用事务  
388 // Create "empty"transaction: no actual transaction, but potentially synchronization. 
389 if(definition.getIsolationLevel()!=TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()){  
390 logger.warn(o:"Custom isolation level specified but no actual transaction initiated; "+ 
391 "isolation level will effectively be ignored: "+ definition): 
392
393 booleannewSynchronization=(getTransactionSynchronization()== SYNCHRONIZATION ALWAYS); 
394 return prepareTransactionStatus(definition,transaction:null,  newTransaction: true,newSynchronizatiomidmugEaantsus  
395396

@Transactional注解内容如下, 可以看到 Propagation属性的默认值为 REQUIRED

@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documented
public @interface Transactional { 
* Alias for {@link #transactionManager}.* @see #transactionManager
@AliasFor("transactionManager") String value()default"";
/**
*A<em>qualifier</em> value for the specified transaction.*<p>May be used to determine the target transaction manager,*matching the qualifier value (or the bean name) of a specific
*{@Link org.springframework.transaction.PlatformTransactionManager]* bean definition.* @since 4.2* @sec #value
*|
@AliasFor("value")
String transactionManager() default"";
/**
* The transaction propagation type.
* <p>Defaults to {@link Propagation#REQUIRED}.
*@seeorg.springframework.transaction.interceptor.TransactionAttribute#getPropagationBe
Propagation propagation() default Propagation.REQUIRED;
/*
* The transaction isolation level.
* <p>Defaults to f@link Isolation#DEFAULT}.
*<p>Exclusively desiqned for use with {@link Propaqation#REQUIRED} or
*{@link Propagation#REQUIRES_NEW} since it only applies to newly stas*transactions.Consider switching the "validateExistingTransactionsflag to

如果当前已经存在事务,进入handleExistingTransaction方法,如图

199 * Create a TransactionStatus for an exilsting transaction 
46G 市/  
401 @ private TransactionStatus handleExistingTransaction(  
481 TrensactionDefinition definition, Object transaction, boolean dobugEnabled) 
throws TramsactionException {
464
495 if(definition.getPnopsgationBehavior()-=TrangactionDefinition.PROPAGATION_NEVER){ 
486 throw new lllegalTransactionstateException( 抛出异常  
497 "Existing transaction found for transaction marked with propagation "never"");  
468 ) 
489
416 if(definition.getPropegationBehavior()=TransactionDefinition.PROPAGATION NOT SUPPORTED)(  
411 if(debugEnsbled){ 挂起事务  
412 logger.debug( o: "Suspending current treasaction"); 
413
414 Object suspendedResounces = suspend(trensection): 
415 boolean new&ymchronization=(getTrensactionSynchronization()== SMNCHROWIZATION ALYS);  
416 retumn prepareTransactionstatus(  
417 definition,transsctianmullnewTransaction: false,newSynchronization, debugEnabled, suspendedReso 
418419
428 if(definition-getPropagationBehevior()= TransactionDefinition.PROPAGATIOW REQUIRES NEM) { 
if(debugEnsbled){
421
422 logger.debug( "Suspending current transaction, creating neu transaction uith name ["+ 
423 definitiom.getMame()+“]");  
434
425 SuspendedtesouncesHolder suspendedtesounces = suspend(transaction);挂起当前环境事务 
426 try ( 
427 booleannew&ynchronization=(getTramssctionSynchronization()I= SMNCHROWIZATIOW NEWER) 
428 DefaultTrensectionStatus status = newTrensectionStatus( 
429 definition,transaction, newTramsaction:true,newSynchronization, debugEnabled,suspendedResou 
438 doBegin(trensection,definition);  
431 prepareSymchronization(status, definition); 
432 returm status;  
433
434 catch (RuntimeException | Error beginEx)( 
435 mesumeAfterbeginException(tramsaction, suspendetesounces, beginEx); 
436 437 } throw beginEx;  创建新事务 
438439
if(definitiongetPropagationBehavior()=TransactionDefinition,PRAPAG4TION_NESTED) {
441 if(lisNestedTransactionAllowed()){  创建谈套事务  
442 throw new NestedTransactionlotSupportedException( 
443 "Transaction manager does not allow nested transactions by default _"+  
naa "specify 'nestedTransactionAllowed’property with value 'true'");  
445 } 
446 if (debugEnabled}{  判断环境是否允许使用savePoint(保存点,回浪点 
447 lagger.debug(o:"Creating nested transaction with name ["+ definition.gethame() + "]");  
448
if(useSavepointForlestedTransactionO)){ 创建带保存点的事务
458 /Create savepoint within existing Spring"managed transaction, 
451 // through the SavepointManager API implemented by TransactionStatus. 
452 //UsuallyusesDBC30 savepoints, Hever activates Spring synchronization:  
453 DofaultTransactionStatus status = 
454 prepareTransactionStatus(definitiontransaction,newTransaction: false,newSynchranizationc false  
455 status.createAndHoldSavepointO):  
456 return status;  
457
458 else {  不能使用保存点则创健新事务,和之的事务一样的  
459 // Mested transaction through nested begin and coemit/rollback calls. 
46B Usually onlyfor JTa:Spring synchronization might get activated here 
'/ in case of a pre existing ITA transaction.
4G1
402
booleannewSynchronization(getTransactionSynchronization()I=SYNCHRGNIZATIONNEVER)
463 DefaultTransactionStatus status = newTransactionStatus( 
464 definitiontransaction,newTransacbantrue,mewSynchromization, debugEnbled,suspendedResourc  
465 doBegin(transaction,definition):  
466 prepareSynchronization(status, definition); 
467 return status!  
468469478
471 // Assumably PROPAEATION SUPPORTS OF PROPAEATION REQUIRED.  
472 if(debugEnabled){ 
logger.debug( o:"Participating in existing transaction");
4了9 if (1sValidateExistingTransaction()) {  其他情况则使用当前事务,沿用当前事务环境  
if(definition:getIsolationLevel()1=TransactionDefinition:ISOLATION_DEFAULT){
Integer currentIsolationLevel=TransactionSynchronizationManager.getCurrentTransactionIsoLatianLevel() if(currentIsolationLevel -null1 currentIsolationLevel I=definition:getIsolat
Constants isoConstants=DofaultTransactionDefinition.canstants:
thrownewIllegalTransactionStateException("Participating transaction with definition ["

简单时序图

389b77bdc3539a2dbdf8e56953cf2b9.png

有哪些不同类型的事务

Spring中的事务传播属性

1f09d04574930125f1cde996062cd16.png

  • 挂起:在新方法里面,不使用外部的事务环境
  • 嵌套事务:一个事务里面包含另一个事务
  • 保存点:一个事务新起时的保存记录点

事务类型不同会有什么不同效果

REQUIRES_NEWNESTED 为例,来讲讲嵌套事务和保存点的概念。

如下是一段伪代码

情景一:

@Transactional   // 默认事务级别
buyShopping(){
    insertOrder();
    stockService.updateStock();
}
@Transactional(propagation = Propagation.REQUIRES_NEW) 
// 如果使用该级别,库存扣减回滚,插入订单也回滚(使用的保存点)
@Transactional(propagation = Propagation.NESTED) 
updateStock(){
    // 省略业务代码
    // 商品库存减 1
    throw // 如果使用该级别,库存扣减回滚,插入订单成功
Exception;
}

情景二:

@Transactional   // 默认事务级别
buyShopping(){
    insertOrder();
    stockService.updateStock();
    throw Exception;
}
// 如果使用该级别,库存扣减成功,插入订单失败回滚(新事务)
@Transactional(propagation = Propagation.REQUIRES_NEW)  
// 如果使用该级别,插入订单失败回滚,库存扣减同样回滚(savePoint机制)
@Transactional(propagation = Propagation.NESTED) 
updateStock(){
    // 省略业务代码
    // 商品库存减 1
}

关于嵌套事务的更多概念可以参考==>

Spring 采用保存点(Savepoint)实现嵌套事务原理

嵌套事务的使用

注意事项

  • 不要随意使用事务的传播属性
  • 不影响事务的业务代码,请使用try/catch处理
  • 影响事务的业务代码,可以抛出异常使其回滚

Spring是如何控制事务的提交与回滚

事务要保证ACID的完整性必须依靠事务日志做跟踪,每一个操作在真正写入数据数据库之前,先写入到日志文件中,如要删除一行数据会先在日志文件中将此行标记为删除,但是数据库中的数据文件并没有发生变化。只有在(包含多个sql语句)整个事务提交后,再把整个事务中的sql语句批量同步到磁盘上的数据库文件

在事务引擎上的每一次写操作都需要执行两遍:

  1. 先写入日志文件中,写入日志文件中的仅仅是操作过程,而不是操作数据本身,所以速度比写数据库文件速度要快很多.
  2. 然后再写入数据库文件中,写入数据库文件的操作是重做事务日志中已提交的事务操作的记录.

日志组

一般不止设置一个日志文件,一个文件写满之后使用另外一个日志文件提高服务器效率。 日志文件的日志同步到磁盘后空间会自动释放,单个日志文件不宜设置过大,如果日志文件过大mysql进程在把日志同步到数据文件的时候可能会崩溃

事务日志用途

事务日志可以帮助提高事务的效率,使用事务日志,存储引擎在修改表的数据的时候只需要修改其内存拷贝,再把该行为记录到持久在磁盘的事务日志中。而不用每次都将修改的数据本身持久到磁盘事务日志采用的是追加方式,因此写日志的操作是磁盘上一小块区域的顺序IO,而不像随机IO需要磁盘在多个地方移动。所以采用事务日志的方式相对来说要快的多,事务日志持久后,内存中的修改在后台慢慢的刷回磁盘。期间如果系统发生崩溃,存储引擎在重启的时候依靠事务日志自动恢复这部分被修改数据。

更多内容可以参考==> 详细分析MySQL事务日志(redo log和undo log)



目录
相关文章
|
11月前
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
2692 1
|
12月前
|
安全 算法 网络协议
解析:HTTPS通过SSL/TLS证书加密的原理与逻辑
HTTPS通过SSL/TLS证书加密,结合对称与非对称加密及数字证书验证实现安全通信。首先,服务器发送含公钥的数字证书,客户端验证其合法性后生成随机数并用公钥加密发送给服务器,双方据此生成相同的对称密钥。后续通信使用对称加密确保高效性和安全性。同时,数字证书验证服务器身份,防止中间人攻击;哈希算法和数字签名确保数据完整性,防止篡改。整个流程保障了身份认证、数据加密和完整性保护。
|
XML Java 开发者
Spring底层架构核心概念解析
理解 Spring 框架的核心概念对于开发和维护 Spring 应用程序至关重要。IOC 和 AOP 是其两个关键特性,通过依赖注入和面向切面编程实现了高效的模块化和松耦合设计。Spring 容器管理着 Beans 的生命周期和配置,而核心模块为各种应用场景提供了丰富的功能支持。通过全面掌握这些核心概念,开发者可以更加高效地利用 Spring 框架开发企业级应用。
391 18
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
12月前
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
612 1
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
1353 2
|
前端开发 Java Spring
探索Spring MVC:@Controller注解的全面解析
在Spring MVC框架中,`@Controller`注解是构建Web应用程序的基石之一。它不仅简化了控制器的定义,还提供了一种优雅的方式来处理HTTP请求。本文将全面解析`@Controller`注解,包括其定义、用法、以及在Spring MVC中的作用。
386 2
|
11月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1070 29
|
11月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
455 4
|
11月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

热门文章

最新文章

推荐镜像

更多
  • DNS