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

详解MySQL的事务实现机制

MySQL事务实现机制

  • 1. 锁机制
  • 2. Redo Log(重做日志)
  • 3. Undo Log(撤销日志)
  • 4. MVCC(多版本并发控制)
  • 综合事务处理流程

在MySQL中(主要以InnoDB为例),事务的实现依赖于多个机制协同工作,确保ACID特性(原子性、一致性、隔离性、持久性)

1. 锁机制

  • 行锁与表锁
    InnoDB主要采用行级锁,能够更细粒度地控制并发访问,降低锁冲突。表锁则在特定场景下使用(例如DDL操作或低并发环境)。

  • 共享锁(S锁)与排他锁(X锁)

    • 共享锁(S锁): 允许事务读数据但不修改,多个事务可以同时获取同一数据的共享锁。
    • 排他锁(X锁): 允许事务修改数据,同时排斥其他事务的读写操作。
  • 间隙锁和临键锁
    为了解决幻读问题,InnoDB在扫描范围内的数据时会加“间隙锁”(锁定两个值之间的间隙)以及“临键锁”(在索引记录上加锁)。这种称为“next-key locking”的机制可以防止其他事务在查询范围内插入新记录。

  • 作用
    锁机制保障了事务的隔离性,防止了脏读、不可重复读和幻读等并发问题。

2. Redo Log(重做日志)

  • 作用与原理
    Redo Log用于记录事务对数据所做的修改,并在事务提交前写入磁盘。它是预写日志的一部分:

    • 预写日志原则(Write-Ahead Logging): 修改操作先写Redo Log,再更新数据页,这样即使系统崩溃,也能根据Redo Log进行数据恢复,确保事务的持久性。
    • 顺序写入: Redo Log以顺序写入的方式记录日志,性能高且能降低磁盘I/O开销。
  • 恢复机制
    在系统崩溃后,利用Redo Log可以重做(Redo)未完成的操作,保证数据不会丢失。

3. Undo Log(撤销日志)

  • 作用与原理
    Undo Log记录数据在修改前的旧版本信息,主要用于:

    • 事务回滚: 如果事务执行过程中发生错误或用户选择回滚,Undo Log可以将数据恢复到修改前的状态,保证原子性。
    • 实现MVCC: Undo Log保存历史版本的数据记录,使得读操作可以访问事务开始前的数据版本,从而实现多版本并发控制(MVCC)。
  • 存储与管理
    Undo Log通常存储在独立的Undo Tablespace中,事务提交后,Undo Log不会立即删除,而是在一定条件下被清理或回收,以支持长事务的快照读。

4. MVCC(多版本并发控制)

  • 基本原理
    MVCC利用数据的多个版本来解决读写并发问题:

    • 每条记录内部通常包含两个隐藏列:创建时间戳和删除时间戳,用于判断记录的版本是否对当前事务可见。
    • 快照读: 读操作不加锁,通过Undo Log提供的历史版本读取事务开始时的数据状态,从而避免读写互相阻塞。
  • 实现优势

    • 提高并发性能: 由于大部分读操作无需等待锁释放,事务之间可以并发执行,极大地提升了系统的吞吐量。
    • 避免幻读: 配合Undo Log和时间戳,MVCC确保每个事务都能看到一致的数据快照,减少了锁竞争和等待。

综合事务处理流程

  1. 事务开始

    • 为事务分配一个唯一的事务ID,并记录开始时间戳。
  2. 数据修改

    • 写操作: 对于每次数据修改,InnoDB会先加相应的行锁(或间隙锁),然后在内存中记录变更,同时生成Redo Log和Undo Log记录。
    • 读操作: 采用MVCC机制读取数据,通过隐藏的时间戳和Undo Log,读取事务开始时的快照数据,不需要加锁,从而避免阻塞。
  3. 事务提交

    • 将Redo Log写入磁盘(保证持久性),事务标记为已提交。
    • 提交后,Undo Log中的旧版本信息可能延迟清理,用于支持其他正在执行的长事务读取旧数据。
  4. 事务回滚

    • 如果事务需要回滚,则利用Undo Log中的记录逐步恢复数据到原始状态,确保操作的原子性。

在 MySQL 的 InnoDB 存储引擎中,事务的实现主要依赖以下几个关键机制:

  1. 锁(Locking)

    • 行级锁与表级锁: InnoDB 默认使用行级锁,确保高并发下的事务隔离性,同时也支持表级锁以适应特殊场景。
    • 意向锁(Intention Locks): 为了快速判断行锁情况,InnoDB 会先设置意向锁,标识事务打算对某行加锁。
    • 锁粒度和锁冲突: 通过细粒度的行级锁,降低冲突概率,同时采用多种锁(如共享锁、排他锁、间隙锁等)来确保事务的一致性和隔离性。
  2. Redo Log(重做日志)

    • 目的: 用于实现持久性(Durability),即事务一旦提交,其修改可以在系统崩溃后恢复。
    • 写前日志(WAL): 在实际数据页修改前,先将修改记录写入内存中的 redo log 缓冲区,并周期性刷新到磁盘,确保数据修改的日志先于数据页写入磁盘。
    • 崩溃恢复: 当系统重启时,利用 redo log 重做(redo)未持久化的数据修改,以恢复事务的提交状态。
  3. Undo Log(撤销日志)

    • 目的: 用于实现原子性(Atomicity)和事务的回滚。
    • 存储修改前数据: 在数据修改前,会将原始数据记录到 undo log 中,万一事务需要回滚,系统可利用 undo log 恢复数据到修改前的状态。
    • MVCC 的支持: Undo log 同时为多版本并发控制(MVCC)提供数据快照支持,使得读操作能够看到一致性的历史版本数据。
  4. MVCC(多版本并发控制)

    • 实现机制: 利用数据行的隐藏列(如事务ID和回滚指针)和 undo log,实现数据版本的管理。
    • 读写分离: MVCC 允许读取旧版本数据,从而避免读操作与写操作直接冲突,提高并发性能。
    • 快照隔离: 通过在查询时根据当前事务的快照来决定哪些数据版本对该事务可见,确保数据的一致性。

相关文章:

详解MySQL的事务实现机制

MySQL事务实现机制 1. 锁机制2. Redo Log(重做日志)3. Undo Log(撤销日志)4. MVCC(多版本并发控制)综合事务处理流程 在MySQL中(主要以InnoDB为例),事务的实现依赖于多个…...

什么是 BA ?BA怎么样?BA和BI是什么关系?

前几天有朋友在评论区提到了BA这个角色,具体是干什么的,我大概来说一下。 什么是BA BA 英文的全称是Business Analyst,从字面上意思就是商业分析师,做过商业智能BI项目的应该比较了解。实际上以我个人的经验,BA 的角…...

Junit在测试过程中的使用方式,具体使用在项目测试中的重点说明

JUnit 是一个广泛使用的 Java 单元测试框架,主要用于编写和运行可重复的测试。以下是 JUnit 在项目测试中的使用方式和重点说明: 1. 基本使用 场景:测试一个简单的 Java 类。 示例: import org.junit.Test; import static org.junit.Assert.*;public class CalculatorTe…...

网络安全之前端学习(HTML篇)

前言:网络安全中有一个漏洞叫xss漏洞,就是利用网页引发弹窗,这就要求我们看得懂源码,所以我会持续更新前端学习,可以不精通,但是一定要会,主要掌握HTML,css,js这三项技术…...

Lineageos 22.1(Android 15)实现负一屏

一、前言 方案是参考的这位大佬的,大家可以去付费订阅支持一波。我大概理一下Android15的修改。 大佬的方案代码 二、Android15适配调整 1.bp调整,加入aidl引入,这样make之后就可以索引代码了 filegroup {name: "launcher-src"…...

Redisson分布式锁(超时释放及锁续期)

🍓 简介:java系列技术分享(👉持续更新中…🔥) 🍓 初衷:一起学习、一起进步、坚持不懈 🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏 🍓 希望这篇文章对你有所帮助,欢…...

SQL授予用户查询某个模式或者具体某个表

例如:需要给sjzt授权查询这个模式下的这个表的操作 数据库:DB_HZ_HYZHFZ 模式:hn_proxy 服务注册表:hn_proxy."serverrg" 账号:sjzt -- 登录到目标数据库 DB_HZ_HYZHFZ -- 授予权限给账号 sjzt 在模式 hn_proxy 中访问…...

Burp Suite 代理配置与网络通信

目录 1. 引言 2. Burp 代理基础配置 2.1 浏览器代理设置 2.2 Burp 监听端口配置 2.3 常见错误排查 3. 网络问题解决 3.1 端口占用检查 3.2 防火墙配置 3.3 证书信任问题 4. 虚拟机环境配置 4.1 NAT 模式与端口转发 4.2 桥接模式配置 4.3 跨设备访问测试 5. 技术概…...

PyCharm安装redis,python安装redis,PyCharm使用失败问题

报错信息 Usage: D:\wb2\wbrj_pys\venv\Scripts\python.exe -m pip install [options] [package-index-options] … D:\wb2\wbrj_pys\venv\Scripts\python.exe -m pip install [options] -r [package-index-options] … D:\wb2\wbrj_pys\venv\Scripts\python.exe -m pip instal…...

使用命令行工具控制wireshark对抓包文件进行针对性处理的总结

近日,工作中有开发对抓包文件进行针对性过滤的小程序的需求,兜兜转转踩了很多坑后还是绕回了wireshark。 作为最出名的开源软件之一,wireshark也具有使用命令行进行操作的功能,这就是我们今天会总结到的“tshark.exe”。 通常&a…...

【STM32实物】基于STM32的太阳能充电宝设计

基于STM32的太阳能充电宝设计 演示视频: 基于STM32的太阳能充电宝设计 硬件组成: 系统硬件包括主控 STM32F103C8T6、0.96 OLED 显示屏、蜂鸣器、电源自锁开关、温度传感器 DS18B20、继电器、5 V DC 升压模块 、TB4056、18650锂电池、9 V太阳能板、稳压降压 5 V三极管。 功能…...

NLP 与常见的nlp应用

自然语言处理(NLP)是一个广泛的领域,它不仅包括自然语言理解(NLU),还涉及一系列其他任务和子领域。以下是NLP领域中的主要组成部分及其相关任务: 1. 自然语言理解(NLU) …...

基于javaweb的SSM+Maven宠物领养宠物商城流浪动物管理系统与实现(源码+文档+部署讲解)

技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...

Java数据类型 Arrays VS ArraysList VS LikedList 解析

在学习Java过程中,在刷题时总是搞不清楚这三种数据结构的区别,打算写篇文章记录一下 Arrays VS ArrayList ArrayList VS LinkedList 总结 Arrays VS ArrayList ArraysArrayList类型Java的基本数据类型Java集合框架中的一个类,实现了List接…...

C++进阶(一)

个人主页:PingdiGuo_guo 收录专栏:C干货专栏 前言 本篇博客是讲解函数的重载以及引用的知识点的。 文章目录 前言 1.函数重载 1.1何为函数重载 1.2函数重载的作用 1.3函数重载的实现 2.引用 2.1何为引用 2.2定义引用 2.3引用特性 2.4常引用 2…...

Elasticsearch 在航空行业:数据管理的游戏规则改变者

作者:来自 Elastic Adam La Roche 数字化客户体验不再是奢侈品,而是欧洲航空公司必不可少的需求。它推动了客户满意度,提升了运营效率,并创造了可持续的竞争优势。随着行业的不断发展,优先投资前沿数字技术和平台的航空…...

Powershell WSL部署ubuntu22.04.5子系统

前提条件WSL 安装 wsl 安装参考1wsl 安装csdn参考2wsl 百度网盘离线下载 本地目录安装ubuntu22.04.5 子系统 powershell 管理员打开执行(实现,下载安装ubuntu子系统,用户创建,远程ssh登录设置,防火墙端口开放)子系统IP 查看方法wsl...

华为网路设备学习-16 虚拟路由器冗余协议(VRRP)

VRRP是针对干线上三层网络设备(如:路由器、防火墙等)的网络虚拟化技术,提供冗余和状态监测等功能。确保在网络中的单点故障发生时,能够快速切换到备份设备,从而保证网络通信的连续性和可靠性。‌ VRRP通过…...

SQLark中如何进行数据筛选与排序

本文将为你介绍在 SQLark 中如何进行数据筛选与排序,掌握这些操作能够极大提升你的工作效率。 SQLark官网链接:www.sqlark.com 数据筛选 在数据库操作中,数据筛选是一项关键功能,它依据特定条件对数据进行过滤,帮助用户从海量数据…...

slq-labs日志

上次写了第五关的布尔盲注,和双查询报错注入,还有其他报错注入的方法 一.extractvalue函数 extractvalue函数 原理 extractvalue 是一个在 XML 数据中提取值的 MySQL 内置函数。它的语法为: EXTRACTVALUE(xml, xpath_expr)xml 是 XML 字符…...

Webrtc编译官方示例实现视频通话

Webrtc编译官方示例实现视频通话 前言 webrtc官网demo中给了一个供我们学习和应用webrtc的一个很好的例子:peerconnection,这期我们就来编译和运行下这个程序看看视频通话的效果以。 1、打开源码工程 继上期源码编译完成后,我们使用vs打开…...

对接SaToken @SaCheckEL 鉴权注解

对接SaToken SaCheckEL 鉴权注解 文章目录 对接SaToken SaCheckEL 鉴权注解前言一、引入插件和配置SaToken属性配置二、配置1.自定义SaTokenInterceptor并注入Bean2.WebMvcConfig配置SaTokenInterceptor,拦截所有请求路径 三、重载SaToken权限接口和方法注入SaCheck…...

【数据结构】顺序表(附源码)

数据结构之顺序表 1、线性表2、顺序表2.1 概念与结构2.2 顺序表的分类 3、动态顺序表3.1 结构3.2 初始化3.3 容量检查3.4 尾部插入数据3.5 删除尾部数据3.6 头部插入数据3.7 头部删除数据3.8 任意位置pos插入数据3.9 任意位置pos删除数据3.10 查找 4、动态顺序表实现的源码 1、…...

java使用Apache POI 操作word文档

项目背景: 当我们对一些word文档(该文档包含很多的标题比如 1.1 ,1.2 , 1.2.1.1, 1.2.2.3)当我们删除其中一项或者几项时,需要手动的对后续的进行补充。该功能主要是对标题进行自动的补充。 具…...

【Linux网络编程】网络基础

目录 1、OSI分层思想2、数据的封装3、ip地址ipv4的ip地址分类:为什么这样划分?举例 4、端口号5、tcp三次握手为什么需要三次握手?tcp连接的标识为什么 IP 地址不能单独标识一条连接? 6、tcp四次挥手为什么需要四次挥手为什么需要三…...

国内首家,百度智能云千帆AppBuilder全面兼容MCP协议

百度智能云千帆 AppBuilder 已兼容 MCP 协议!作为国内首家支持 MCP 协议的大模型应用开发平台(Claude、LangGraph、Cursor、Cline、N8N等海外平台已支持),千帆 AppBuilder 完成兼容后,用户可通过千帆 AppBuilder 轻松调…...

eclipse [jvm memory monitor] SHOW_MEMORY_MONITOR=true

eclipse虚拟机内存监控设置SHOW_MEMORY_MONITORtrue D:\eclipse-jee-oxygen-2-win32-x86_64\workspace\.metadata\.plugins\org.eclipse.core.runtime\.settings org.eclipse.ui.prefs (文件比较多,别找错了) SHOW_MEMORY_MONITORtrue 重启 -xms 1024…...

k8s中的组件

1.namespace Namespace 用于将集群资源划分为不同的逻辑组&#xff0c;方便管理和隔离 kubectl get namespace 查看所有逻辑组 kubectl describe namespace <namespace-name> 查看某个逻辑组信息详情 kubectl create namespace ... 创建逻辑组 kubectl delete names…...

单目3d detection算法记录

1、centernet object as points 这篇文章的核心单目3d检测主要是利用中心点直接回归出3d模型的所有属性&#xff0c;head共享整个backbone&#xff0c;其中3d属性包括&#xff1a;2d目标中心点、2dw和h、2d offsets、3doffsets、3d dimmession、rot还有depth。 其中对应的dep…...

vue3二次封装tooltip实现el-table中的show-overflow-tooltip效果

开发过程中遇到需要根据后端返回的数据长度来判断是否需要使用el-tooltip的情况&#xff0c;想到el-table里面就有这种交互效果&#xff0c;如果不论文字是否超出容器长度都展示tooltip的话&#xff0c;交互效果难免会差很多&#xff0c;所以二次封装了这个组件&#xff1a; 给…...

STM32八股【1】-----启动流程和startup文件理解

启动流程 知识点 MCU 上电复位。MSP从向量表第0个地址读取一个32位&#xff08;2字节&#xff09;的值并保存&#xff0c;该值为栈顶地址。PC计数器从第1个地址读取一个两字节的值并保存&#xff0c;该值为程序入口&#xff0c;一般是Reset_Handler。想了解FLASH地址映射可以…...

Go语言中package的使用规则《二》

在 Go 语言中&#xff0c;包&#xff08;Package&#xff09; 是代码组织和复用的核心单元。以下是其定义、引用规则及使用习惯的详细说明&#xff1a; 一、包的定义规则 目录与包名 一个包对应一个目录&#xff08;文件夹&#xff09;&#xff0c;目录名通常与包名一致。 包名…...

初级:控制流程面试题精讲

一、引言 在Java开发中&#xff0c;控制流程语句是构建程序逻辑的基础。面试官通过相关问题考察候选人对if-else、switch、循环等语句的理解和运用能力&#xff0c;以及在复杂业务场景下合理选择控制流程语句的水平。本文将深入剖析常见的控制流程面试题&#xff0c;结合实际开…...

HTTP 失败重试(重发)方案

在 Qt 网络开发中&#xff0c;使用 QNetworkAccessManager 进行 HTTP 请求时&#xff0c;可能会遇到网络超时、服务器错误等情况。为了提高请求的可靠性&#xff0c;可以实现 HTTP 失败重试&#xff08;重发&#xff09; 机制。下面介绍几种常见的 失败重发方案&#xff1a; 单…...

TNNLS 2024 | 基于残差超密集网络的高光谱图像空间光谱融合方法

A Spatio-Spectral Fusion Method for Hyperspectral Images Using Residual Hyper-Dense Network IEEE Transactions on Neural Networks and Learning Systems 2024 这篇文章的研究背景是针对高光谱图像&#xff08;HS&#xff09;与全色图像&#xff08;PAN&#xff09;的…...

深入探究 JVM 堆的垃圾回收机制(二)— 回收

GC Roots 枚举需要遍历整个应用程序的上下文&#xff0c;而在进行可达性分析或者垃圾回收时&#xff0c;如果我们还是进行全堆扫描及收集&#xff0c;那么会非常耗时。JVM 将堆分为新生代及老生代&#xff0c;它们的回收频率及算法不一样。 1 回收算法 在进行可达性分析时&am…...

【ELK】节省存储 之 压缩存储方式调整

目录 集群版本&#xff1a; 7.17.6 解释几个概念&#xff1a; 段&#xff08;Segment&#xff09; 合并(Merge) 索引设置&#xff1a; 压缩方式(index.codec)&#xff1a; 测试设置前提条件 对比 在创建的时候指定压缩类型&#xff08;index.codec&#xff09; 对比 在…...

MATLAB 控制系统设计与仿真 - 26

状态空间控制系统概述 状态空间描述 现代控制理论是建立在状态空间基础上的控制系统分析和设计理论&#xff0c;它用状态变量来刻画系统的内部特征&#xff0c;用‘一节微分方程组’来描述系统的动态特性。系统的状态空间模型描述了系统输入/输出与内部状态之间的关系&#x…...

下载与快速上手 NVM:Node.js 版本管理工具

一、准备工作&#xff1a;卸载旧版 Node.js 重要提示&#xff1a;在安装 NVM 前&#xff0c;请先彻底删除已安装的 Node.js&#xff0c;避免路径冲突&#xff1a; 检查安装路径 bash where node常见路径&#xff1a; C:\Program Files\nodejs\C:\Users\用户名\AppData\Local\n…...

SQL Server Management Studio(SSMS)安装教程

目录 一、SSMS的下载 二、SSMS 的安装 三、连接服务器 四、卸载 SSMS 一、SSMS的下载 1.进入 SQL Server Management Studio 官方下载页面&#xff1a;SQL Server Management Studio点击进入下载页面 2.点击链接开始下载&#xff0c;浏览器右上角会显示下载进度&#xff1b;…...

运维知识:Linux下Vim编辑器使用详解

运维知识&#xff1a;Linux下Vim编辑器使用详解 引言 在Linux的世界里&#xff0c;Vim不仅仅是一个文本编辑器&#xff0c;更是程序员的「瑞士军刀」。从1991年Bram Moolenaar发布第一个版本至今&#xff0c;Vim以其高效的模态编辑、高度可定制性和跨平台兼容性&#xff0c;成…...

复习HCIA

一、网络基础概念 1. OSI七层模型与TCP/IP四层模型 OSI七层模型详解&#xff1a; 物理层&#xff08;Physical Layer&#xff09;&#xff1a; 功能&#xff1a;传输原始比特流&#xff08;0/1&#xff09;&#xff0c;定义电气、机械特性&#xff08;如电压、线缆类型&#…...

在QT中进行控件提升操作

目录 一、概述 二、功能需求 三、提升操作 1&#xff09;拖入标准控件 2&#xff09;自定义类 3&#xff09;提升控件 一、概述 QT中提供的标准控件能够满足我们大多数情况下的功能需求&#xff0c;但是在一些特殊应用场合&#xff0c;我们可能需要对控件的功能进行扩展&am…...

Linux下JDK1.8安装配置

目录 1.下载完上传到Linux系统中 2.解压JDK压缩包 3.配置JDK环境变量 4.设置环境变量生效 5.查看环境变量是否配置成功 官网下载地址:Java Downloads | Oracle 1.下载完上传到Linux系统中 2.解压JDK压缩包 tar -zxvf jdk-8u151-linux-x64.tar.gz -C /usr/local (解压…...

JVM 知识点梳理

JDK 、JRE、JVM JDK&#xff08; Java Development Kit &#xff09; Java开发工具包 JRE 开发命令工具&#xff08;运行java.exe、编译javac.exe、javaw.exe&#xff09; JRE&#xff08; Java Runtime Environment &#xff09;Java运行环境 JVM Java核心类库&#xff08;l…...

求职招聘网站源码,找工作招工系统,支持H5和各种小程序

招聘找活招工平台系统源码 招聘求职找工作软件 发布信息积分充值招聘系统,里面带纤细教程 功能介绍: 招工小程序主要针对工地招工工人找工作,工地可以发布招工信息,工人可以发布找活信息,招工信息可以置顶,置顶需要积分,积分可以通过签到、分享邀请好友、充值获取,后…...

拓展 Coco AI 功能 - 智能检索 Hexo 博客

在之前的文章中&#xff0c;我们成功让 Coco AI 检索 Hugo 博客&#xff0c;这对于博客作者来说是一大福音。然而&#xff0c;从 Hexo 迁移到 Hugo 的成本不容小觑&#xff0c;毕竟大多数开发者对 Node.js 更熟悉&#xff0c;而 Golang 相对陌生。那么&#xff0c;既然 Coco AI…...

深入解析 Java Stream API:从 List 到 Map 的优雅转换!!!

&#x1f680; 深入解析 Java Stream API&#xff1a;从 List 到 Map 的优雅转换 &#x1f527; 大家好&#xff01;&#x1f44b; 今天我们来聊聊 Java 8 中一个非常常见的操作&#xff1a;使用 Stream API 将 List 转换为 Map。&#x1f389; 具体来说&#xff0c;我们将深入…...

【一起学Rust | Tauri2.0框架】基于 Rust 与 Tauri 2.0 框架实现全局状态管理

前言 在现代应用程序开发中&#xff0c;状态管理是构建复杂且可维护应用的关键。随着应用程序规模的增长&#xff0c;组件之间共享和同步状态变得越来越具有挑战性。如果处理不当&#xff0c;状态管理可能会导致代码混乱、难以调试&#xff0c;并最终影响应用程序的性能和可扩…...

金桔网桥路由版3

上一集我们讲到了二层云交换机&#xff0c;我把在云上搭建的桥接模式的VPN服务器称为二层云交换机。 那么现在我家到办公室的网络结构就变成这样的&#xff0c; 这样的好处就是我的电视盒子通过网线看电视&#xff0c;走的是OpenWrt路由器通过二层云交换机由办公室的OpenWrt路由…...