【MySQL】MVCC工作原理、事务隔离机制、undo log回滚日志、间隙锁
一、什么是MVCC?
MVCC,即 Multiversion Concurrency Control(多版本并发控制),它是数据库实现并发控制的一种方式。
MVCC 的核心思想是:
为每个事务提供数据的“快照”版本,从而避免加锁,提高读操作的并发性。
作用:
- 允许 读操作(SELECT)不用加锁,从而避免阻塞。
- 避免“读写冲突”,提高并发性能。
- 实现事务的 隔离性(特别是实现 REPEATABLE READ、READ COMMITTED)
💡 二、MVCC 是如何工作的(以 InnoDB 为例)
InnoDB 如何实现 MVCC?
它通过以下两个隐藏字段实现版本控制:
trx_id
:每行记录最后一次修改它的事务ID。roll_pointer
:指向旧版本(undo log)的指针,形成多版本链。
此外,事务开始时有一个 read view(快照视图),用来判断哪些版本是“可见的”。
举个例子:
- 假设 A 开始一个事务,读取一行数据。
- 此时 B 事务修改了该行数据,并提交。
- A 仍然能看到旧版本的数据(通过 undo log 追溯),这是快照隔离。
👉 这种读取叫做 一致性读(Consistent Read),完全不加锁!
📌 四、MyISAM 为什么不支持 MVCC?
MyISAM 不支持事务,因此也就不支持:
- undo log
- 多版本
- read view 快照
当有一个查询时,它只能使用表级锁来保证一致性。这种方式:
- 并发性能低(特别是写多的时候)
- 无法提供事务隔离级别(没有REPEATABLE READ等)
🧠 总结:
MySQL 存储引擎 MVCC 差异总结
- InnoDB:支持事务 + 行级锁 + MVCC(多版本并发控制)
-> 读不加锁,性能好,支持一致性读 - MyISAM:不支持事务,不支持 MVCC,使用表级锁
-> 读写容易阻塞,性能差,读的是最新数据
🧱 一、前置知识:事务隔离级别(SQL标准)
事务隔离级别从低到高:
隔离级别 | 描述 | 常见问题 |
---|---|---|
READ UNCOMMITTED | 可以读到未提交的数据 | 脏读(读未提交的数据) |
READ COMMITTED | 只能读到已提交的数据 | 不可重复读 |
REPEATABLE READ | 多次读取同一数据结果一致 | 幻读 |
SERIALIZABLE | 全部加锁,串行执行 | 性能差但最安全 |
🔍 二、MVCC 如何支持隔离性?
✅ REPEATABLE READ(可重复读,MySQL 默认)
多次
SELECT
相同数据时,读到的是事务开始时的数据快照(read view),不受其他事务影响。
✔ 具体实现:
- 事务一开始,InnoDB 创建一个 read view。
- 所有
SELECT
查询都是基于这个 read view。 - 即使别的事务修改并提交了数据,本事务看到的还是原来的版本(通过 undo log 回溯)。
- 会出现
幻读
,即读取到的不是最新数据,因为可重复读采用的是undo log的read view快照机制,用的是事务开始保存的快照,而不是实时数据。
🧠 举个例子:
-- 事务 A
START TRANSACTION;
SELECT * FROM user WHERE id=1; -- 假设 name='Tom'-- 事务 B
START TRANSACTION;
UPDATE user SET name='Jerry' WHERE id=1;
COMMIT;-- 回到事务 A
SELECT * FROM user WHERE id=1; -- name 仍然是 'Tom',实现了 repeatable read
事务 A 的所有读取都基于它开始时的快照,看到的是“旧世界”。
✅ READ COMMITTED(已提交读)
每次
SELECT
都读取当前最新提交版本的数据。
✔ 具体实现:
- 每次读取都会生成一个新的undo log的 read view。
- 所以可以读到别的事务已提交的新数据。
- 可能出现
不可重复读
,即,同一事务中select的是不同数据。
🧠 举个例子:
-- 事务 A
START TRANSACTION;
SELECT * FROM user WHERE id=1; -- name = 'Tom'-- 事务 B
START TRANSACTION;
UPDATE user SET name='Jerry' WHERE id=1;
COMMIT;-- 回到事务 A
SELECT * FROM user WHERE id=1; -- name = 'Jerry'(读到了新数据)
这种机制虽然不会脏读,但不能重复读,因为两次查询结果不一样。
🧠 总结:
InnoDB 实现事务隔离性核心在于:MVCC + undo log + read view
REPEATABLE READ:
- 每个事务在开始时创建 read view
- 所有查询基于这个快照版本
- 即使其他事务提交了修改,也读不到(实现“可重复读”)
READ COMMITTED:
- 每次查询时都重新生成 read view
- 总是读取最新提交的数据
- 能避免脏读,但可能“不可重复读”
MySQL 默认使用 REPEATABLE READ,避免幻读靠间隙锁
(gap lock)
📦 一、四种事务隔离级别及存在的问题汇总
隔离级别 | 是否可读未提交 | 是否可重复读 | 是否会幻读 | 使用场景(读一致性) |
---|---|---|---|---|
READ UNCOMMITTED | ✅ 是 | ❌ 否 | ✅ 是 | 最低一致性,无任何保障 |
READ COMMITTED | ❌ 否(读提交) | ❌ 否 | ✅ 是 | 大多数数据库默认,如Oracle |
REPEATABLE READ | ❌ 否 | ✅ 是 | ❌(InnoDB中) | MySQL默认,支持一致快照 |
SERIALIZABLE | ❌ 否 | ✅ 是 | ✅ 否(加锁) | 串行执行,开销大 |
🔍 每种隔离级别的问题示例
问题类型 | 描述 | 发生条件 |
---|---|---|
脏读(Dirty Read) | 读到了未提交的数据 | 仅在 READ UNCOMMITTED 下可能发生 |
不可重复读(Non-repeatable Read) | 同一条记录两次读结果不一致 | READ COMMITTED |
幻读(Phantom Read) | 两次读取结果行数不一致(新增/删除) | REPEATABLE READ 但有范围查询时才会发生 |
🧬 二、MVCC 实现关键机制:undo log + read view
✅ undo log(回滚日志)
- 记录旧版本数据,用于:
- 回滚(ROLLBACK)
- 一致性读(Consistent Read)
undo log 的基本结构
每条记录维护:
- 修改前的值(旧版本)
- 事务 ID(trx_id)
- 回滚指针(roll_pointer)指向上一个版本
✅ read view(快照视图)
- 事务在 第一次执行一致性读(SELECT)时创建
- 用于判断某条数据的哪个版本“对当前事务可见”
判断规则(InnoDB MVCC 可见性判断):
当前事务ID = T
记录版本的 trx_id = R如果 R < 最小活跃事务ID:可见(已经提交)
如果 R == 当前事务ID:可见(自己改的)
如果 R 是活跃事务ID之一:不可见(别人还没提交)
🧱 三、幻读的由来与间隙锁的解决方案
🧨 什么是幻读(Phantom Read)?
指一类特殊的不可重复读 —— 两次范围查询返回不同数量的结果。
示例:
-- 事务 A
START TRANSACTION;
SELECT * FROM user WHERE age > 20;-- 事务 B
INSERT INTO user (name, age) VALUES ('NewUser', 21);
COMMIT;-- 回到事务 A
SELECT * FROM user WHERE age > 20; -- 发现多了一条,产生幻读
🧰 InnoDB 的解决方法:间隙锁(Gap Lock)
在可重复读隔离级别下,为防止幻读,InnoDB 对范围查询加“间隙锁”。
间隙锁含义:
- 不锁定具体记录,而锁定“两个记录之间的间隙”。
- 其他事务不能在这个间隙中插入新数据。
举例:
SELECT * FROM user WHERE age > 20 FOR UPDATE;
-- 会锁住 20 ~ ∞ 之间的“空隙”,禁止插入
⚠ 注意:
- 间隙锁只在 REPEATABLE READ + 索引条件范围查询 + FOR UPDATE 或隐式锁定下生效
- 不使用
FOR UPDATE
时,一般是一致性读,只靠 undo log,不加锁
🧠 总结:
事务隔离级别问题对比
- READ UNCOMMITTED: 有脏读,不推荐使用
- READ COMMITTED: 无脏读,有不可重复读,Oracle默认
- REPEATABLE READ: 无脏读、可重复读、InnoDB用间隙锁避免幻读(MySQL默认)
- SERIALIZABLE: 全部加锁,开销大,极少使用
InnoDB 实现关键:MVCC
- undo log:记录旧版本数据
- read view:事务可见性判断依据
- 间隙锁:锁定范围,阻止幻读(只在RR可重复读下有效)
https://github.com/0voice
相关文章:
【MySQL】MVCC工作原理、事务隔离机制、undo log回滚日志、间隙锁
一、什么是MVCC? MVCC,即 Multiversion Concurrency Control(多版本并发控制),它是数据库实现并发控制的一种方式。 MVCC 的核心思想是: 为每个事务提供数据的“快照”版本,从而避免加锁&…...
Spring Boot 集成 RocketMQ 全流程指南:从依赖引入到消息收发
前言 在分布式系统中,消息中间件是解耦服务、实现异步通信的核心组件。RocketMQ 作为阿里巴巴开源的高性能分布式消息中间件,凭借其高吞吐、低延迟、高可靠等特性,成为企业级应用的首选。而 Spring Boot 通过其“约定优于配置”的设计理念&a…...
PCL 点云RANSAC提取平面(非内置函数)
文章目录 一、算法实现1.1实现步骤二、实现代码三、实现效果参考资料一、算法实现 1.1实现步骤 1、确定模型。三个点确定一个平面,方程式为 a x + b y + c z + 1 = 0 ax+by+cz+1=0...
中介者模式:理论、实践与 Spring 源码解析
摘要 本论文以中介者模式为核心,系统阐述其设计原理、应用场景及在 Spring 框架中的实现机制。通过机票预订系统、银行交易系统等典型案例,具象化展示模式如何解耦复杂对象交互;结合 Spring 5.3.29 源码,深入剖析事件驱动模型中ApplicationEventPublisher与ApplicationLis…...
2025.04.14【Table】| 生信数据表图技巧
Custom title A set of examples showing how to customize the titles of a table made with GT Custom footer How to customize the footer and the references section of a gt table 文章目录 Custom titleCustom footer 生信数据可视化:Table图表详解1. R语…...
Unified Modeling Language,统一建模语言
UML(Unified Modeling Language,统一建模语言)是一种标准化的图形化建模语言,用于可视化、规范和文档化软件系统的设计。UML 提供了一套通用的符号和规则,帮助开发者、架构师和团队成员更好地理解和沟通软件系统的结构…...
OCP证书有效期是永久,但需要更新
在数据库管理领域,OCP证书作为Oracle认证体系中的重要组成部分,一直是数据库专业人士追求的目标。许多考证者会有疑惑:OCP证书是永久有效的吗?需要更新吗? Oracle官方明确规定:OCP证书一经获得,终身有效。无…...
服务器本地搭建
socket函数 它用于创建一个新的套接字(socket)。 函数原型 #include <sys/socket.h> int socket(int domain, int type, int protocol);参数解释 domain:它指定了通信所使用的协议族,常见的取值如下: AF_INET…...
调节磁盘和CPU的矛盾——InnoDB的Buffer Pool
缓存的重要性 无论是用于存储用户数据的索引【聚簇索引、二级索引】还是各种系统数据,都是以页的形式存放在表空间中【对一个/几个实际文件的抽象,存储在磁盘上】如果需要访问某页的数据,就会把完整的页数据加载到内存中【即使只访问页中的一…...
[dp12_回文子串] 最长回文子串 | 分割回文串 IV
目录 1.回文子串 题解 2.最长回文子串 题解 3.分割回文串 IV 题解 dp[i][j] 表示 s 字符串 [i, j] 的子串,是否是回文串( 建始末表) 将两个 for 循环的结果,借助二维 dp 来存 1.回文子串 链接:647. 回文子串 给你一个字符…...
分布式应用架构的演变
整体演变过程 第一阶段:单一应用架构 单一应用架构,是把所有服务都放在一个项目中,进行打包部署到服务器上,如果流量特别大的话,就在另外的服务器上部署相同的功能模块用来分摊流量。但是这样的话,一旦有某…...
zephyr RTOS 中 bt_le_adv_start函数的功能应用
目录 概述 1 功能 1.1 功能介绍 1.2 函数原型 2 参数说明 2.1 广播参数(bt_le_adv_param) 2.2 常用广播选项(options) 2.3 广播数据(bt_data) 3 示例代码 3.1 启动可连接广播(带设备名…...
双按键控制LED(中断优先级)
1.启动时,两个LED灯熄灭,1秒钟后(定时器实现),LED自动点亮; 2.按键1按下后,通过中断int0把两个LED熄灭5s时间,int0优先级设置为最高(优先级必须设置,设置后才…...
美团即时零售大动作,将独立的闪购将会改变什么?
4月12日上午,美团核心本地商业CEO王莆中在社交媒体上发文,宣布美团将在下周正式发布即时零售品牌,标志着美团将进一步发展即时零售业务。 首先,从市场格局角度来看,美团将独立的闪购品牌推出,会进一步加剧…...
如何安装git?
以下是 Windows、macOS 和 Linux 系统安装 Git 的详细步骤: 一、Windows 系统安装 Git 下载安装包 访问 Git 官网下载页,点击下载 Windows 版安装程序(如 Git-2.45.1-64-bit.exe)。 运行安装程序 安装选项: 选择安装路…...
Ubuntu上docker、docker-compose的安装
今天来实践下Ubuntu上面安装docker跟docker-compose,为后面安装dify、fastgpt做准备。 一、安装docker sudo apt-get updatesudo apt-get install docker.io 然后系统输入 docker --version 出现下图即为docker安装成功。 二、安装docker-compose 我先看下系统…...
ubuntu如何设置静态ip
服务器有时是通过dhcp动态获取ip的,有时出于远程登录方便的考虑,会将其设置为静态ip,以下是设置静态ip的方法 在 Ubuntu 中设置静态 IP 的方法取决于你使用的网络管理工具(如 netplan、NetworkManager 或 ifconfig)。…...
js原型和原型链
js原型: 1、原型诞生的目的是什么呢? js原型的产生是为了解决在js对象实例之间共享属性和方法,并把他们很好聚集在一起(原型对象上)。每个函数都会创建一个prototype属性,这个属性指向的就是原型对象。 …...
大数据 - 2. Hadoop - HDFS
前言 HDFS:分布式文件系统 为什么海量数据需要分布式存储技术? 文件过大时,单台服务器无法承担,要靠数量来解决。数量的提升带来的是网络传输、磁盘读写、CPU、内存等各方面的提升。 众多的服务器一起工作,如何保证…...
嵌入式硬件常用总线接口知识体系总结和对比
0.前言 在嵌入式工程实现中,多多少少我们都使用过总线,各种各样的总线应用于不同场合,不同场景有不同的优势,但是我们在作为工程师过程中在如何选择项目合适的总线,根据什么来选?需要我们对项目全局和总线特征有所了解,本文目的就是对比多种总线的关键特征 我们在聊到…...
prime 1 靶场笔记(渗透测试)
环境说明: 靶机prime1和kali都使用的是NAT模式,网段在192.168.144.0/24。 Download (Mirror): https://download.vulnhub.com/prime/Prime_Series_Level-1.rar 一.信息收集 1.主机探测: 使用nmap进行全面扫描扫描,找到目标地址及…...
(二十四)安卓开发中的AppCompatActivity详解
在安卓开发中,AppCompatActivity 是一个非常核心的类,它继承自 Activity,并通过 Android Support Library(现已迁移至 AndroidX)提供了对 ActionBar 和 Material Design 的支持。它的主要作用是帮助开发者在不同版本的…...
AI大模型+全渠道整合:容联七陌智能客服赋能制造业升级
自《中国制造2025》战略提出以来,制造业的智能化发展进入快车道,但行业仍面临劳动力成本上升、供应链不透明、客户需求碎片化等挑战。企业亟需通过技术手段实现降本增效,而智能化客户服务成为关键突破口。 与此同时,客服行业正经历…...
Vue 技术解析:从核心概念到实战应用
Vue.js 是一款流行的渐进式前端框架,以其简洁的 API、灵活的组件化结构和高效的响应式数据绑定而受到开发者的广泛欢迎。本文将深入解析 Vue 技术的核心概念、原理和应用场景,帮助开发者更好地理解和使用 Vue.js。 一、Vue 的设计哲学与核心概念 &…...
中英文提示词对AI IDE编程能力影响有多大?
深度剖析 🧠:中英文提示词对AI IDE编程能力影响有多大?(附实战建议) 作者:AI助手 | 日期:2023-10-27 | 标签:AI, IDE, Prompt Engineering, LLM, 编程效率 摘要:随着 AI…...
ARM处理器程序烧写方式
一、烧写原理 无论是jtag还是串口烧写,本质都是先通过上位机(keil 或者flymcu或者芯片官方上位机等烧写bin的上位机)往mcu的ram里烧写一段代码即.FLM文件,这段代码在上位机(keil体现在配置项里,flymcu应该…...
AI 项目详细开发步骤指南
AI 项目详细开发步骤指南 一、环境搭建详解 1. JDK 17 安装与配置 Windows 系统安装步骤: 访问 Oracle 官网下载 JDK 17 安装包:https://www.oracle.com/java/technologies/downloads/#java17下载 Windows x64 Installer 版本双击安装包,…...
文本纠错WPS插件:提升文档质量的利器
文本纠错WPS插件:提升文档质量的利器 引言 在数字化办公日益普及的今天,文档的质量直接影响到我们的工作效率和形象。一个错别字或标点错误,可能就会让我们的专业形象大打折扣。今天,我要向大家介绍一款强大的WPS插件——文本纠…...
Node.js 模块包的管理和使用是
一、模块包的概念 1.模块分类: 核心模块:Node.js 内置模块(如 fs, http, path),无需安装直接引用。 本地模块:开发者自己编写的模块文件,通过相对路径引入。 第三方模块:通过 npm…...
腾讯云golang一面
go垃圾回收机制 参考自:https://zhuanlan.zhihu.com/p/334999060 go 1.3 标记清除法 缺点 go 1.5 三色标记法 屏障机制 插入屏障 但是如果栈不添加,当全部三色标记扫描之后,栈上有可能依然存在白色对象被引用的情况(如上图的对象9). 所以要对栈重新进行三色标记扫…...
【Three.js基础学习】35.Particles Cursor Animation Shader
前言 关于着色器应用和画布,实现黑白色照片动态效果 一、代码 script.js import * as THREE from three import { OrbitControls } from three/addons/controls/OrbitControls.js import particlesVertexShader from ./shaders/particles/vertex.glsl import p…...
安卓性能调优之-掉帧测试
掉帧指的是某一帧没有在规定时间内完成渲染,导致 UI 画面不流畅,产生视觉上的卡顿、跳帧现象。 Android目标帧率: 一般情况下,Android设备的屏幕刷新率是60Hz,即每秒需要渲染60帧(Frame Per Second, FPS&a…...
六、分布式嵌入
六、分布式嵌入 文章目录 六、分布式嵌入前言一、先要配置torch.distributed环境二、Distributed Embeddings2.1 EmbeddingBagCollectionSharder2.2 ShardedEmbeddingBagCollection 三、Planner总结 前言 我们已经使用了TorchRec的主模块:EmbeddedBagCollection。我…...
13-scala模式匹配
模式匹配是检查某个值(value)是否匹配某一个模式的机制,一个成功的匹配同时会将匹配值解构为其组成部分。它是Java中的switch语句的升级版,同样可以用于替代一系列的 if/else 语句。 语法 一个模式匹配语句包括一个待匹配的值&a…...
Multisim使用说明详尽版--(2025最新版)
一、Multisim14前言 1.1、主流电路仿真软件 1. Multisim:NI开发的SPICE标准仿真工具,支持模拟/数字电路混合仿真,内置丰富的元件库和虚拟仪器(示波器、频谱仪等),适合教学和竞赛设计。官网:艾…...
试一下阿里云新出的mcp服务
前言 MCP这段时间的发展可谓是如火如荼,各种教程也是层出不穷,基本的教程都是如何集成各类型的mcp(比如高德地图)到开发工具(比如cursor),效果很好,但是有个问题就是,配置教程较为繁琐。 阿里云悄然上线的mcp 今天早上…...
正弦波有效值和平均值(学习笔记)
一个周期的正弦波在坐标轴上围的面积有多大? 一般正弦波以 y Asin(wx)表示,其中A为振幅,W为角速度。周期T 2π/w; 确定积分区间是x 0,到x 2π。 计算绝对值积分: 变量代还:wx θ,dx dθ…...
科研软件分享
这个帖子不定期更新,分享博主自己使用的很好用的科研软件 1 connectedpaper Connected Papers | Find and explore academic papers 2 Semantic Scholar...
Python(12)深入解析Python参数传递:从底层机制到高级应用实践
目录 一、参数传递的编程哲学1.1 参数传递的本质1.2 参数传递类型矩阵 二、参数传递核心规则2.1 位置参数与关键字参数2.2 可变参数处理 三、参数传递高级特性3.1 类型约束与提示3.2 参数内存优化 四、参数传递工程实践4.1 防御性参数校验4.2 参数依赖注入 五、参数传递性能优化…...
MVCC是什么?MVCC的作用是什么?MVCC实现方式有哪些?
MVCC(多版本并发控制)详解 一、MVCC是什么? MVCC(Multi-Version Concurrency Control,多版本并发控制)是数据库管理系统中的一种并发控制机制,它通过维护数据的多个版本来实现非阻塞读和高并发…...
007.Gitlab CICD缓存与附件
文章目录 缓存与产物缓存与产物概述 同分支不同job数据共享默认数据共享不同 Job 数据共享 不同分支相同job数据共享跨分支同job数据共享 不同分支不同job数据共享跨分支跨job数据共享 将文件/夹保存为附件产物介绍创建产物跨job共享产物 缓存与产物 缓存与产物概述 缓存是一…...
A006-基于Selenium和JMeter的吉屋web端的自动化测试设计与实现
产出:自动测试脚本测试用例开题报告自动化测试报告论文jmeter性能测试 --------------------**论文主要内容***----- 第1章 吉屋web端需求分析 1.1 吉屋web端功能需求分析 由于社会对知识获取的需求不断增长,海量繁多的房屋信息已难以依靠传统人工高效…...
图像预处理-边缘填充,透视变换和色彩空间基础
一.边缘填充 一般来图片操作之后会有空区域,就是对空出来的区域进行了像素值的填充,(0,0,0)也就是黑色像素值的填充。 # 默认黑色填充 import cv2 as cvimg cv.imread(../images/lena.png) # 先让原图旋转45度 M cv.getRotatio…...
数字化赋能,众趣科技助力智慧园区深化管理运营能力
数字化、网络化和智能化,被公认为是未来社会发展的大趋势。随着全球物联网、云计算等新一代信息技术不断成熟,传统的招商管理运营模式难以满足园区当下所需,以“园区互联网”为理念的“智慧园区”应运而生,同时融入社交、移动、物…...
《AI大模型应知应会100篇》 第16篇:AI安全与对齐:大模型的灵魂工程
第16篇:AI安全与对齐:大模型的灵魂工程 摘要 在人工智能技术飞速发展的今天,大型语言模型(LLM)已经成为推动社会进步的重要工具。然而,随着这些模型能力的增强,如何确保它们的行为符合人类的期…...
MCP的另一面
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
Golang|锁相关
文章目录 并发安全性与原子操作读写锁分布式锁 并发安全性与原子操作 普通数据类型在并发读写中是会出现问题的,有时候操作会被吞,导致脏写,比如上面n加了两次应该为2,但是由于并发,n最后还是只加了一次 读写锁 sync.…...
大模型面经 | 介绍一下大模型微调方法Prefix Tuning、Prompt Tuning、P-Tuning和P-Tuning v2
大家好,我是皮先生!! 今天给大家分享一些关于大模型面试常见的面试题,希望对大家的面试有所帮助。 往期回顾: 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题一) 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题二) 大模型面经 | 春招、秋招算法…...
JMeter的高并发和高频率和分布式
性能测试 模拟各种正常的、峰值的测试环境,检测程序的各项性能指标是否能够达标 高并发 JMeter中内置了定时器,可以实现时间模式相关的性能测试 需求1:同一时刻100个同学去访问学生管理系统的查询所有学院信息功能,统计高并发情况下平均响…...
设计模式-模板模式
设计模式-模板模式,不用重复写大的逻辑,父类定义好不变的模板方法,子类使用,当框架是父类的框架时可以继承...