Airtable 的 MySQL 8.0 升级之旅

警惕参数变化,MySQL 8.0 升级避免再次踩坑 MySQL 8.0新特性专栏目录 我们知道MySQL 8.0相对于MySQL 5.7加入了很多新特性,在功能和安全性上做了很多的优化和调整,这就不可避免地会修改一些参数或者函数。**我们现有业务数据从MySQL 5.7及之前的版本升级到8.0,需要特别警惕这些参数的变化,这些变化可能会导致业务行为发生一些意料之外的结果!!!** 最近MySQL 8.0 升级的过程中,我梳理了一些业务可能用到的、重要的参数变化,包括一些MySQL 8.0中已经废弃的参数和部分常见参数默认值的变化。 阅读详情

简介

去年,我们把 Airtable 的 MySQL 数据库从 5.6 升级到了 8.0。MySQL 大版本升级总是需要精心策划、测试和部署;由于我们一次性升级了两个大版本,所以这次升级更加困难。这对我们的基础架构团队来说是一项艰巨的任务,花了一年多时间才得以顺利完成。

作为该项目的一部分,我们为我们的 MySQL 基础架构引入了强大的测试与运维新功能,并在这个过程中学到了许多关于 MySQL 内部实施细节的知识。我们将在本文中分享经验和心得。

系统背景

MySQL 是 Airtable 的主要存储系统。我们选择 MySQL 是因为它既稳定又高效。我们在 AWS RDS 运行 MySQL,并对其基础架构进行了大幅度改进,使得数据库的配置、管理和监控变得简单许多。

我们之所以决定升级到 MySQL 8.0,是因为与 5.6 相比,它有极具吸引力的新功能和性能提升:

  • 支持使用 ALGORITHM=INSTANT 的在线 schema 变更。这意味着某些类型的 schema 变更(包括添加列,这是我们最常见的 schema 变更类型)可以作为仅元数据的快速操作来执行。
  • JSON 数据类型。一直以来,我们使用包含 JSON blob 的文本类型列来解决 MySQL 缺乏在线 schema 变更的问题,尤其是对于大型表而言。
  • 其他新功能包括常用表表达式、窗口函数、SKIP LOCKED 以及更多类型的索引,这些功能在不同情况下非常有用。
  • 总体性能提升。据 Oracle 报告,MySQL 8.0 在某些情况下的处理速度是原来的两倍。

在开始这个项目时,我们就知道这将是一项艰巨的任务。任何重大的基础架构变更都伴随着巨大的风险,而升级主存储系统将这一风险提升到了新的高度。最重要的是,我们必须避免在正确性、性能或可用性方面出现任何问题,以免影响直面客户的工作。

自动化和预生产测试

项目第一阶段的重点是针对 MySQL 8.0 运行现有的自动化测试套件。我们配置了 CI 系统,以便针对每个拉取请求同时运行 MySQL 5.6 和 8.0 的所有测试。MySQL 8.0 的失败会发出警告,但不会阻止合并。我们还升级了一些非生产测试环境。

这次测试发现了一些语法或兼容性问题,这些问题相对来说比较容易解决:

  • 自 5.6 版以来,新增了许多关键字和保留字。我们的一个表中有一列名为 grouping,但在 8.0.1 中 GROUPING 变成了保留字。我们对代码进行了调整,找出所有受影响的查询,并添加了反引号来转义列名。
  • 8.0 中的用户管理与 5.6 不兼容。这是我们自己造成的问题,因为我们跳过了 5.7(作为桥接版本),而且我们试图直接从 5.6 主节点到 8.0 从节点。我们试图通过仅使用这两个版本共有的功能部分来解决这个问题,但由于添加新 MySQL 用户的操作比较少见,最终我们决定不深究这个兼容性问题。

在项目的这一阶段,我们还花了大量时间构建仪表盘、监控和运维工具,用于配置和升级 MySQL 8 实例。

使用生产流量进行测试

经过几个月成功的自动化测试和预生产测试,我们确信我们的应用程序和 MySQL 8 不存在基础问题。然而,我们仍然需要了解 MySQL 8 在规模更大、查询种类更多的生产工作负载下的性能如何。

我们最重要的两个 MySQL 集群是:(1)基础分片 (base shards),用于存储表和单元格等 Airtable 基础相关的基础范围数据 (base-scoped data);(2)主分片 (main shard),用于存储用户和工作空间信息等非基础范围数据 (non-base-scoped data)。因为历史原因,我们内部也称基础分片为应用程序 live 分片或 live 分片。

file

对我们来说,在生产中测试新的基础分片是相当安全的。我们的内部分片管理系统可以让我们控制如何将新的基础范围数据分配给分片,我们还可以根据负载、硬件问题或其他系统事件在分片之间转移现有的基础范围数据。这意味着我们可以缓慢地提升单个分片的流量,如果出现问题,我们可以安全地将基础范围数据转移到其他地方,并停用有问题的分片。

利用这一功能,我们启动了一个运行 MySQL 8 的新基础分片,并转移了几个内部专用基础范围数据。一周后没有出现异常(根据我们的监控和用户报告),我们也开始在 MySQL 8 分区上分配新的基础范围数据。

随着 MySQL 8 基础分区上的流量开始增加,我们遇到了两个主要问题,下面将对这两个问题进行描述。

问题 1:大型 WHERE IN 子句

我们发现了一个性能问题,在 MySQL 8 中,带有大型 WHERE IN 子句的查询的优化方式不同。我们的查询使用了包含数百甚至数千个值的 WHERE IN 子句。在 MySQL 5.6 中,查询优化器会使用适当的索引进行过滤,但在 MySQL 8 中,优化器会选择执行全表扫描。我们推测,MySQL 8 范围优化器比 5.6 使用更多内存,导致这些查询超出 range_optimizer_max_mem_size 阈值。解决方法很简单:增加 range_optimizer_max_mem_size,这样之后,我们的查询再次使用了索引。

问题 2:插入更新的难题

插入更新(upsert)问题是我们在升级过程中最棘手的。

我们注意到 MySQL 8 分区上的死锁率和查询速度明显提高。这种情况每次会不可预测地发生几分钟,在此期间服务器会变得非常慢。大多数查询,即使是看似无害的查询,也需要 30 多秒钟才能完成。性能指标和 InnoDB 状态监控器输出(通过执行 SHOW ENGINE INNODB STATUS)显示有大量事务被回滚,但不清楚这是根本原因还是潜在问题的症状。

我们为 InnoDB 监控输出采样添加了指令,并分析了运行事务在缓慢期间隐含的锁等待图。在调查了多个死胡同后,我们发现了一个关键问题,即大多数受阻查询都是对具有唯一二级索引的表进行 INSERT … ON DUPLICATE KEY UPDATE 查询,而键冲突发生在唯一二级索引上(而不是主键上)。
进一步调查发现了一个MySQL 错误报告,该报告在 5.7.26 中得到了修复,改变了 INSERT … ON DUPLICATE KEY UPDATE 查询的锁定行为。错误修复减少了键冲突情况下的锁定范围,其副作用是允许事务更紧密地交错。这意味着像我们这样的工作负载更有可能出现等待和死锁。

在我们的案例中,InnoDB 监控输出样本显示问题出在唯一索引的 next key 锁。当出现某些病态的死锁序列时,一些非常大的事务就会回滚,在回滚的过程中又阻塞了其他事务。

Jakub Lopuszanski 在 MySQL 错误报告上发表的评论概述了一些可能的解决方法。我们考虑了其中两个方案:调整应用程序工作负载,不使用 AUTO_INCREMENT 主键列;将隔离级别从 REPEATABLE READ 降为 READ COMMITTED。

在 Airtable,我们通常使用应用程序生成的随机 ID 作为主键,但我们仍有使用 AUTO_INCREMENT 主键(以及应用程序生成的 ID 上的唯一索引)的过时的表。我们考虑过完全迁移 AUTO_INCREMENT 主键,以解决间隙锁争用问题,但这需要大量的应用级变更(以及许多 schema 变更),而且仍然无法完全解决具有多个唯一索引的表的问题。

因此,我们决定将事务隔离级别从 REPEATABLE READ 降为 READ COMMITTED。在 READ COMMITTED 中,大多数操作根本不使用间隙锁,因此死锁的可能性大大降低。切换的主要缺点是,我们失去了 REPEATABLE READ 提供的快照隔离。

幸运的是,我们能够利用基础分片工作负载的一个独特属性。基础分片负责存储基础范围内的数据,每个基础范围数据的操作都通过一个 NodeJS 服务器进程进行序列化。从概念上讲,这意味着我们不应该对基础数据进行多个并发读取或写入操作,因此我们不需要 REPEATABLE READ 更强的快照隔离属性。

为了验证我们的理解,我们在数据库访问层中实施了客户端检查,如果我们发出的查询不在单个应用程序的范围内(即缺少 WHERE applicationId = ? 子句),就会产生警告。这种检查捕获了大约 10 个案例,其中没有一个是真正的错误,只需要进行简单修复。

修复这些警告后,我们在所有环境中为基础分片启用了 READ COMMITTED,再也没有出现与 upsert 相关的性能问题。

记录/回放

对于主分区,我们必须采取不同的生产测试策略。一般来说,对主分区进行更改风险很大。因为我们只有一个主分区,所以不能像基础分区那样逐步增加和减少流量。这意味着一旦出现问题,整个网站都可能瘫痪。

我们决定建立一个记录/回放系统,这样我们就可以根据主分区的快照和实际生产工作负载的记录来执行离线测试。我们还简要考虑了其他方案:

  • 仿真测试。很难构建真实的仿真工作负载,我们对真实生产工作负载的多样性很感兴趣。事实上,我们已经针对 MySQL 8 运行了现有的仿真工作负载(我们的自动测试套件)。
  • 对新旧数据库进行双重写入,然后将读取切换到新数据库。我们决定不采用这种方法,因为我们的应用程序大量使用事务和 ACID 一致性保证。此外,虽然这种方案提供了许多很好的运行特性,但我们认为它比记录/回放的工作量要大得多。

记录和回放真实的 SQL 流量是一项艰巨的工作,因为它根本就不牢靠。在记录或回放过程中,轻微的扰动和不精确会导致查询的到达时间或排序不同。这意味着数据库状态会不同,查询到达服务器的确切时间会不同,并发查询获得锁的顺序也会不同。一些在现实生活中有效的插入可能会在回放中失败,随后的更新也会失败。

尽管存在这些限制,我们仍希望记录/回放能揭示主要工作负载中的任何重大问题。根据我们在基础分片上的经验,我们认为自己已经意识到了有问题的查询模式(大型 WHERE IN 子句、并发向上插入),并知道要密切关注查询延迟和错误率等指标。

我们有几种记录流量的方法:

在 MySQL 层记录(如通过慢查询记录器)是最准确的,因为它能捕获针对数据库运行的每个查询。但缺点是会给数据库实例增加大量负载。ProxySQL 层的记录也非常准确,但它缺乏有关事务和连接状态的应用级信息,而这些信息对重回保真度非常重要。对于我们来说,ProxySQL 的更改也很难进行增量部署和测试。最后,在应用层进行记录会增加运行查询的额外开销,但它更易于测试和逐步发布。

最终,我们选择了在应用层进行记录,因为这便于测试和逐步发布。我们增强了 MySQL 客户端封装程序,以便将查询记录到本地磁盘。然后,我们使用 logrotate 将查询日志发送到 S3。

我们应用程序的读取比写入多得多,但大部分读取都是简单的连接和点查询。我们决定记录 100% 的写入,只记录 10% 的读取(以减少开销)。在几周的时间里,我们慢慢增加了记录次数。在发布过程中,我们观察了服务器端和应用程序的性能指标,没有发现任何明显的开销。

为了回放流量,我们开发了一个简单的回放客户端,它可以读取记录的查询日志,并针对主数据库的快照回放查询。为了驱动足够的负载,我们使用 Kubernetes 同时运行多个并发回放客户端。整个回放过程从端到端都是自动化的:从快照中创建一个新的 MySQL 实例,将查询日志下载到 EFS,以及在 Kubernetes 上运行和协调回放客户端。

全面回放测试的结果很有启发性:

  • 我们发现了少量写入错误(不到百万分之一)。经过调试,我们确定这些都是回放过程中引入的人工痕迹(例如,记录了同一条记录的 INSERT 和 UPDATE,但在重播过程中,INSERT 语句可能需要更长的时间才能完成,导致 UPDATE 语句在 INSERT 语句完成之前就被回放了)。
  • 我们发现并修复了在基础分片上首次遇到的大 WHERE IN 子句问题的更多实例。我们还增加了主分片上 range_optimizer_max_mem_size 的值,并借此机会将其中一些查询分页为更小的批次。
  • 在性能调查过程中,我们还发现了其他一些低效查询,并与应用程序开发人员合作对其进行了优化。这些优化包括强制使用特定索引、减少耗时查询的频率以及重构查询以扫描更少的数据。

在整个过程中,回放工具可以轻松重现上述问题,并验证我们的修复措施。我们还增加了对更快速度回放的支持,并用 3 倍和 5 倍的速度回放对我们的主数据库进行了负载测试。

虽然记录/回放有其局限性,但事实证明它仍然非常有用。我们发现并修复了查询计划效率低下的实际问题,并对我们的写入工作负载能否正确执行充满信心。

降级过程

没有备份计划,任何基础设施升级计划都是不完整的。即使我们进行了所有的测试和验证工作,我们仍然希望能够在最坏的情况下将主系统安全降级到 MySQL 5.6。

file

我们的计划是建立一个如上图所示的复制体系。我们希望从当前的 MySQL 5.6 主副本 [A],复制到新的 MySQL 8 副本 [B],然后再复制到 MySQL 5.6 后备副本 [C]。然后,我们要运行一致性检查,以确保三台主机上的数据库状态完全相同。升级时,我们将把 MySQL 8 副本 [B] 升为主节点。降级时,我们会将 MySQL 5.6 后备副本 [C] 升级。

这听起来很简单,但 MySQL 只支持在连续的主要版本之间复制,而且只支持从较低版本复制到较高版本。我们需要克服这两个限制。

为了了解情况,我们首先尝试在 RDS 中配置这种复制拓扑。RDS(正确地)将此配置识别为不支持,但我们还是通过使用 mysql.rds_set_external_master 手动完成了配置。切换到基于行的复制后,从 MySQL 5.6 向 MySQL 8.0 的向上复制似乎有效,但向下复制回 5.6 却无效。

我们开始研究,并找到了一篇关于从 MySQL 8.0 复制到 MySQL 5.7 的 Percona 博文。MySQL 8.0 使用了 MySQL 5.6 不支持的新默认字符集和校对。我们根据下表更新了 MySQL 8 实例的参数,使其与 MySQL 5.6 的默认设置相匹配:

file

这解决了大部分错误,但仍会间歇性地出现问题。经过进一步调试,我们发现这些问题与一些用于内部记录的 RDS 特定表(mysql.rds_sysinfo、mysql.rds_configuration、mysql.rds_replication_status、mysql.rds_history、mysql.rds_heartbeat2 和 mysql.rds_history)有关。我们找不到重新配置这些 RDS 表的方法,因此编写了一个脚本,使用以下操作序列自动跳过违规的 binlog 条目:

  • CALL MySQL.rds_stop_replication
  • CALL MySQL.rds_reset_external_master
  • CALL MySQL.rds_set_external_master(…)
  • CALL MySQL.rds_start_replication

这样,我们就可以近乎实时地从 A 数据库顺利复制到 B 数据库,再复制到 C 数据库。

在实现了对数据库 C 的可靠复制后,我们的下一个关注点是验证数据是否与上游数据库保持一致。为了回答这个问题,我们编写了另一个脚本:a) 暂停在数据库 A 上的复制;b) 等待数据库 C 跟上;c) 在每个表上运行 MySQL 的CHECKSUM TABLE,以验证数据已成功从 MySQL 8 复制到 5.6。这让我们确信,如果需要退回到数据库 C,数据不会丢失或损坏。

如果需要,可以降级回 MySQL 5.6,这让我们有信心继续升级到 MySQL 8。

升级过程

从概念上讲,升级过程很简单:

  • 配置运行 8.0 的新 MySQL 副本
  • 建立从 5.6 主系统到 8.0 副系统的复制
  • 从旧的主系统向副本进行故障切换 (failover)

file

前两个步骤相对安全。它们可以随时执行(甚至回滚),而不会影响生产流量。最后一步,即故障切换到新的主服务器,才是最危险的地方。

我们考虑的第一个问题是可怕的「脑裂 」情况,即故障转移过程中的错误导致两个 MySQL 实例都认为自己是主实例。当这两个实例接受客户端写入时,它们的状态就会发生变化,从而导致数据不一致。修复「脑裂」是一个代价高昂的手动过程,因此我们希望确保在故障切换过程中发生的错误不会导致「脑裂」。

file

防止「脑裂」的一种方法是「围栏 (fencing)」:防止向旧主站写入数据。典型的围栏方法是使用 MySQL 的 read_only 参数,在将新主站改为读写模式之前将旧主站改为只读模式。作为额外的保证,我们还使用了一个「隔离」AWS VPC 安全组来阻止来自应用程序的网络流量,并以与 MySQL 的 read_only 参数相同的方式进行协调:禁用到旧主站的流量,启用到新主站的流量,然后执行 DNS 切换。安全组的更改传播速度很快,因此这不会给我们的故障转移程序增加额外的时间。

file

我们考虑的第二个问题是在 failover 过程中出现错误,导致没有可用的主服务器。例如,如果我们无法启用到新主数据库的流量,就会导致无法访问数据库实例,整个站点就会瘫痪。

为了解决这个问题,我们开发了一系列脚本,使整个升级过程完全自动化。这样,我们就可以在非生产环境中广泛测试升级,从而增强了我们的信心。我们还将 failover 过程的所有步骤压缩到一个脚本中。这是一项重要的操作简化,因为这意味着无需手动复制粘贴多个命令或在多个终端窗口之间切换。

作为最后的检查,我们还问自己:即使我们做了所有的准备和测试,还有什么地方会出错?我们认为,剩下的最大风险就是在升级上线后遇到以前不知道的新性能问题。为了解决这个问题,我们准备了一系列减轻数据库负载的技术:

  • 我们建立了动态对不同客户的操作进行限流的能力。
  • 我们建立了强制特定事务使用 READ COMMITTED 的能力,以防某些工作负载意外遇到上述的 upsert 问题。
  • 我们调整了杀死长时间运行查询的策略。
  • 我们准备了一份重度用户工作负载列表,必要时可以禁用这些负载。

升级当天

所有的准备工作都指向了升级那一天的到来。这无疑是一个关键时刻:MySQL 8 的升级是 Airtable 历史上迄今为止最大规模的一次整体基础设施更换。由于整个过程已经在文档中明确规定,实际上在升级的具体时间 T 之前,我们并没有太多工作要做。我们将升级时间安排在下班后,以尽量减少对客户的潜在影响。

作为额外的预防措施,所有参与升级的工程师都在深夜开始工作,我们还非正式地建议他们在下午小睡一会儿。这听起来有点傻,但我们希望整个团队都能休息好,为紧急情况做好准备。

T - 2 小时,我们启动了所有必要的连接,准备升级。
T - 1 小时,我们进行复制检查。
T - 30 分钟,我们将升级团队集合到 Zoom 上,并验证与生产环境的连接性。
T - 15 分钟,我们禁用后台处理服务。
T,我们执行规定的升级命令并等待。房间里的紧张气氛溢于言表。最初的迹象是积极的:网站加载了,我们能够加载基础范围数据,而且没有大量错误涌入我们的监控系统。到目前为止,一切顺利。

之后,我们开始启动后台服务。这就是我们遇到的第一个障碍:我们的一个计划 cron 作业超时了。我们重新禁用了它,并深入研究。我们意识到,它正在运行一些大型扫描查询,这些查询通常是通过缓存提供的,但我们的新主服务仍处于冷启动状态,正在预热缓存。等了一会儿后,我们重新启用了 cron 作业,让它重新开始处理。

T+2 小时,没有再出现任何错误,我们结束了今晚的工作。在接下来的几天里,我们继续积极监控网站的健康状况。两周后,没有再出现任何问题,我们正式宣布升级成功。

结论

我们从 MySQL 5.6 升级到 8.0 的旅程堪称一场史诗般的挑战。这一壮举的完成依赖于多个团队工程师的共同付出。我们必须克服许多深层次的技术挑战,并开发出一批与 MySQL 基础架构相关的新测试和运维工具。

这次经历给我们带来的一个重要启示是,我们在规划、准备和测试方面花费的时间确实得到了回报。举例来说,拥有安全降级功能(尽管我们并没有使用它)对于做出是否升级的决定是绝对必要的。我们开发的记录/回放系统也已经产生了红利,我们已经用它来测试后续的一系列 MySQL 基础设施变更。此外,我们为升级当天开发的负载分流技术和运行手册在其他网站事故中也证明非常有用。

最后,我们感到非常欣慰的是,最终的结果与我们付出的努力相匹配。尽管我们做了充分准备,但在大型升级当天,总有可能出现意外。我们对各种可能的结果都做好了心理准备,我们得到的结果非常接近最佳情况。


💡 更多资讯,请关注 Bytebase 公号:Bytebase

开源自动化工具n8n:从零构建可视化工作流,连接AI与数百应用 工作流自动化是现代软件工程中提升效率的核心技术,其原理在于通过预定义的规则与逻辑,将不同系统、服务或数据源串联起来,实现任务的自动执行与流转。这项技术的核心价值在于打破数据孤岛,减少人工重复操作,显著提升个人与团队的协作效率与响应速度。在应用场景上,它广泛覆盖了数据同步、定时任务、跨平台通知、CI/CD扩展以及当前热门的AI工作流编排等领域。n8n作为一个开源、可自托管的可视化工作流自动化平台,正是这一理念的杰出实践。它通过拖拽节点的直观方式,让用户无需深入编码即可连接数百种应用与服务,构建复杂的自动化流程 阅读详情

相关推荐

SpringBoot+Vue+MySQL 高校学科竞赛平台 完整可运行版(源码+文档)

本项目基于SpringBoot+Vue+MySQL构建高校学科竞赛管理平台,覆盖学生、教师、领队教师、管理员四大角色,实现竞赛发布、报名、刷题、评分、公示等全流程闭环管理。系统架构清晰,技术主流,配套完整源码、数据库脚本、万字论文、开题报告、答辩PPT及部署文档,支持一键运行,适用于毕业设计、课程设计及院系二次开发,真正实现“开箱即用”。

招风的黑耳优快云 295

airtable mysql_airtable(airtable中国版)

A puck of mass 79.1 g and radius 4.45 cm slides along an air table at a speed 。球的大规模外部g和半径达44.5厘米空气桌子上滑步的v =速度1.47米/秒,显示在下面的图表。它使称在第二个球碰撞的半径6.92厘米和大众140克(出生后的休息),这样.错误编号:145 问题分析: 文件无法打开错误,一般提示为:cant ...

weixin_36328628的博客 547

Vivado时序违例debug

显示了数据路径延迟。例如,对于违例路径,若布线延迟超过50%,说明该延迟是导致时序不能收敛的主要因素,因此可围绕降低布线延迟这一靶心达到时序收敛。对于跨时钟域路径,Requirement数值会有所变化,但如果数值为0.1,显然是不合理的。目的时钟路径单元,时钟从adc0_bufg/O输出,到达PLLE4_ADV,经过BUFGCE输出,最终到达SRLC32E移位寄存器,对应。源时钟路径单元,时钟从adc0_bufg/O输出,到达PLLE4_ADV,经过BUFGCE输出,最终到达FDRE触发器,对应。

weixin_44513618的博客 1622

[轻松掌握Airtable:从表格到数据库的完美转型]

Airtable提供了灵活的数据库管理功能,结合Python的强大编程能力,可以实现高效的数据管理流程。Airtable API 官方文档PyAirtable GitHub 仓库Langchain_community 文档。

afTFODguAKBF的博客 1307

Workbuddy+DeepSeek V4傻瓜流配置全指南:API接入、模型切换与Agent实战

AI编程助手的核心价值不在于模型本身,而在于如何稳定、安全、低门槛地调用其能力。Agent作为智能体范式,依赖可靠的运行时环境与标准化API通信;DeepSeek V4系列凭借高吞吐、低延迟和强工具调用支持,成为当前生产级Agent的理想引擎。Workbuddy则通过本地配置管理、环境变量注入与UTF-8无BOM容错等工程设计,将复杂部署简化为可复现、可版本化、可团队协同的实践流程。本文聚焦API接入路径下的真实卡点——从Key获取验证、models.json字段语义到沙箱权限控制,覆盖开发者在Window

weixin_33702545的博客 2394

Cadence Spectre仿真保姆级教程:从DC/AC到PSS/PV,手把手教你搞定模拟电路分析

作为业界标准的Cadence Spectre仿真器,以其精确的算法和丰富的分析类型,成为每个模拟IC工程师必须掌握的利器。本文将带你从零开始,系统掌握Spectre仿真的核心技能,从最基础的DC工作点分析到复杂的PSS相位噪声仿真,每个步骤都配有详细的操作指导和实用技巧。记得我第一次使用Spectre仿真一个简单的两级运放时,花了整整三天时间才得到正确的AC响应曲线。过程中踩过的坑、浪费的时间,现在想来都是宝贵的学习资源。与传统的AC分析不同,STB分析可以在不破坏环路的情况下评估稳定性。

weixin_30898555的博客 336

Airtable 在线数据库介绍

Airtable 常用功能介绍 Airtable 是新型的在线编辑表格工具,可以把文字、图片、链接、文档等各种富文本聚合在一起。这里简单分析这个软件的功能和特点。 一、建立数据库 1、注册并登录Airtable 这里可以使用国外的网络 2、新建一个工作区(workspace,类似于数据库)。每个工作区下面有很多表格(类似于数据表)。 3、点击进入数据表表(界面和excel类似) 4、在第一栏...

MichaelAn的博客 7315

FPGA波束形成:从算法到硬件的艺术之旅

本文深入探讨了FPGA在波束形成技术中的应用,从算法原理到Verilog硬件实现的全过程。文章详细分析了FPGA并行处理、低延迟和可重构特性如何优化波束形成系统性能,并提供了Verilog关键模块代码示例和资源优化策略,为工程师实现高效FPGA波束形成解决方案提供实用指导。

tea88的博客 1047

airtable mysql_http客户端与和风天气

应用与外界交互,使用api接口是最常见的。现在利用wxbit解释下如何获取和风天气的天气预报api。和风天气网站(https://www.heweather.com)注册账号。进入控制台,应用管理,新建应用。(貌似免费用户只能建一个免费账号。)记住应用的key。组件设计界面,拖入3个可视组件:文本输入框、按钮、标签,1个非可视组件:http客户端。(这个是wxbit服务器新改名的组件,赞一个。原名...

weixin_39952031的博客 504

iOS WKWebView H5微信支付跳转

iOS WKWebView H5微信支付跳转 需求:iOS客户端实现嵌入H5进行微信支付跳转到微信客户端,支付完成后再跳转回我们的APP,解决WKWebView无法跳转回APP的BUG. 阅读前提: 了解WKWebView基本初始化及使用 了解如何利用URL Schemes进行应用间跳转 公司或个人已经在微信后台注册了一级域名 GitHub地址(附代码) :iOS WKWebView H5微信支付跳转 简书地址 :iOS WKWebView H5微信支付跳转 博客地址 :iOS WKWe...

ForeverMyheart的博客 2047

YOLOv8剪枝 稀疏训练+slim剪枝测试精度仅掉1.6个点,速度提高10.3fps!

摘要 本文介绍了YOLOv8剪枝方法Slim(Network Slimming),通过L1正则化作用于BN层的缩放因子(γ),自动识别并剪除冗余通道,实现模型轻量化。核心步骤包括:稀疏训练(引入L1正则化)、通道剪枝(按γ阈值裁剪)、微调恢复精度。实验表明,该方法能有效压缩模型大小、减少计算量,且支持通过调整speed_up等超参数控制剪枝强度。移植代码需修改C2F模块以适配剪枝,并配置稀疏训练参数(如reg、sl_epochs)。最终剪枝模型需移除优化器以减小体积,但不支持多卡训练。

FJN110的博客 862

开源插件ACTable已经打包放到Maven中央仓库啦!

开源插件ACTable(基于Mybatis自动建表、并支持共通CUDR)上线啦!由于很多小伙伴在使用actable的时候都不得不下载源码,然后在本地install打包然后使用,所以最近我抽空,将其打包放在了maven中央仓库上,因此包的结构有所调整,引入方式如下:pom.xml中引入<dependency> <groupId>com.gitee.sunchenbin.mybatis.acta

孙琛斌的专栏 7848

SQL进阶技巧:数据预处理如何对数据进行分桶【分箱】?

本文详细介绍了数据分析中常见的几种分桶方式:基于业务规则的分桶、等距分桶及等频分桶等,针对每种分桶方式给出了SQL实现

石榴姐yyds 4021

mybatis的自动建表方法——ACTable

ACTable的使用 ACTable简单说就是对mybatis的一个增强组件,可以在你启动java应用的时候自动得执行建表语句 在你成功使用mybatis操作数据库后,额外如官方链接所示接入actable即可实现自动建表 https://www.yuque.com/sunchenbin/actable/ag3y1y 跳转后的是springboot的操作步骤,目前只支持mysql。 按照官方的步骤,配置好actable实现启动时自动建表后请注意一下, 即完成如下配置 。 注意@Component会覆盖@

weixin_45583482的博客 4857

CAPL如何设置或修改CANoe TCP/IP协议栈的底层配置

MSS = MTU - tcpHeader - ipHeader,也就是MTU = MSS(1360) + tcpHeader(20) + ipHeader(20) = 1400,说明CAPL是可以动态设置网络底层配置参数的!然后在CAPL中设置此网卡MTU值为1400,然后创建UDP套接字,一次性发送2000个字节,在Trace窗口看看首帧报文二层Data的长度。所以我们还不能用UDP协议来验,应该用TCP协议来验,也就是在TCP三次握手时通过Tester的MSS值推导出自己的MTU值。

jasonj333 992

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

spring-boot + mybatis-enhance-actable 实现mybatis自动建表

spring-boot + mybatis-enhance-actable 实现mybatis自动建表 因为mybatis-enhance-actable是基于mybatis的自动构建工具所以使用前需要先配好mybatis 配置mybatis参照 https://blog.csdn.net/weixin_43866295/article/details/86500610,这里就不多说了 1.导入...

weixin_43866295的博客 9487

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

A.CTable开源框架Mybatis增强自动创建表/更新表结构/实现类似hibernate共通的增删改查-mybatis-enhance-actable

mybatis-enhance-actable-1.3.1.RELEASE 不用再为mybatis无法自动创建表,不提供基本的增删改查而苦恼啦!有了A.CTable这将不再成为你苦恼的理由,而且学习简单,只要进行简单的配置,然后稍微看下源码注解就可以上手了,最新版本集成了tk.mybatis能够更好的支持日常的CUDR。

孙琛斌的专栏 2万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Docker Compose:搭建本地多服务开发环境

从一个 Java API、PostgreSQL 和 Redis 开始,配置服务名、端口、环境变量、健康检查、数据卷和依赖关系。理解 Compose 文件如何被解析、项目如何隔离,以及哪些数据不能依赖“重建容器”保留,能够把个人开发环境整理成团队可复用的启动入口。

m0_62221377的博客 476

AI全栈实战 | 3.9-01 爬虫入门:requests 加 BeautifulSoup 三分钟跑通,但 90% 的人栽在这 4 个“礼貌“问题上

⚠️:本文内容仅用于。请遵守目标站点的服务条款与相关法律法规,不得对目标服务造成负担,不得采集、传播个人隐私数据。技术是中性的,边界在你手里。爬虫的入门技术(requests 发请求 + BeautifulSoup 解析)三分钟就能学会。真正区分"会用爬虫"和"会做爬虫的人"的,是这篇我们跑通"请求→解析→存储"的最小闭环,然后重点把"合规与礼貌"这根弦给你绷上。

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 432

【基于 WebSocket 的多用户网页五子棋】—— 数据管理模块

但行好事,莫问前程

qq_42996461的博客 250

C++算法(七)

C++ stack算法题和一些客观题

2503_94479566的博客 378

OpenClaw 深度调查:把 AI 助手做成你自己的控制平面

对 openclaw/openclaw 的完整技术尽调:Gateway 架构、Agent 运行时、工具与沙箱、30 个消息通道、181 个插件、安全信任边界、工程代价与采用建议。17 章 / 10 张图,全部数字标注口径,数据截至 2026-10-31。

厚积薄发 294

IDEA 简介:从零认识 IntelliJ IDEA

IDEA 全称,是由 JetBrains 公司开发的一款主流 Java 集成开发环境(IDE)。它集代码编辑、编译、调试、测试、版本控制、构建管理等功能于一体,被大量 Java 开发者视为日常开发的首选工具。所谓 IDE(Integrated Development Environment,集成开发环境),就是把写代码所需的各类工具整合到同一个界面中。相比只用文本编辑器加命令行编译,IDE 能显著减少重复操作,让开发者把精力集中在业务逻辑上。

ztI10的博客 176

TransactionInactiveError:await 之后事务已经不活跃了

TransactionInactiveError 出现于 IndexedDB 事务已结束(非 active 状态)时调用 put、get 等操作。常见于 await 后或 setTimeout 中执行请求,因任务已完成,事务已提交或进入 finished 状态。请求必须在创建事务的同一任务中挂起,否则无效。解决方法:在 onsuccess 回调内同步发起后续操作,或提前将所有请求挂入事务。避免在异步上下文中使用事务操作,确保请求在事务活跃期内完成。

qq_40822000的博客 159

云计算课程小组PPT汇报任务书

36人分为6组,每组6人;形式:生活案例调研 + 理论解读;汇报时长7‑9min;PPT建议10‑14页。

Michelle8023的博客 207
上一篇: 月之暗面真的很强?我们来用一个问题评测这些 ChatGPT 平替
下一篇: Bytebase 2.15.0 - GitOps 整体升级
Bytebase
博客等级 码龄5年 1349粉丝 258原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值