参考指南:MySQL & MariaDB Online DDL

MySQL教程栏目介绍指导MySQL & MariaDB Online DDL

图文无关

概述

在早期的 MySQL 版本中,DDL 操作(如创建索引等)通常都需要对数据表加锁,操作过程中 DML 操作都会被阻塞,影响正常业务。MySQL 5.6 和 MariaDB 10.0 开始支持  Online  DDL,可以在执行 DDL 操作的同时,不影响 DML 的正常执行,线上直接执行 DDL 操作对用户基本无感知(部分操作对性能有影响)。

不同版本的数据库对各种 DDL 语句的支持存在一定的差异,本文将会针对 MySQL 和 MariaDB 对 Online DDL 的支持情况做一个汇总,在需要执行 DDL 操作时,可以参考本文的 Online DDL 支持情况 部分。

本文将会持续修正和更新,最新内容请参考我的 GITHUB 上的 程序猿成长计划 项目,欢迎 Star,更多精彩内容请 follow me。

ALTER TABLE 语句中,支持通过 ALGORITHMLOCK 语句来实现 Online  DDL:

ALGORITHM –  控制 DDL 操作如何执行,使用哪个算法LOCK – 控制在执行 DDL 时允许对表加锁的级别

ALTER TABLE tab ADD COLUMN c varchar(50), ALGORITHM=INPLACE, LOCK=NONE;复制代码

ALGORITHM 支持的算法

ALGORITHM 说明

DEFAULT默认算法,自动使用可用的最高效的算法COPY最原始的方式,所有的存储引擎都支持,不使用 Online DDL,操作时会创建临时表,执行全表拷贝和重建,过程中会写入 Redo Log 和大量的 Undo Log,需要添加读锁,非常低效INPLACE尽可能避免表拷贝和重建,更确切的名字应该是 ENGINE 算法,由存储引擎决定如何实现,有些操作是可以立即生效的(比如重命名列,改变列的默认值等),但有些操作依然需要全表或者部分表的拷贝和重建(比如添加删除列、添加主键、改变列为 NULL 等)NOCOPY该算法是 INPLACE 算法的子集,用于避免聚簇索引(主键索引)的重建造成全表重建,也就说用该算法会禁止任何引起聚簇索引重建的操作INSTANT用于避免 INPLACE 算法在需要修改数据文件时异常低效的问题,所有涉及到表拷贝和重建的操作都会被禁止

NOCOPY 算法支持:MariaDB 10.3.2+,MySQL 不支持该算法。INSTANT 算法支持:MariaDB 10.3.2+,MySQL 8.0.12+。

算法使用规则:

如果用户指定的算法为 COPY,则 InnoDB 使用 COPY 算法。如果用户指定的是 COPY 之外的其它算法,则 InnoDB 会按照算法效率,选择最高效的算法,最差的情况下采用用户指定的算法。比如用户指定了 ALOGRITHM = NOCOPY,则 InnoDB 会从 (NOCOPY, INSTANT) 中选择支持的最高效的算法。

ALGORITHM 优劣

MySQL 服务主要为 Server 层存储引擎层 两部分组成,Server 层包含了 MySQL 大部分核心功能,所有的内置函数,跨存储引擎的功能如存储过程、触发器、视图等。存储引擎层负责数据的存储和读取,采用了插件式的架构模式。

COPY 算法 作用在 Server 层,其执行过程都是在 Server 层,因此所有存储引擎都支持使用该算法,执行过程如下图

COPY算法执行过程

INPLACE 算法 作用于存储引擎层,是 InnoDB 存储引擎特有的 DDL 算法,执行过程如下图所示

INPLACE 算法执行过程

LOCK 策略

默认情况下,MySQL/MariaDB 在执行 DDL 期间会使用尽可能少的锁,如果必要,可以通过 LOCK 子句控制在执行 DDL 时允许对表加锁的级别。如果指定的操作所要求的限制级别不满足(EXCLUSIVE > SHARED > NONE),则语句执行失败并报错。

策略 说明

DEFAULT使用当前操作支持的粒度最小的锁策略NONE不获取任何表锁,允许所有的 DML 操作SHARED对表添加共享锁(读锁),只允许只读的 DML 操作EXCLUSIVE对表添加排它锁(写锁),不允许任何 DML 操作

为了避免执行 DDL 时,由于锁表导致生产服务不可用,在执行表结构变更语句时,可以添加 LOCK=NONE 子句,如果语句需要获取共享锁或者排它锁,则会直接报错,这样就可以避免意外锁表,造成线上服务不可用了。

Online DDL 执行过程

Online  DDL 操作主要分为三个阶段:

Online DDL 执行过程

阶段 1:初始化

在初始化阶段,服务器会根据存储引擎的能力,操作的语句和用户指定的 ALGORITHMLOCK 选项来决定允许多大程度的并发。在这个阶段会创建一个 可升级的元数据共享锁(SU)来保护表定义。

阶段 2:执行

这个阶段会 准备执行 DDL 语句,根据 阶段 1 评估的结果来决定是否将元数据锁升级为 排它锁 (X),如果需要升级为排它锁,则只在 DDL 的 准备阶段 短暂的添加排它锁。

阶段 3:提交表定义

在表定义的提交阶段,元数据锁会升级为排它锁来更新表的定义。独占排它锁的持续时间非常短。

元数据锁(MDL,Metadata Lock)主要用于 DDL 和 DML 操作之间的并发访问控制,保护表结构(表定义)的一致,保证读写的正确性。MDL 不需要显式的使用,在访问表时会自动加上。

MDL

由于上面三个阶段中对元数据锁的独占,  Online  DDL 过程必须等待已经持有元数据锁的并发事务提交或者回滚才能继续执行。

注意:当  Online  DDL 操作正在等待元数据锁时,该元数据锁会处于挂起状态,后续的所有事务都会被阻塞。在 MariaDB 10.3 之后,可以通过添加 NO WAIT 或者 WAIT n 来控制等待所得超时时间,超时立即失败。

ALTER TABLE tbl_name [WAIT n|NOWAIT] ...CREATE ... INDEX ON tbl_name (index_col_name, ...) [WAIT n|NOWAIT] ...DROP INDEX ... [WAIT n|NOWAIT]DROP TABLE tbl_name [WAIT n|NOWAIT] ...LOCK TABLE ... [WAIT n|NOWAIT]OPTIMIZE TABLE tbl_name [WAIT n|NOWAIT]RENAME TABLE tbl_name [WAIT n|NOWAIT] ...SELECT ... FOR UPDATE [WAIT n|NOWAIT]SELECT ... LOCK IN SHARE MODE [WAIT n|NOWAIT]TRUNCATE TABLE tbl_name [WAIT n|NOWAIT]复制代码

评估 Online DDL 操作的性能

Online DDL 操作的性能取决于是否发生了表的重建。在对大表执行 DDL 操作之前,为了避免影响正常业务操作,最好是先评估一下 DDL 语句的性能再选择如何操作。

复制表结构,创建一个新的表在新创建的表中插入少量数据在新表上面执行 DDL 操作检查执行操作后返回的 rows affected 是否是 0。如果该值非 0,则意味着需要拷贝表数据,此时对 DDL 的上线需要慎重考虑,周密计划

比如

Revid AI Revid AI

AI短视频生成平台

Revid AI 96 查看详情 Revid AI

修改某一列的默认值(快速,不会影响到表数据)

Query OK, 0 rows affected (0.07 sec)复制代码

添加索引(需要花费一些时间,但是 0 rows affected 说明没有发生表拷贝)

Query OK, 0 rows affected (21.42 sec)复制代码

修改列的数据类型(需要花费很长时间,并且重建表)

Query OK, 1671168 rows affected (1 min 35.54 sec)复制代码

由于在执行  Online  DDL 过程中需要记录并发执行的 DML 操作发生的变更,然后在执行完 DDL 操作之后再应用这些变更,因此使用  Online  DDL 操作花费的时间比不使用 Online 模式执行要更长一些。

Online  DDL 支持情况

INSTANT 算法支持:MariaDB 10.3.2+,MySQL 8.0.12+。NOCOPY 只支持 MariaDB 10.3.2 以上版本,不支持 MySQL,这里就暂且忽略了。

重点关注是否 重建表支持并发 DML:不需要重建表,支持并发 DML 最佳。

Online DDL Select Path

二级索引

操作 INSTANT INPLACE 重建表 并发 DML 只修改元数据

创建或者添加二级索引❌✅❌✅❌删除索引❌✅❌✅✅重命名索引 (⚠️MySQL 5.7+,MariaDB 10.5.2+)❌✅❌✅✅添加 FULLTEXT 索引❌✅ ①❌ ①❌❌添加 SPATIAL 索引(⚠️MySQL 5.7+,MariaDB 10.2.2+)❌✅❌❌❌修改索引类型✅✅❌✅✅

说明:

① 第一次添加全文索引字段时需要重建表,之后就不需要了

主键

操作 INSTANT INPLACE 重建表 并发 DML 只修改元数据

添加主键❌✅ ②✅ ②✅❌删除主键❌❌✅❌❌删除一个主键同时添加一个新的❌✅✅✅❌

说明:

重建聚簇索引总是需要拷贝表数据(InnoDB 是“索引组织表”),所以最好是在创建表的时候就定义好主键如果创建表是没有指定主键,InnoDB 会选择第一个 NOT NULLUNIQUE 索引作为主键,或者使用系统生成的 KEY② 对聚簇索引来说,使用 INPLACE 模式比 COPY 模式要高效一些:不会产生 undo logredo log,二级索引是有序的,所以可以按顺序加载,不需要使用变更缓冲区

普通列

操作 INSTANT INPLACE 重建表 并发 DML 只修改元数据

列添加✅ ③✅❌ ③✅ ③❌列删除❌ ④✅✅✅❌列重命名❌✅❌✅ ⑤✅改变列的顺序❌ ⑫✅✅✅❌设置默认值✅✅❌✅✅修改数据类型❌❌✅❌❌扩展 VARCHAR 长度(⚠️MySQL 5.7+, MariaDB 10.2.2+)❌ ⑬✅❌ ⑥✅✅删除列的默认值✅✅❌✅✅改变自增值❌✅❌✅❌ ⑦设置列为 NULL❌✅✅ ⑧✅❌设置列为 NOT NULL❌✅ ⑨✅ ⑨✅❌修改 ENUMSET 列的定义✅✅❌ ⑩✅✅

说明:

③ 并发 DML:当插入一个自增列时,不支持并发的 DML 操作,添加自增列时,大量的数据会被重新组织,代价高昂

③ 重建表:添加列时,MySQL 5.7及之前版本需要重建表,MySQL 8.0 当 ALGORITHM=INPLACE 时,需要重建表,ALGORITHM=INSTANT 时不需要重建

③ INSTANT算法:添加列时,使用 INSTANT 算法有下面这些限制

添加列操作不能和其它不支持 INSTANT 算法的操作合并为一条 ALTER TABLE 语句新增的列只能添加到表的最后,不能放到其它列的前面,在 MariaDB 10.4 之后,支持在任意位置添加不能将列添加到 ROW_FORMAT=COMPRESSED 的表中不能将列添加到包含 FULLTEXT 的表中不能将列添加到临时表中,临时表只支持 ALGORITHM=COPY不能将列添加到驻留在数据字典表空间中的表中在添加列的时候不会计算行的大小限制,该限制在执行 DML 操作插入或者更新表时才会被检查

④ 删除列时,大量的数据需要被重新组织,代价高昂,在 MariaDB 10.4 之后,删除列支持 INSTANT 算法

⑤ 重命名列时,确保只改变列名,不改变数据类型,这样才能支持并发的 DML 操作

⑥ 扩展 VARCHAR 长度时,INPLACE 是有条件的,必须保证用于标识字符串长度的长度字节不变(这里说的都是字节,不是 VARCHAR 的字符长度,字节占用与采用的字符集有关,utf8 字符集下,一个字符占 3 个字节, utf8mb4 则 4 个字节)

当 VARCHAR 列长度在 0-255 个字节时,长度标识占用一个字节当 VARCHAR 列长度大于 255 个字节时,长度标识占用两个字节

因此,INPLACE 只支持 0-255 个字节之间或者 256 个字节到更大的长度之间的变更。VARCHAR 列长度减小是不支持 INPLACE 的。

⑦ 自增列值变更是修改的内存中的值,不是数据文件

⑧ ⑨ 设置列为 [NOT] NULL 时,大量的数据被重新组织,代价高昂

⑩ 修改 ENUMSET 类型的列定义时,是否需要表拷贝取决于已有元素的个数和插入成员的位置

⑫ 在 MariaDB 10.4 之后,列排序支持 INSTANT 算法

⑬ 在 MariaDB 10.4.3  之后,InnoDB 支持使用 INSTANT 算法增加列的长度,但是也有一些限制,具体参考 Changing the Data Type of a Column

生成列

操作 INSTANT INPLACE 重建表 并发 DML 只修改元数据

添加 STORED 列❌❌✅❌❌修改 STORED 列的排序❌❌✅❌❌删除 STORED 列❌✅✅✅❌添加 VIRTUAL 列✅✅❌✅✅修改 VIRTUAL 列的排序✅❌✅❌❌删除 VIRTUAL 列✅✅❌✅✅

外键

操作 INSTANT INPLACE 重建表 并发 DML 只修改元数据

添加外键约束❌✅ ⑭❌✅✅删除外键约束❌✅❌✅✅

说明:

⑭ 添加外键时,只有当 foreign_key_checks 选项被禁用的时候才支持 INPLACE 算法

操作 INSTANT INPLACE 重建表 并发 DML 只修改元数据

修改 ROW_FORMAT❌✅✅✅❌修改 KEY_BLOCK_SIZE❌✅✅✅❌设置持久表统计信息❌✅❌✅✅指定字符集❌✅✅ ⑮❌❌转换字符集❌❌✅ ⑯❌❌优化表❌✅ ⑰✅✅❌使用 FORCE 选项重建表❌✅ ⑱✅✅❌执行空的重建❌✅ ⑲✅✅❌重命名表✅✅❌✅✅

说明:

⑮⑯ 当字符集不同时,需要重建表⑰⑱⑲ 如果表中包含 FULLTEXT 的字段,则不支持 INPLACE

表空间

操作 INSTANT INPLACE 重建表 并发 DML 只修改元数据

重命名常规表空间❌✅❌✅✅启用或者禁用常规表空间加密❌✅❌✅❌启用或者禁用 file-per-table 表空间加密❌❌✅❌❌

限制

在临时表 TEMPORARY TABLE 上创建索引时会发生表拷贝如果表上有 ON...CASCADE 或者 ON...SET NULL 约束,则 ALERT TABLE 不支持字句 LOCK=NONE在 Onlne DDL 操作完成之前,它必须等待相关表已经持有元数据锁的事务提交或者回滚,在这个过程中,相关表的新事务会被阻塞,无法执行当在大表上执行涉及到表重建的 DDL 时,会存在以下限制没有任何机制可以暂停 Online DDL操作或限制 Online DDL 操作的 I/O 或CPU使用率如果操作失败,则回滚 Online DDL操作的代价非常高昂长时间运行的 Online  DDL 可能会导致复制延迟。 Online  DDL 操作必须在 Master 上执行完成后才能在 Slave 上执行,在这个过程中, 并发处理的 DML 在 Slave 上面必须等待 DDL 操作完成后才会执行。

写在最后

本文将会持续修正和更新,更多精彩内容请 follow me。

更多相关免费学习推荐:mysql教程(视频)

以上就是参考指南:MySQL & MariaDB Online DDL的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1030987.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月2日 03:17:19
下一篇 2025年12月2日 03:18:02

相关推荐

  • 网络进化!

    Web 应用程序从静态网站到动态网页的演变是由对更具交互性、用户友好性和功能丰富的 Web 体验的需求推动的。以下是这种范式转变的概述: 1. 静态网站(1990 年代) 定义:静态网站由用 HTML 编写的固定内容组成。每个页面都是预先构建并存储在服务器上,并且向每个用户传递相同的内容。技术:HT…

    2025年12月24日
    000
  • 为什么多年的经验让我选择全栈而不是平均栈

    在全栈和平均栈开发方面工作了 6 年多,我可以告诉您,虽然这两种方法都是流行且有效的方法,但它们满足不同的需求,并且有自己的优点和缺点。这两个堆栈都可以帮助您创建 Web 应用程序,但它们的实现方式却截然不同。如果您在两者之间难以选择,我希望我在两者之间的经验能给您一些有用的见解。 在这篇文章中,我…

    2025年12月24日
    000
  • CSS如何实现任意角度的扇形(代码示例)

    本篇文章给大家带来的内容是关于CSS如何实现任意角度的扇形(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 扇形制作原理,底部一个纯色原形,里面2个相同颜色的半圆,可以是白色,内部半圆按一定角度变化,就可以产生出扇形效果 扇形绘制 .shanxing{ position:…

    2025年12月24日
    000
  • html中怎么运行sql语句_html中运行sql语句方法【教程】

    必须通过后端服务执行SQL操作。一、PHP与MySQL交互:使用PHP脚本在服务器端连接数据库,执行查询并嵌入HTML输出,避免硬编码凭证。二、Ajax调用API:前端通过JavaScript向后端API发送请求,服务端执行SQL并返回JSON数据,前端动态渲染结果。三、SQLite与JavaScr…

    2025年12月23日
    000
  • html手机怎么运行_手机运行html方法【教程】

    1、使用手机浏览器可直接打开本地HTML文件,只需通过文件管理器点击文件并选择浏览器打开即可预览;2、借助Spck Editor等专用编辑器应用能实现实时编辑与预览,适合开发调试;3、对于含JavaScript或需服务器支持的动态内容,应安装KSWEB类应用搭建本地服务器,再通过http://loc…

    2025年12月23日
    000
  • html如何连接_连接HTML与数据库或API接口【接口】

    HTML无法直接连接数据库或调用API,需借助JavaScript fetch、PHP中转、Node.js后端或Python Flask等服务端技术实现动态数据交互。 如果您希望在网页中动态获取数据,HTML本身无法直接连接数据库或调用API接口,必须借助服务器端语言或JavaScript等客户端技…

    2025年12月23日
    000
  • HTML如何添加批注功能_评论系统实现方案【教程】

    可实现HTML文本批注功能的四种方案:一、基于HTML5自定义属性与JS的静态批注;二、遵循W3C标准的语义化批注;三、嵌入Utterances或Giscus等第三方评论系统;四、自建AJAX评论后端+前端组件。 如果您希望在HTML页面中为特定文本添加可交互的批注功能,或构建一个轻量级的评论系统,…

    2025年12月23日
    000
  • html怎么在本地服务器运行_本地服务器运html方法【指南】

    使用本地服务器运行HTML文件需通过HTTP协议,可选Python命令启动服务、Node.js的http-server、VS Code的Live Server插件或XAMPP等工具,确保AJAX等功能正常。 要在本地服务器运行HTML文件,不能直接双击打开,因为部分功能(如AJAX、API调用)需要…

    2025年12月23日
    200
  • phpstudy怎么运行本地html_phpstudy运行本地html方法【教程】

    确保Apache或Nginx服务已启动;2. 将HTML文件放入WWW目录;3. 浏览器访问localhost即可运行页面。 在使用 PHPStudy 时,运行本地 HTML 文件非常简单。PHPStudy 是一个集成了 Apache/Nginx、PHP 和 MySQL 的集成环境工具,主要用于本地…

    2025年12月23日
    000
  • HTML页面如何生成短链接_URL压缩转换方法【攻略】

    可借助第三方服务、API调用、Nginx反向代理、PHP脚本或GitHub Pages五种方式将HTML页面URL转为短链接:1.用bit.ly等平台手动缩短;2.调用Bitly API批量生成;3.配置Nginx rewrite规则重定向;4.部署PHP+MySQL实现动态跳转;5.利用GitHu…

    2025年12月23日
    000
  • Java JDBC中SQL INSERT语句的常见语法错误及修复指南

    本文旨在解决java jdbc应用中常见的sql `insert`语句语法错误,特别是因缺少括号而导致的错误。我们将深入分析错误信息,指出问题根源,并提供正确的sql语句范例及java jdbc `preparedstatement`的使用方法。文章还将涵盖jdbc数据库操作的最佳实践、错误处理和调…

    2025年12月23日
    000
  • wampserver怎么运行html程序_wampserver运行html程序方法【教程】

    使用WampServer运行HTML程序需将文件放入www目录,启动Apache服务后通过http://localhost/项目路径访问,确保在本地服务器环境下正确解析运行。 如果您在本地开发网页,但无法正确查看HTML文件的运行效果,可能是由于未通过本地服务器环境进行访问。WampServer 提…

    2025年12月23日
    000
  • 平板怎么运行html代码_平板运行html代码步骤【指南】

    可在平板上通过四种方式查看HTML效果:一、用浏览器直接打开本地.html文件;二、使用JSFiddle等在线编辑器实时预览;三、安装Acode等编程应用离线编写并预览;四、通过KSWEB搭建本地服务器运行含动态内容的页面。 如果您希望在平板设备上查看或测试HTML代码的效果,但不确定如何操作,则可…

    2025年12月23日
    000
  • html上怎么运行php代码吗_html中运行php代码方法【教程】

    要使PHP代码在HTML中执行,必须通过支持PHP的服务器环境。首先将文件保存为.php格式并部署到配置好PHP模块的服务器(如Apache)根目录,通过http://localhost访问;或修改服务器配置(如.htaccess)令.html文件解析PHP;推荐使用.php文件混合HTML与PHP…

    2025年12月23日
    000
  • html怎么用sublime运行php_sublime运行html中php方法【教程】

    可在Sublime Text中通过配置PHP环境变量并创建Build System运行PHP代码,或使用PHP内置服务器、XAMPP等集成环境结合浏览器预览实现解析与调试。 如果您在使用Sublime Text编辑HTML或PHP文件时,希望直接运行PHP代码并查看输出结果,但发现无法像在浏览器中那…

    2025年12月23日
    000
  • PHP表单提交后防止页面刷新并保留数据与错误提示的教程

    本教程旨在解决php表单提交时页面刷新、用户输入数据丢失以及错误提示显示不佳的问题。核心方法是利用服务器端php的`$_post`变量,在表单提交并进行服务器端验证失败后,不进行页面重定向,而是直接在当前页面重新渲染表单,同时回填用户之前输入的数据并显示验证错误信息,从而显著提升用户体验。 引言:优…

    2025年12月23日
    000
  • 如何通过JavaScript/jQuery获取HTML元素内容并与PHP后端交互

    本教程详细阐述了如何利用JavaScript和jQuery从HTML页面中动态获取特定` `标签的文本内容,并进一步探讨了如何将这些前端捕获的数据通过AJAX技术安全地传递给PHP后端进行处理,例如执行SQL查询。文章涵盖了从前端事件触发、数据捕获到后端数据接收、处理及安全防护的全流程,旨在提供一个…

    2025年12月23日
    000
  • php怎么在html5中运行_php在html5中运行方法【教程】

    PHP在服务器端运行,通过嵌入HTML5文件生成动态内容。1. PHP与HTML5协同工作:PHP代码嵌入.html或.php文件,由服务器解析后输出纯HTML至浏览器。2. 创建index.php文件,使用标准HTML5结构,在其中插入等PHP代码,实现动态内容展示。3. 搭建本地环境可选用XAM…

    2025年12月23日 好文分享
    000
  • epp4怎么运行html文件_EPP4运行html文件步骤【指南】

    首先确认EPP4已安装并启动Apache服务,将HTML文件放入www目录后,通过http://localhost/路径访问即可预览页面,确保文件位置与路径正确。 打开EPP4后运行HTML文件并不复杂,只需正确操作即可在浏览器中预览页面效果。EPP4(Easy PHP Pack 4)是一个集成开发…

    2025年12月23日
    000
  • html怎么用浏览器运行php_浏览器运html中php文件方法【教程】

    正确答案是搭建本地开发环境。需安装XAMPP等集成工具,将.php文件放入htdocs目录,通过http://localhost访问,确保服务器解析PHP并返回HTML给浏览器显示。 PHP 是服务器端语言,不能直接通过浏览器像 HTML 那样双击打开运行。你看到的“在浏览器中运行 PHP”其实是指…

    2025年12月23日
    000

发表回复

登录后才能评论
关注微信