海山数据库(He3DB)源码详解:CommitTransaction函数源码详解
文章目录
- 海山数据库(He3DB)源码详解:CommitTransaction函数
- 1. 执行条件
- 2. 执行过程
- 2.1 获取当前节点状态:
- 2.2 检查当前状态:
- 2.3 预提交处理:
- 2.4 提交处理:
- 2.5 释放资源:
- 2.6 提交事务:
- 作者介绍
海山数据库(He3DB)源码详解:CommitTransaction函数
本文介绍了事务提交过程中,具体执行提交任务的CommitTransaction函数详细执行流程。
1. 执行条件
- 当事务处于TRANS_INPROGRESS状态且事务块处于TBLOCK_STRATED或者TBLOCK_END状态下,由CommitTransactionCommand函数调用CommitTransaction函数完成提交事务。
- 在ParallelWorkerMain函数中由EndParallelWorkerTransaction调用。
2. 执行过程
2.1 获取当前节点状态:
获得当前节点变量值CurrentTransactionState,
并创建两个临时变量latestXid和is_parallel_worker。
TransactionState s = CurrentTransactionState;TransactionId latestXid;bool is_parallel_worker;
- CurrentTransactionState主要保存了当前事务状态相关的参数,主要是事务状态、事务块状态、XID、保存点、父节点等级等一系列参数。
- latestXid用来传递保存XID值。
- is_parallel_worker主要用于判断当前事务是否使用并行执行(并行执行指的是数据库将某些查询操作分布到多个工作进程中执行,以提高性能)。
2.2 检查当前状态:
检查并行执行模式,检查当前事务状态并判断父节点状态。
/* Enforce parallel mode restrictions during parallel worker commit. */if (is_parallel_worker)EnterParallelMode();ShowTransactionState("CommitTransaction");/** check the current transaction state*/if (s->state != TRANS_INPROGRESS)elog(WARNING, "CommitTransaction while in %s state",TransStateAsString(s->state));Assert(s->parent == NULL);
- 如果执行并行执行模式,调用EnterParallelMode函数执行++s->parallelModeLevel。
- 检查当前事务状态,如果不是TRANS_INPROGRESS,则执行elog函数保存并返回主线程PostgreMain,执行Abort过程。
- 断言检查当前父节点状态,出错直接退出(调试用的)。
2.3 预提交处理:
第一、通过死循环处理用户定义的一些延迟触发器和一些portal操作。
for (;;){/** Fire all currently pending deferred triggers.*/AfterTriggerFireDeferred();/** Close open portals (converting holdable ones into static portals)* If there weren't any, we are done. otherwise loop back to check* if they queued deferred triggers. Lather, rinse, repeat.*/if (!PreCommit_Portals(false))break;}
这里的死循环行为是:因为,事务(增删改)操作完成之后会触发定义的延迟触发器,进行一些其他的行为,而这些其他行为中可能会包括游标的增删改查,导致了一个套娃操作。所以,这里的AfterTriggerFireDeferred函数处理延迟触发器,PreCommit_Portals处理游标,直到触发器处理完且没有游标需要处理,跳出函数。
- 不断调用AfterTriggerFireDeferred函数,在当前事务提交之前调用,执行并处理掉所有待处理的延迟触发器。
- 通过判断PreCommit_Portals函数的执行结果,来选择是否跳出死循环。PreCommit_Portals函数的作用,首先是将本次事务过程中的持久化游标物质化,并关闭游标对应需要的执行器,释放持有的锁;然后关闭本次事务过程中的一些非持久门户(Non-holdable portals),其他事务留存下来的持久性门户(Portals)不做改变。如果游标没有做任何操作,即该事务没有其他游标操作,返回false,否则返回true。
持久化游标物质化是指将持久化游标的结果集存储到磁盘或内存中,确保之后的游标查询结果不受后续事务操作对数据的影响。
第二、通过回调函数关闭参数对应的事务内部服务。
CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_PRE_COMMIT: XACT_EVENT_PRE_COMMIT);
第三、清理并行执行的资源,清理所有的触发器。
/* If we might have parallel workers, clean them up now. */if (IsInParallelMode())AtEOXact_Parallel(true);/* Shut down the deferred-trigger manager */AfterTriggerEndXact(true);
第四、在关闭游标后调用PreCommit_on_commit_actions函数。
执行ON COMMIT子句定义的行为,包括对临时表的处理和游标的处理等,确保之前的游标都被正确的关闭,不会造成悬空引用(类似于悬空指针)。
/** Let ON COMMIT management do its thing (must happen after closing* cursors, to avoid dangling-reference problems)*/PreCommit_on_commit_actions();
第五、调用smgrDoPendingSyncs函数和AtEOXact_LargeObject函数。
/** Synchronize files that are created and not WAL-logged during this* transaction. This must happen before AtEOXact_RelationMap(), * so that we don't see committed-but-broken files after a crash.*/smgrDoPendingSyncs(true, is_parallel_worker);/* close large objects before lower-level cleanup */AtEOXact_LargeObject(true);
-
smgrDoPendingSyncs函数会在当前事务期间,对那些被创建且其更改没有记录在 WAL(Write-Ahead Logging)日志中的文件进行同步。这是为了确保如果发生崩溃,这些文件的状态是一致的,并且不会留下已提交但损坏的文件。
-
AtEOXact_LargeObject函数主要是清理一些超出常规字段所能存储限制的“大对象”,关闭与大型对象关联的文件描述符(LO fds),并清空 cookie 数组。
这样做的结果是,这些文件描述符将不再有效,无法再被用来访问或操作大型对象。无论事务是提交还是中止,持有这些 LO fds 的内存上下文和资源所有者在事务结束时都将被销毁。这意味着这些资源在事务结束时无论如何都会被清理。
在事务提交的情况下,需要关闭这些 LO fds,以避免在提交时出现关于资源泄露的警告。这是因为在提交时,系统会检查所有资源是否已经被正确管理,包括打开的文件描述符。
在事务中止的情况下,可以跳过关闭 LO fds 的步骤。这是因为在中止事务时,系统会回滚所有更改,并且通常不需要执行与提交相同的清理操作。
第六、调用PreCommit_Notify函数处理事务提交前与NOTIFY命令相关的操作。
它确保了NOTIFY命令能够在事务提交时正确地通知其他会话或应用程序。
/** Insert notifications sent by NOTIFY commands into the queue.This* should be late in the pre-commit sequence to minimize time spent* holding the notify-insertion lock.However, this could result in* creating a snapshot,so we must do it before serializable cleanup.*/PreCommit_Notify();
第七、判断当前是否为并行执行模式。
False,执行PreCommit_CheckForSerializationFailure 函数,在事务准备提交时,检查当前事务是否可能与其他事务发生了冲突。如果检测到冲突,函数会抛出一个错误,导致当前事务回滚。(这里主要发生在并发执行情况下或者多个表的复杂查询事务)
通过这种方式,PostgreSQL 确保事务的串行化执行,避免数据不一致的问题。
/** Mark serializable transaction as complete for predicate locking* purposes.This should be done as late as we can put it and still allow* errors to be raised for failure patterns found at commit.This is not* appropriate in a parallel worker however,because we aren't committing* the leader's transaction and its serializable state will live on.*/if (!is_parallel_worker)PreCommit_CheckForSerializationFailure();
- 串行化是事务隔离级别中最高的级别,它确保事务的执行就像它们是串行执行的一样,避免了所有并发问题。
- 可序列化事务(Serializable Transaction):可序列化事务是数据库事务的最高隔离级别,它通过完全串行化事务的执行来避免所有类型的并发问题,如脏读、不可重复读和幻读。
- 谓词锁定(Predicate Locking):谓词锁定是一种数据库锁定技术,用于锁定满足特定条件的数据行,而不是锁定整个表或数据页。这允许更细粒度的并发控制。
第八、关闭中断机制,清理重置映射,正式开始提交事务清理资源。
/* Prevent cancel/die interrupt while cleaning up */HOLD_INTERRUPTS();/* Commit updates to the relation map --- do this as late as possible */AtEOXact_RelationMap(true, is_parallel_worker);
2.4 提交处理:
第一、修改事务状态,开始事务提交。
/** set the current transaction state information appropriately during* commit processing*/s->state = TRANS_COMMIT;s->parallelModeLevel = 0;
第二、根据并行事务状态,处理日志。
检查并行执行状态。不是并行事务,调用RecordTransactionCommit函数记录当前XID的日志。是并行事务,则调用ParallelWorkerReportLastRecEnd函数处理WAL日志,将当前XID置为InvalidTransactionId。
if (!is_parallel_worker){/** We need to mark our XIDs as committed in pg_xact.This is where we* durably commit.*/latestXid = RecordTransactionCommit();}else{/** We must not mark our XID committed; the parallel leader is* responsible for that. */latestXid = InvalidTransactionId;/** Make sure the leader will know about any WAL we wrote before it* commits. */ParallelWorkerReportLastRecEnd(XactLastRecEnd);}
ParallelWorkerReportLastRecEnd函数的目的是确保领导者进程在我们提交事务之前知道工作者进程已经写入的所有 WAL 日志。这是必要的,因为在并行事务处理中,领导者进程需要等待所有工作者进程完成它们的任务,并且记录了它们所有的更改,然后才能安全地提交整个事务。
第三、通知系统当前进程(MyProc)已经结束了一个事务。
ProcArrayEndTransaction 函数用于通知系统当前进程(MyProc)已经结束了一个事务,并且提供了要结束的事务 XID(latestXid)。ProcArrayEndTransaction 调用的顺序要求:
- 必须在释放当前进程持有的锁之前执行。这是因为在锁释放之前,其他进程需要知道当前进程已经结束了事务,以避免潜在的死锁或资源争用问题。
- 同时,它也必须在 RecordTransactionCommit 调用之后执行。RecordTransactionCommit 函数用于记录事务提交到 WAL(Write-Ahead Logging)日志,确保事务的持久性。
ProcArrayEndTransaction(MyProc, latestXid);
ProcArrayEndTransaction函数标记了一个事务不在运行。从这一步以后,即便出错也来不及阻止事务提交了,后续都是资源的释放和参数重置过程。
2.5 释放资源:
第一、释放TopTransactionResourceOwner所拥有的资源。
- AtEOXact_Buffers函数清理缓冲区。
- AtEOXact_RelationCache函数清理关系缓存。
- AtEOXact_Inval函数在主事务结束时处理排队中的无效信息。
- AtEOXact_MultiXact函数结束多事务。
ResourceOwnerRelease(TopTransactionResourceOwner,RESOURCE_RELEASE_BEFORE_LOCKS,true, true);/* Check we've released all buffer pins */AtEOXact_Buffers(true);/* Clean up the relation cache */AtEOXact_RelationCache(true);/** Make catalog changes visible to all backends.This has to happen after* relcache references are dropped (see comments for* AtEOXact_RelationCache), but before locks are released (if anyone is* waiting for lock on a relation we've modified, we want them to know* about the catalog change before they start using the relation). */AtEOXact_Inval(true);AtEOXact_MultiXact();ResourceOwnerRelease(TopTransactionResourceOwner,RESOURCE_RELEASE_LOCKS,true, true);ResourceOwnerRelease(TopTransactionResourceOwner,RESOURCE_RELEASE_AFTER_LOCKS,true, true);
ResourceOwnerRelease函数释放参数TopTransactionResourceOwner及其后代拥有的所有资源,但不删除“资源Owner”对象本身。
第二、处理删除操作并通知事务成功完成。
smgrDoPendingDeletes(true);/** Send out notification signals to other backends (and do other* post-commit NOTIFY cleanup). This must not happen until after our* transaction is fully done from the viewpoint of other backends.*/AtCommit_Notify();
第三、依次清理资源。
- AtEOXact_GUC(true, 1);
处理:运行时配置参数(GUC)。
作用:在事务结束时应用或撤销事务期间设置的配置更改。 - AtEOXact_SPI(true);
处理:服务器过程接口(SPI)。
作用:清理 SPI 在事务中使用的资源和状态。 - AtEOXact_Enum();
处理:枚举类型。
作用:管理枚举类型的元数据,确保事务结束后枚举状态是一致的。 - AtEOXact_on_commit_actions(true);
处理:提交时执行的动作。
作用:执行在事务提交时需要进行的特定动作或回调。 - AtEOXact_Namespace(true, is_parallel_worker);
处理:命名空间。
作用:清理命名空间相关的资源,可能与并行工作有关。 - AtEOXact_SMgr();
处理:存储管理器。
作用:管理文件和存储相关的资源,如释放锁或处理文件删除。 - AtEOXact_Files(true);
处理:文件资源。
作用:清理事务中使用的文件,如临时文件。 - AtEOXact_ComboCid();
处理:组合命令 ID。
作用:管理与组合命令 ID 相关的事务状态。 - AtEOXact_HashTables(true);
处理:哈希表。
作用:清理或刷新哈希表,确保数据结构的一致性。 - AtEOXact_PgStat(true, is_parallel_worker);
处理:pg_stat 统计信息。
作用:更新统计收集模块的状态,可能与并行工作有关。 - AtEOXact_Snapshot(true, false);
处理:事务快照。
作用:清理事务快照,确保 MVCC 状态下的数据可见性正确。 - AtEOXact_ApplyLauncher(true);
处理:逻辑复制应用启动器。
作用:管理逻辑复制相关的事务结束时的资源和状态。 - pgstat_report_xact_timestamp(0);
处理:事务时间戳统计。
作用:报告事务的时间戳信息给 pg_stat 模块,0 可能表示当前时间或其他特定值。
/** Everything after this should be purely internal-to-this-backend* cleanup.*/AtEOXact_GUC(true, 1);AtEOXact_SPI(true);AtEOXact_Enum();AtEOXact_on_commit_actions(true);AtEOXact_Namespace(true, is_parallel_worker);AtEOXact_SMgr();AtEOXact_Files(true);AtEOXact_ComboCid();AtEOXact_HashTables(true);AtEOXact_PgStat(true, is_parallel_worker);AtEOXact_Snapshot(true, false);AtEOXact_ApplyLauncher(true);pgstat_report_xact_timestamp(0);
第四、重置全局变量和状态变量。
重置CurrentResourceOwner、XactTopFullTransactionId、CurTransactionResourceOwner、TopTransactionResourceOwner、nParallelCurrentXids和事务状态变量TransactionState s。ResourceOwnerDelete函数会删除TopTransactionResourceOwner参数的对象及其后代。
CurrentResourceOwner = NULL;ResourceOwnerDelete(TopTransactionResourceOwner);s->curTransactionOwner = NULL;CurTransactionResourceOwner = NULL;TopTransactionResourceOwner = NULL;AtCommit_Memory();s->fullTransactionId = InvalidFullTransactionId;s->subTransactionId = InvalidSubTransactionId;s->nestingLevel = 0;s->gucNestLevel = 0;s->childXids = NULL;s->nChildXids = 0;s->maxChildXids = 0;XactTopFullTransactionId = InvalidFullTransactionId;nParallelCurrentXids = 0;
2.6 提交事务:
修改事务状态为TRANS_DEFAULT,放开中断机制,完成事务提交。
s->state = TRANS_DEFAULT;RESUME_INTERRUPTS();
作者介绍
李超,移动云数据库工程师,负责云原生数据库He3DB的研发。
相关文章:

海山数据库(He3DB)源码详解:CommitTransaction函数源码详解
文章目录 海山数据库(He3DB)源码详解:CommitTransaction函数1. 执行条件2. 执行过程2.1 获取当前节点状态:2.2 检查当前状态:2.3 预提交处理:2.4 提交处理:2.5 释放资源:2.6 提交事务: 作者介绍…...

【网络】传输层TCP协议的报头和传输机制
目录 引言 报头和有效载荷 确认应答机制 捎带应答机制 超时重传机制 排序和去重 连接管理机制 个人主页:东洛的克莱斯韦克-CSDN博客 引言 TCP是传输层协议,全称传输控制协议。TCP报头中有丰富的字段以及协议本身会制定完善的策略来保证网络传输的…...

【活动报名】打造编程学习“知识宝库”:高效笔记记录与整理指南
如何高效记录并整理编程学习笔记? 在编程学习的旅程中,拥有一套高效的笔记记录和整理方法至关重要。以下将从三个方向为您详细介绍如何打造属于自己的编程学习“知识宝库”。 方向一:笔记工具选择 选择合适的笔记工具是高效记录编程学习笔记…...

使用Arduino IDE生成带有bootloader的烧录文件
使用Arduino IDE生成bin(烧录)文件 1、在“项目”中,选择“导出已编译的二进制文件” 2、在工程目录中,会出现“build”文件夹 3、在build文件夹中,有hex文件,以及包含bootloader的bin和hex文件 bin和h…...

搭建高可用OpenStack(Queen版)集群(九)之部署nova计算节点
一、搭建高可用OpenStack(Queen版)集群之部署计算节点 一、部署nova 1、安装nova-compute 在全部计算节点安装nova-compute服务 yum install python-openstackclient openstack-utils openstack-selinux -y yum install openstack-nova-compute -y 若yu…...

C# 字符串扩展方法
功能 1.判断一个字符串是否为null或者空字符串 2.判断一个字符串是否为null或者空白字符 3.判断一个字符串是否为数字 4.判断一个字符串是否为邮件 5.判断一个字符串是否为字母加数字 6.判断一个字符串是否为手机号码 7.判断一个字符串是否为电话号码 8.判断一个字符串是否为网…...

JookDB和MobaXterm下载安装使用
文章目录 1.使用背景2.MobaXterm的下载安装使用3.JooKDB的下载安装使用 1.使用背景 由于xshell和xftp等工具都是收费的,即使有破解版但是有的公司里不让用盗版的软件。可以使用MobaXterm来替代。 同理可使用JooKDB来代替收费的navicat 来连接数据库。 2.MobaXterm…...

Docker安装Nacos(详细教程)
Docker安装Nacos的步骤相对直接,但需要注意一些细节以确保安装成功。以下是一个详细的安装步骤指南: 1. 安装Docker 首先,确保你的系统中已经安装了Docker。如果尚未安装,你可以通过访问Docker的官方网站或使用包管理器…...

Pandas:提供了快速、灵活和表达式丰富的数据结构。
引言 Pandas是Python中最为广泛使用的数据分析和操作库之一,特别适用于处理结构化数据。该库的名称源自“Panel Data”的缩写,意为面板数据或多维数据。Pandas基于NumPy构建,继承了其高效的数组计算能力,并在此基础上进一步扩展&…...

强!小目标检测全新突破!检测速度快10倍,GPU使用减少73.4%
强!小目标检测全新突破,提出Mamba-in-Mamba结构,通过内外两层Mamba模块,同时提取全局和局部特征,实现了检测速度快10倍,GPU使用减少73.4%的显著效果! 【小目标检测】是近年来在深度…...

重修设计模式-创建型-原型模式
重修设计模式-创建型-原型模式 原型模式就是利用已有对象(原型)通过拷贝方式来创建对象的模式,达到节省对象创建时间的目的。适用于对象创建成本较大,且同一类的不同对象之间差别不大的场景。 比如一个对象中的数据需要经过复杂…...

S71200 - 编程 - 笔记
1 DEMO 1.1气阀控制 1.2 红绿灯 基于PLC红绿灯控制_哔哩哔哩_bilibili 2 介绍变量DB,M,I,Q的使用 在PLC编程中,通常会使用多种类型的变量来实现逻辑控制、数据存储和输入输出操作。以下是常见的PLC变量类型及其用途ÿ…...

【项目】畅聊天地博客测试报告
项目简介:本项目采用 SSM框架结合 Websocket 技术构建。用户通过简单的注册和登录即可进入聊天室,与其他在线用户实时交流。系统支持文字消息的快速发送和接收、消息实时推送,确保交流的及时性和流畅性。SSM 框架为项目提供了稳定的架构和高效…...

【Next】全局样式和局部样式
不同于 nuxt ,next 的样式绝大部分都需要手动导入。 全局样式 使用 sass 先安装 npm i sass -D 。 我们可以定义一个 styles 文件,存放全局样式。 variables.scss $fs30: 30px;mixin border() {border: 1px solid red; }main.scss use ./variables …...

关于Docker的详细介绍
Docker是一个开源的应用容器引擎,它允许开发者将应用程序及其依赖项打包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,实现虚拟化。以下是关于Docker的详细介绍: ### 一、Docker的定义 Docker是一…...

一台佳能G3811彩色喷墨打印机打印没颜色报5200的维修记录
一台佳能G3811彩色喷墨打印机,用户送修,称打印没有颜色,加电开机连电脑安驱动打印测试,确实没有颜色,于是清洗喷头结果打印机那个显示屏上 ,上来就报错P08,电脑提示5200; 话不多说,开始维修,仅记录当时的维修方法及步骤,其它未列出。。。 维修方法: 1、进维…...

【LeetCode】452.用最少数量的箭引发气球
能够找到问题的解法与把问题足够简化是天壤之别。比如我知道这题可以用贪心算法来解决,但是代码实现的过程中就走上了复杂的路,但是官方题解给的代码则相当简洁。这说明我思考的不够深入,导致化繁为简的能力不够强。 1. 题目 2. 分析 一道贪…...

网络安全流程规范文件解读(安全专业L1级)
技术能力项编号AQ-AQ-L1-02.01(安全维护作业计划执行能力) 课程目标: 通过学习课程,学员可以: 1.了解ZGYD网络安全流程规范 2.独立执行安全维护作业计划。 流程规范 一、《ZGYD远程接入安全管理办法》 二、《ZGYD网络运维账号口令管理办…...

Java、python、php版的邮件发送与过滤系统的设计与实现 (源码、调试、LW、开题、PPT)
💕💕作者:计算机源码社 💕💕个人简介:本人 八年开发经验,擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等,大家有这一块的问题可以一起交流&…...

st算法求RMP
st算法(sparse_tabel)可以在O(N log N)的预处理后实现O(1)的查询效率。 rmq:Range Maximum (Minimum) Query的缩写,顾名思义是用来求某个区间内的最大值或最小值,通常用在需要多次询问一些区间的最值得问题中。 #inc…...

零基础学习Redis(1) -- Redis简介
Redis是一个在内存中存储数据的一个中间组件,可用作数据库或数据缓存,通常在分布式系统中使用 (不了解分布式? 点击传送) 1. Redis特性 在内存中存储数据,通过键值对的方法存储key为string,v…...

安装MySQL数据库【后端 8】
安装MySQL数据库 MySQL是世界上最流行的开源关系型数据库管理系统(RDBMS)之一,广泛应用于Web应用程序开发中。无论你是初学者还是有一定经验的开发者,掌握MySQL的安装都是必不可少的技能。本文将指导你如何在不同的操作系统上安装…...

JAVA学习-练习试用Java实现“整数转换英文表示”
问题: 将非负整数 num 转换为其对应的英文表示。示例 1: 输入:num 123 输出:"One Hundred Twenty Three" 示例 2: 输入:num 12345 输出:"Twelve Thousand Three Hundred Fo…...

TPshop商城的保姆教程(Ubuntu)
1.上传TPSHOP源码 选择适合自己的版本下载 TPshop商城源文件下载链接: 百度网盘 请输入提取码 上传tpshop的源码包到特定目录/var/www/html 切换到/var/www/html 目录下 cd /var/www/html修改HTML目录下所有文件权限 chmod -R 777 * 2.打开网址配置 TPshop安…...

MySQL存储过程、触发器、视图
数据库中的存储过程、触发器和视图是三种常用的数据库对象,它们在管理数据、优化性能和简化复杂操作中起着重要的作用。下面是每种对象的详细介绍和示例: 存储过程 存储过程是一组为了执行特定功能而预编译的SQL语句。它类似于编程中的函数,…...

每一行txt文件的内容将作为CSV文件中的一行,逗号、空格和句号,冒号作为分隔符拆分成多列
将指定文件夹中的每个txt文件的内容读取出来,并将每个文件的内容按逗号、空格和句号作为分隔符拆分成多列,每一行txt文件的内容将作为CSV文件中的一行,此文件夹中的文件会有非utf-8字符,是如下的代码,如果是utf-8编码的…...

基于inotif的文件同步备份
1 ftp 因为服务器是linux的,而备份服务器是windows server的,故而采取lftp进行同步文件。 1.1 全量同步 cat > /appdata/script/sync_all.sh <<EOF #!/bin/bash # FTP 服务器信息 FTP_SERVER"ftp://192.168.0.5" FTP_USER"…...

luckyexcel 编辑预览excel文件
luckyexcel 编辑预览excel文件 支持后端传文件流预览编辑,也支持选择本地文件编辑预览 看效果 上代码 <template><div style"margin: 30px"><div class"button-box2"><div><div style"color: red">…...

记录Java使用websocket
实现场景:每在小程序中添加一条数据时,后台将主动推送一个标记给PC端,PC端接收到标记将进行自动播放音频。 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import or…...

(javaweb)分层解耦
目录 一.三层架构 二.分层解耦 三.IOC&DI入门 四.IOC详解 五. DI详解 一.三层架构 复用性差,难以维护和管理 前端发起请求,先会到达controller,再调用service进行逻辑处理,逻辑处理的前提是先拿到数据,到dao…...