当前位置: 首页 > news >正文

数据库事务的超级详细讲解,包括事务特性、事务隔离级别、MVCC(多版本并发控制)

数据库事务:

主要有事务特性,事务的隔离级别,MVCC。

事务特性:

事务(Transaction)是指作为单个逻辑工作单元执行的一系列操作,这些操作要么全部成功执行,要么全部不执行,不能出现部分执行的情况。事务具有以下四个特性,通常缩写为ACID:

1、原子性(Atomicity):事务是一个不可分割的工作单位,要么全部执行,要么全部不执行。如果事务中的任何一步操作失败,整个事务都会被回滚(Rollback),回到操作之前的状态,不会造成数据的损坏或不一致。

2、一致性(Consistency):事务在执行前后,数据库从一个一致性状态转移到另一个一致性状态。即使在事务执行过程中出现异常,数据库也会通过回滚操作,将数据恢复到一致性状态。

3、隔离性(Isolation):事务的执行不会受到其他事务的影响,每个事务在执行过程中都应该感觉不到其他事务的存在。即使多个事务同时操作同一数据,也不会互相干扰。隔离性能够防止并发事务导致的数据异常和不一致问题。

4、持久性(Durability):一旦事务被提交(Commit),其所做的修改将会永久保存在数据库中,并且即使系统发生故障,这些修改也不会丢失。数据库系统会将事务的修改持久化到磁盘中,以保证数据的持久性。

案例说明事务的特性:

假设有一个银行系统,用户 A 和用户 B 分别有 1000 元和 2000 元存款。用户 A 想要向用户 B 转账 500 元。这个转账操作可以通过以下 SQL 语句来实现:

sqlCopy Code-- 开启事务
START TRANSACTION;-- 扣除用户 A 的账户余额
UPDATE accounts SET balance = balance - 500 WHERE user_id = 'A';-- 增加用户 B 的账户余额
UPDATE accounts SET balance = balance + 500 WHERE user_id = 'B';-- 提交事务
COMMIT;

以上 SQL 语句实现了转账操作的原子性。如果在转账过程中发生了异常,比如数据库连接断开或者用户 A 的余额不足,那么整个事务都会被回滚,用户 A 和用户 B 的账户余额都会恢复到转账前的状态,确保了事务的一致性和持久性。

此外,隔离性的特点可以保证即使有其他用户同时查询用户 A 和用户 B 的账户余额,也不会受到转账操作的影响,保证了数据的隔离性。

隔离级别:

数据库事务的隔离级别定义了事务在并发执行时,系统如何控制事务之间的交互,即一个事务所做的更改在何时对其它事务可见。不同的隔离级别可以在并发性和一致性之间提供不同程度的平衡。SQL 标准定义了四种隔离级别,每种级别都可以减少一种或多种并发问题,但隔离级别越高,性能可能会越低,因为事务之间的并发能力减弱。

1. 读未提交(Read Uncommitted)
  • 定义:最低的隔离级别,允许事务读取尚未提交的数据变更,可能会导致脏读、不可重复读和幻读。
  • 问题:脏读。
  • 案例:事务A修改了一条数据但尚未提交,事务B在此时读取了这条未提交的数据。如果A回滚,B读到的数据就是错误的。
2. 读已提交(Read Committed)
  • 定义:允许事务读取并且仅读取已经提交的数据变更,可以避免脏读,但不可重复读和幻读仍可能发生。
  • 问题:不可重复读。
  • 案例:事务A读取了一条数据,事务B更新了这条数据并提交,当事务A再次读取同一数据时,数据已经变更。
3. 可重复读(Repeatable Read)
  • 定义:确保如果一个事务读取了一条记录,则在这个事务剩余的时间里,无论其他事务如何更新,都不会影响到这条记录的读取结果。可以避免脏读和不可重复读,但幻读仍可能发生。
  • 问题:幻读。
  • 案例:事务A读取了几行数据,事务B插入了一行新数据并提交,当事务A再次查询同一范围的数据时,会看到之前未出现的新行。
4. 串行化(Serializable)
  • 定义:最高的隔离级别,通过强制事务串行执行,避免脏读、不可重复读和幻读,但并发性能最差。
  • 问题:性能问题。
  • 案例:事务A和事务B需要操作同一数据集,B必须等待A完成并提交后,才能开始执行,从而保证了数据的一致性,但大大降低了并发性能。

并发问题解释:

  • 脏读(Dirty Reads):事务读取了另一个事务未提交的数据。
  • 不可重复读(Non-Repeatable Reads):事务在同一查询中多次读取同一数据集,结果却不同,因为其他事务在两次读取之间更新了数据。
  • 幻读(Phantom Reads):事务在重新执行针对某个范围的查询时,发现其他事务插入了满足查询条件的新数据。

在选择隔离级别时,需要在数据一致性和系统性能之间做出权衡。高隔离级别能更好地保证数据的一致性,但可能会降低系统的并发性能;低隔离级别虽然并发性能较好,但在数据一致性上可能存在缺陷。

MVCC:

MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种数据库事务并发控制的方法,主要用于解决读-写冲突,实现高并发访问数据库而不会出现数据不一致的情况。MVCC通过在数据库中保存数据的不同版本来实现并发控制,每个事务在执行时看到的数据版本都是一致的,但不同事务之间可以并发执行而不会相互影响。

MVCC实现原理:
1. 数据版本控制:

MVCC的核心思想是为每个数据项维护多个版本,并且每个事务只能看到适合自己版本的数据。数据库中的每个数据项都会有一个版本号或者时间戳与之关联。

  • 版本号:可以是整数或者时间戳,用于标识数据版本的顺序。
  • 时间戳:记录数据版本的生成时间,通常精确到毫秒或更高精度。
2. 版本链:

数据库中的数据通常以行(Row)为单位存储,每一行数据可能会有多个版本,这些版本按照时间顺序形成一个版本链。版本链可以用一个双向链表或者类似的数据结构来实现。

  • 每个数据行的版本链:包含了该数据行的所有版本,按照时间顺序排列。
  • 链表节点:存储了数据的具体内容以及指向下一个版本的指针。
3. 读操作实现:

当一个事务要执行读操作时,它会根据自己的事务ID或者时间戳确定要读取的数据版本,然后遍历该数据行的版本链,找到最接近但不超过事务版本的数据版本。

  • 快照读(Snapshot Read):事务读取数据时不会阻塞其他事务对同一数据的写操作,而是读取数据版本链中对应版本的数据。
  • 读取过程:事务通过版本链中的版本号或者时间戳来定位数据,确保读取到的数据是在该事务开始之前已经提交的。
4. 写操作实现:

当一个事务要执行写操作时,它会为数据生成一个新版本,并将新版本插入到数据行的版本链中。通常会使用写时复制(Copy-On-Write)或者类似的机制来实现写操作。

  • 生成新版本:事务会生成一个新的版本号或者时间戳,并将新版本写入到数据库中。
  • 写时复制:旧版本的数据不会立即被覆盖,而是在新版本生成后才被修改,这样可以保留旧版本的数据用于事务的隔离和回滚。
5. 提交操作实现:

当一个事务提交时,它会释放对数据库的锁,并清理与该事务相关的数据版本。这通常包括将该事务生成的新版本标记为已提交,并删除回滚段中与该事务相关的数据。

  • 释放锁:事务提交后,其他事务可以访问该数据,并且可以读取该事务生成的新版本。
  • 清理数据:删除回滚段中与该事务相关的数据,确保数据库的存储空间得到有效利用。
6. 事务隔离级别:

MVCC可以实现不同的事务隔离级别,包括读未提交、读已提交、可重复读和串行化。不同的隔离级别决定了事务对数据的读取和写入行为,从而影响了并发控制的实现方式。

  • 隔离级别:用于控制事务之间的相互影响程度,包括读取到的数据版本以及事务的可见性等方面。
总结:

MVCC通过多版本控制和版本链来实现数据库的并发控制,保证了事务之间的隔离性,从而确保了数据的一致性和完整性。MVCC是许多现代数据库系统的核心技术之一,如MySQL、PostgreSQL等都采用了MVCC来实现事务的并发控制。

MVCC实现流程:

当一个事务开始时,数据库系统会为其分配一个唯一的事务ID或者时间戳,并根据该事务ID或时间戳来执行读取和写入操作。

1. 读操作流程:
  1. 事务开始:事务T开始时,获取一个唯一的事务ID或时间戳。
  2. 确定读取版本:根据事务T的隔离级别,确定要读取的数据版本:
    • 如果隔离级别是读未提交,则可以读取到其他未提交事务的数据。
    • 如果隔离级别是读已提交或更高级别,则只能读取已提交事务生成的数据版本。
  3. 读取数据:根据确定的数据版本,从数据库中读取数据。通常是通过版本链中的版本号或时间戳来定位数据。
  4. 提交或回滚:如果读取数据时发现该数据已被删除或不可见,则根据事务的隔离级别决定是提交还是回滚该事务。
2. 写操作流程:
  1. 事务开始:事务T开始时,获取一个唯一的事务ID或时间戳。
  2. 生成新版本:为要写入的数据生成一个新版本,并将新版本插入到数据行的版本链中。通常采用写时复制或类似的机制来实现。
  3. 写入数据:将新版本的数据写入到数据库中。此时,其他事务仍然可以读取旧版本的数据,保持了数据的一致性。
  4. 提交或回滚:事务T完成所有写操作后,根据事务的提交或回滚指令来决定是否将写入的数据版本提交或回滚。
    • 如果提交事务,则将新版本标记为已提交,其他事务可以读取该版本。
    • 如果回滚事务,则删除新版本,并保留旧版本的数据。
3. 并发控制流程:
  1. 读-写冲突检测:当一个事务T1要读取数据时,如果发现有其他事务T2正在对该数据进行写操作,则需要进行冲突检测。
    • 如果T2的写操作已提交,则T1可以读取T2提交的新版本。
    • 如果T2的写操作未提交,则根据事务隔离级别决定是否允许T1读取T2的未提交数据。
  2. 写-写冲突检测:当一个事务T1要对数据进行写操作时,如果发现有其他事务T2正在对同一数据进行写操作,则需要进行冲突检测。
    • 如果T2的写操作已提交,则T1需要等待T2完成后再进行写操作。
    • 如果T2的写操作未提交,则根据事务隔离级别决定是否允许T1覆盖T2的未提交数据。
  3. 事务隔离级别的控制:根据事务的隔离级别,决定事务对数据的读取和写入行为,从而控制事务之间的相互影响程度。
  4. 并发度控制:根据系统的并发度限制,控制同时执行的事务数量,避免系统过载和性能下降。
4. 事务提交流程:
  1. 提交指令:当一个事务T完成所有操作后,执行提交指令。
  2. 标记提交:将事务T生成的新版本标记为已提交状态,其他事务可以读取该版本。
  3. 释放锁:释放事务T持有的锁资源,其他事务可以对相应数据进行读写操作。
  4. 清理数据:删除回滚段中与事务T相关的数据版本,释放存储空间。
  5. 提交完成:事务T提交完成,其他事务可以读取其写入的数据版本。

MVCC通过以上流程实现了数据库的并发控制,保证了事务之间的隔离性和数据的一致性。

MVCC案例说明:

假设有一个简单的数据库表,记录了用户的姓名和年龄,初始数据如下:

IDNameAge
1Alice25
2Bob30

现在有两个事务,T1 和 T2,分别对数据库进行操作:

  • 事务 T1
    1. T1 开始,读取 ID 为 1 的用户信息,姓名为 Alice,年龄为 25。
    2. T1 更新 ID 为 1 的用户信息,将年龄增加 1,变为 26。
    3. T1 提交事务。
  • 事务 T2
    1. T2 开始,读取 ID 为 1 的用户信息,姓名为 Alice,年龄为 25。此时由于T1未提交,T2读取到的是旧版本的数据。
    2. T2 提交事务。

通过MVCC,事务T2读取到了ID为1的用户信息时,虽然T1已经对该数据进行了更新,但T2读取到的是旧版本的数据,这样就避免了T2读取到脏数据的情况。

总的来说,MVCC通过版本控制实现了数据库的高并发访问,保证了事务之间的隔离性,从而确保了数据的一致性。

相关文章:

数据库事务的超级详细讲解,包括事务特性、事务隔离级别、MVCC(多版本并发控制)

数据库事务: 主要有事务特性,事务的隔离级别,MVCC。 事务特性: 事务(Transaction)是指作为单个逻辑工作单元执行的一系列操作,这些操作要么全部成功执行,要么全部不执行&#xff…...

鸿蒙Lottie动画-实现控制动画的播放、暂停、倍速播放、播放顺序

介绍 本示例展示了lottie对动画的操作功能。引入Lottie模块,实现控制动画的播放、暂停、倍速播放、播放顺序、播放到指定帧停止或从指定帧开始播放、侦听事件等功能,动画资源路径必须是json格式。 效果预览 使用说明: 进入页面默认开始201…...

C++面试100问与自动驾驶100问

C的学习和面试其实是非常的不友好的,首先C的学习内容非常的多,其次C的面试不单单面试C的知识点,还有它的“七大姑八大姨”(计算机网络、数据结构、算法、计算机组成原理、操作系统、编译、xxx的底层实现 and so on)。 …...

加速 Redis 操作:掌握管道技术提升性能与效率

Redis 管道技术是一种用于优化 Redis 命令执行效率的机制。在传统的 Redis 操作中,每次向 Redis 服务器发送一个命令,都需要等待命令执行完成并返回结果,这样会导致频繁的网络通信和服务器端的命令执行开销,降低系统的性能和吞吐量…...

深入浅出 -- 系统架构之分布式系统底层的一致性

在分布式领域里,一致性成为了炙手可热的名词,缓存、数据库、消息中间件、文件系统、业务系统……,各类分布式场景中都有它的身影,因此,想要更好的理解分布式系统,必须要理解“一致性”这个概念。 其实关于…...

idea Springboot 电影推荐系统LayUI框架开发协同过滤算法web结构java编程计算机网页

一、源码特点 springboot 电影推荐系统是一套完善的完整信息系统,结合mvc框架和LayUI框架完成本系统springboot dao bean 采用协同过滤算法进行推荐 ,对理解JSP java编程开发语言有帮助系统采用springboot框架(MVC模式开发)&…...

xss【2】

1.xss钓鱼 钓鱼攻击利用页面,fish.php黑客钓鱼获取到账号密码存储的位置 xss进行键盘记录 2.xss常规防范 3.xss验证payload XSS(跨站攻击)_details/open/ontoggle-CSDN博客...

时序分解 | Matlab实现GSWOA-VMD改进鲸鱼优化算法优化变分模态分解时间序列信号分解

时序分解 | Matlab实现GWO-CEEMDAN基于灰狼算法优化CEEMDAN时间序列信号分解 目录 时序分解 | Matlab实现GWO-CEEMDAN基于灰狼算法优化CEEMDAN时间序列信号分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现GSWOA-VMD改进鲸鱼优化算法优化变分模态分解时间序…...

css- 4

1.浮动 1. 浮动最初用于实现文字环绕效果 2. 现在,浮动是主流的布局方式之一 1.1元素浮动之后的特点 元素浮动之后,称为浮动元素,具有如下特点: 1. 浮动元素脱离文档流 2. 多个浮动的元素会水平排列,一行放不下自动换…...

22.括号生成

题目描述 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 示例 1: 输入:n 3 输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”] 示例 2: 输入…...

JAVA八股--redis

JAVA八股--redis 如何保证Redis和数据库数据一致性redisson实现的分布式锁的主从一致性Redis脑裂现象及解决方案介绍I/O多路复用模型undo log 和 redo log(没掌握MyISAM 和 InnoDB 有什么区别? 如何保证Redis和数据库数据一致性 关于异步通知中消息队列…...

[图像处理] MFC载入图片并绘制ROI矩形

上一篇: [图像处理] MFC载入图片并进行二值化处理和灰度处理及其效果显示 文章目录 前言完整代码重要代码效果 前言 上一篇实现了MFC通过Picture控件载入图片。 这一篇实现ROI功能的第一部分,在Picture控件中,通过鼠标拖拽画出一个矩形。 完…...

Godot 4 教程《勇者传说》依赖注入 学习笔记(0):环境配置

文章目录 前言相关地址环境配置初始化环境配置文件夹结构代码结构代码运行 资源文件导入像素风格窗口环境设置背景设置,Tileap使用自动TileMap 人物场景动画节点添加站立节点添加移动动画添加 通过依赖注入获取Godot的全局属性项目声明 当前项目逻辑讲解角色下降添加代码位置问…...

强行让Java和Go对比一波[持续更新]

概述 很多Java开发如果想转Golang的话,比较让Java开发蛋疼的第一是语法,第二是一些思想和设计哲学的Gap,所以我这儿强行整理一波Java和Golang的对比,但是由于GO和Java在很多方面都有不同的设计,所以这些对比的项可以更…...

理解七层网络协议

osi体系结构 上三路(管数据) 应用层 通过http等,把传输的格式,数据打包 处理网络应用。直接为端用户服务,提供各类应用过程的接口和用户接口。例如:HTTP、Tenlent、FTP、SMTP、NFS等。基于TCP的FTP、HTTP…...

网络协议——HTTP协议

目录 ​编辑 一,HTTP协议基本认识 二,认识URL 三,http协议的格式 1,发送格式 2,回应格式 四,服务端代码 五,http报文细节 1,Post与Get方法 2,Content_lenth 3&…...

八股面试——数据库——索引

索引的概念 B树的概念: 索引的作用 聚簇索引与非聚簇索引 聚簇索引就是主键值,在B树上,通过主键大小(数据在B树叶子节点按主键顺序排序)寻找对应的叶子节点,叶子节点保存的一整条记录。 非聚簇索引&#x…...

【二分查找】Leetcode 二分查找

题目解析 二分查找在数组有序可以使用,也可以在数组无序的时候使用(只要数组中的一些规律适用于二分即可) 704. 二分查找 算法讲解 当left > right的时候,我们循环结束,但是当left和right缩成一个点的时候&#x…...

Python+Vuecil笔记

Nginx 进入目录: C:\nginx-1.20.2\nginx-1.20.2 start nginx 开始 nginx -s stop 停止 nginx -s quit 退出CSS 通过标签去写css 循环展示数据 JS 点击时执行事件 Django 配置media 在seetings里面修改 STATIC_URL /static/ MEDIA_URL /upload/ MEDIA_ROOT os.pat…...

C语言关于随机数知识点的总结

在C语言中&#xff0c;随机数的生成通常依赖于特定的库函数&#xff0c;最常用的是 <stdlib.h> 头文件中的 rand() 函数。以下是对随机数知识点的总结、举例和分析&#xff1a; 随机数知识点总结 1.随机数种子&#xff1a;rand() 函数生成的随机数是伪随机数&#xff0…...

网络应用层和传输层

网络中有很多协议这些协议的不同导致了分层这一现象&#xff0c;不同层的主要功能不一样。 应用层&#xff1a;应用程序。数据具体如何使用 传输层&#xff1a;关注起点和终点 网络层&#xff1a;关注路径规划 数据链路层&#xff1a;关注相邻节点的转发 物理层&#xff1…...

Vue3:优化-从响应式数据中获取纯数据

一、情景说明 我们知道&#xff0c;Vue3中&#xff0c;创建变量时&#xff0c;常用ref、reactive来包裹&#xff0c;这样&#xff0c;这个变量就是响应式数据 然而&#xff0c;有时候&#xff0c;我们只需要纯数据 例如&#xff0c;我们在调用后端接口的时候&#xff0c;我们只…...

C#.手术麻醉系统源码 手麻系统如何与医院信息系统进行集成?

C#.手术麻醉系统源码 手麻系统如何与医院信息系统进行集成&#xff1f; 手术麻醉系统与医院信息系统的集成是一个关键步骤&#xff0c;它有助于实现信息的共享和流程的协同&#xff0c;从而提高医疗服务的效率和质量。手麻系统与lis、his、pacs等系统的对接是医院信息化建设的重…...

学习CSS Flexbox 玩flexboxfroggy flexboxfroggy1-24关详解

欢迎来到Flexbox Froggy&#xff0c;这是一个通过编写CSS代码来帮助Froggy和朋友的游戏! justify-content 和 align-items 是两个用于控制 CSS Flexbox 布局的属性。 justify-content&#xff1a;该属性用于控制 Flexbox 容器中子项目在主轴&#xff08;水平方向&#xff09;…...

springboot项目如何配置跨域?

在Spring Boot项目中配置跨域&#xff08;CORS&#xff0c;Cross-Origin Resource Sharing&#xff09;主要是为了允许来自不同源&#xff08;不同的协议、域名或端口&#xff09;的前端应用能够访问后端API。Spring Boot提供了多种方式来配置跨域支持。 1. 使用CrossOrigin注…...

实现第一个动态链接库 游戏插件 成功在主程序中运行 dll 中定义的类

devc 5.11编译环境 dll编译环境设置参考 Dev c C语言实现第一个 dll 动态链接库 创建与调用-CSDN博客 插件 DLL代码和主程序代码如下 注意 dll 代码中的class 类名需要 和主程序 相同 其中使用了函数指针和强制类型转换 函数指针教程参考 以动态库链接库 .dll 探索结构体…...

算法第三十九天-验证二叉树的前序序列化

验证二叉树的前序序列化 题目要求 解题思路 方法一&#xff1a;栈 栈的思路是「自底向上」的想法。下面要结合本题是「前序遍历」这个重要特点。 我们知道「前序遍历」是按照「根节点-左子树-右子树」的顺序遍历的&#xff0c;只有当根节点的所有左子树遍历完成之后&#xf…...

Rust---复合数据类型之字符串与切片(2)

目录 字符串操作删除 (Delete)连接 (Concatenate)字符串转义前情回顾: Rust—复合数据类型之字符串(1) 字符串操作 删除 (Delete) 删除方法仅适用于 String 类型,分别是: pop(),remove(),truncate(),clear(),此外还有drain() 方法。 pop 方法:pop() 方法返回一个 O…...

iOS 应用内网络请求设置代理

主要通过URLSessionConfiguration 的connectionProxyDictionary 属性 为了方便其他同学使用&#xff0c;我们可以通过界面来进行设定&#xff08;是否开启代理、服务端、端口&#xff09;&#xff0c;从而达到类似系统上的设定 具体链接参考&#xff1a;为 iOS 网络请求设置代理…...

什么是MariaDB

2024年4月6日&#xff0c;周六晚上 今晚在Debian12上安装mysql时&#xff0c;运行后却发现是MariaDB MariaDB是一个开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它是MySQL的一个分支和替代品。MariaDB由MySQL的原始开发者之一Michael "Monty&qu…...

做国外购物的网站怎么发货/百度发视频步骤

高阶函数英文叫Higher-order function。什么是高阶函数&#xff1f;我们以实际代码为例子&#xff0c;一步一步深入概念。 变量可以指向函数 以Python内置的求绝对值的函数abs()为例&#xff0c;调用该函数用以下代码&#xff1a; 1 2 >>>abs(-10) 10 但是&#xff0c…...

基于php网站建设/抚州网站seo

今天看了Corotational模型的代码。 在Vega中&#xff0c;获得模型内力的方法是先构造一个ForceModel对象&#xff0c;再调用其对应方法。 对于Corotational模型&#xff0c;构造的流程为: 构造CorotationalLinearFEM -> 构造CorotationalLinearFEMForceModel 获取内力时&am…...

兰州网站推广排名/郑州seo公司

题意&#xff1a;易理解... 分析&#xff1a;容易看出可以用指数型母函数来求解&#xff0c;但是由于结果太大&#xff0c;然后题目要求求出后面两位即可&#xff0c;于是我就在想应该会有周期性&#xff0c;与之我就用母函数求出了前20的值&#xff0c; 经过观察确实是有规律的…...

简约网站设计/什么是网络营销

被测试的简单函数源文件位于 /klee_src/examples/get_sign 目录下 该源代码分为三个部分 第一个部分为被测试的函数 int get_sign(int x) {if (x 0)return 0;if (x < 0)return -1;elsereturn 1; } 第二个部分为主函数 int main() {int a;klee_make_symbolic(&a, size…...

wordpress 文章字体/cfa一级看多久两分钟

我有一个在经纬度网格上的数据集。我需要从这个数据集中选择一个近乎完美的“矩形”覆盖北美。某物&#xff0c;但位于北美上空&#xff1a;1。我如何选择纬度和经度&#xff1f;因为经度向两极靠拢&#xff0c;所以我需要更多的经度往北。在这是我的拙劣和可能不正确的尝试。我…...

农业科技公司网站案例/软文营销的五个步骤

注&#xff1a;刚刚看完了这篇论文&#xff0c;顺便整理了一下这篇论文的思路&#xff0c;还是得膜一下伟诗大佬&#xff0c;666 论文地址&#xff1a;Person Re-identification 论文解析 Matching people across nonoverlapping camera views at different locations and di…...