ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MySQL迁移PostgreSQL兼容性对照与实战踩坑记录

MySQL迁移PostgreSQL兼容性对照与实战踩坑记录 前阵子接了个“从 MySQL 迁到 PostgreSQL”的评估活儿老板丢给我一句话“你先把两边兼容性标准摸清楚。”我第一反应不是翻官方文档而是打开 DeepSeek让它先给我拉一份差异清单出来。倒不是偷懒而是这类对比东西两本官方手册翻起来实在太费劲AI 能先把骨架搭好我再拿经验和实测去校验效率直接翻倍。这份“DeepSeek 总结的 PostgreSQL 和 MySQL 兼容性标准”本质上就是一份数据库迁移前的“科目三考试大纲”。它解决的是这样一个痛点当你在 MySQL 上写惯了AUTO_INCREMENT、ON DUPLICATE KEY UPDATE突然切到 PostgreSQL 的IDENTITY、ON CONFLICT时代码不是简单地换几个关键字就能跑起来的背后是整条 SQL 语义、数据类型、事务行为、索引策略的连锁差异。这篇文章我会把整个梳理思路、核心对照表、踩坑记录完整拆给你适合三种人看准备做数据库迁移的 DBA 或后端开发、在混合架构里同时维护两套库的团队、以及想用 AI 加速技术调研但对输出内容半信半疑的人。我会告诉你哪些地方可以直接信 AI哪些地方必须自己动手验证。1. 兼容性标准的价值在哪为什么需要这份对比先说结论所谓“PostgreSQL 和 MySQL 兼容性标准”不是一个官方发布的白皮书级别文档而是一套在迁移、同步、跨库开发时用来判断“能不能直接跑、改了能不能跑、改了会不会出隐性问题”的规则集。它最核心的价值在于减少迁移项目里的“惊悚时刻”——比如上线后才发现排序规则不同导致分页数据乱跳或者某个GROUP BY行为不一致直接把聚合结果搞错。我自己做过的迁移项目里至少会碰到三类典型场景。第一类是存量系统迁移。一个跑了好几年的业务系统从 MySQL 搬到 PostgreSQL可能是出于成本、功能扩展或者信创选型的要求。这种场景下兼容性标准决定了迁移改造的工作量边界。如果只是LIMIT、OFFSET这种语法差异改起来很轻松但如果上游写了几百个存储过程里面全是 MySQL 的DELIMITER和游标写法那 PostgreSQL 这边的PL/pgSQL重写工程量就要另算了。第二类是异构数据同步。现在很多团队用 Canal、Debezium 之类工具做 MySQL 到 PostgreSQL 的实时同步或者反过来。同步工具本身只负责搬运数据但两边对数据类型、约束、默认值的定义不同会导致同步链路经常报错。比如 MySQL 的tinyint(1)同步到 PostgreSQL 后怎么映射是转成smallint还是boolean不同映射方案对下游应用的影响天差地别。这时候一份清晰的类型映射标准就是救命稻草。第三类是统一开发规范。有些中大型团队内部既有 MySQL 又有 PostgreSQL新人写代码时经常问“同一套 SQL 能不能两边跑”。我的回答通常是别想太多两边都有方言你只能选一个主用库另一个靠兼容层或者代码层面规避。而兼容性标准就是用来界定“哪些 SQL 特性可以跨库通用哪些必须按库分别写”。DeepSeek 这类大模型在这个环节的价值不是替你做最终判断而是能快速把两边官方文档里零散的知识点拉通生成一个初版对比框架。你拿这个框架去查文档、做实验效率比自己从零开始翻手册高太多。但注意AI 输出的版本可能过时也可能把“例外情况”漏掉所以我的原则是AI 搭骨架文档补血肉实验做验收。2. 用 DeepSeek 梳理兼容性标准的具体流程很多人在技术调研时不知道该怎么问 AI拿到答案又不知道该不该信。我把自己实际操作的一套流程分享出来核心就四步定义边界、分轮提问、交叉验证、落成文档。2.1 第一步先锁定版本边界我和 DeepSeek 的第一轮对话不是直接问“PostgreSQL 和 MySQL 有什么区别”而是先明确版本号。原因很简单MySQL 5.7 和 8.0 的差异巨大PostgreSQL 12 和 15、16 也不一样。比如 MySQL 8.0 才开始支持窗口函数和 CTE如果你拿 5.7 的标准去对比 PostgreSQL 15那结论会失真。我的提问方式是“请以 PostgreSQL 15 和 MySQL 8.0 为基准对比它们在 SQL 语法、数据类型、事务隔离级别、索引特性、存储过程、备份恢复工具方面的主要差异。输出格式用表格每一条差异请标注影响等级高、中、低。”这样 AI 给出的结果有明确的范围表格化也方便后续处理。2.2 第二步按主题拆解成多个子问题一次问太多AI 的回答会比较泛缺少针对性。我会拆成几个子问题逐个问数据类型映射、DDL 行为差异、DML 与查询语法差异、事务与锁机制差异、索引和分区策略差异、存储过程与触发器写法差异。每个子问题单独一轮对话比如“请对比 PostgreSQL 和 MySQL 在字符串类型上的差异包括 varchar、text、char 的长度限制、存储效率、排序规则以及迁移时需要注意的坑。”这种问法得到的回答比“全面对比”要深入得多AI 会更倾向于展开讲细节而不是堆砌三五个通用点。2.3 第三步用反向提问来验证错误信息大模型有个问题会一本正经地说错话。比如你问“MySQL 8.0 支持 FULL OUTER JOIN 吗”它可能回答“支持”。实际上 MySQL 8.0 不支持 FULL OUTER JOINPostgreSQL 才支持。为了验证这类细节我会反向追问“请检查这个说法是否正确MySQL 8.0 支持 FULL OUTER JOIN。如果不支持请给出官方文档的说明和替代写法。”反向提问的目的是让 AI 自己去做事实核查。虽然它不能真正联网检索除非接入了联网能力但当你明确要求“校验”时它会更倾向于调取训练数据里更可靠的信息而不是顺着你的话往下说。2.4 第四步把结果沉淀成标准文档每一轮有效的回答我会要求 DeepSeek 整理成标准化的条目包含差异点、双方写法示例、迁移时建议、影响等级。最后汇成一张总表。这张表就是我们团队内部使用的“兼容性标准 v1.0”后续每发现一个新坑就往里补。这里有一个很重要的实操建议不要让 AI 的回答直接进生产文档一定要亲手跑一遍。后面第 4 部分我会详细讲哪些地方 AI 容易判断失误以及我怎么用测试用例去纠偏。3. 兼容性标准的核心内容对照这一部分我直接把经过校验的核心差异整理出来。你完全可以把下面这些表格当作自己迁移项目的起点但上线前务必结合自己的数据样本做一轮回归测试。3.1 SQL 语法与查询行为差异先说 DDL。PostgreSQL 和 MySQL 在修改表结构上的语法基本相似但 PostgreSQL 支持一条ALTER TABLE里组合多个操作MySQL 8.0 也支持有限的组合但有些组合还是会报错。实际迁移中DDL 脚本往往需要拆开重写。DML 层面最典型的差异是“插入或更新”的写法。MySQL 用INSERT ... ON DUPLICATE KEY UPDATEPostgreSQL 从 9.5 开始用INSERT ... ON CONFLICT (column) DO UPDATE SET ...。两者语义上不完全等价MySQL 的“重复”判断依据是主键或唯一索引PostgreSQL 必须在ON CONFLICT里明确指定冲突目标。如果你的 MySQL SQL 经常靠唯一索引来触发更新迁移到 PG 后必须把冲突列写清楚。字符串连接也是重灾区。MySQL 默认用空格或CONCAT()函数||符号默认表示逻辑或除非你开启PIPES_AS_CONCAT模式。PostgreSQL 直接用||做字符串连接符合 SQL 标准。迁 SQL 时所有CONCAT(a, b)可以保留但所有依赖||的 MySQL 写法必须改写。我整理了一个高频语法差异对照表方便你直接抄场景MySQL 8.0PostgreSQL 15字符串连接CONCAT(a, b)插入或更新INSERT ... ON DUPLICATE KEY UPDATEINSERT ... ON CONFLICT (col) DO UPDATE/NOTHING分页LIMIT n OFFSET mLIMIT n OFFSET m语法一致空值排序ASC 时 NULL 排最前DESC 时 NULL 排最后ASC 时 NULL 排最后DESC 时 NULL 排最前可加 NULLS FIRST/LAST 控制全外连接8.0 不支持 FULL OUTER JOIN原生支持 FULL OUTER JOIN布尔类型用 TINYINT(1) 模拟TRUE/FALSE 是 1/0 别名原生 BOOLEAN 类型TRUE/FALSE/NULL字符串比较默认不区分大小写取决于 collation默认区分大小写可用 ILIKE 做不区分大小写匹配3.2 数据类型映射与“隐性陷阱”数据类型映射是迁移中最容易出“线上事故”的环节。表面上类型对上了实际行为却有差异。举几个典型例子。MySQL 的DATETIME范围是 1000-01-01 到 9999-12-31PostgreSQL 的TIMESTAMP范围是 4713 BC 到 294276 AD前者的合法值在后者的范围内一般不用管。但 MySQL 的TIMESTAMP类型有 2038 年问题而且跟时区绑定迁移到 PG 时如果直接映射成TIMESTAMP WITH TIME ZONE行为差异会非常明显。我的建议是MySQL 的TIMESTAMP一律按业务语义映射成 PostgreSQL 的TIMESTAMP WITHOUT TIME ZONE或TIMESTAMP WITH TIME ZONE不要无脑对应。整数类型也有坑。MySQL 有TINYINT、SMALLINT、MEDIUMINT、INT、BIGINTPostgreSQL 只有SMALLINT、INTEGER、BIGINT。MySQL 的tinyint(1)在 PG 里没有直接对应通常映射到BOOLEAN会改变 JDBC 或 ORM 的读取结果如果业务把tinyint(1)当数字用映射成 boolean 就会出问题。更稳妥的做法是统一映射成SMALLINT再用应用层转换。字符串类型方面MySQL 的VARCHAR(255)在 UTF-8 字符集下最大长度按字符算但 InnoDB 索引有 767 字节或 3072 字节的限制。PostgreSQL 的VARCHAR(n)和TEXT没有字节限制索引也不受前缀长度限制。迁移时基本可以把 MySQL 的VARCHAR迁成 PG 的VARCHAR长度保持不变即可但要注意索引大小写比较规则的变化会影响查询计划。JSON 类型也经常被忽略。MySQL 的JSON和 PG 的JSONB虽然都叫 JSON但存储和查询方式完全不同。MySQL 的 JSON 存储的是二进制序列化对象用JSON_EXTRACT()取字段PG 的JSONB是二进制格式支持高效的-和-操作符还支持 GIN 索引加速。迁移时 JSON 数据本身能搬过去但所有 JSON 字段读取的 SQL 都得重写。3.3 事务、锁与隔离级别差异PostgreSQL 的默认隔离级别是 READ COMMITTEDMySQL InnoDB 的默认隔离级别是 REPEATABLE READ。这个差异直接影响并发行为。在 REPEATABLE READ 下MySQL 通过快照读实现同一事务内多次查询结果一致而 PG 的 REPEATABLE READ 虽然也提供快照但对冲突的处理有些区别。更关键的是“幻读”处理方式。MySQL InnoDB 用间隙锁来防止幻读事务在 REPEATABLE READ 下执行SELECT ... FOR UPDATE时会锁住范围内不存在的记录。PostgreSQL 使用更轻量的行锁和可见性规则不采用间隙锁机制而是依赖可重复读快照和序列化快照隔离SSI。如果你的业务在 MySQL 下依赖间隙锁来防止并发插入重复数据迁到 PG 后要重新评估你的锁策略否则可能插入出重复值。我用一个表格帮你梳理锁机制核心差异维度MySQL InnoDBPostgreSQL默认隔离级别REPEATABLE READREAD COMMITTED行锁实现对索引记录加锁存在间隙锁对行版本加锁无间隙锁机制锁等待检测自动死锁检测超时回滚检测到死锁自动回滚一个事务MVCC 实现在聚簇索引里保存隐藏列使用更直观的多版本行数据tupleDDL 是否支持事务不支持DDL 隐式提交支持DDL 可以回滚外键约束支持但会显著带来锁开销支持行为更接近 SQL 标准DDL 事务性是一个很容易被低估的差异。在 MySQL 里执行CREATE TABLE或ALTER TABLE时前面的 SQL 会自动提交这意味着你没法在一个事务里先建表再插入数据然后一并回滚。PostgreSQL 可以这是 PG 在开发体验上的一个显著优势。迁移过程中如果你用自动化工具跑 DDL 脚本在 MySQL 上可能需要额外考虑脚本原子性在 PG 上则少一个顾虑。3.4 索引、分区与自增列策略索引方面MySQL 的默认索引结构是 BTreePostgreSQL 默认也是 B-Tree但类型更多样GIN 适合 JSONB 和全文检索GiST 适合几何类型和范围类型BRIN 适合非常大且物理顺序与逻辑顺序一致的表。迁移时如果原来 MySQL 的查询依赖某些复杂条件迁到 PG 后可以考虑用更高效的索引类型。分区表是迁移中最容易引发性能问题的点。MySQL 8.0 的分区表限制较多比如分区键必须是主键或唯一索引的一部分而且很多查询优化器对分区的处理并不高效。PostgreSQL 从 10 开始支持声明式分区12 之后分区能力大幅增强分区裁剪也更成熟。但要注意两边的分区语法差异很大MySQL 用PARTITION BY RANGE (col)PG 用PARTITION BY RANGE (col)语法上有点类似但建表结构、约束定义、索引创建方式都不同需要整体重写。自增列更是个经典对比点。MySQL 用AUTO_INCREMENT一个表只能有一个自增列而且自增值是全局性的重启后会有一定的跳跃。PostgreSQL 支持SERIAL伪类型和标准的GENERATED AS IDENTITY后者更规范。如果你的 MySQL 表用了AUTO_INCREMENT迁移到 PG 时建议统一改成GENERATED ALWAYS AS IDENTITY并检查所有依赖自增值的业务代码比如拿到新 ID 的方式。MySQL 获取自增 ID 的常见写法是LAST_INSERT_ID()PG 有RETURNING id或currval()两种方式。这个差异影响很大尤其是 ORM 框架的批量插入策略。你在迁移时要把这段代码重点标记出来。4. 从 MySQL 迁到 PostgreSQL最容易踩的五个坑这部分是真正的实战教训。第 3 部分讲的是标准这里讲的是标准之外那些“文档上没说透、不测不知道”的坑。4.1 标识符大小写规则完全不同PostgreSQL 对未加引号的标识符会自动转成小写。你建表时写CREATE TABLE UserInfo实际生成的是小写的userinfo。查询时写SELECT * FROM UserInfo也会自动转成小写去匹配所以能查到。但如果你在 MySQL 里建了UserInfo和userinfo两张表迁移到 PG 后它们就冲突了因为 PG 默认不区分大小写未加引号。更坑的是你在 PG 里用双引号建一个UserInfo表之后每次查询都必须用双引号带同样的拼写否查不到。MySQL 则跟操作系统有关。Linux 下表名区分大小写取决于lower_case_table_names参数Windows 下不区分。所以同一个迁移方案在不同的 MySQL 环境下表现都不一样。我建议迁移前先在源库跑一遍“大小写重名检查”把那些仅靠大小写区分的表名列名提前重命名否则迁移过程中随时可能报错。4.2 NULL 排序不一致引发分页错乱一次性能测试里我同事跑一个分页接口MySQL 上一切正常切到 PG 后前两页出现了重复数据。排查了大半天最后发现问题的根源就是 NULL 值的默认排序位置。MySQL 里ORDER BY col ASC时 NULL 在最前PG 里ORDER BY col ASC时 NULL 在最后。如果你的条件里有WHERE col IS NOT NULL两边一致但如果你就是允许 NULL 参与排序那分页 offset 一移动结果集就变了。解决方式很简单给每一条ORDER BY都显式写NULLS FIRST或NULLS LAST并保证在 MySQL 和 PG 里的语义一致。但前提是你知道这个规则的存在。4.3 GROUP BY 的严格程度差异MySQL 5.7 之后有了ONLY_FULL_GROUP_BY开启后行为接近 PG但很多老项目没开导致线上 SQL 里大量存在“SELECT 非聚合列但没出现在 GROUP BY 里”的写法。这种 SQL 拿到 PostgreSQL 上直接报错因为 PG 一直按 SQL 标准严格要求。迁移时你没法改几千条业务 SQL但可以分两步走第一步在 MySQL 里开启ONLY_FULL_GROUP_BY跑一轮回归测试把所有报错的 SQL 揪出来第二步统一改写。改写逻辑通常是把非聚合列加进GROUP BY或者用ANY_VALUE()/MIN()/MAX()包裹起来。注意 PG 没有ANY_VALUE()函数需要自己用MIN()或MAX()替代。4.4 字符集与排序规则导致索引失效MySQL 的utf8mb4_general_ci排序规则不区分大小写所以在 MySQL 里WHERE name abc能匹配到ABC。PostgreSQL 默认排序规则通常是C或基于系统 locale 的规则字符串比较区分大小写。迁移后如果应用层没改原来能查到的数据突然查不到了。另外索引的行为也跟着排序规则走。MySQL 在不区分大小写的排序规则下建的索引本身就支持大小写不敏感的等值查询PG 的普通 B-Tree 索引区分大小写如果想达到同样效果需要建lower(name)表达式索引。这些差异如果不提前测试会出现“API 响应变慢”“数据莫名丢失”这类幻觉。4.5 存储过程语法完全两套体系MySQL 存储过程用DELIMITER声明分隔符用IN/OUT/INOUT声明参数游标写法也很有 MySQL 味道。PostgreSQL 用CREATE OR REPLACE FUNCTION和PL/pgSQL没有DELIMITER概念参数模式也不一样。存储过程的迁移基本等于重写不是换个关键字就能搞定。我的建议是迁移前先盘点所有存储过程和触发器评估业务逻辑复杂度。如果只是薄薄一层数据封装考虑在应用层用 SQL 直接替代如果存储过程里跑着复杂的分批计算那就早点安排专人做PL/pgSQL重写。DeepSeek 在这块也能帮上忙把 MySQL 的存储过程粘贴进去让它翻译成 PL/pgSQL然后人工审查。翻译质量大概七成能用剩下的三成都是边界条件和异常处理逻辑必须靠 DBA 手工补。5. 一份可以直接落地的兼容性评估实操方案前面这些差异点你可以直接拿去做知识储备。但真正的项目落地不能只靠这篇文章我建议你按下面的步骤来推进一次完整的兼容性评估。5.1 梳理存量资产建一个 DB 对象清单第一步是把目标库里的所有对象摸清楚表、字段、索引、约束、视图、存储过程、触发器、事件调度MySQL 的 EVENT。这些信息可以从information_schema里查出来导出成清单。没有清单就谈兼容性等于没有地图就上路。我常用的做法是写一个通用查询脚本从 MySQL 的information_schema.columns、tables、statistics里拉全量元数据再写一个脚本从 PG 的pg_catalog里拉对应信息然后按库名、表名、字段名做映射对比。这一步别指望完全自动化因为遗留系统里经常有“孤儿表”“废弃索引”这些需要 DBA 靠经验判断是否迁移。5.2 用 DeepSeek 生成迁移规则初稿有了对象清单后你把表结构、索引定义、存储过程代码等样本输入给 DeepSeek请求它按“数据类型映射、约束迁移、索引重建、SQL 改写、存储过程重写”五个类别输出迁移规则。这是在前面 2.2 节基础上的深化目标从“了解差异”变成“生成可执行的转换方案”。人工审查是关键。你要逐条校验 AI 给出的迁移规则是否符合你们团队的版本和配置。比如 AI 说“MySQL 的unsigned int映射到 PG 的INTEGER CHECK (col 0)”这个建议本身合理但如果你不想引入额外的 CHECK 约束可以改成BIGINT或者换用DOMAIN这就要你的业务经验来拍板。5.3 设计核心验证用例跑一轮迁移演练没有测试的迁移方案都是空谈。我建议准备一张“兼容性验证矩阵”每条规则至少配一个正向用例和一个反向用例。比如验证大小写排序就往表里插入abc和ABC分别跑WHERE name abc、ORDER BY name、GROUP BY name记录两边结果集是否一致。数据迁移工具方面如果用 PostgreSQL 自带的pgloader迁 MySQL它支持自动类型映射和部分约束转换但碰到特殊类型和复杂索引也会“摆烂”。你可以先用小表样本演练对比源库和目标库的行数、字段值、约束数量、索引数量确保没丢东西再切全量。5.4 建立持续校验机制避免一次迁移终生后悔所谓“持续校验机制”是指迁移完成后的一段时间内对线上 SQL 日志做差异分析。你可以在 MySQL 侧开启慢查询日志在 PG 侧用pg_stat_statements收集执行统计定时对比两类库上相同业务 SQL 的执行计划差异。这不是一次性的工作而是运维常态。我在实际项目里还习惯把 DeepSeek 当成“兼容性值班机器人”。每次开发提一条新 SQL先让它判断“这条 SQL 在 MySQL 和 PG 上行为是否一致”不一致的话给出改写建议。这个流程很简单但确实能拦住很多新手在开发阶段埋下的雷。6. 常见问题与排查技巧实录这一部分我把平时被问得最多的几个兼容性问题整理成速查表都是实打实踩过坑才积累下来的。问题场景原因分析排查与解决办法迁移后部分中文乱码MySQL 字符集是 latin1 或 utf8mb3PG 默认 UTF-8 处理迁移前统一转成 UTF-8检查连接字符串的字符集参数同样一条 SQLMySQL 秒回PG 慢 10 倍通常是对 NULL 排序、函数写法差异导致索引失效用 EXPLAIN 对比执行计划检查是否需要建表达式索引自增 ID 出现重复或跳号PG 的序列默认 CACHE 机制事务回滚会消耗序列值不必强求完全一致接受跳号若业务要求紧凑递增改为应用层分配外部系统通过 JDBC 连接报错驱动版本或 SQL 方言设置不匹配换用最新 JDBC 驱动检查连接 URL 是否指定了 compatible 参数时间字段相差 8 小时MySQL TIMESTAMP 含时区PG TIMESTAMP WITHOUT TIME ZONE 不含时区统一约定业务时区必要时改用 TIMESTAMPTZ外键约束迁移不成功MySQL 和 PG 对外键引用行为定义有差异且表加载顺序影响建约束数据先导入约束后添加并用 SET CONSTRAINTS 检查延迟约束应用程序里大量使用SELECT LAST_INSERT_ID()MySQL 专属函数PG 不支持改用 RETURNING或 ORM 层统一处理自增主键回填再分享一个我自己经常用的排查技巧当你怀疑某个差异是数据库行为导致的不要凭记忆猜直接在两个库各开一条事务执行同一个操作序列记录每一步的返回结果和锁等待情况。比如验证间隙锁MySQL 下开两个会话一个执行SELECT ... FOR UPDATE另一个尝试插入范围内的数据观察是否阻塞PG 下做同样的实验观察差异。这类并行对比测试是最快确认行为差异的方法。另一个技巧是关于 AI 辅助排查的。遇到一个诡异的兼容性问题把完整的 SQL、建表语句、错误信息、两边版本号都扔给 DeepSeek让它分析可能原因。AI 给出的原因可能不准但常能提供新的排查方向比如“检查 collation 是否一致”或者“检查驱动层的 rewriteBatchedStatements 参数”。这些方向有时候比你自己闷头查快得多。7. 关于这份标准我最后想说的几句实在话这套兼容性标准的整理过程说到底是“AI 提速 人工兜底”的组合打法。DeepSeek 可以帮你快速把两边的差异点拉出来但它不知道你的表结构里有哪些历史包袱也不知道你的业务逻辑里藏着多少隐式依赖。真正让标准生效的是你愿意花时间把每一条差异都放到真实数据和真实 SQL 里去验证。我自己操作下来最有感触的一点是数据库兼容性问题通常不在主流程上爆发而是在边界条件下爆发。你以为改完AUTO_INCREMENT就万事大吉了结果半夜被 NULL 排序的分页问题叫醒你以为类型映射表对着改就结束了结果某个tinyint(1)字段让整个报表工具读出来全是布尔值。所以我的习惯是每次都把兼容性标准的验证用例做得“变态”一点故意插入 NULL、超长字符串、特殊字符、负数、极值看两边谁先出问题。最后再给一个建议如果你所在团队短期内有迁移计划与其等迁移前再突击调研不如现在就找一张最复杂的业务表做一次“双库对照演练”。不需要真的全量迁移挑几张核心表就行。这个过程会让你和你的开发团队对 PG 和 MySQL 的差异建立肌肉记忆等真迁移的时候你会庆幸提前做了这些功课。
返回列表