InnoDB引擎架构

news2024/7/31 5:49:18

1、逻辑存储结构:

表空间(ibd文件):一个Mysql实例可以对应多个表空间,用于存储记录、索引等数据。

段:分为数据段、索引段、回滚段、

InnoDB是索引组织表,数据段就是B+树的叶子节点,索引段就是B+树的非叶子节点,段用来管理多个(Extent)区

区:表空间中的单元结构,每个区的大小为1M,默认情况下,InnoDB存储引擎页大小为16K,即一个区中共有64个连续的页

页:是InnoDB存储引擎磁盘管理的最小单元,每个页大小16KB,为保证页的连续性,InnoDB存储引擎每次从磁盘申请4-5个区

行:InnoDB存储引擎是按行进行存放的

Trx_id:每次对某条记录进行改动时,都会把对应事务的ID赋值给 trx_id 隐藏列,也即是最后一次操作事务的ID

Roll_pointer:每次对某条记录进行改动时,都会把旧版本写入到 undo 日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息

2、InnoDB-架构 

2.1  内存结构

2.1.1 BufferPool:缓冲池

缓冲池是属于内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查的时候会先操作缓冲池中的数据(如果此时缓冲区没有数据,则从磁盘加载并缓存),然后再以一定的频率或者规则刷新到磁盘,以减少磁盘的IO次数,加快处理速度。

如果没有缓冲区的话,每一次增删改查操作都会去操作磁盘空间,就会存在大量的磁盘IO,在业务中磁盘IO是随机IO,非常的耗时耗性能,所以需要尽量减少磁盘IO。

缓冲池的处理单位是页,底层采用的是链表数据结构来管理Page,根据状态,将Page分为三种类型:

  • free page:空闲page,未被使用
  • clean page:被使用page,数据没有被修改过
  • dirty page:脏页,被使用page,数据被修改过,数据与磁盘中的数据不一致

2.2.2 Change Buffer:更改缓冲区

在执行DML语句时,如果这些数据page没有在Buffer Pool中,不会直接就去操作磁盘,而会将当前的数据变更存储在Change Buffer(更改缓冲区)中,在未来数据被读取的时候,再将数据合并恢复到Buffer Pool中,再将合并后的数据刷新到磁盘。

作用:每一次操作磁盘会造成大量的磁盘IO,有了ChangeBuffer之后,可以在缓冲池中进行合并处理,就会大量减少磁盘IO

2.2.3 Adaptive Hash Index:

自适应hash索引,用于优化对Buffer Pool(缓冲池)数据的查询,InnoDB会监控对表上各索引页的查询,如果发现Hash索引可以提升速度,则创建Hash索引。注意:自适应Hash索引,无需人工干涉,是系统根据情况自动完成。

自适应哈希索引有一个标志开关来设置是否启用:adaptive_hash_index.

2.2.4 Log Buffer:日志缓冲区

日志缓冲区,保存要写入磁盘中的Log日志数据(redo log、undo log),默认16MB,日志会定期刷新到磁盘中,如果需要更新、插入或删除许多行的事务,增加日志缓冲区大小可以节省磁盘IO

参数:

InnoDB_log_buffer_size:缓冲区大小、

InnoDB_flush_log_at_trx_commit:日志刷新到磁盘的时机(该参数有3个值:1、0、2)

1、每次事务提交刷新到磁盘

0、每秒日志写入并刷新到磁盘

2、每次事务提交后,并每秒刷新到磁盘

2.2 磁盘结构

2.2.1 System Tablespace:系统表空间,是内存结构中【更改缓冲区(Change Buffer)】的存储区域。参数:innodb_data_file_path

2.2.2 File-Per-Table Tablespace:每个表文件的表空间,包含单个InnoDB表的数据和索引,并存储在文件系统上的单个数据文件中。参数:innodb_file_per_table (默认开启)

2.2.3 General Tablespace:通用表空间,需要通过create TableSpace语法创建,创建表时可以指定。(相当于我们可以自己手动创建表空间,然后在新建表时指定到我们手动创建的表空间)

2.2.4 Undo Tablespace:撤销表空间,MySQL实例在初始化时会自动创建两个默认的undo表空间(默认16MB),用于存放undo log日志。

2.2.5 Temporary Tablespace:临时表空间,InnoDB会使用会话临时表空间和全局临时表空间,存储用户创建的临时表数据等。

2.2.6 Doublewrite Buffer Files:双写缓冲区,InnoDB引擎将数据页从Buffer Pool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据

2.2.7 Redo Log:重做日志,实现事务的持久性,由重做日志缓冲(redo buffer)重做日志文件(redo log)组成,前者是在内存中,后者在磁盘中。当事务提交后,会把所有修改信息都放到该日志中,用于刷新脏页到磁盘时发生错误,进行数据恢复。

2.3 后台线程

作用:将InnoDB缓冲池中的数据在合适的时机刷新到磁盘文件中。

2.3.1 Master Thread

核心后台线程,负责调度其他线程,还负责将缓冲池中的数据异步刷新到磁盘中,保持数据的一致性,还包括脏页的刷新、合并插入缓存、undo页的回收。

2.3.2 IO Thread 

在InnoDB存储引擎中大量使用了AIO来处理IO请求,这样可以极大地提高数据库的性能,而IO Thread主要负责这些IO请求的回调

2.3.3 Purge Thread

主要用于回收事务已经提交了的undo Log,在事务提交之后,undo Log可能不用了,就用它来回收

2.3.4 Page Cleaner Thread

协助 Master Thread 刷新脏页到磁盘的线程,它可以减轻Master Thread 的工作压力,减少阻塞

3、事务原理

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

1.原子性(Atomicity) 一个事务必须被视为一个不可分割的最小单元, 整个事务中的所有操作要么全部提交成功, 要么全部失败,对于一个事务来说,不可能只执行其中的一部分操作

2.一致性(Consistency) 如果在执行事务之前数据库是一致的,那么在执行事务之后数据库也还是一致的;

3.隔离性(Isolation) 事务操作之间彼此独立和透明互不影响。事务独立运行。这通常使用锁来实现。 一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。 事务的100%隔离,需要牺牲速度。

4.持久性(Durability) 事务一旦提交,其结果就是永久的。即便发生系统故障,也能恢复。

原子性、一致性、持久性由redolog 和undo log 控制完成

隔离性由锁和MVCC来控制完成 

—>  持久性由redo log保证

Redo Log:重做日志,实现事务的持久性,由重做日志(redo buffer)和重做日志(redo log)组成,前者是在内存中,后者在磁盘中,事务提交后,会把所有修改信息都放到该日志中,用于刷新脏页到磁盘时发生错误,进行数据恢复。

 说明:图中说明的是当一个事务被提交之后在InnoDB中是怎么的处理机制来保证事务的持久性,首先事务提交之后,会到内存结构中的Buffer Pool中对应的数据页的进行数据修改等操作,完成操作后,此时在内存中事务已经执行完成,而并没有及时刷新到磁盘中,当前内存中这个被更新的数据页叫做脏页,而在Buffer Pool中进行操作时,在内存区中的Redolog Buffer中会记录所有的操作,然后由后台线程定期刷新到磁盘中的Redo Log中,然后在Buffer Pool中的数据刷新到磁盘中发生错误时,可以通过磁盘中的Redo Log进行数据的恢复。当Buffer Pool数据正确同步到磁盘后,磁盘中的Redolog也就没有用了,所以在磁盘中的两个redolog通过互相复制来达到及时更新。 这种先写日志,后同步数据的做法叫WAL(Write-Ahead Log)

那为什么要多此一举,先写到Redolog Buffer中,再传到Redo Log中呢,直接每次事务之后将数据从Buffer Pool中刷新到磁盘不就行了嘛?这里存在一个问题,事务中对数据页的操作绝大部分时候是随机的,如果每次事务都立即刷新到磁盘中的话,会产生多次的磁盘IO,这将会很耗费性能,所以我们通过Redolog这样来保证数据的持久性。

—>  原子性由undo log保证 

undo log:回滚日志,用于记录数据被修改前的信息,作用包含:提供回滚和MVCC(多版本控并发制)

undo log 和 redo log 记录物理日志不一样,它是逻辑日志,可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,会记录一条对应相反的update记录,执行rollback时,就可以从undo log中的逻辑记录读取到相应内容并回滚。

undo log 销毁:在事务执行时产生,事务提交时,并不会立即删除undo log,这些日志可能还用于MVCC。

undo log 存储:采用段的方式进行管理和记录,存放在rollback回滚段中,内部包含1024个undo log segment。

4、MVCC

4.1  概 念

什么是MVCC?

MVCC是在并发访问数据库时,通过对数据做多版本管理,避免因为写数据时要加写锁而阻塞读取数据的请求,造成写数据时无法读取数据的问题。

通俗的讲就是MVCC通过保存数据的历史版本,根据比较数据的版本号来决定数据的是否显示,在不需要加读锁的情况就能达到事务的隔离效果,最终可以在读取数据的时候可以同时进行修改,修改数据时候可以同时读取,极大的提升了事务的并发性能。

4.2  InnoDB MVCC实现的核心知识点

4.2.1 事务版本号

每个事务开启前都会从数据库获得一个自增长的事务ID,可以从事务ID判断事务的执行先后顺序。

4.2.2 表的隐藏列

DB_TRX_ID记录操作该数据事务的事务ID;
DB_ROLL_PTR指向上一个版本数据在undo log 里的位置指针;
DB_ROW_ID隐藏ID ,当创建表没有合适的索引作为聚集索引时,会用该隐藏ID创建聚集索引;

4.2.3 Undo Log

Undo Log 主要用于记录数据被修改之前的日志,在表信息修改之前先会把数据拷贝到undo log 里,当事务进行回滚时可以通过undo log 里的日志进行数据还原。

 Undo Log的用途

(1)保证事务进行rollback时的原子性和一致性,当事务进行回滚的时候可以用undo log的数据进行恢复。

(2)用于MVCC快照读的数据,在MVCC多版本控制中,通过读取undo log的历史版本数据可以实现不同事务版本号都拥有自己独立的快照数据版本。

4.2.4 事务版本号、表格的隐藏列、undo log的关系

我们通过一次数据修改的模拟过程来理解事务版本号、隐藏列、undolog之间的使用关系

(1)首先准备一张原始数据表

(2)开启一个事务A:对user_info表执行 update user_info set name =“李四”where id=1 会进行如下流程操作

1、首先获取一个事务编号104
2、把user_info表修改前的数据拷贝到undo log
3、修改user_info表 id=1的数据
4、把修改后的数据事务版本号改成 当前事务版本号,并把DB_ROLL_PTR 地址指向undo log数据地址。

(3) 最后执行完的结果如图

4.2.5 undolog 版本链

不同事务或相同事务对同一条记录进行修改,会导致该记录的undo log生成一条记录版本链表,该链表的头部是最新的旧记录,链表的尾部是最早的旧记录。

4.2.6 Read View

在InnoDB中每个事务开启后都会得到一个(Read view)。副本主要保存了当前数据库系统中正处于活跃(没有commit)的事务的ID号,其实简单的说这个副本中保存的是系统中当前不应该被本事务看到的其他事务id列表。(当每个事务开启时,都会被分配一个 ID , 这个 ID 是递增的,所以最新的事务,ID 值越大)

所以我们知道 Read View 主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个 Read View 读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。

Read View遵循一个可见性算法,主要是将要被修改的数据的最新记录中的 DB_TRX_ID(即当前事务 ID )取出来,与系统当前其他活跃事务的 ID 去对比(由 Read View 维护),如果 DB_TRX_ID 跟 Read View 的属性做了某些比较,不符合可见性,那就通过 DB_ROLL_PTR 回滚指针去取出 Undo Log 中的 DB_TRX_ID 再比较,即遍历链表的 DB_TRX_ID(从链首到链尾,即从最近的一次修改查起),直到找到满足特定条件的 DB_TRX_ID , 那么这个 DB_TRX_ID 所在的旧记录就是当前事务能看见的最新老版本
 

Read View的几个重要属性:

m_ids: 当前系统活跃(未提交)事务版本号集合
min_trx_id: 最小活跃事务ID
max_trx_id: 预分配事务ID,当前最大事务ID+1(因为事务ID是自增的)
creator_trx_id: 创建当前read view的事务版本号

Read view 匹配条件:

1、数据事务ID==creator_trx_id

成立的话可以访问该版本,说明数据是当前这个事务更改的

2、数据事务ID <min_trx_id 则显示

如果数据事务ID小于read view中的最小活跃事务ID,则可以肯定该数据是在当前事务启之前就已经存在了的,所以可以显示。

3、数据事务ID>=max_trx_id则不

如果数据事务ID大于read view 中的当前系统的最大事务ID,则说明该数据是在当前read view 创建之后才产生的,所以数据不予显示。

4、min_trx_id<=数据事务ID<max_trx_id 则与活跃事务集合trx_ids里匹配

如果数据的事务ID大于最小的活跃事务ID,同时又小于等于系统最大的事务ID,这种情况就说明这个数据有可能是在当前事务开始的时候还没有提交的。

所以这时候我们需要把数据的事务ID与当前read view 中的活跃事务集合trx_ids 匹配:

情况1: 如果事务ID不存在于trx_ids 集合(则说明read view产生的时候事务已经commit了),这种情况数据则可以显示。

情况2: 如果事务ID存在trx_ids则说明read view产生的时候数据还没有提交,但是如果数据的事务ID等于creator_trx_id ,那么说明这个数据就是当前事务自己生成的,自己生成的数据自己当然能看见,所以这种情况下此数据也是可以显示的。

情况3: 如果事务ID既存在trx_ids而且又不等于creator_trx_id那就说明read view产生的时候数据还没有提交,又不是自己生成的,所以这种情况下此数据不能显示。

5、不满足read view条件时候,从undo log里面获取数据

当数据的事务ID不满足read view条件时候,从undo log里面获取数据的历史版本,然后数据历史版本事务号回头再来和read view 条件匹配 ,直到找到一条满足条件的历史数据,或者找不到则返回空结果;

4.3  InnoDB实现MVCC的原理

4.3.1 模拟MVCC实现流程

下面我们通过开启两个同时进行的事务来模拟MVCC的工作流程。

(1)创建user_info表,插入一条初始化数据

(2) 事务A和事务B同时对user_info进行修改和查询操作

事务A:update user_info set name =”李四”

事务B:select * fom user_info where id=1

问题:

先开启事务A ,在事务A修改数据后但未进行commit,此时执行事务B。最后返回结果如何。

执行流程如下图:

 

 上图执行流程说明:

1、事务A:开启事务,首先得到一个事务编号102;

2、事务B:开启事务,得到事务编号103;

3、事务A:进行修改操作,首先把原数据拷贝到undolog,然后对数据进行修改,标记事务编号和上一个数据版本在undo log的地址。

4、事务B: 此时事务B获得一个read view ,read view对应的值如下

5、事务B: 执行查询语句,此时得到的是事务A修改后的数据

6、事务B: 把数据与read view进行匹配

发现不满足read view显示条件,所以从undo lo获取历史版本的数据再和read view进行匹配,最后返回数据如下。

4.4  快照读和当前读

当前读:

读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于日常操作,如:select ... lock in share mode(共享锁),select ... for update、update、insert、delete(排它锁)都是一种当前读

 

快照读:

简单的select(不加锁)就是快照读,快照读读取的是记录数据的可见版本,有可能是历史数据,不加锁是非阻塞锁

        Read Committed:每次select,都生成一个快照读

        Repeatable Read:开启事务后第一个select语句才是快照读的地方

        Serializable:快照读会退化为当前读

数据库并发场景有三种:

读-读:不存在任何问题,也不需要并发控制

读-写:有线程安全问题,可能会造成事务隔离性的问题,可能遇到脏读,幻读,不可重复读

写-写:有线程安全问题,可能会存在更新丢失的问题,比如第一类
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/65076.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Flink1.16.0的SQLGateway迁移Hive SQL任务

使用Flink的SQL Gateway迁移Hive SQL任务 前言 我们有数万个离线任务&#xff0c;主要还是默认的DataPhin调度CDP集群的Hive On Tez这种低成本任务&#xff0c;当然也有PySpark、打Jar包的Spark和打Jar包的Flink任务这种高成本的任务【Java和Scala都有】。毕竟SQL上手门槛极低…

【邻接表】【数组表示链表】怎么用数组链表 表示 邻接表

怎么用数组链表 表示 邻接表***邻接表&#xff08;数组链表&#xff09;是怎么存储的&#xff1f;***邻接表&#xff08;数组链表&#xff09;是怎么存储的&#xff1f; 正常情况下&#xff0c;我们用链表存储的话&#xff0c;我们让 1 指向 2 我们会给出 1 和 2的地址&#xf…

Java基于JSP二手书交易平台设计与实现

现代网络技术发展迅速&#xff0c;传统的书店销售模式受到诸如场地、资金、宣传等因素制约&#xff0c;已经不能满足人们的日益增长的图书购买需求&#xff0c;网上书店应运而生&#xff0c;基于web的网络书店给人们带来了很大便利&#xff0c;网络书店不仅是传统售书模式的发展…

AidLux智慧交通AI安全实战学习

本次参加AidLux训练营&#xff0c;Rocky作为主讲老师&#xff0c;学习到了利用目标检测算法流程和AI攻防策略进行结合&#xff0c;从而达到安全。 1.检测汽车模型的训练 本次目标检测的模型是Yolov5&#xff0c;首先对标注图片 进行转换&#xff0c;转换为yolov5的格式&#…

《痞子衡嵌入式半月刊》 第 61 期

痞子衡嵌入式半月刊&#xff1a; 第 61 期 这里分享嵌入式领域有用有趣的项目/工具以及一些热点新闻&#xff0c;农历年分二十四节气&#xff0c;希望在每个交节之日准时发布一期。 本期刊是开源项目&#xff08;GitHub: JayHeng/pzh-mcu-bi-weekly&#xff09;&#xff0c;欢…

激光切割机机械结构设计

目 录 摘 要………………………………………………………………………………………Ⅰ ABSTRACT…………………………………………………………………………………… Ⅱ 1 绪论 1 1.1课题背景 1 1.2现实意义 1 1.3设计任务 1 1.4总体设计方案分析 2 2 机械部分XY工作台及Z轴的…

分享99个小清新PPT模板,总有一款适合您

PPT下载链接&#xff1a;https://pan.baidu.com/s/1VW0Eljx1Ac9QEEBaiIvqcg?pwd40hn 提取码&#xff1a;40hn 源码下载链接&#xff1a;ppt.rar - 蓝奏云 采集的参数 page_count 1 # 每个栏目开始业务content"text/html; charsetgb2312"base_url "https:…

如何查找无物流信息单号

我是在一家大公司里面上班&#xff0c;我公司都是那种厂家直销&#xff0c;所以每天发货量是比较大&#xff0c;同时一天都是几家快递同时发货&#xff0c;我是负责每天跟踪物流信息状况&#xff0c;公司要求每天都上报当天发货的快递在24小时之内有没有物流信息&#xff0c;如…

嵌入式编程别忽略了C语言的标准

正文大家好&#xff0c;我是bug菌~最近做代码评审发现很多同事的编码都游走在风险的边沿&#xff0c;其中最显眼的就是局部变量定义位置比较随意。对于C语言编程老手而言&#xff0c;绝大部分都已经养成了"变量定义必放在语句块的开头"这一习惯&#xff0c;依稀还记得…

windows虚拟机中docker运行springboot容器报错:Unable to access jarfile /app.jar

1.在Windows系统中创建了虚拟机&#xff0c;并且在虚拟机中安装了docker&#xff0c;但是在使用Dockerfile创建镜像并且运行时报错 2.使用shell脚本运行的&#xff0c;并且检查后也没有发现文件或者路径有错 解决&#xff1a; 使用vim加参数的形式打开shell脚本&#xff0c;可以…

微服务架构下的认证鉴权解决方案

背景 单体应用在向微服务化架构演进时&#xff0c;需要考虑如何解决服务认证授权的问题。如果处理不好&#xff0c;会引发架构的混乱&#xff0c;带来安全、性能、难以维护的问题。 以最典型的包含WEB页面的具备登录态管理的系统为例。在最初阶段&#xff0c;登录鉴权一般通过…

文华财经期货技术分析日内多空信号共振指标公式,波段行情短线抄单操盘幅图指标

​期货交易的很大一个误区是“痴迷于各种指标公式” 大家千万不要痴迷于指标&#xff0c;记住一点:行情软件界面之中的K线图叫主图&#xff0c;其余指标叫附图。 这从叫法上就该知道&#xff0c;我们寻找买卖点要在主图K线上来寻找&#xff0c;指标只是起到辅助分析的作用&…

操作系统02_内存分页管理_分段管理_设备管理_IO处理_索引文件结构_文件目录_位示图---软考高级系统架构师007

存储管理可以分为固定存储管理和分页存储管理。 现在固定存储管理已经不用也不考,但要知道因为固定存储管理指的是整存整取 也就是把一整个程序,比如说10G的游戏全部都存到内存里 这样的话是非常占用内存的,这个固定存储管理现在已经不用了。 然后这里我们主要看分页存储管: …

蓝桥杯比赛 NOC竞赛C++项目选择题真题和模拟题汇总

题目来源&#xff1a;第10届蓝桥杯青少年组C选拔赛 1、下面哪个密码最安全 A. 111111 B. 123456 C. qwerty D. Z2a8Q1 2、如果今天是星期六&#xff0c;再过60天是星期几&#xff1f; A. 星期三 B. 星期四 C. 星期五 D. 星期六 3、90到100之间有几个素数&#xff1f; …

mmcv和openCV两个库imcrop()和imresize()方法的对应【基础分析】

&#x1f947; 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 &#x1f389; 声明: 作为全网 AI 领域 干货最多的博主之一&#xff0c;❤️ 不负光阴不负卿 ❤️ 文章目录MMCV 全家桶mmcv.imresize(img, (1000, 600), return_scaleTrue) 方法实现对应的…

Unity 之 Post Processing后处理不同项目配置(URP项目配置)

Unity 之 Post Processing后处理不同项目配置&#xff08;URP项目配置&#xff09;一&#xff0c;Post Processing介绍二&#xff0c;正常项目配置2.1 场景配置2.2 摄像机配置2.3 集成步骤小结三&#xff0c;URP项目配置3.1 具体配置步骤3.2 最终实现效果四&#xff0c;代码控制…

【每天一个cmake技巧】简单的cmake demo

简单的cmake demo 一个简单的cmake 工程&#xff0c;包括生成动态库和链接动态库的demo工程和test工程。 demo下载链接&#xff1a; https://download.csdn.net/download/sinat_35178307/87243966 目录结构 该工程可以生成一个dll&#xff0c;一个调用dll的demo&#xff0c;…

【数据分享】维基百科Wiki负面有害评论(网络暴力)文本数据多标签分类挖掘可视化...

原文链接&#xff1a;http://tecdat.cn/?p8640讨论你关心的事情可能很困难。网络暴力骚扰的威胁意味着许多人停止表达自己并放弃寻求不同的意见&#xff08;查看文末了解数据免费获取方式&#xff09;。平台努力有效地促进对话&#xff0c;导致许多社区限制或完全关闭用户评论…

C++中的菱形继承问题及解决方案

存在问题 C中支持多重继承&#xff0c;但是由于这个特性&#xff0c;导致会有如下继承关系。 这样&#xff0c;类D就会同时拥有从类B中继承下来的A中的函数&#xff0c;也会拥有从类C中继承下来的A中的函数&#xff0c;会产生模糊调用的现象。 解决方案 为了解决这个问题&a…

spring源码 - AOP原理理解

AOP使用 1.我们都知道我们在使用spring aop时需要在configuration类上增加EnableAspectJAutoProxy 2.然后在准备AOP类就可以对相应类的方法进行aop Component Aspect public class MyAspect { Pointcut("execution(* com.my.service.*.*(..))") public void as…