第八章、项目发布与总结

本文总结了项目发布过程中的单元测试、监控配置、项目部署,并深入探讨了MySQL的存储引擎、事务特性和锁机制,还涉及了Spring事务管理、Redis缓存策略和Spring框架组件。
摘要由CSDN通过智能技术生成

第八章、项目发布与总结

1、单元测试

在这里插入图片描述

  • @BeforeClass:类加载之前(初始化数据)
  • @AfterClass:类加载之后(销毁数据)
  • @Before:调用方法之前(初始化数据)
  • @After:调用方法之后(销毁数据)

测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = CommunityApplication.class)
public class SpringBootTests {
    @Autowired
    private DiscussPostService discussPostService;
    // 提升作用域
    DiscussPost data;

    @BeforeClass
    public static void beforeClass(){
        System.out.println("before Class");
    }

    @AfterClass
    public static void afterClass(){
        System.out.println("after Class");
    }

    /**
     * 初始化测试数据
     */
    @Before
    public void before(){
        System.out.println("before");
        data=new DiscussPost();

        data.setUserId(111);
        data.setTitle("Test Title");
        data.setContent("Test Data");
        data.setCreateTime(new Date());

        discussPostService.addDiscussPost(data);
    }

    /**
     * 删除测试数据
     */
    @After
    public void after(){
        System.out.println("after");
        // 删除测试数据
        discussPostService.updateStatus(data.getId(),2);
    }

    @Test
    public void testFindById(){
        DiscussPost post = discussPostService.findDiscussPostById(data.getId());
        // 结果是否非空
        Assert.assertNotNull(post);
        System.out.println(data);
        System.out.println(post);
        // 查到的数据与初始化的数据是否一致
        Assert.assertEquals(data.getTitle(),post.getTitle());
        Assert.assertEquals(data.getContent(),post.getContent());
    }

    @Test
    public void testUpdateScore(){
        int rows = discussPostService.updateScore(data.getId(), 2000.00);
        // 期望的值
        Assert.assertEquals(1,rows);

        DiscussPost post = discussPostService.findDiscussPostById(data.getId());
        // 判断是否相同 delta:精度
        Assert.assertEquals(2000.00,post.getScore(),2);
    }
}

2、项目监控

在这里插入图片描述
1. 导包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2. 配置

# actuator
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=info,caches
management:
  endpoints:
    web:
      exposure:
        include: *
        exclude: info,caches

/actuator/health

/actuator/info

自定义监控/actuator/database

@Component
@Endpoint(id = "database")
public class DataBaseEndpoints {

    private static final Logger logger = LoggerFactory.getLogger(DataBaseEndpoints.class);

    @Autowired
    private DataSource dataSource;

    @ReadOperation
    public String checkConnection() {
        try (
                Connection conn = dataSource.getConnection()
        ) {
            return CommunityUtil.getJsonString(0,"获取连接成功!");
        } catch (SQLException e) {
            logger.error("获取连接失败"+e.getMessage());
            return CommunityUtil.getJsonString(1,"获取连接失败!");
        }
    }
}

权限管理

只有管理员可以访问

antMatchers(
        "/discuss/delete",
        "/data/**",
        "/actuator/**"
).hasAnyAuthority(AUTHORITY_ADMIN)

3、项目部署

在这里插入图片描述

4、项目总结

在这里插入图片描述
在这里插入图片描述

5、常见面试题

在这里插入图片描述

1. MySQL

1.1 存储引擎

在这里插入图片描述
存储引擎

存储数据、建立索引、更新/查询数据等技术的实现方式。
存储引擎是基于表的,而不是基于库的,所以存储引擎也可以被称为表类型。

基本操作

  1. 创建表时,指定存储引擎
create table tableName(
	// 字段信息
	...
) engine = innoDB
  1. 查看当前数据库支持的存储引擎
show engines;
1. InnoDB

介绍

一种兼顾高可靠性和高性能的通用存储引擎,在MySQL 5.5之后,InnoDB是默认的MySQL存储引擎。

特点

  • DML操作遵循ACID模型,支持事务
  • 行级锁,提高并发访问性能
  • 支持外键 FOREIGN KEY 约束,保证数据的完整性和正确性

文件

  • xxx.ibd文件:xxx代表表名,innoDB引擎的每张表都会对应这样一个表空间文件,存储该表的表结构(frm,sdi)、数据和索引

参数:innodb_fille_per_table
在这里插入图片描述

2. MyISAM

介绍

MyISAM是MySQL早期的默认存储引擎

特点

  • 不支持事务,不支持外键
  • 支持表锁,不支持行锁
  • 访问速度快

文件

  • xxx.sdi: 存储表结构信息
  • xxx.MYD:存储数据
  • xxx.MYI:存储索引
3. Memory

介绍

Memory引擎的表数据是存储在内存中的,由于受到硬件问题、或断电问题的影响,只能将这些表作为临时表或缓存使用。

特点

  • 内存存放
  • hash索引(默认)

文件

  • xxx.sdi:存储表结构信息

MyISAM 由 MangoDB 替代 ,MEMORY 由 Redis 替代

三者对比
在这里插入图片描述

2. 事务

2.1 简介

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么全部成功,要么全部失败。

在这里插入图片描述

默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务。

基本操作

  1. 查看/设置事务提交方式
select @@autocommit;
-- 设置为手动提交事务
set @@autocommit = 0 ; 
  1. 提交事务
commit;
  1. 回滚事务
rollback;

如果业务正常提交,执行commit 指令
如果业务出现异常,执行rollback 指令

  1. 开启事务
start transactionbegin ;
2.2 特性
  • 原子性、一致性、隔离性、持久性

原子性(Atomicity)

  • 事务是不可分割的最小操作单元,要么全部成功,要么全部失败;

一致性(Consistency)

  • 事务完成时,必须使所有的数据都保持一致状态;

隔离性(Isolation)

  • 数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行;

持久性(Durability)

  • 事务一旦提交或回滚,它对数据库的数据的改变是永久的。
2.3 隔离性

并发事务出现的问题

1. 第一类丢失更新

  • 某一个事务的回滚,导致另外一个事务已更新的数据丢失了
    在这里插入图片描述
    事务1的回滚,导致了事务2已提交的数据丢失了

2. 第二类丢失更新

  • 某一个事务的提交,导致另外一个事务已经更新的数据丢失了。
    在这里插入图片描述
    事务1的提交导致了事务2的已更新的数据丢失了。

3. 脏读

  • 一个事务读到另一个事务还没有提交的数据;
    在这里插入图片描述
    事务A执行了update语句后,事务B执行了select语句,此时事务A并未提交,事务B却读取到了更新后的数据。

4. 不可重复读

  • 一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
    在这里插入图片描述
    事务A的第二个select语句执行时,事务Bupdate已经提交了,所以造成读取的两次数据不一致。

5. 幻读

  • 一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了“幻影”。
    在这里插入图片描述
    事务A在执行insert语句时,此时事务Binsert语句已经提交,所以在执行时,会发现数据已被插入,但是事务A的下一个select语句却查不到数据。

事务的隔离级别
在这里插入图片描述

基本操作

-- 查看事务隔离级别
select @@transaction_isolation

-- 设置事务隔离级别
set [session|global] transaction isolation level {read uncommitted | read committed | repeatable read | serializble}

Read uncommitted

  • 未提交读
  • 解决了更新丢失,但还是可能会出现脏读

Read committed

  • 读已提交
  • 解决了更新丢失和脏读问题

Repeatable Read

  • 可重复读
  • 解决了更新丢失、脏读、不可重复读、但还是会出现幻读

Serializable

  • 可串行化
  • 解决了更新丢失、脏读、不可重复读、幻读

小结

生产中要根据业务的情形来使用隔离级别,随着隔离级别增高,数据库的性能会直线下降,所以运用需要权衡。

2.4 Spring 事务

Spring中的默认隔离级别是 Read committed (读已提交)

1. 声明式事务
  • 通过XML配置,生命某方法的事务特征。
  • 通过注解,声明某方法的事务特征。

@Transactional

  • isolation:隔离级别
  • propagation:传播机制
    1. REQUIRED:支持当前事务(外部事务),如果不存在则创建新事务;
    2. REQUIRES:创建一个新事务,并且暂停当前事务(外部事务);
    3. NESTED:如果当前存在(外部事务),则嵌套在该事务中执行(独立的提交和回滚),否则就和REQUIRED一样。
2. 编程式事务
  • 通过Transaction Template 管理事务,并通过它执行数据库的操作。

    TransactionTemplate.setIsolationLevel();
    TransactionTemplate.setPropagationBehavior();

3. 锁

3.1 介绍
  1. 锁是计算机协调多个进程或线程并发访问某一资源的机制。
  2. 如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题。

分类

  1. 全局锁:锁定数据库中的所有表;
  2. 表级锁:每次操作锁住整张表;
  3. 行级锁:每次操作所著对应的数据行;
3.2 全局锁
  1. 对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句、DDL语句,已经更新操作的事务提交语句都将被阻塞;
  2. 典型应用场景:全库的逻辑备份。获取一致性视图,保证数据的完整性。

基本操作

-- 加全局锁
flush tables with read lock;

-- 备份数据
mysqldump -uroot -p1234 itcast>itcast.sql; -- 存放路径

-- 释放锁
unlock tables;

全局锁存在的问题

  1. 如果在主库上备份,那么在备份期间都不能执行更新,业务基本就得停摆。
  2. 如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟。

在这里插入图片描述
在这里插入图片描述

3.3 表级锁

每次操作锁住整张表。锁定粒度大,发生锁冲突的该路最高,并发度最低。分为:

  • 表锁
  • 元数据锁
  • 意向锁
1. 表锁

1. 表共享读锁(read lock)
2. 表独占写锁(write lock)

操作

  • 加锁:lock tables tableName read/wirte
  • 释放锁:unlock tables 或 客户端断开连接

加个read锁后,当前客户端和其他客户端可以读。当前客户端不可以写,其他客户端阻塞

加了write锁后,当前客户端可读可写。其他客户端不可读不可泄,处于阻塞状态。

读锁不对阻塞其他客户端的读,但会阻塞写。写锁既会阻塞其他客户端的读,又会阻塞其他客户端的写

2. 元数据锁

meta data lock MDL

1.系统自动控制,无需显示使用,在访问一张表的时候会自动加上。
2. 主要作用是维护表元数据的数据一致性,在表上有活动事务时,不可以对元数据进行写入操作。为了避免DML与DDL冲突,保证读写的正确性。

在MySQL5.5中引入,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更操作的时候,加MDL写锁(排他)。

操作

-- 查看元数据锁
select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;
3. 意向锁

意向共享锁(IS)

  • 与表锁共享锁(read)兼容,与表锁排他锁(write)互斥。

意向排他锁(IX)

  • 与表锁共享锁(read)及排他锁(write)都互斥。意向锁之间不会互斥。
-- 查看意向锁及行锁的加锁情况
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data 
from performance_schema.data_locks;
3.4 行级锁
1. 行锁
  1. 共享锁:允许事务去读一行,阻止其他事务获得相同数据集的排他锁。
  2. 排他锁:允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。
    在这里插入图片描述

在这里插入图片描述

默认情况下,InnoDBREPEATABLE READ 事务隔离级别运行,InnoDB使用next-key锁进行搜索和索引扫描,以防止幻读

  1. 针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。
  2. InnoDB的行锁是针对于索引加的锁,不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁。

操作

-- 查看意向锁及行锁的加锁情况
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data 
from performance_schema.data_locks;

2. 间隙锁/临建锁

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
悲观锁

当要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制,也称为悲观锁。

乐观锁

乐观并发控制相信事务之间的数据竞争(data race)的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。

4. 索引

InnoDB中采用B+Tree的数据结构存储索引。

索引

帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

优点

  1. 提高数据检索的效率,降低数据库的成本;
  2. 通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗

缺点

  1. 索引列占用额外的空间
  2. 索引大大的提高了查询效率,同时也降低了更新表的速度,如对表进行插入、更新、删除时效率降低

在这里插入图片描述
在这里插入图片描述
为什么InnoDB存储引擎选择使用B+Tree索引结构?

  • 相对于二叉树,层级较少,搜索效率高;
  • 相对于B-Tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;
  • 相对于hash索引,B+Tree支持范围匹配及排序操作;

5. Redis

5.1 数据类型

在这里插入图片描述

5.2 过期策略

在这里插入图片描述

5.3 淘汰策略

在这里插入图片描述
在这里插入图片描述

5.4 缓存穿透(查不到)

在这里插入图片描述

5.5 缓存击穿(热点数据,缓存过期)

在这里插入图片描述

5.5 缓存雪崩(缓存不能正常服务)

在这里插入图片描述

5.6 分布式锁

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6. Spring IOC

在这里插入图片描述

7. Spring AOP

在这里插入图片描述

8. Spring MVC

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值