基于CI/CD的MySQL到PostgreSQL异构数据库平滑迁移实战
1. 项目概述为什么CI/CD是数据库迁移的“安全带”在数据库迁移这个领域尤其是从MySQL到PostgreSQLPG这种异构数据库的迁移传统的手工操作或一次性脚本执行无异于一场高风险、高不确定性的“外科手术”。你可能会遇到数据丢失、类型转换错误、性能骤降甚至迁移中途失败导致业务长时间中断的噩梦。我经历过不止一次在凌晨三点对着满屏的错误日志祈祷数据能找回来。所以当团队再次面临一个核心业务系统从MySQL迁移到PG的任务时我决定将“平滑迁移”这个目标从一句口号变成一个可量化、可验证、可自动化的工程实践。而实现这一点的核心就是引入持续集成/持续交付CI/CD流水线。MySQL2PG的迁移远不止是简单的mysqldump导出再psql导入。它涉及到表结构DDL的转换、数据类型映射比如MySQL的DATETIME到PG的TIMESTAMPTEXT字段的字符集处理、自增主键AUTO_INCREMENT 到 SERIAL/BIGSERIAL、索引、约束、视图甚至是存储过程和函数的改写。任何一个环节的疏漏都可能在生产环境引发故障。CI流水线的作用就是为这个复杂过程系上“安全带”。它通过自动化的、可重复的步骤在真正割接前持续地对迁移方案进行验证、测试和演练将风险前置并可视化最终确保迁移过程平滑、可控。简单说它让迁移从“赌博”变成了“科学实验”。2. 迁移流水线整体架构设计一套有效的MySQL2PG CI流水线其核心设计思想是“模拟生产分阶段验证”。它不应该只是一个执行迁移脚本的跑马场而应该是一个覆盖迁移全生命周期质量门禁的自动化工厂。基于这个思路我设计了一套四阶段的流水线架构。2.1 核心阶段划分与质量门禁流水线被设计为四个串行阶段每个阶段都是一个质量门禁只有当前阶段所有检查通过才能进入下一阶段。这种设计确保了问题能被尽早发现和修复。结构转换与代码检查阶段这是第一道防线。核心任务是使用专业的迁移工具如pgloader、ora2pg的MySQL模式或自研脚本将MySQL的Schema表、视图、索引、约束转换为PG兼容的DDL。此阶段的质量门禁包括语法检查使用pg_dump的--schema-only模式生成PG的Schema并用psql的-c命令或pgTAP进行预执行语法校验。差异对比将转换后的PG Schema与源MySQL Schema进行自动化对比确保没有表、列、索引的遗漏。我常用一个自研Python脚本通过information_schema抽取关键元数据进行比对。自定义规则检查例如检查是否还有MySQL特有的数据类型如TINYINT(1)被错误地转成了BOOLEAN以外的类型或者检查外键约束名称是否超长PG有更严格的命名长度限制。数据迁移试运行与验证阶段此阶段在独立的测试数据库中进行。它执行全量或抽样数据迁移并进行严格的数据一致性校验。质量门禁包括行数校验对比源库和目标库每个表的记录总数必须完全一致。关键字段校验对核心业务表的主键、金额、时间戳等关键字段进行哈希校验如MD5或SHA256。我会对每个表按主键排序后将关键字段拼接成字符串计算哈希对比两端结果。数据采样校验随机抽取一定比例的数据比如0.1%进行逐字段的精确比对。这对于发现字符集转换乱码、时区问题、数值精度丢失特别有效。应用兼容性测试阶段迁移后的数据库最终是要服务应用的。此阶段将最新的应用代码或专门的分支指向迁移后的PG测试库运行全套自动化测试套件。质量门禁就是测试用例的通过率。需要特别关注ORM层测试如果你的应用使用了Hibernate、MyBatis、Sequelize等ORM需要确保其生成的SQL在PG上语法正确特别是分页LIMIT/OFFSETvsLIMIT ... OFFSET、锁机制等方言差异。原生SQL测试所有手写的、包含MySQL特有函数如DATE_FORMAT、GROUP_CONCAT或语法如ON DUPLICATE KEY UPDATE的SQL都必须在此阶段暴露出来并完成改写。性能基准测试与回滚演练阶段这是上线前的最后一道也是最重要的关卡。它确保迁移后性能不会退化并且当出现问题时能快速回退。性能基准测试使用像pgbench针对PG和sysbench针对MySQL工具在同等硬件和数据集下对核心事务如订单创建、查询进行压力测试对比TPS每秒事务数和延迟P95 P99。性能下降应在预期的可接受范围内例如10%。回滚方案演练自动化执行预定义的回滚脚本例如将流量切回MySQL并验证回滚后数据的一致性和应用功能正常。这个演练必须定期执行确保回滚路径始终畅通。2.2 工具链选型与集成流水线的实现依赖于一系列开源工具和云服务的组合。我的选型基于“成熟、可编程、易集成”的原则。迁移工具pgloader。我首选它因为它用Common Lisp编写性能极佳支持从MySQL直接迁移到PG并在过程中自动处理许多数据类型转换如将DATETIME转换为timestamptz。它的配置文件.load文件可以纳入版本控制并通过CI流水线参数化执行。备选是AWS DMS或Google的Datastream如果项目在云上且追求全托管服务。CI/CD平台GitLab CI或GitHub Actions。两者都提供强大的Pipeline as Code能力。我个人更熟悉GitLab CI它的.gitlab-ci.yml配置文件非常灵活可以清晰定义上述四个阶段并且与代码仓库、容器注册表无缝集成。测试环境使用Docker Compose或Kubernetes在流水线中动态拉起包含MySQL源库和PG目标库的临时环境。这保证了每次测试的隔离性和纯净度。镜像使用官方版本即可。校验脚本主要用Python编写辅以Shell脚本。Python的sqlalchemy、psycopg2、pymysql库非常适合用来编写数据对比和校验逻辑。这些脚本本身也是项目资产纳入版本库。性能测试pgbench内置适合PG基准对于更复杂的业务场景模拟我会用Locust或k6编写针对应用接口的压测脚本集成到流水线中。注意工具链的选择应保持一致性。避免在流水线中混合使用多种异构的迁移工具这会给问题排查带来额外复杂度。一旦选定pgloader就将其配置模板化、版本化。3. 流水线核心环节实现详解有了架构设计接下来就是如何用代码和配置将其实现。我将以GitLab CI为例拆解几个最核心的环节。3.1 可配置的迁移任务定义我们不应该将数据库连接信息、表名单等硬编码在流水线脚本里。我采用环境变量和配置文件相结合的方式。首先在GitLab的项目设置中配置以下CI/CD变量标记为Masked和Protected确保安全SRC_DB_URL:mysql://user:passwordmysql-host:3306/source_dbTGT_DB_URL:postgresql://user:passwordpg-host:5432/target_dbEXCLUDE_TABLES:audit_log, system_cache需要排除迁移的表然后创建一个pgloader.load配置文件模板它会被CI流水线渲染和使用LOAD DATABASE FROM mysql://{{ .SRC_USER }}:{{ .SRC_PW }}{{ .SRC_HOST }}/{{ .SRC_NAME }} INTO postgresql://{{ .TGT_USER }}:{{ .TGT_PW }}{{ .TGT_HOST }}/{{ .TGT_NAME }} WITH include drop, create tables, create indexes, reset sequences, workers 8, concurrency 2, multiple readers per thread, rows per range 50000 CAST type datetime to timestamptz drop default drop not null using zero-dates-to-null, type tinyint to boolean using tinyint-to-boolean ALTER SCHEMA source_db RENAME TO public BEFORE LOAD DO $$ CREATE SCHEMA IF NOT EXISTS public; $$, $$ ALTER DATABASE {{ .TGT_NAME }} SET search_path TO public; $$;在CI脚本中我会使用envsubst或类似工具将这些环境变量注入到模板中生成最终的.load文件。这样同一套流水线配置可以通过不同的环境变量组合轻松应对开发、测试、预生产等不同环境的迁移任务。3.2 数据一致性校验的自动化实现这是流水线的“火眼金睛”。我编写了一个Python校验脚本validate_data.py它会在数据迁移阶段后被调用。#!/usr/bin/env python3 import sys import hashlib import pymysql import psycopg2 from contextlib import contextmanager # 从环境变量获取连接信息 src_conn pymysql.connect(...) tgt_conn psycopg2.connect(...) def get_table_counts(conn, schema, is_pgFalse): 获取所有表的行数 query SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema %s AND table_type BASE TABLE ORDER BY table_name; if not is_pg else SELECT schemaname||.||tablename as full_name, n_live_tup as rows FROM pg_stat_user_tables WHERE schemaname %s ORDER BY full_name; # ... 执行查询并返回字典 {table_name: count} def hash_table_key_fields(src_cur, tgt_cur, table, key_columns): 对比指定表关键字段的哈希值 src_query fSELECT {,.join(key_columns)} FROM {table} ORDER BY {key_columns[0]} tgt_query fSELECT {,.join(key_columns)} FROM {table} ORDER BY {key_columns[0]} src_cur.execute(src_query) tgt_cur.execute(tgt_query) src_hash hashlib.md5() tgt_hash hashlib.md5() for src_row, tgt_row in zip(src_cur.fetchall(), tgt_cur.fetchall()): src_hash.update(str(src_row).encode()) tgt_hash.update(str(tgt_row).encode()) return src_hash.hexdigest(), tgt_hash.hexdigest() def main(): src_counts get_table_counts(src_conn, source_db, is_pgFalse) tgt_counts get_table_counts(tgt_conn, public, is_pgTrue) all_pass True for table, src_count in src_counts.items(): tgt_count tgt_counts.get(table) if tgt_count ! src_count: print(f[FAIL] 表 {table} 行数不一致: MySQL{src_count}, PG{tgt_count}) all_pass False else: print(f[PASS] 表 {table} 行数一致: {src_count}) # 关键业务表哈希校验 critical_tables [(orders, [order_id, amount, created_at]), (users, [user_id, email])] with src_conn.cursor() as src_cur, tgt_conn.cursor() as tgt_cur: for table, keys in critical_tables: src_hash, tgt_hash hash_table_key_fields(src_cur, tgt_cur, table, keys) if src_hash tgt_hash: print(f[PASS] 表 {table} 关键字段哈希一致) else: print(f[FAIL] 表 {table} 关键字段哈希不一致) all_pass False sys.exit(0 if all_pass else 1) if __name__ __main__: main()这个脚本集成了行数校验和关键字段哈希校验。在CI流水线中如果它返回非零退出码整个阶段就会被标记为失败流水线自动停止。3.3 集成应用测试与性能基准在“应用兼容性测试”阶段我们需要动态配置应用连接串。对于Spring Boot应用可以在流水线中通过环境变量覆盖application.yml中的spring.datasource.url。对应的GitLab CI Job配置可能如下integration_test: stage: test image: maven:3.8-openjdk-11 variables: SPRING_DATASOURCE_URL: jdbc:postgresql://$PG_TEST_HOST:$PG_TEST_PORT/$PG_TEST_DB script: - echo 使用PG数据库进行集成测试: $SPRING_DATASOURCE_URL - mvn clean verify -Dspring.datasource.url$SPRING_DATASOURCE_URL artifacts: when: always reports: junit: - target/surefire-reports/TEST-*.xml - target/failsafe-reports/TEST-*.xml性能基准测试则单独一个Job在专用的压力测试环境中运行performance_benchmark: stage: performance image: postgres:14 services: - name: postgres:14 alias: pg-perf script: - | # 初始化pgbench数据 pgbench -i -s 100 pgbench_db # 运行混合读写测试持续60秒 pgbench -c 10 -j 2 -T 60 -r pgbench_db # 提取关键指标TPS TPS$(pgbench -c 10 -j 2 -T 10 -n pgbench_db 21 | grep tps ) echo 性能基准结果: $TPS # 这里可以添加逻辑与基线值比较如果下降超过阈值则失败 # if [ $(echo $TPS $BASELINE_TPS * 0.9 | bc) -eq 1 ]; then exit 1; fi rules: - if: $CI_PIPELINE_SOURCE schedule # 可以设置为定时任务定期跑性能基准4. 避坑指南与实战经验即使有了完美的流水线设计在实际操作中依然会踩坑。下面分享几个让我印象深刻的教训和对应的技巧。4.1 字符集与排序规则的“幽灵”问题MySQL的utf8mb4和PG的UTF8看似对应但排序规则Collation的差异会导致查询结果顺序不一致甚至影响唯一性约束。MySQL的utf8mb4_unicode_ci是大小写不敏感的而PG默认的排序规则通常是大小写敏感的。踩坑实录在一次迁移后应用发现用户登录时邮箱UserExample.com和userexample.com在PG里被识别为两个不同的账号而在MySQL里是同一个。原因是应用依赖了MySQL的大小写不敏感特性。解决方案应用层修正最佳实践是在应用层进行规范化处理如登录前将邮箱转为小写不依赖数据库的排序规则。数据库层处理如果必须依赖在PG中可以使用citext扩展大小写不敏感的文本类型或者在创建索引/约束时使用LOWER()函数。但必须在CI的结构检查阶段就加入对此类字段的检测规则例如扫描所有VARCHAR字段如果其在MySQL中使用了_ci排序规则则在流水线中抛出警告要求明确处理方案。4.2 时区处理的“时间旅行”MySQL的DATETIME类型不包含时区信息而PG的timestamp无时区和timestamptz带时区行为不同。如果应用代码对时区的假设模糊迁移后会引发时间错误。实操心得统一使用UTC在应用和数据库中所有时间戳的存储和内部处理都使用UTC时间。这是最根本的解决方案。迁移工具配置在pgloader配置中明确使用type datetime to timestamptz并指定using zero-dates-to-null来处理MySQL中的0000-00-00 00:00:00非法日期。流水线验证在数据校验阶段专门编写针对时间字段的抽样检查。不仅比较值是否相等还要比较其代表的绝对时间例如都转换为Unix时间戳后比较。可以随机抽取100条记录将时间字段在应用层渲染后比对。4.3 自增主键与序列的“断档”风险MySQL的AUTO_INCREMENT和PG的SERIAL背后是序列SEQUENCE在迁移后可能不同步。如果迁移过程中使用了COPY或INSERT ... SELECT并手动指定了ID可能会造成PG序列的当前值远小于表中已有的最大ID导致后续插入产生主键冲突。排查技巧 在数据迁移完成后流水线中必须增加一个“序列同步”步骤。脚本如下#!/bin/bash # 此脚本在数据迁移Job成功后执行 for TABLE in $(psql $TGT_DB_URL -t -c SELECT tablename FROM pg_tables WHERE schemanamepublic AND has_sequencet;); do # 获取表的最大ID MAX_ID$(psql $TGT_DB_URL -t -c SELECT MAX(id) FROM \$TABLE\; | tr -d ) # 获取关联序列的名字通常是 ${TABLE}_id_seq SEQ_NAME${TABLE}_id_seq # 重置序列 if [ ! -z $MAX_ID ] [ $MAX_ID ! NULL ]; then psql $TGT_DB_URL -c SELECT setval($SEQ_NAME, $MAX_ID); echo 已重置序列 $SEQ_NAME 为 $MAX_ID fi done将这个脚本作为数据迁移阶段后的一个固定步骤可以彻底避免因序列未更新导致的插入失败。4.4 长事务与锁的“性能杀手”在迁移海量数据时如果使用单条大事务可能会产生巨大的WAL日志长时间持有锁阻塞查询甚至导致主从延迟。注意事项分批迁移在pgloader配置中合理设置batch rows和batch size参数将大事务拆分为多个小批次提交。监控与调整在流水线的数据迁移阶段实时监控目标PG数据库的锁情况pg_stat_activitypg_locks和WAL增长。可以在CI Job中嵌入监控脚本如果发现长事务或锁等待超时则自动终止并标记失败提醒调整批次参数。分离索引对于超大表可以考虑在迁移数据时不创建索引disable triggerscreate no indexes待数据全部导入后再在流水线的后续步骤中并行创建索引这通常比带着索引导入快一个数量级。5. 将流水线融入研发流程从项目到常态一个成功的MySQL2PG迁移CI流水线其价值不应随着一次迁移结束而消失。它应该沉淀为团队的基础设施和研发规范。流程固化将这套流水线模板化。任何新的、需要进行数据库迁移的项目都可以快速复制这套.gitlab-ci.yml和配套脚本只需修改数据库连接等配置即可。这大大降低了后续项目的启动成本。质量卡点在团队的工作流中将数据库Schema的变更也纳入版本控制例如使用Liquibase或Flyway。任何对MySQL的DDL变更在合并到主分支前都必须通过这条迁移流水线的“结构转换与检查”阶段确保其能平滑转换为PG语法。这相当于为异构数据库环境设置了前置质量门禁。常态化演练为重要的生产数据库配置一个定期的、指向预生产环境的“演练”流水线每周或每月自动运行一次。这不仅能持续验证迁移脚本的有效性适应源库的变化还能不断测量和优化迁移性能确保当真正需要割接时你对整个过程的时间和资源消耗了如指掌。最后我想说的是这套CI流水线的建立最大的收获不是那一次成功的迁移而是它带给团队的信心和工程化思维。面对复杂、高风险的操作我们不再依赖个人的经验和临场发挥而是依靠可重复、可验证、自动化的流程。当控制台的绿灯依次亮起从结构检查到性能测试全部通过时你知道这次迁移已经成功了九成。剩下的只是一个按下确认键的动作。

相关新闻

虚拟化性能优化:深入解析大页内存原理、模式选择与KVM实战配置

虚拟化性能优化:深入解析大页内存原理、模式选择与KVM实战配置

1. 项目概述:为什么大页内存是虚拟化性能的“定海神针”在虚拟化环境里折腾过性能调优的朋友,大概都听过“内存墙”这个词。当你的虚拟机(VM)数量一多,或者单个VM对内存需求巨大时,传统的4KB小页内存管理方…

2026/8/4 3:59:30 阅读更多 →
C++面向对象封装SDL游戏开发实战:从框架设计到性能优化

C++面向对象封装SDL游戏开发实战:从框架设计到性能优化

1. 项目概述:为什么选择C、面向对象与SDL的组合?如果你对游戏开发感兴趣,尤其是想从底层理解图形渲染和程序逻辑,那么C、面向对象编程(OOP)和SDL(Simple DirectMedia Layer)这个组合…

2026/8/4 3:58:30 阅读更多 →
科研 Agent 先别急着搜:为什么 schema discovery 才是工作流的第一步

科研 Agent 先别急着搜:为什么 schema discovery 才是工作流的第一步

导语 过去一周,Agent 讨论的重点已经不只是“模型更强了”,而是“模型开始跨任务工作了”。但科研工作流里,真正先卡住 Agent 的,往往不是搜不到论文,而是它根本不知道有哪些字段能筛、哪些算子能用、哪些排序合法。对…

2026/8/4 3:58:30 阅读更多 →

最新新闻

语义缓存管理

语义缓存管理

"怎么退换货"有无数种问法——精确缓存(完全相同字符串才命中)对这种场景几乎无效,每个改写都穿透到模型烧一遍 token。需要的是"语义"层面命中。 核心论点 语义缓存(Semantic Cache,按语义相似度…

2026/8/4 4:41:52 阅读更多 →
从一到无穷大 #74:智能全域巡检的产品形态与能力边界

从一到无穷大 #74:智能全域巡检的产品形态与能力边界

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。 文章目录引言产品形态公有云已经走到哪里统一对象:UModel 到底统一了什么STAROps 主…

2026/8/4 4:41:52 阅读更多 →
终极Windows界面优化指南:用ExplorerPatcher完美定制任务栏与开始菜单

终极Windows界面优化指南:用ExplorerPatcher完美定制任务栏与开始菜单

终极Windows界面优化指南:用ExplorerPatcher完美定制任务栏与开始菜单 【免费下载链接】ExplorerPatcher This project aims to enhance the working environment on Windows 项目地址: https://gitcode.com/GitHub_Trending/ex/ExplorerPatcher Windows界面…

2026/8/4 4:41:52 阅读更多 →
Agent 惊艳全场却瘫痪生产?20 个核心概念揭秘企业级 AI 应用落地真相!

Agent 惊艳全场却瘫痪生产?20 个核心概念揭秘企业级 AI 应用落地真相!

模型智商 只是上限, 工程体系 才决定底线 这两年,AI 圈最不缺的就是新词,特别是 “Agent” 。从智能体、数字员工、AI Copilot,到各种自动化助手,名称层出不穷。 但只要你真正带团队做过企业级 AI 应用的落地&#xff…

2026/8/4 4:41:52 阅读更多 →
若依框架深度解析:从RBAC权限到代码生成的企业级Java开发实践

若依框架深度解析:从RBAC权限到代码生成的企业级Java开发实践

1. 项目概述:为什么选择若依作为企业级项目的起点?如果你是一名Java开发者,或者正在寻找一个能快速搭建后台管理系统的框架,那么“若依”这个名字你大概率不会陌生。它不是一个新潮的AI框架,也不是一个底层算法库&…

2026/8/4 4:41:52 阅读更多 →
Python命令行参数解析:从sys.argv到argparse与click实战指南

Python命令行参数解析:从sys.argv到argparse与click实战指南

1. 从命令行到脚本:为什么参数传递是Python开发的必修课如果你写过Python脚本,尤其是那些需要处理不同输入、配置不同运行模式的脚本,那么你一定遇到过这个问题:如何让脚本“听话”地接收外部指令?是每次打开代码文件修…

2026/8/4 4:40:51 阅读更多 →

日新闻

AI Agent白手起家26: 使用标准事件驱动大模型实践

AI Agent白手起家26: 使用标准事件驱动大模型实践

纲要 练习目标:掌握大模型标准事件的调用回顾 LangChain 中的核心标准事件 invokestreambatchastream_eventswith_structured_output 环境准备实战代码:多种事件调用对比 同步调用与流式输出批量处理异步事件流监听结构化输出 运行说明与预期结果总结与扩…

2026/8/4 0:00:40 阅读更多 →
dealsea是什么?跨境卖家必知的美国deal站入门指南

dealsea是什么?跨境卖家必知的美国deal站入门指南

说实话,第一次听说美国这个老牌折扣网站的跨境卖家,十个有八个会问同一个问题:这个平台到底是干嘛的?我见过一个做家居出口的朋友,他在亚马逊上月销二十万美金,却从来没用过它。我给他看了首页——一屏一屏…

2026/8/4 0:01:40 阅读更多 →
清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

清华大学重磅EST:植物自导电闪蒸焦耳热600°C/2600°C两步法!稀土超积累植物秒级转化为CeO₂-石墨烯电催化剂!

通讯作者:邓兵、刘建国通讯单位:清华大学DOI:https://doi.org/10.1021/acs.est.6c00603研究背景稀土元素(REEs)是清洁能源技术与电子器件不可或缺的核心原料,然而传统提取方式依赖能耗高、排放大的采矿与强…

2026/8/4 0:01:40 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/3 4:58:13 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/3 1:53:31 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/3 4:36:35 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/3 13:07:03 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/3 5:19:38 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/3 8:27:36 阅读更多 →