【MySQL 数据宝典】【事务&锁】- 002 事务控制的演进

c++多线程(1)------创建和管理线程td::thread std::thread 是 C++11 标准库中用于创建和管理线程的核心类,定义在 <thread> 头文件中。它使得多线程编程变得简单、类型安全且跨平台。 阅读详情

一、事务处理思路

1.1 排队

排队处理是事务管理最简单的方法,就是完全顺序执行所有事务的数据库操作,不需要加锁,简单的说就是全局排队。序列化执行所有的事务单元,数据库某个时刻只处理一个事务操作,特点是强一致性,处理性能低。
image.png

1.2 排它锁

引入锁之后就可以支持并发处理事务,如果事务之间涉及到相同的数据项时,会使用排他锁,或叫互斥锁,先进入的事务独占数据项以后,其他事务被阻塞,等待前面的事务释放锁。
image.png

1.3 读写锁

读和写操作:读读、写写、读写、写读。
读写锁就是进一步细化锁的颗粒度,区分读操作和写操作,让读和读之间不加锁,这样下面的两个事务就可以同时被执行了。
image.png
读写锁,可以让读和读并行,而读和写、写和读、写和写这几种之间还是要加排他锁。

1.4 乐观锁

通过版本进行判断,MVCC 就是其中一种实现方式

二、 MVCC

2.1 基础概念

MVCC(Multi Version Concurrency Control)被称为多版本控制,是指在数据库中为了实现高并发的数据访问,对数据进行多版本处理,并通过事务的可见性来保证事务能看到自己应该看到的数据版本。
MVCC最大的好处是读不加锁,读写不冲突。在读多写少的系统应用中,读写不冲突是非常重要的,极大的提升系统的并发性能,这也是为什么现阶段几乎所有的关系型数据库都支持 MVCC 的原因,不过目前MVCC只在** Read Commited** 和 **Repeatable Read **两种隔离级别下工作。

2.2 Undo Log 多版本链

在前面我们介绍过,每条数据都有两个隐藏的字段,事务 Id (trx_id),回滚指针 (roll_pointer)

  • trx_id : 记录最近一次更新这条数据的事务 Id
  • roll_pointer : 指向之前生成的 undo log

生成流程

image.png
接着又有一个事务B (trx_id=58) 过来,对同一条数据进行修改,将值改为B,事务B的id是58,在更新之前会生成一个undo log来记录之前的值.然后会让roll_pointer指向这个实际的undo log回滚日志:
image.png
如果再有一个事务C (trx_id=69) 继续更新该条记录值为C,则会跟第二步的步骤一样
image.png
总结: 每一条数据都有多个版本,版本之间通过 undo log 链来进行连接
好处: 每个事务提交的时候一旦需要回滚操作,可以保证同一个事务只能读到比当前版本更早提交的值

2.3 Read View

核心解决问题: 需要判断一下版本链中的哪个版本是当前事务可见的
image.png
如上是一个 Read View 所存储的信息

  • m_ids :表示在生成 ReadView 时当前系统中活跃的读写事务的 事务id 列表。
  • min_trx_id :表示在生成 ReadView 时当前系统中活跃的读写事务中最小的 事务id ,也就是 m_ids 中的最 小值。
  • creator_trx_id :表示生成该 ReadView 的事务的 事务id 。
  • max_trx_id :表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。

注意max_trx_id并不是m_ids中的最大值,事务id是递增分配的。比方说现在有id为1,2,3这三 个事务,之后id为3的事务提交了。那么一个新的读事务在生成ReadView时,m_ids就包括1和2,mi n_trx_id的值就是1,max_trx_id的值就是4。

我们前边说过,只有在对表中的记录做改动时(执行INSERT、DELETE、UPDATE这些语句时)才会 为事务分配事务id,否则在一个只读事务中的事务id值都默认为0。

核心流程

  1. 假设数据库有一行数据,很早就有事务操作过,事务id 是32. 此时两个事务并发过来执行了, 一个事务A (id=45),一个事务B (id=59). 事务A需要读取数据,而事务B需要更新数据,如下图:

image.png

如果不加任何限制,这里会出现脏读的情况,也就是一个事务可能会读到一个没有提交的值.

  1. 现在事务A直接开启一个ReadView,这个ReadView里的m_ids就包含了事务A和事务B的两个id,45和59,然后min_trx_id就是45,max_trx_id就是60. creator_trx_id就是45,是事务A自己。

image.png

  1. 此时事务A第一次查询这行数据,首先会判断一下当前这行数据的txr_id是否小于ReadView中的min_trx_id,此时发现txr_id=32,是小于ReadView里的min_trx_id就是45的,说明你事务开启之前,修改这行数据的事务已经提交了,所以此时可以查到这行数据,如下图所示:

image.png

  1. 接下来事务B开始操作该条数据,他把这行数据的值修改为了值B,然后将这行数据的txr_id设置为自己的id,也就是59,同时roll_pointer指向了修改之前生成的一个undo log,然后事务B提交,如下图所示

image.png

  1. 这时事务A再次执行了查询,但是却发现数据行里的txr_id=59
  • max_trx_id(60)>trxid (59) > mintrxid(45): 说明当前事务的数据是可能在自己同一时刻开启的
  • m_ids(45,59)包含了当前事务,说明就是同一时刻

所以当前记录无法查询
image.png

  1. 事务A根据roll_point顺着undo log版本链向下找,找到最近的一条undo log,trx_id是32。由于trx_id=32小于ReadView里的min_trx_id(45),说明这个undo log版本是在事务A开启之前就执行且提交的。因此,事务A可以查询最近的这个undo log里的值,这时undo log版本链的作用就体现出来了,它保存了一条快照链条,而事务A读取到的数据就是之前的快照数据。

image.png

Read View总结

  • 通过Read View判断记录的某个版本是否可见的方式总结:
    • trx_id = creator_trx_id
      如果被访问版本的trx_id,与readview中的creator_trx_id值相同,表明当前事务在访问自己修改过的记录,该版本可以被当前事务访问.
    • trx_id < min_trx_id
      如果被访问版本的trx_id,小于readview中的min_trx_id值,表明生成该版本的事务在当前事务生成readview前已经提交,该版本可以被当前事务访问.
    • trx_id >= max_trx_id
      如果被访问版本的trx_id,大于或等于readview中的max_trx_id值,表明生成该版本的事务在当前事务生成readview后才开启,该版本不可以被当前事务访问.
    • trx_id > min_trx_id && trx_id < max_trx_id
      如果被访问版本的trx_id,值在readview的min_trx_id和max_trx_id之间,就需要判断trx_id属性值是不是在m_ids列表中?
      • 在:说明创建readview时生成该版本的事务还是活跃的,该版本不可以被访问
    • 不在:说明创建readview时生成该版本的事务已经被提交,该版本可以被访问
  • 生成readview时机
    • RC隔离级别:每次读取数据前,都生成一个readview.
    • RR隔离级别:在第一次读取数据前,生成一个readview,之后read view不再更新.

2.4 MVCC 在 MySQL 中的具体实现

2.4.1 简介

MySQL中实现MVCC(多版本并发控制)的机制主要基于undo log多版本链和ReadView机制。下面是MySQL中MVCC的实现方式的详细说明:

2.4.2 数据表隐藏字段

MySQL为了实现MVCC,在每个表中添加了一些隐藏字段:

  • DATA_TRX_ID(6字节): 记录最新更新该行记录的事务ID,每个事务处理时会自动设置为当前事务ID。但值得注意的是,DATA_TRX_ID只有在事务提交之后才会更新。
  • DATA_ROLL_PTR(7字节): 一个rollback指针,指向当前行数据的上一个版本。通过这个指针将数据的多个版本连接在一起构成一个undo log版本链。
  • DB_ROW_ID(6字节): 隐含的自增ID,用来唯一标识每一行的字段。
  • DELETE BIT位: 标识当前记录是否被删除,实际上并不是真正的删除数据,而是一个标志。真正的删除操作是在事务提交的时候执行。

2.4.3 场景示例

查询 SELECT
  1. 在查询时,InnoDB只查找版本早于当前事务版本的数据行,即数据行的版本必须小于等于当前事务的版本。这确保当前事务读取的行都是事务之前已经存在的,或者是由当前事务创建或修改的行。
  2. 对于被删除的行,其删除操作的版本一定是未定义的或者大于当前事务的版本号,这意味着在当前事务开始之前,行没有被删除。只有符合以上两点,才会返回查询结果。
删除 DELETE
  • 删除操作会修改DATA_TRX_ID的值为当前执行删除操作的事务ID,并将DELETE BIT设置为True,表示被删除。
增加 INSERT
  • 新记录的DATA_TRX_ID会被设置为当前事务ID。
修改 UPDATE
  • 修改操作会使用排它锁锁定该行,以保证写操作的一致性。
  • 同时,会记录redo log,将更新之后的数据记录到redo log中,以便日后使用。
  • 也会记录undo log,将更新之前的数据记录到undo log中,以便回滚操作。

2.4.4 总结

通过undo log多版本链和ReadView机制的结合,MySQL实现了MVCC机制,确保了数据库在并发操作下的一致性和隔离性。

三、MVCC 读操作分类

在 MVCC 并发控制中,读操作可以分为两类: 快照读(Snapshot Read)与当前读 (Current Read)。

  • 快照读
    快照读是指读取数据时不是读取最新版本的数据,而是基于历史版本读取的一个快照信息(mysql读取undo log历史版本) ,快照读可以使普通的SELECT 读取数据时不用对表数据进行加锁,从而解决了因为对数据库表的加锁而导致的两个如下问题
    1. 解决了因加锁导致的修改数据时无法对数据读取问题.
    2. 解决了因加锁导致读取数据时无法对数据进行修改的问题.
  • 当前读
    当前读是读取的数据库最新的数据,当前读和快照读不同,因为要读取最新的数据而且要保证事务的隔离性,所以当前读是需要对数据进行加锁的
    • Update delete insert select ....lock in share mode
    • select for update 为当前读

MVCC已经实现了读读、读写、写读并发处理,如果想进一步解决写写冲突,可以采用下面两种方案:

  • 乐观锁
  • 悲观锁
数据科学技术与应用【中国大学MOOC】:数据可视化_第五次作业_答案 数据科学技术与应用 数据可视化 第五次作业 答案 题目来源:中国大学MOOC-东华大学-宋晖等-数据科学技术与应用 1 ( 30分 ) 2012—2017年我国人均可支配收入为[1.47, 1.62, 1.78, 1.94, 2.38, 2.60](单位:万元)。按照要求绘制以下图形。 1)模仿例4-1和例4-3,绘制人均可支配收入折线图。用小矩形标记数据点,黑色虚线,用注解标注最高点,图标题为“Income chart”,设置坐标轴标题,最后将图形保存为JPG文件。 2)模仿例4-2,使用多个子图分别绘制 阅读详情

相关推荐

PCB工艺-SI9000使用教程

本文介绍了阻抗计算工具SI9000的使用方法,重点讲解了微带线与带状线的区别、共面阻抗概念及参考面选择。通过USB差分走线实例,详细说明了如何选择计算模型、填写参数并确定线宽线距。文章还提供了层叠设计资料和工厂常规阻抗表格作为参考,建议制板时标注需控阻抗的线路供板厂调整。最后简单提及了嘉立创阻抗计算工具作为备选方案。

weixin_50120208的博客 2023

MySQL建库建表操作学习笔记

SQL(Structured Query Language,结构化查询语言)是用于在关系型数据库上执行数据操作、数据检索以及数据维护的标准语言。:用于定义对数据库对象(库、表、列、索引)的操作,如 CREATE、DROP、ALTER、RENAME、TRUNCATE 等。保存可变长度的字符串(可包含字母、数字以及特殊字 符)。:用于定义对数据库记录的操作,如 INSERT、DELETE、UPDATE、SELECT 等。:用于定义对数据库、表、字段、用户的访问权限和安全级别,如 GRANT、REVOKE 等。

Eternitycai的博客 219

【FPGA】Robei EDA 的使用(7)—— Robei文件上板试验

#沐朝露兮以自华,觅大道兮以求成 我又滚过来了,研究了20多天RISCV,结果最后因为硬件问题导致无法在比赛中使用RISCV CPU,虽然已经临近比赛后期了,非常的崩溃,但是也没有什么办法。唉,一切不过是从头再来罢了。(写写博客舒缓我心中苦闷) ————————————————进入正文的分割线———————————————— 今天介绍一下如何利用 Robei EDA 生成文件,导入vivado中,综合下载到开发板里。拿我一个PWM控制舵机的代码为例。 Robei EDA设置 假设代码模块(model文件)经

Ninquelote的博客 2561

MySQL 单点详解(14)

给定一条 SQL,联合索引的列该怎么排呢?

2401_88601046的博客 343

不会ps,你也可以成为ps高手,最强傻瓜式人像一键磨皮美白瘦脸美妆PS插件

比如:美肤是用来去斑点的,如果效果不太理想,就加大百分比,反之就减小。瘦脸如果脸胖的就打开,正常的就关闭。所谓的一键调节,要不只能调节一种效果,要不就是个预设,然后让你自己再调。同时,该软件还加入了贴心的批量处理功能,能同时处理上千张照片,让您喝着茶也能将工作做完。、自动检测照片中的人脸,包括鼻子,嘴巴,耳朵,眼睛和眉毛。、依托强大的脸部识别功能,可以高效的对人物全身皮肤进行智能识别,处理,使肤质平滑、过渡均匀。,这是网上下载的模糊照片,经过简单处理,你可以发现,眼睛变的更亮,皮肤更白,眼袋消失。

心语家园 - www.xinyucn.cc 2896

S32DS3.5图形化配置实战:从零构建S32K144通信接口工程

本文详细介绍了如何使用S32DS3.5图形化配置工具从零构建S32K144通信接口工程。通过实战演示引脚配置、时钟树设置、SPI接口搭建等关键步骤,帮助开发者快速掌握NXP S32K系列开发技巧,提升嵌入式开发效率。特别针对S32DS3.5版本的新特性进行了深度解析,包括智能代码生成和调试优化方法。

weixin_26834815的博客 199

Flink SQL 连接器实战:MySQL Source、Flink CDC 与 JDBC Sink 全解析

提供有界流读取,适合批处理和维表场景,简单直接但无法感知变更。MySQL CDC提供无界流读取,通过「全量快照 + binlog 增量」的方式实现实时捕获,是实时数仓的核心入口,但需要 MySQL 侧正确配置 binlog 和权限。JDBC Sink负责结果回写,关键在于区分仅插入流和更新流,更新流必须依赖主键完成 upsert。掌握这三者的差异,本质上就是掌握了 Flink 中「有界与无界」「追加与更新」这两组最基本的语义。

2401_83857914的博客 421

NRF24L01学习操作教程(二)——NRF实现一对一,一对多通讯

以上内容详细介绍了,使用NRF24L01实现1对1单向通讯、1对1双向通讯、1对多双向通讯。

Joseph Wen的博客 7388

Mysql+Redis八股

慢查询是指对数据库的操作超过了 long_query_time 这个时间阈值,通常为10s,生产环境中可以自己设置。超过这个时间会被记录到慢查询日志。查询的数据量过大,会导致查询操作变慢。查询语句比较复杂,比如涉及到多个表的连接和子查询,可能导致查询变慢。索引失效的情况下,查询会退化成全表扫描,导致查询变慢。硬件资源不足,比如数据库服务器上同时运行了多个查询语句,这些语句之间竞争 cpu、内存等资源,导致服务器负载过高,查询变慢。确保开启了慢查询日志,运行语句,找到查询慢的 SQL 语句。

m0_73945675的博客 142

Android 以太网802.1x 配置

802.1X认证网络配置摘要:本文介绍了通过wpa_supplicant.conf文件配置802.1X企业网络认证的两种方法:PEAP-MSCHAPv2方式和TLS方式。PEAP方式需设置SSID、用户名、密码,可选择是否验证CA证书;TLS方式则需要配置客户端证书、私钥及CA证书路径。文件配置完成后需设置权限并重启设备。最后提出如何验证802.1X配置是否生效的问题,但未给出具体验证方法。该配置适用于需要802.1X认证的企业网络环境。

zhaoyufei133的博客 458

Windows10下RTABMAP+T265实现三维建图

win10+rtabmap+t265扫描地形

Suxiang1997的博客 3485

MySQL 的 REPEATABLE READ 到底能不能防幻读——从快照读、当前读到 Next-Key Lock

本文系统讲解 InnoDB 可重复读级别下的幻读问题:从三类读异常切入,剖析快照读依赖 MVCC、当前读依赖 Next-Key Lock 的双防线机制,用双会话实验复现幻读仍会出现的边界场景,并解释各数据库在幻读防护上行为分歧的根源。

大模型全栈工程师 · Thanks_ks 293

ldpc编解码器设计与仿真

计算校验节点到变量节点的消息 m_{c \to v}=2 \cdot atanh(\prod_{v’ \in N©\setminus v}tanh(\frac{m_{v’ \to c}}{2}))。计算变量节点到校验节点的消息 m_{v \to c}=L_{v,0}+\sum_{c’ \in M(v)\setminus c}m_{c’ \to v}。◦ 对于每个变量节点 v,计算最终 LLR 值 L_{v,f}=L_{v,0}+\sum_{c \in M(v)}m_{c \to v}。

youngerwang的博客 808

数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南

Oracle 提供了ORA_ROWSCN伪列(System Change Number),记录最后修改行的 SCN,类似 PostgreSQL 的xmin。实践中通常仍使用 version 字段方案,逻辑与 MySQL 完全相同。-- Oracle:通过 ORA_ROWSCN 实现乐观锁-- 更新时比对 SCN// 自定义注解// AOP 切面@Aspect@Component@Slf4jtry {

yjc_1111的专栏 393

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Docker 部署 WordPress+MySQL 高可用架构

点「安装 WordPress」

一直在努力学习的菜鸟 219

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

SQLite 是什么?和 MySQL、Redis 有什么区别,项目中应该怎么选?

SQLite 是轻量级嵌入式关系型数据库,无需独立服务,直接通过文件存储数据,适合本地工具、桌面应用、移动端离线数据及单机轻量业务。与 MySQL 相比,它部署简单但并发写入受限;与 Redis 不同,它支持完整 SQL 与事务,适用于结构化数据持久化。三者可协同使用:MySQL 处理核心业务,Redis 实现高速缓存与计数,SQLite 降低部署复杂度。选型应基于场景需求,而非技术偏好。

栈外手记|2018 年起深耕后端开发。跳出代码栈,分享技术、项目踩坑与行业思考,看见技术之外更多可能。 327

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex&trade;-M4F 内核的信息,请参见《Cortex&trade;-M4F 技术参考手册》。

MySQL 库表操作学习笔记

SQL(结构化查询语言)是关系型数据库标准语言,可以改库结构、设置权限、增删改查数据、维护数据库。

2403_89660238的博客 165

MySQL 8.0 双向主从复制故障修复与重建指南

MySQL 8.0 双向主从复制故障修复 SOP:XtraBackup 重建备用节点,解决 GTID 1236 / 历史日志冲突

「YYL DBA手记」 数据库 · 架构 · 运维 · 实战 yyldba.blog.youkuaiyun.com 290

MySQL 8.0停服了,信创替代的窗口正在关闭

最近跟几个做信创的朋友聊天,发现一个被忽略的问题。MySQL 8.0在今年4月正式停了官方支持,Oracle不再出安全补丁,bug也没人修了。但大量企业的业务系统还跑在上面。这事搁以前不算急,慢慢选就行了。但现在不行了,国资委79号文写得很清楚,2027年底前央国企核心系统得完成国产化替换。MySQL停服跟信创deadline撞在一起,留给MySQL用户做决定的时间不多了。我做过不少数据库迁移项目,MySQL替代这个事,坑比大多数人想的要多。今天聊几个我觉得最容易被忽视的点。

databasedb的博客 330

MySQL 的四种隔离级别

本文聚焦数据库事务隔离级别,阐述SQL标准的四个级别:读未提交(RU)、读已提交(RC)、可重复读(RR)、串行化(Serializable),按严格程度递增。核心观点为:隔离性通过加锁换取,级别越高,并发越差。重点解析脏读(读未提交)、不可重复读(读已提交)、幻读(可重复读)的本质及应对机制。指出MySQL默认使用RR,而Oracle/PostgreSQL默认为RC,迁移时需注意隔离级别差异。关键区别在于ReadView生成时机:RC每次查询刷新快照,RR仅首次SELECT时生成,确保事务内一致性。建议生

weixin_48269137的博客 250

MySQL:库与表的操作

本文系统讲解MySQL库的操作,涵盖创建、查看、修改、删除数据库及字符集、校验规则的配置与影响。重点说明CREATE DATABASE语法、字符集(如utf8mb4)与校验规则(如utf8_general_ci vs utf8_bin)对大小写敏感性和排序的影响。通过实例演示不同校验规则下查询与排序结果差异。同时介绍SHOW DATABASES、USE、ALTER DATABASE、DROP DATABASE等操作,并强调备份恢复(mysqldump)与连接状态监控(SHOW PROCESSLIST)的重要

2401_87306079的博客 311

MySQL 主从复制进阶(2026):GTID、复制延迟排查与故障切换

load 高到底是 CPU 还是 IO?free 的 available 才是关键。us/sy/wa 决策树 + iostat/sar/iftop 实战,CPU/内存/磁盘/网络四大瓶颈定位方法论。

2502_91473995的博客 181

Linux、Shell、MySQL 测试卷逐题细讲(下篇:MySQL)

本文为Linux、Shell、MySQL测试卷下半段MySQL部分逐题讲解,包含填空、选择与SQL分析三类题型。填空题覆盖COUNT、HAVING、DISTINCT、事务、约束、索引等核心语法;选择题辨析存储过程、索引类型、ACID、存储引擎、用户管理等考点。SQL大题围绕员工、部门、职位、地点四张关联表,考察多表连接、分组聚合、自连接、相关子查询、NULL处理等高频写法,标注LEFT JOIN统计计数、NULL判断、子查询别名等易错坑点,同时梳理试卷OCR识别带来的干扰问题,重点提示SQL实操中的常见失误

dongziwen1的博客 179

MySQL表的连接

内连接实际上就是利用 where 子句对两种表形成的笛卡儿积进行筛选,我们前面所学习的查询都是内连接,也是在开发过程中使用的最多的连接查询。案例:显示Smith的名字和部门名称。

wairuigood的博客 195

MySQL 为什么选择 B+ 树作为索引结构

B 树和 B+ 树都是多路平衡树,但 B+ 树在数据库场景下更有优势,主要体现在以下几个方面。对比对象主要问题B+ 树的优势二叉树 / 红黑树树高过大,I/O 次数多多路平衡,树高仅 3~4 层哈希表不支持范围查询、排序天然有序,支持范围与排序B 树节点存数据,扇出小;查询路径不一致非叶子只存键,扇出大;查询路径稳定B+ 树用更矮的树高减少磁盘 I/O,用有序的叶子链表支撑范围查询,用只存键的非叶子节点换取更大的扇出,是磁盘数据库索引场景下综合表现最优的选择。

2601_96129122的博客 315

任务4-1 了解MySQL的数据类型

本文梳理了MySQL数据类型:数值型涵盖整型与实型,金额首选DECIMAL;字符串型按长度与用途分为CHAR、VARCHAR、TEXT及BLOB;日期型包含DATE、TIME、DATETIME及TIMESTAMP;特殊类型有ENUM、JSON等。掌握类型特性是高效建表的基础。

howard2005的专栏 138
上一篇: 【MySQL 数据宝典】【事务&锁】- 001 ACID特性介绍
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值