MySQL进阶篇之InnoDB存储引擎
06、InnoDB引擎
6.1、逻辑存储结构

-
表空间(
Tablespace)表空间在MySQL中最终会生成
ibd文件,一个mysql实例可以对应多个表空间,用于存储记录、索引等数据。
-
段(
Segment)段,分为数据段(
Leaf node segment)、索引段(Non-leaf node segment)、回滚段(Rollback segment)。InnoDB是索引组织表,数据段就是B+树的叶子节点,索引段即为B+树的非叶子结点。
段用来管理多个Extent(区).
-
区(
Extent)区,表空间的单元结构,每个区的大小为1M。默认情况下,InnoDB存储引擎页大小为16K,即一个区中一共有64个连续的页。
-
页(
Page)页,是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB。为了保证页的连续性,InnoDB存储引擎每次从磁盘申请4-5个区。
-
行(
Row)InnoDB存储引擎数据是按行进行存放的。
Trx_id:每次对某条记录进行改动时,都会把对应的事务id复制给trx_id隐藏列。Roll_pointer:每次对某条引记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。
6.2、架构
MySQL5.5版本开始,默认使用InnoDB存储引擎,它擅长事务处理,具有崩溃恢复特性,在日常开发中使用非常广泛。下面是InnoDB架构图,左侧为内存结构,右侧为磁盘结构。

6.2.1、内存结构
1、Buffer Pool
① 缓冲池是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度。
② 缓冲池以Page页为单位,底层采用链表数据结构管理Page。根据状态,将Page分为三种类型:
free page:空闲page,未被使用。clean page:被使用page,数据没有被修改过。dirty page:脏页,被使用page,数据被修改过,页中数据与磁盘的数据产生了不一致。
2、Change Buffer
① 更改缓冲区(针对于非唯一二级索引页),在执行DML语句时,如果这些数据Page没有在Buffer Pool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区Change Buffer中,在未来数据被读取时,再将数据合并恢复到Buffer Pool中,再将合并后的数据刷新到磁盘中。
注意:
在MySQL5.x版本,该缓冲区成为插入缓冲区(
Insert Buffer)。在MySQL8.0版本之后,引入了
Change Buffer。
② Change Buffer的意义是什么?
与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样,删除和更新可能会影响索引树中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘IO。有了Change Buffer之后,我们可以在缓冲池中进行合并处理,减少磁盘IO。
3、Adaptive Hash Index
① 自适应hash索引,用于优化对Buffer Pool数据的查询。InnoDB存储引擎会监控对表上各索引页的查询,如果观察到hash索引可以提升速度,则建立hash索引,称之为自适应hash索引。
② 自适应哈希索引,无需人工干预,是系统根据情况自动完成。
③ 参数:adaptive_hash_index

4、Log Buffer
① 日志缓冲区,用来保存要写入到磁盘中的log日志数据(redo log、undo log),默认大小为16MB,日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事务,增加日志缓冲区的大小可以节省磁盘I/O。
② 参数:
-
innodb_log_buffer_size:缓冲区大小 -
innodb_flush_log_at_trx_commit:日志刷新到磁盘时机1:日志在每次事务提交时写入并刷新到磁盘0:每秒将日志写入并刷新到磁盘一次2:日志在每次事务提交后写入,并每秒刷新到磁盘一次。

6.2.2、磁盘结构
1、System Tablespace
① 系统表空间是更改缓冲区(Change Buffer)的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建的,它也可能包含表和索引数据。(在MySQL5.x版本中还包含InnoDB数据字典、undolog等)。
② 参数:innodb_data_file_path

2、File_Per_Table Tablespaces
① 每个表的文件表空间包含单个InnoDB表的数据和索引,并存储在文件系统上的单个数据文件中。
② 参数:innodb_file_per_table
默认是开启的。

3、General Tablespaces
①通用表空间,需要通过CREATE TABLESPACE语法创建通用表空间,在创建表时,可以指定该表空间。
- 创建通用表空间
CREATE TABLESPACE 表空间名称 ADD
DATAFILE 'file_name'
ENGINE = engine_name;
- 创建表时,可以指定表空间
CREATE TABLE 表名称(...
)TABLESPACE ts_name;
② 演示

创建完表空间,可以新开一个标签页面,
cd /var/lib/mysql切换到该目录下,通过ls查看是否存在myitheima.ibd文件。
4、Undo Tablespaces
撤销表空间,MySQL实例在初始化时会自动创建两个默认的undo表空间(初始大小16M),用于存储undo日志。
默认为:

5、Temporary Tablespaces
InnoDB使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。
6、Doublewrite Buffer Files
双写缓冲区,InnoDB引擎将数据页从Buffer Pool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。

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

1、后台线程的作用:将InnoDB存储引擎缓冲池中的数据在合适的时机刷新到磁盘中的文件里。
2、后台线程有四类:
① Master Thread
核心后台线程,负责调度其他线程,还负责将缓冲池中的数据异步刷新到磁盘中,保持数据的一致性,还包括脏页的刷新、合并插入缓存、undo页的回收。
② IO Thread
在InnoDB存储引擎中大量使用了AIO来处理IO请求,这样可以极大地提高数据库的性能,而IO Thread主要负责这些IO请求的回调。
| 线程类型 | 默认个数 | 职责 |
|---|---|---|
| Read Thread | 4 | 负责读操作 |
| Write Thread | 4 | 负责写操作 |
| Log Thread | 1 | 负责将日志缓冲区刷新到磁盘 |
| Insert Buffer Thread | 1 | 负责将写缓冲区内容刷新到磁盘 |
通过指令show engine innodb status;进行查看

③ Purge Thread
主要用于回收事务以及提交了的undo log,在事务提交之后,undo log可能不用了,就用它来回收。
④ Page Cleaner Thread
协助Master Thread刷新脏页到磁盘的线程,它可以减轻Master Thread的工作压力,减少阻塞。
6.3、事务管理
6.3.1、概述
1、事务
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
2、事务特性
- 原子性(
Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。 - 一致性(
Consistency):事务完成时,必须使所有的数据都保持一致状态。 - 隔离性(
Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。 - 持久性(
Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
3、事务原理

原子性、一致性、持久性是由InnoDB存储引擎底层的两个日志保障的,分别为:redo log、undo log。
隔离性是由InnoDB存储引擎的锁机制和MVCC(多版本并发控制)实现的。
原子性——undo log
持久性——redo log
一致性——undo log + redo log
隔离性——锁+MVCC
6.3.2、redo log
1、redo log:重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性。
该日志由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file),前者是在内存中,后者是在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中,用于在刷新脏页到磁盘时,发生错误时,进行数据恢复使用。
2、原理

① 当我们执行update操作时,需要访问缓冲区,看是否有此时需要的数据,若没有,则通过后台线程把所需的数据从磁盘中读取出来,然后缓存在缓冲区中。
② 现在可以直接执行update或者delete操作,直接对缓冲区的数据进行操作,则缓冲区中的数据发生了变更,但是磁盘中对应的数据未发生变更,此时缓冲区中变更的数据页称为脏页。
③ 脏页会在一定的时机通过后台线程刷新到磁盘中,从而使缓冲区与磁盘中的数据保持一致。
④ 但是脏页并不是时时刷新,而是一段时间之后通过后台线程刷新到磁盘中。
⑤ 假如此时缓冲区中的脏页往磁盘中进行刷新的时候,发生了错误,导致了内存中脏页的数据没有刷新到磁盘中。此时事务已经提交了,且已经告知用户事务提交成功了,但是内存中脏页的数据没有刷新到磁盘中,导致了事务的持久性未得到保障。

⑥ 当redo log出现之后,当进行增删改的之后,首先将对应的数据记录在redo log buffer中,在redo log buffer中会记录数据页的变化。
⑦ 当事务提交的时候,会将redo log buffer中的数据页变化刷新到磁盘中,持久化的保存在磁盘中。
⑧ 在过一段时间之后,通过后台线程刷新脏页到磁盘中,假如发生了上述⑤的情况,可以通过redo log进行维护。
问:为啥当事务提交的时候,需要将
redo log buffer中的数据页变化刷新到磁盘中?而不是当事务提交的时候,直接将内存中脏页刷新到磁盘中答:当事务提交的时候,直接将内存中脏页刷新到磁盘中,会存在严重的性能问题。当进行事务的时候,通常会操作很多条记录,这些记录都是随机操作我们的数据页,那么此时就会涉及大量的磁盘IO。
然而当我们在操作的时候用了
redo log,当事务提交的时候,不会直接把脏页刷新,而是将redo log文件异步刷新到磁盘中。由于它是redo log日志文件,日志文件都是追加的,那么此时它就是顺序磁盘IO,顺序磁盘IO速度高于随机磁盘IO。这种机制叫WAL(Write-Ahead Logging)。
6.3.3、undo log
1、undo log(保障事务的原子性)
回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚和MVCC(多版本并发控制)。
undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之依然,当update一条记录时,它记录一条对应相反的update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。
Undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC。
Undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的rollback segment回滚段中,内部包含1024个undo log segment。
6.4、MVCC
6.4.1、基本概念
-
当前读
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。
对于我们日常的操作,如:
select ... lock in share mode(共享锁),select ... for update、update、insert、delete(排他锁)都是一种当前读。 -
快照读
简单的
select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。Read Committed:每次select,都生成一个快照读。Repeatable Read:开启事务后第一个select语句才是快照读的地方。Serializable:快照读会退化为当前读。
-
MVCC全称
Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。
6.4.2、隐藏字段
1、记录中的隐藏字段
| 隐藏字段 | 含义 |
|---|---|
| DB_TRX_ID | 最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID |
| DB_ROLL_PTR | 回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。 |
| DB_ROW_ID | 隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。 |
2、ibd2sdi xxx.ibd:查看xxx.ibd文件

6.4.3、undo log
1、undo log介绍
回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志。
当insert的时候,产生的undo log 日志只在回滚时需要,在事务提交后,可被立即删除。
而update、delete的时候,产生的undo log 日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。
2、undo log版本链

不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链条,链表的头部是最新的旧记录,链表尾部是最早的旧记录。
6.4.4、readView
1、介绍
ReadView(读视图)是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。
ReadView中包含了四个核心字段:
| 字段 | 含义 |
|---|---|
| m_ids | 当前活跃的事务ID集合 |
| min_trx_id | 最小活跃事务ID |
| max_trx_id | 预分配事务ID,当前最大事务ID+1(因为事务ID时自增的) |
| creator_trx_id | ReadView创建者的事务ID |
2、版本链数据访问规则
trx_id:代表是当前事务ID
① trx_id == creator_trx_id:可以访问该版本 (原因:成立,说明数据是当前这个事务更改的)
② trx_id < min_trx_id:可以访问该版本 (原因:成立,说明数据已经提交了)
③ trx_id > max_trx_id:不可以访问该版本 (原因:成立,说明该事务是在ReadView生成后才开启)
④ min_trx_id <= trx_id <= max_trx_id:如果trx_id不在m_ids中是可以访问该版本的(原因:成立,说明数据已经提交了)
3、不同的隔离级别,生成ReadView的时机不同:
READ COMMITTED:在事务中每一次执行快照读时生成ReadView。REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。
4、案例
① RC隔离级别下,在事务中每一次执行快照读时生成ReadView。

事务5中查询id为30的记录,生成ReadView,当前的trx_id为4:
- trx_id4,①②③均不符合;在④中,3<=trx_id4<=6,但4在[3,4,5]中,不可以访问当前记录版本。需要回滚访问0x00003版本。
- trx_id3,①②③均不符合;在④中,3<=trx_id3<=6,但3在[3,4,5]中,不可以访问0x00003版本。需要回滚访问0x00002版本。
- trx_id2,①不符合;在②中,trx_id2<3,可以访问0x00002版本。
② RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。

过程与①相同,不同的是第二次查询复用第一次查询的ReadView。
相关文章:
MySQL进阶篇之InnoDB存储引擎
06、InnoDB引擎 6.1、逻辑存储结构 表空间(Tablespace) 表空间在MySQL中最终会生成ibd文件,一个mysql实例可以对应多个表空间,用于存储记录、索引等数据。 段(Segment) 段,分为数据段&#x…...
商标侵权行为的种类有哪些
商标侵权行为的种类有哪些 1、商标侵权行为的种类有以下七种: (1)未经商标注册人的许可,在同一种商品上使用与其注册商标相同的商标的; (2)未经商标注册人的许可,在同一种商品上使用与其注册商标近似的商标,或者在类似商品上使…...
Similarity-Preserving KD(ICCV 2019)原理与代码解析
paper:Similarity-Preserving Knowledge Distillationcode:https://github.com/megvii-research/mdistiller/blob/master/mdistiller/distillers/SP.py背景本文的灵感来源于作者观察到在一个训练好的网络中,语义上相似的输入倾向于引起相似的…...
在Linux和Windows上安装seata-1.6.0
记录:381场景:在CentOS 7.9操作系统上,安装seata-1.6.0。在Windows上操作系统上,安装seata-1.6.0。Seata,一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。版本:JDK…...
兼职任务平台收集(二)分享给有需要的朋友们
互联网时代,给人们带来了很大的便利。信息交流、生活缴费、足不出户购物、便捷出行、线上医疗、线上教育等等很多。可以说,网络的时代会一直存在着。很多人也在互联网上赚到了第一桶金,这跟他们的努力和付出是息息相关的。所谓一份耕耘&#…...
目标检测三大数据格式VOC,YOLO,COCO的详细介绍
注:本文仅供学习,未经同意请勿转载 说明:该博客来源于xiaobai_Ry:2020年3月笔记 对应的PDF下载链接在:待上传 目录 目标检测常见数据集总结 V0C数据集(Annotation的格式是xmI) A. 数据集包含种类: B. V0C2007和V0C2012的区别…...
SpringBoot实现统一返回接口(除AOP)
起因 关于使用AOP去实现统一返回接口在之前的博客中我们已经实现了,但我突然突发奇想,SpringBoot中异常类的统一返回好像是通过RestControllerAdvice 这个注解去完成的,那我是否也可以通过这个注解去实现统一返回接口。 正文 这个方法主要…...
ChatGpt - 基于人工智能检索进行论文写作
摘要 ChatGPT 是一款由 OpenAI 训练的大型语言模型,可用于各种自然语言处理任务,包括论文写作。使用 ChatGPT 可以帮助作者提高论文的语言流畅度、增强表达能力和提高文章质量。在写作过程中,作者可以使用 ChatGPT 生成自然语言的段落、句子、单词或者短语,作为启发式的写…...
实例三:MATLAB APP design-多项式函数拟合
一、APP 界面设计展示 注:在左侧点击数据导入,选择自己的数据表,如果数据导入成功,在右侧的空白框就会显示数据导入成功。在多项式项数右侧框中输入项数,例如2、3、4等,点击计算按钮,右侧坐标框就会显示函数图像,在平均相对误差下面的空白框显示平均相对误差。...
springboot多种方式注入bean获取Bean
springboot动态注入bean1、创建Bean(demo)2、动态注入Bean3、通过注解注入Bean4、通过config配置注入Bean5、通过Import注解导入6、使用FactoryBean接口7、实现BeanDefinitionRegistryPostProcessor接口1、创建Bean(demo) Data public class Demo(){private String name;publi…...
Markdown及其语法详细介绍(全面)
文章目录一、基本语法1.标题2.段落和换行3.强调4.列表5.链接6.图片7.引用8.代码9.分割线10表格二、扩展语法1.标题锚点标题 {#anchor}2.脚注3.自动链接4.任务列表5.删除线6.表情符号7.数学公式三、Markdown 应用1.文档编辑2.博客写作3.代码笔记四、常见的工具和平台支持 Markdo…...
在Linux和Windows上安装sentinel-1.8.5
记录:380场景:在CentOS 7.9操作系统上,安装sentinel-1.8.5。在Windows上操作系统上,安装sentinel-1.8.5。Sentinel是面向分布式、多语言异构化服务架构的流量治理组件。版本:JDK 1.8 sentinel-1.8.5 CentOS 7.9官网地址…...
面试攻略,Java 基础面试 100 问(十)
StringBuffer、StringBuilder、String区别 线程安全 StringBuffer:线程安全,StringBuilder:线程不安全。 因为 StringBuffer 的所有公开方法都是 synchronized 修饰的,而 StringBuilder 并没有 synchronized 修饰。 StringBuf…...
Zero-shot(零次学习)简介
zero-shot基本概念 首先通过一个例子来引入zero-shot的概念。假设我们已知驴子和马的形态特征,又已知老虎和鬣狗都是又相间条纹的动物,熊猫和企鹅是黑白相间的动物,再次的基础上,我们定义斑马是黑白条纹相间的马科动物。不看任何斑…...
51单片机简易电阻电感电容RLC测量仪仿真设计
51单片机简易电阻电感电容RLC测量仪仿真( proteus仿真程序讲解视频) 仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0040 51单片机简易电阻电感电容RLC测量仪仿真51单片机最小系统的相关知识复位…...
[软件工程导论(第六版)]第6章 详细设计(课后习题详解)
文章目录1 假设只有SEQUENCE和DO-WHILE两种控制结构,怎样利用它们完成 IF THEN ELSE操作?2 假设只允许使用SEQUENCE和IF-THEN-ELSE两种控制结构,怎样利用它们完成DO WHILE操作?3 画出下列伪码程序的程序流程图和盒图:4…...
【2.19】算法题2:贪心算法、动态规划、分治
题目:给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。方法一:贪心算法原理:若当前指针所指元素之前的和小…...
【Redis】Redis 发布订阅通信模式 ( 发布订阅模式 | 订阅频道 | 发布消息 | 接收消息 )
文章目录一、发布订阅模式二、订阅频道三、发布消息四、接收消息一、发布订阅模式 Redis 中 存在一种 发布订阅 消息通信模式 : 消息发布者 : 负责发送消息 , 订阅者需要订阅该发布者频道 ;消息订阅者 : 负责接收消息 ; 订阅者 先 订阅 发布者频道 , 当 发布者 发布消息时 , …...
VNCTF 2023复现
文章目录象棋王子电子木鱼BabyGo象棋王子 签到题,直接在源码中找就ok。 找到一处编码,在控制台输出。 flag为:flag{w3lc0m3_t0_VNCTF_2023~~~} 电子木鱼 需要先理清代码逻辑。 存在三个路由。 一:/路由用来查看当前的功德数量…...
python基础知识有哪些需要背(记住是基础知识)我是初学者
大家好,小编来为大家解答以下问题,一个有趣的事情,一个有趣的事情,今天让我们一起来看看吧! 1、python基础知识有哪些需要背(记住是基础知识)我是初学者 或看好Python的广阔前景,或…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...
大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程
基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程 下载安装Docker Docker官网:https://www.docker.com/ 自定义Docker安装路径 Docker默认安装在C盘,大小大概2.9G,做这行最忌讳的就是安装软件全装C盘,所以我调整了下安装路径。 新建安装目录:E:\MyS…...
Python第七周作业
Python第七周作业 文章目录 Python第七周作业 1.使用open以只读模式打开文件data.txt,并逐行打印内容 2.使用pathlib模块获取当前脚本的绝对路径,并创建logs目录(若不存在) 3.递归遍历目录data,输出所有.csv文件的路径…...
