MySql MVCC 详解
注意以下操作都是以InnoDB引擎为操作基准。
一,前置知识准备
1,MVCC简介
MVCC 是多版本并发控制(Multiversion Concurrency Control)的缩写。它是一种数据库事务管理技术,用于解决并发访问数据库的问题。MVCC 通过创建多个版本的同一数据,每个版本与一个事务关联,来实现并发控制。
数据库在执行更新操作时,会保留之前版本的数据,以便其他正在执行事务的用户可以访问这些数据。每个事务都能看到一个稳定的数据快照,并且仅接触到他们自己的版本,这意味着每个事务可以独立地读取和写入数据,而不会干扰其它事务。
MVCC 在数据库的可伸缩性和性能方面具有重要作用,尤其是对于高并发的应用程序,如电子商务网站和社交媒体应用。
2,MySQL的逻辑架构
第一层:处理客户端连接、授权认证,安全校验等。
第二层:服务器server层,负责对SQL解释、分析、优化、执行操作引擎等。
第三层:存储引擎,负责MySQL中数据的存储和提取。
3,事务的四大特性
ACID是指数据库事务所必须具备的四个特性,包括:
-
原子性(Atomicity):事务是一个不可分割的原子操作,要么全部执行成功,要么全部失败回滚,不允许出现部分执行成功或失败的情况。【undolog】
-
一致性(Consistency):事务执行前和执行后,数据库的完整性约束没有被破坏,也就是说,在事务完成后,数据库从一个一致性状态转变为另一个一致性状态。
-
隔离性(Isolation):事务之间是相互隔离的,一个事务的执行不能被其他事务干扰。多个事务并发执行时,它们之间的执行是独立的,每个事务感觉就像是在独占数据库。【锁,mvcc】
-
持久性(Durability):事务完成后,对于数据的修改是永久性的,即使系统故障也不会导致数据的丢失。因此,数据库中所有的数据修改都需要记录到日志中,以便在系统故障恢复时进行重做。【redolog】
4,事务的四大隔离级别
事务的隔离级别是指多个事务同时操作一个数据库时,数据库系统对这些事务分配的隔离程度。在不同的隔离级别下,事务之间的隔离程度也不同。常见的隔离级别包括:
-
读未提交(Read Uncommitted):允许一个事务读取另一个事务未提交的数据。这种隔离级别对数据的完整性和一致性影响较大。【存在脏读】
-
读已提交(Read Committed):一个事务只能读取已经提交的数据,其他未提交的事务所做的修改对它不可见。这种隔离级别对数据完整性和一致性的保护较好。【解决脏读,存在不可重复读】【mysql InnoDB 通过 mvcc 解决 】
-
可重复读(Repeatable Read):一个事务在执行期间看到的数据是固定的,不受其他并发事务的影响。即使其他事务已经提交了对数据的修改,当前事务也只能看到自己在读取数据时的版本。这种隔离级别对数据的完整性和一致性有一定保护。【解决不可重复读,存在幻读】【mysql InnoDB 通过 mvcc 解决 】
-
串行化(Serializable):最高的隔离级别,确保事务之间的操作是完全独立的,一个事务的操作必须等另一个事务结束后才能开始。这种隔离级别对数据完整性和一致性的保护最好,但并发性能较低。【解决脏读,解决不可重复读,解决幻读】【mysql InnoDB 通过 加锁解决 】
在实际应用中,应根据业务需求和系统性能等因素选择合适的隔离级别。
5,mysql 常用的日志
server 层
- 错误日志(Error Log): 记录 MySQL 服务器启动、运行过程中出现的重要错误和警告信息。
- 慢查询日志(Slow Query Log): 记录执行时间超过预设时间的查询语句,通常用于优化查询性能。
- 二进制日志(Binary Log): 记录数据库更新操作,用于主从复制和数据恢复。
- 中继日志(Relay Log): 只在主从复制时使用,记录从服务器复制主服务器二进制日志的过程。
引擎层
- 重做日志(Redo log): 是一种用于恢复数据库中未提交和已提交事务的机制。其包含了所有已经被写入到磁盘上的事务,通常被存储在磁盘上的一组文件中。当数据库系统宕机或者发生崩溃时,可以通过redo log来恢复数据库并且保证ACID属性。
- 回滚日志(Undo log): 则用于撤销已经提交或者未提交的事务。它记录了事务执行前的数据,以便当出现错误时可以将数据回滚到事务执行前的状态。在数据库中,undo log通常被用于避免脏读、不可重复读和幻读等问题。
二,mvcc 原理
1,当前读和快照读
在学习 MVCC 多版本并发控制之前,我们必须先了解一下,什么是 MySQL InnoDB 下的当前读和快照读。
-
当前读,像 select lock in share mode (共享锁), select for update; update;insert; delete (排他锁)这些操作都是一种当前读,为什么叫当前读 ? 就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。
-
快照读,像不加锁的 select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读,之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC.可以认为 MVCC 是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本。
在InnoDB中的每一条记录实际都会存在三个隐藏列
-
DB_TRX_ID:事务 ID,是根据事务产生时间顺序自动递增的,是独一无二的。如果某个事务执行过程中对该记录执行了增、删、改操作,那么InnoDB存储引擎就会记录下该条事务的 id。
-
DB_ROLL_PTR:回滚指针,本质上就是一个指向记录对应的undo log的一个指针,InnoDB 通过这个指针找到之前版本的数据
-
DB_ROW_ID:主键,如果有自定义主键,那么该值就是主键;如果没有主键,那么就会使用定义的第一个唯一索引;如果没有唯一索引,那么就会默认生成一个隐藏列作为主键。
2,undolog
这些数据快照都是存储在undolog 中的,这些数据分为两类
-
Insert undo log :insert生成的日志,仅在事务回滚中需要,并且可以在事务提交后立即丢弃。
-
Update undo log:update/delete生成的日志,除了用于事务回滚,还用于一致性读取,只有不存在innodb为其分配快照的事务之后才能丢弃它们,在一致读取中可能需要update undo log中的信息来构建数据库行的早期版本。
删除操作实际上不会直接删除,而只是标记为删除,最终的删除操作是purge线程完成的
purge线程作用,一是清理undo log,二是清除page里面带有Delete_Bit标识的数据行。在InnoDB中,事务中的Delete操作实际上并不是真正的删除掉数据行,而是一种Delete Mark操作,在记录上标识删除,真正的删除工作需要后台purge线程去完成。
3,Read View(读视图)
事务进行快照读操作的时候生产的读视图(Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照。
记录并维护系统当前活跃事务的ID(trx_id)(没有commit,当每个事务开启时,都会被分配一个ID,
这个ID是递增的,所以越新的事务,ID值越大),是系统中当前不应该被本事务看到的其他事务id列表。
Read View主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个Read
View读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo
log里面的某个版本的数据。
Read View几个属性
MVCC 只在 Read Commited(读已提交) 和 Repeatable Read(可重读读) 两种隔离级别下工作。
-
在RC隔离级别下,是每个快照读都会生成并获取最新的Read View,这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因。
-
在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View,从而做到可重复读。
4,可见性算法
1、首先比较DB_TRX_ID < up_limit_id,如果小于,则当前事务能看到DB_TRX_ID所在的记录,如果大于等于进入下一个判断。
2、接下来判断DB_TRX_ID >= low_limit_id,如果大于等于则代表DB_TRX_ID所在的记录在Read View生成后才出现的,那么对于当前事务肯定不可见,如果小于,则进入下一步判断。
3、判断DB_TRX_ID是否在活跃事务中,如果在,则代表在Read View生成时刻,这个事务还是活跃状态,还没有commit,修改的数据,当前事务也是看不到,如果不在,则说明这个事务在Read View生成之前就已经开始commit,那么修改的结果是能够看见的。
5,mvcc能否解决幻读
在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做幻行。
在快照读读情况下,mysql通过mvcc来避免幻读。
在当前读读情况下,mysql通过next-key来避免幻读。
不能把快照读和当前读得到的结果不一样这种情况认为是幻读,这是两种不同的使用。所以mysql的RR级别是解决了幻读的。
三,mvcc 场景验证
所谓光说不练假把式,光练不说傻把式,又练又说真把式,上面说的只是结论,下面进行实际的操作演示。
mysql 版本 5.7
创建测试表
CREATE TABLE `user` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL,`age` tinyint(3) DEFAULT NULL,`gender` tinyint(1) DEFAULT NULL,PRIMARY KEY (`id`),KEY `idx_abc` (`name`,`age`,`gender`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
(开始之前将事务自动提交关闭)
1,场景一
当前的事务隔离级别为,可重复读(Repeatable Read)
步骤一,t1时刻同时开启事务
步骤二,t2时刻事务2更新并提交
步骤三,t3时刻事务1查询
问题,事务1在t3时刻是否能查询t2时刻事务2提交的数据。
预期结果能
因为执行的是select所以为快照读,但是由于Read View是在快照读的时候才产生,并且可重复读(Repeatable
Read)隔离级别下,只产生一个Read
View。事务2更新并提交完成时候,由于此时事务1还没进行快照读。所以此时事务1查询的时候是可以查询到事务2更新并提交后的数据的。
sql 执行验证
查询结果符合预期
通过算法核对
trx_list:1,3 【当前活跃事务为 1,3,因为2已经提交了】
low_limit_id:4【当前系统最大事务版本号+1,因为已经开启了3个事务,所以下一个应该是4】
up_limit_id:1 【创建当前read view 时“系统正处于活跃事务最小版本号,活跃的只有1,3,最小的是1】
算法验证:验证当前事务1是否能看到事务2提交的数据。
(1)DB_TRX_ID < up_limit_id 【2<1】不成立继续判断
(2)DB_TRX_ID >= low_limit_id 【2>=4】不成立继续判断
(3)判断DB_TRX_ID是否在活跃事务中,不在,则说明这个事务在Read View生成之前就已经开始commit,那么修改的结果是能够看见的。
2,场景二
当前的事务隔离级别为,可重复读(Repeatable Read)
步骤一,t1时刻同时开启事务
步骤二,t2时刻事务1进行快照读
步骤三,t3时刻事务2修改并提交
步骤四,t4时刻事务1进行快照读
问题,事务1在t4时刻是否能查询t3时刻事务2提交的数据。
预期结果不能
事务1在t2时刻执行的是select所以为快照读,此时Read View产生,并且可重复读(Repeatable
Read)隔离级别下,只产生一个Read View。事务2在t3更新并提交完成时候,由于此时事务1已经产生了Read
View,再次进行快照读。所以此时事务1查询的时候是可以查询不到事务2更新并提交后的数据的,因为读取的是快照中的数据。
sql 执行验证
查询结果符合预期
通过算法核对
第一次查询
trx_ids:1,2,3 【当前活跃事务为 1,2,3,此时事务2还没开始修改提交】
low_limit_id:4【当前系统最大事务版本号+1,因为已经开启了3个事务,所以下一个应该是4】
up_limit_id:1 【创建当前read view 时“系统正处于活跃事务最小版本号,活跃的只有1,3,最小的是1】
第二次查询
可重复读(Repeatable Read)事务隔离级别下只产生一个read view
trx_ids:1,3 【当前活跃事务为 1,3,此时事务2已经修改提交】
low_limit_id:4【当前系统最大事务版本号+1,因为已经开启了3个事务,所以下一个应该是4】
up_limit_id:1 【创建当前read view 时“系统正处于活跃事务最小版本号,活跃的只有1,3,最小的是1】
第二次快照读的时候,当前数据的DB_TRX_ID为2
(1)DB_TRX_ID < up_limit_id 【2<1】不成立继续判断
(2)DB_TRX_ID >= low_limit_id 【2>=4】不成立继续判断
(3)判断DB_TRX_ID是否在活跃事务中,在,则代表在Read View生成时刻,这个事务还是活跃状态,还没有commit,修改的数据,当前事务也是看不到。
3,场景三
当前的事务隔离级别为,可重复读(Repeatable Read)
如果事务中全部都是快照读,不会产生幻读问题,但是当快照读和当前读一起使用的时候就会产生幻读问题。
Mysql的解决方案是加锁,想要解决这个问题,必须要保证当前读和快照读的数据必须要一致,只能去阻止其他事务进行插入操作,所以只能加锁。
sql 执行验证
1,如果事务中全部都是快照读,不会产生幻读问题
2,当快照读和当前读一起使用的时候就会产生幻读问题
3,如果事务中全部都是当前读,不会产生幻读问题【加锁实现的】
提交后立刻执行
4,场景四
当前的事务隔离级别为,读已提交(Read Committed)
验证在此隔离级别,每一次快照读都会产生一次新的read view
步骤一,t1时刻同时开启事务
步骤二,t2时刻事务1进行快照读
步骤三,t3时刻事务2修改并提交
步骤四,t4时刻事务1进行快照读
问题,事务1在t4时刻是否能查询t3时刻事务2提交的数据。
预期结果能
事务1在t2时刻执行的是select所以为快照读,此时Read View产生,读已提交(Read
Committed)隔离级别下,产生多个Read
View。所以事务2在t3更新并提交完成时候,事务1在t4时刻再次进行快照读。此时又产生了新的Read View。新的Read
View是在t3时刻事务2修改并提交产生的所以可以查看到。
sql 验证
符合预期结果
通过算法核对
第一次查询
trx_ids:1,2,3 【当前活跃事务为 1,2,3,此时事务2还没开始修改提交】
low_limit_id:4【当前系统最大事务版本号+1,因为已经开启了3个事务,所以下一个应该是4】
up_limit_id:1 【创建当前read view 时“系统正处于活跃事务最小版本号,活跃的只有1,3,最小的是1】
第二次查询
可重复读(Repeatable Read)事务隔离级别下只产生一个read view
trx_ids:1,3 【当前活跃事务为 1,3,此时事务2已经修改提交】
low_limit_id:4【当前系统最大事务版本号+1,因为已经开启了3个事务,所以下一个应该是4】
up_limit_id:1 【创建当前read view 时“系统正处于活跃事务最小版本号,活跃的只有1,3,最小的是1】
第二次快照读的时候,当前数据的DB_TRX_ID为2
(1)DB_TRX_ID < up_limit_id 【2<1】不成立继续判断
(2)DB_TRX_ID >= low_limit_id 【2>=4】不成立继续判断
(3)判断DB_TRX_ID是否在活跃事务中,不在,则说明这个事务在Read View生成之前就已经开始commit,那么修改的结果是能够看见的。
相关文章:

MySql MVCC 详解
注意以下操作都是以InnoDB引擎为操作基准。 一,前置知识准备 1,MVCC简介 MVCC 是多版本并发控制(Multiversion Concurrency Control)的缩写。它是一种数据库事务管理技术,用于解决并发访问数据库的问题。MVCC 通过创…...

工业机器视觉megauging(向光有光)使用说明书(三,轻量级的visionpro)
下来我们说说第二个相机的添加: 第一步,点击相机二,如下: 第二步,点击:加载工具组.xml,加载toolgroupxml2目录下的:工具组.xml 注意,一个相机只能用一个toolgroupxml,第…...

Linux 环境下,jdbc连接mysql问题
1. 下载MySQL的JDBC驱动: 从MySQL官网下载最新的MySQL Connector/J,并将其解压到某个目录,比如/usr/local/mysql/。 2. 将JDBC驱动添加到类路径: 将JDBC驱动添加到类路径,可以使用以下命令: export CLA…...

Python读写txt文件数据
🎈 博主:一只程序猿子 🎈 博客主页:一只程序猿子 博客主页 🎈 个人介绍:爱好(bushi)编程! 🎈 创作不易:如喜欢麻烦您点个👍或者点个⭐! …...
Linux虚假唤醒
为什么会有虚假唤醒一说。Linux内核这么强大,怎么会出现这样的情况?一直以来也很困惑,看了下文链接中的介绍后,豁然开朗。 从计算机设计的角度,如果一层解决不了,那就再多加一层。推算到这里,就…...

倒计时模块复习
经典回顾倒计时 倒计时的基本布局介绍。 一个内容区域和一个输入区域,内容区域进行划分 直接使用flex布局会更快一点。 js代码 我们利用一下模块化思想,直接把获得时间这个功能写成一个函数。方便后续的调用 function getTime() {const date new Date…...

k8s(三): 基本概念-ReplicaSet与Deployment
PeplicaSet ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合,通常用来保证给定数量的、完全相同的 Pod 的可用性。 最佳实践 Deployment 是一个可以拥有 ReplicaSet 并使用声明式方式在服务器端完成对 Pod 滚动更新的对象。 尽管 Rep…...

Linux 的介绍和云服务器上web 程序部署
目录 一.linux的介绍 1.1linux是什么 1.2linux的发展历程 1.3linux发行版 二.Linux环境搭建 2.1阿里云-云服务器配置 2.2使用终端软件连接Linux 三.操作Linux,部署web程序 3.1Linux指令 3.2部署web程序 第一步:认识yum 第二步:安装…...
Oauth2.0 学习
OAuth 2.0 服务器端通常通过验证每次请求中的访问令牌(access token)的方式来确保其合法性和有效性。以下是一些通常采用的验证方法: Token Validation Endpoint: OAuth 2.0 规范允许实现一个专门的令牌验证端点,称为 Token Valid…...

Elasticsearch:什么是向量数据库?
向量数据库定义 向量数据库是将信息存储为向量的数据库,向量是数据对象的数值表示,也称为向量嵌入。 它利用这些向量嵌入的强大功能来对非结构化数据和半结构化数据(例如图像、文本或传感器数据)的海量数据集进行索引和搜索。 向…...

rename--统一的PRF
基本概念 将ARF/PRF进行合并,合同之后的不见,称之为统一的PRF(Physical Register File);存储的是speculative的,以及正确的(retire)寄存器值; 使用free list,存储PRF中,哪些寄存器是…...

010-editor破解(1)
查看字符串 使用rabin2 -z /home/burning/010editor/010editor | tee 22.txt 查看字符串。 6698 0x003ba380 0x007ba380 68 69 .rodata ascii The password you entered is for an earlier version of this program. 6699 0x003ba3c8 0x007ba3c8 70 71 .rodata ascii You will…...

Ubuntur编译ROS报错:error PCL requires C++14 or above
ubuntu20.04 编译ROS包 报错: error: PCL requires C14 or above: 修改Cmakelists.txt文件: set(CMAKE_CXX_STANDARD 14) 再次编译成功....

17.认识下Docker之docker的核心原理(2)
1.容器-我的小世界 不知道大家看没看过小说《完美时间》,里面石昊经常进入一个小世界在里面与世隔绝的修炼或者战斗,总之就是在一个完全封闭的空间里做他想做的事情而与外界隔离,不受侵扰。通过前面的分析我们知道,Namepace让应用…...

【EasyExcel实践】万能导出,一个接口导出多张表以及任意字段(可指定字段顺序)
文章目录 前言正文一、POM依赖二、核心Java文件2.1 自定义表头注解 ExcelColumnTitle2.2 自定义标题头的映射接口2.3 自定义有序map存储表内数据2.4 表头工厂2.5 表flag和表头映射枚举2.6 测试用的实体2.6.1 NameAndFactoryDemo2.6.2 StudentDemo 2.7 启动类2.8 测试控制器 三、…...

代码随想录算法训练营第四十二天 _ 动态规划_01背包问题、416.分割等和子集。
学习目标: 动态规划五部曲: ① 确定dp[i]的含义 ② 求递推公式 ③ dp数组如何初始化 ④ 确定遍历顺序 ⑤ 打印递归数组 ---- 调试 引用自代码随想录! 60天训练营打卡计划! 学习内容: 二维数组处理01背包问题 听起来…...

市场上好用的aspera替代方案,你知道哪些
Aspera作为一个高速文件传输方案曾经非常受欢迎,但是其昂贵的价格却限制了许多用户的选择,因此市场上出现了众多Aspera替代方案,本文将会介绍市场上最好的Aspera替代方案。 最近几年,网络传输已成为现代商业运作中必不可少的一部…...

Stm32_串口的帧(不定长)数据接收
目录标题 前言1、串口中断接收固定帧头帧尾数据1.1、任务需求1.2、实现思路1.3、程序源码: 2、串口中断接收用定时器来判断帧结束3、串口中断接收数据空闲中断3.1、串口的空闲中断3.2、实现思路3.3、程序源码 4、串口的空闲中断DMA转运4.1、DMA简介4.2、DMA模式4.3、…...
L0、Linux常用命令
一、防火墙: 在 Linux 中,关闭防火墙可以使用不同的命令,这取决于你所使用的防火墙软件。在一些常见的 Linux 发行版中,防火墙可能是 iptables 或 firewalld两种: centos6使用iptables作为默认防火墙;cento…...
Golang实践录:读取toml配置
本文对 toml 文件进行解析。 下载 对于toml格式文件,golang 有很多库可以解释 yaml 文件,如toml、viper。由于 viper 可解析格式较多,本文采用该库。 toml语法规则 toml语法规则在官方中文文档上有说明,这里直接使用。 TOML 是…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...

Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...