持续热爱!
Consistency,一致性。Availability,可用性。Partition tolerance,分区容错性。
CAP指出在分布式系统中,不可能同时满足以上三点。
首先一个分布式系统,必然是要考虑P的,即通过将数据复制到多个节点来提高容错性。
而如果要选择A、C,放弃P,不将数据备份到多个节点。那么当然,不用考虑不同结点间数据的同步,一致性就不存在了,而不用考虑一致性问题,能够保证响应时间及时响应用户,可用性问题也就解决了。
每个属性都不可再分。即每个列不可再分。 1NF是所有关系型数据库的最基本要求。
简单来说,就是通过x可以唯一的确定y,比如身份证号可以唯一的确定人名。 那么,就称x函数确定y或y函数依赖于x。记作 x→y。
x称为这个函数依赖的决定属性组,也称为决定因素。
若 x→y,y→x,则记作 x←→y。 若y函数不依赖于x,则记作
若 x→y ,但y不是x的子集,则称 x→y 是非平凡的函数依赖。 若 x→y ,但y是x的子集,则称 x→y 是平凡的函数依赖。
例子,以学生学号sno,课程编号cno,学生课程成绩grade为例。
若 x → y,且 x 的任何一个真子集 x',都不可能 x' → y,则称 y 对 x 完全函数依赖。 记作
比如通过学生学号sno,课程编号cno可以确定学生该课程的成绩grade。 但无法从(sno, cno)的任何真子集中如sno确定学生某一课程的成绩。则称grade对(sno, cno)完全函数依赖。
若 x → y,但 y 不完全函数依赖于 x,则称 y 对 x 部分函数依赖。 记作
比如身份证号码id和手机号码phone可以确定姓名name。 但存在存在 id → name,即部分函数依赖。
sno → 系名dept_name, 系名dept_name → 系主任dept_manager_name。 且dept_name 不是 → sno,不是sno的子集。所以dept_manager_name传递函数依赖于sno。若
则称k为候选码(Candidate Key)。若候选码多于一个,则选定其中一个作为主码(Primary Key,主键)。
如身份证号码id、学号sno都能确定学生的姓名sname,如下表。 那么id、sno为码。若选择id为主键,即主码。
| id | sno | sname |
|---|---|---|
| cno(课程号) | sno(学号) | grade(学生课程成绩) |
|---|---|---|
sdept。| cno(课程号) | sno(学号) | grade(学生课程成绩) | sdept(学生系名) |
|---|---|---|---|
2NF就是消除下图中的虚线。
| cno(课程号) | sno(学号) | grade(学生课程成绩) |
|---|---|---|
| sno(学号) | sdept(学生系名) |
|---|---|
sno是码,sno → sdept,sdept → sloc,且符合传递依赖的定义,所以 sloc 传递依赖于 sno。| sno(学号) | sdept(学生系名) | sloc(学生宿舍地址,同一个系的学生一个地址) |
|---|---|---|
| sno(学号) | sdept(学生系名) |
|---|---|
| sdept(学生系名) | sloc(学生宿舍地址,同一个系的学生一个地址) |
|---|---|
TransactionDefinition接口中规定了7种类型的事务传播行为。 事务传播行为是Spring框架独有的事务增强特性,不属于事务实际提供方即数据库的行为。| 事务传播行为类型 | 说明 |
|---|---|
| REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。 |
| SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
| MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
| REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
| NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
| NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
| NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则创建一个事务。 |
x代码解读复制代码<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.5.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>fun.roran</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- lombok start --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- lombok end --></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build><repositories><repository><id>alimaven</id><name>aliyun maven</name><url>http://maven.aliyun.com/nexus/content/groups/public/</url><releases><enabled>true</enabled></releases><snapshots><enabled>false</enabled></snapshots></repository></repositories></project>
xxxxxxxxxx代码解读复制代码server:port: 80spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMTusername: rootpassword: 123456
xxxxxxxxxx代码解读复制代码CREATE TABLE `tx` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`value` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
xxxxxxxxxx代码解读复制代码package fun.roran.demo.dao;public interface TxDAO {void a();void b();}
xxxxxxxxxx代码解读复制代码package fun.roran.demo.dao.impl;import fun.roran.demo.dao.TxDAO;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;import javax.annotation.Resource;@Repositorypublic class TxDAOImpl implements TxDAO {@ResourceJdbcTemplate jdbcTemplate;@Overridepublic void a() {jdbcTemplate.execute("INSERT INTO tx (value) VALUES ('a')");}@Overridepublic void b() {jdbcTemplate.execute("INSERT INTO tx (value) VALUES ('b')");}}
xxxxxxxxxx代码解读复制代码package fun.roran.demo.service;public interface TxServiceA {void a();}
xxxxxxxxxx代码解读复制代码package fun.roran.demo.service.impl;import fun.roran.demo.dao.TxDAO;import fun.roran.demo.service.TxServiceA;import fun.roran.demo.service.TxServiceB;import org.springframework.stereotype.Service;import javax.annotation.Resource;@Servicepublic class TxServiceAImpl implements TxServiceA {@Resourceprivate TxDAO txDAO;@Resourceprivate TxServiceB txServiceB;@Overridepublic void a() {txDAO.a();txServiceB.b();}}
xxxxxxxxxx代码解读复制代码package fun.roran.demo.service;public interface TxServiceB {void b();}
xxxxxxxxxx代码解读复制代码package fun.roran.demo.service.impl;import fun.roran.demo.dao.TxDAO;import fun.roran.demo.service.TxServiceB;import javax.annotation.Resource;public class TxServiceBImpl implements TxServiceB {@Resourceprivate TxDAO txDAO;@Overridepublic void b() {txDAO.b();}}
a()开启事务a()开启事务的情况下,a()、b()相当于处于同一个事务。它们要么全都提交,要么全都不提交。b()抛出异常,a()、b()会一起回滚。 注意,即使b()的异常被a()捕获,仍是要一起回滚的。a()调用完b()后抛出异常回滚,b()也会回滚。
a()不开启事务a()不开启事务,b()开启事务。a()调用完b()后抛出异常,b()自然不会回滚。 同样若b()抛出异常回滚,也不会影响a()已经执行过的代码。
a()开启事务a()开启事务的情况下,b()会加入a()的事务。二者属于同一事务。b()抛出异常,a()、b()会一起回滚。 注意,即使b()的异常被a()捕获,仍是要一起回滚的。a()调用b()后抛出异常,则b()也会回滚。
a()不开启事务a()不开启事务,则a()、b()都处在非事务环境下。
a()开启事务a()开启事务的情况下,b()会加入a()的事务。二者属于同一事务。b()抛出异常,a()、b()会一起回滚。 注意,即使b()的异常被a()捕获,仍是要一起回滚的。a()调用b()后抛出异常,则b()也会回滚。
a()不开启事务b()时会抛出异常。xxxxxxxxxx代码解读复制代码org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
a()开启事务a()开启事务,执行b()时,会将a()的事务挂起,b()创建一个自己的事务。b()抛出异常回滚,若a()没有对异常进行补获,则也要回滚。 若a()捕获了异常,则a()不用回滚。a()调用完b()后抛出异常,a()回滚,b()不用回滚(因为b()的事务已经提交了)。
a()不开启事务b()会开启一个自身的事务。 b()若发生异常回滚不会影响到a()已执行操作,a()调用完b()后抛出异常自然不会影响到b()。
a()开启事务a()开启事务,但在执行b()的过程中,a()的事务被挂起且b()是无事务方式执行的。a()调用b()后抛出异常,则b()不会被回滚(除了其他b()的其它操作可以回滚)。b()执行中抛出异常,则b()已经执行的操作也不会回滚。 同时若a()没有捕获b()抛出的异常,a()也会被回滚。若a()捕获了,则不会被回滚。a()、b()哪个操作抛出异常且未捕获,a()一定会被回滚,b()一定不会回滚。
a()不开启事务a()、b()都处于无事务状态。a()开启事务b()抛出异常。xxxxxxxxxx代码解读复制代码org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
a()不开启事务a()、b()都处于无事务状态。a()开启事务b()时,开启一个事务,这个事务是a()的子事务。b()抛出异常并回滚时。该异常若被a()捕获,则a()不会回滚,否则a()回滚。a()调用b()后抛出异常,则a()、b()一起回滚。a()不开启事务b()开启了事务。
a()、b()方法写在同一个类中,那么事务传播行为将失效。xxxxxxxxxx代码解读复制代码package fun.roran.demo.service.impl;import fun.roran.demo.dao.TxDAO;import fun.roran.demo.service.TxServiceA;import fun.roran.demo.service.TxServiceB;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;@Servicepublic class TxServiceAImpl implements TxServiceA {@Resourceprivate TxDAO txDAO;@Transactional(rollbackFor = Exception.class)@Overridepublic void a() {txDAO.a();b();}@Transactional(propagation = Propagation.NEVER, rollbackFor = Exception.class)@Overridepublic void b() {txDAO.b();}}
a()方法,发现能够正常运行,不抛出异常。TxServiceAImpl对象生产代理对象后,代理对象底层还是调用TxServiceAImpl对象的b()方法,而这个方法是不支持事务传播功能的。this调用方法,而是通过注入代理对象类调用。xxxxxxxxxx代码解读复制代码package fun.roran.demo.service.impl;import fun.roran.demo.dao.TxDAO;import fun.roran.demo.service.TxServiceA;import fun.roran.demo.service.TxServiceB;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;@Servicepublic class TxServiceAImpl implements TxServiceA {@Resourceprivate TxDAO txDAO;@Resourceprivate TxServiceA txServiceA;@Transactional(rollbackFor = Exception.class)@Overridepublic void a() {txDAO.a();txServiceA.b();}@Transactional(propagation = Propagation.NEVER, rollbackFor = Exception.class)@Overridepublic void b() {txDAO.b();}}
public方法@Transactional只能用于 public 的方法上,否则事务失效。 如果要用在非public方法上,可以开启 AspectJ 代理模式。