Article Directory
Foreword
Why slag slag will suddenly learn this Spring transaction isolation level and spread it?
Tucao said a colleague yesterday, after an update query to the old data, so this decision to put forward a clear slag slag.
Crime scene
Then I tried it save * (check -> update-> check), as well as xx (check -> update-> check);
result
Our database is RC level
The first case: found in old data, update the database after navicat do not see the data update, query data found old
The second situation: found in old data, navicat after the updated database to see the data update, query data found in the old (but also a cache hit)
That is the first case when the update is not committed.
Causes
show you the code
@Getter
@Setter
@Configuration
public class TransactionConfiguration {
private static final String CUSTOM_PLATFORM_TRANSACTION_MANAGER_NAME = "platformTransactionManager";
private static final String CUSTOM_TRANSACTION_INTERCEPTOR_NAME = "customTransactionInterceptor";
private static final String CUSTOM_BEAN_NAME_AUTO_PROXY_CREATOR_NAME = "beanNameAutoProxyCreator";
/**
* 默认的只读事务
*/
private static final String[] DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES = { "get*", "count*", "find*",
"query*", "select*", "list*", "*", };
/**
* 默认只对 "*Service" , "*ServiceImpl" Bean 进行事务处理,"*"表示模糊匹配, 比如 :
* userService,orderServiceImpl
*/
private static final String[] DEFAULT_TRANSACTION_BEAN_NAMES = { "*Service", "*ServiceImpl" };
/**
* 可传播事务配置
*/
private static final String[] DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES = { "add*", "save*", "insert*",
"delete*", "update*", "edit*", "batch*", "create*", "remove*", };
/**
* 自定义事务 BeanName 拦截
*/
private String[] customTransactionBeanNames = {};
/**
* 自定义方法名的事务属性相关联,可以使用通配符(*)字符关联相同的事务属性的设置方法; 只读事务
*/
private String[] customReadOnlyMethodRuleTransactionAttributes = {};
/**
* 自定义方法名的事务属性相关联,可以使用通配符(*)字符关联相同的事务属性的设置方法; 传播事务(默认的)
* {@link org.springframework.transaction.annotation.Propagation#REQUIRED}
*/
private String[] customRequiredMethodRuleTransactionAttributes = {};
@Autowired
@Qualifier(value="druidDataSource")
private DataSource dataSource;
@Bean(name = CUSTOM_PLATFORM_TRANSACTION_MANAGER_NAME)
public PlatformTransactionManager platformTransactionManager() {
return new DataSourceTransactionManager(this.dataSource);
}
/**
* 配置事务拦截器,注意:transactionInterceptor 名称的 bean 可能已经存在,导致该生成 bean
* 的方法不能执行,所以定义成另外一个名字
*
* @param platformTransactionManager
* 事务管理器
* @return
*/
@Bean(name = CUSTOM_TRANSACTION_INTERCEPTOR_NAME)
public TransactionInterceptor customTransactionInterceptor(
@Qualifier(CUSTOM_PLATFORM_TRANSACTION_MANAGER_NAME) PlatformTransactionManager platformTransactionManager) {
NameMatchTransactionAttributeSource transactionAttributeSource = new NameMatchTransactionAttributeSource();
RuleBasedTransactionAttribute readOnly = this.readOnlyTransactionRule();
RuleBasedTransactionAttribute required = this.requiredTransactionRule();
// 默认的只读事务配置
for (String methodName : DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES) {
transactionAttributeSource.addTransactionalMethod(methodName, readOnly);
}
// 定制的只读事务配置
for (String methodName : customReadOnlyMethodRuleTransactionAttributes) {
transactionAttributeSource.addTransactionalMethod(methodName, readOnly);
}
// 默认的传播事务配置
for (String methodName : DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES) {
transactionAttributeSource.addTransactionalMethod(methodName, required);
}
// 定制的传播事务配置
for (String methodName : customRequiredMethodRuleTransactionAttributes) {
transactionAttributeSource.addTransactionalMethod(methodName, required);
}
return new TransactionInterceptor(platformTransactionManager, transactionAttributeSource);
}
/**
* 当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务
* {@link org.springframework.transaction.annotation.Propagation#REQUIRED}
*/
private RuleBasedTransactionAttribute requiredTransactionRule() {
RuleBasedTransactionAttribute required = new RuleBasedTransactionAttribute();
required.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
required.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
required.setTimeout(TransactionDefinition.TIMEOUT_DEFAULT);
return required;
}
/**
* 只读事务
* {@link org.springframework.transaction.annotation.Propagation#NOT_SUPPORTED}
*/
private RuleBasedTransactionAttribute readOnlyTransactionRule() {
RuleBasedTransactionAttribute readOnly = new RuleBasedTransactionAttribute();
readOnly.setReadOnly(true);
readOnly.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
return readOnly;
}
/**
* 配置事务拦截
* <p>
* {@link #customTransactionInterceptor(PlatformTransactionManager)}
*/
@Bean(name = CUSTOM_BEAN_NAME_AUTO_PROXY_CREATOR_NAME)
public BeanNameAutoProxyCreator customTransactionBeanNameAutoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
// 设置定制的事务拦截器
beanNameAutoProxyCreator.setInterceptorNames(CUSTOM_TRANSACTION_INTERCEPTOR_NAME);
// 默认 + 定制
String[] unions = ArrayUtils.addAll(DEFAULT_TRANSACTION_BEAN_NAMES, customTransactionBeanNames);
beanNameAutoProxyCreator.setBeanNames(unions);
beanNameAutoProxyCreator.setProxyTargetClass(true);
return beanNameAutoProxyCreator;
}
}
This one on the Internet is readily possible to search, that is, after you copy over the use of non-brain type, cc ~
analysis
Cook the code above that, a bit like xml configuration of the transaction. It is a method name to match, and then add the transaction.
The reason that this is the case, then look at those two cases before due.
The reason the first case
save to open a default transaction, and then get the time, the transaction pending. update and restore the original transaction, get and hang, then submit.
The reason the second case
Common approach is to not open a transaction, and then get the normal run, update start a business, get here is not going to suspend update transaction, the transaction should be regarded as a sub, this time, update submitted to the transaction. get hit cache, found in old data.
Spring transaction propagation and isolation level learning
spring.io go from official website
spring transaction level
Enum Propagation
PROPAGATION_REQUIRED
The default isolation level
if a transaction is currently with the current transaction. If not, create one.
be careful
When the inner function rollback problem, will result in a rollback outer function together.
PROPAGATION_REQUIRES_NEW
Always New Transaction.
important point
Do not affect each other, transaction rollback
PROPAGATION_NESTED
Transaction nesting.
Daitao old sow, one after another, ah ha ha.
Is a transaction inside, there is another transaction. Outside large transaction rollback transaction rollback will result in a small, but small transaction rollback does not affect the large transaction execution.