深入探讨锁升级问题
1. 引言
本文深入探讨锁升级问题。
2. 锁升级问题概述
2.1 锁升级的概念
2.1.1 定义
锁升级是指数据库管理系统将较低粒度的锁(如行级锁)转换为较高粒度的锁(如表级锁)的过程。这种情况通常发生在事务对同一对象的多个较低粒度的锁操作导致系统开销过大,或者系统检测到可能出现死锁等并发问题时。例如,在一个数据库事务中,如果对表中的大量行都加了行级锁,数据库可能会判断将这些行级锁升级为表级锁会更高效,从而进行锁升级操作。
2.1.2 目的
主要目的是为了减少系统的资源开销和管理成本。因为管理大量的细粒度锁(如行级锁)需要更多的内存和 CPU 资源来维护锁的信息,包括锁的状态、锁的持有者等。通过锁升级,可以简化锁的管理结构,降低系统开销。
2.2 锁升级的触发条件
2.2.1 锁数量达到阈值
1. 原理: 当一个事务对一个表中的行级锁数量达到数据库系统设定的某个阈值时,可能会触发锁升级。不同的数据库系统对于这个阈值的设定可能不同,这取决于数据库的配置和内部算法。
2. 例: 在某些数据库中,如果一个事务对一个表中的超过 50% 的行都加了行级锁,系统可能会考虑进行锁升级。假设一个表有 100 行数据,当一个事务已经对其中 51 行都加了行级锁时,就有可能触发锁升级。
2.2.2 系统资源考虑
1. 原理: 如果数据库系统检测到管理大量行级锁所消耗的系统资源(如内存、CPU 时间用于锁的维护和检查)超过了一定限度,并且认为升级为表级锁可以减少这种资源消耗,就会触发锁升级。这通常是基于数据库内部的性能优化算法来判断的。
2. 例: 在高并发环境下,如果系统发现由于大量的行级锁操作导致内存中的锁信息存储区域接近满负荷,并且对这些行级锁的操作导致频繁的锁检查和等待,数据库可能会决定将部分行级锁升级为表级锁,以减少内存占用和锁管理的复杂性。
2.2.3 避免死锁风险
1. 原理: 当数据库系统预测到当前的锁模式可能会导致死锁情况发生时,可能会进行锁升级。例如,在多个事务对同一表中的行进行交叉锁定,并且系统检测到死锁的可能性较高时,通过将部分行级锁升级为表级锁,可以改变锁的模式,避免死锁的发生。
2. 例: 假设有两个事务 T1 和 T2,T1 对表中的行 R1 和 R2 加了行级锁,T2 对行 R2 和 R3 加了行级锁,并且两个事务接下来可能会尝试获取对方已经锁定的行,系统检测到这种潜在的死锁情况,可能会将 T1 或 T2 对部分行的行级锁升级为表级锁,从而改变锁的获取顺序,避免死锁。
2.3 锁升级的影响
2.3.1 并发性能降低
1. 原理: 锁升级后,从细粒度的行级锁变为表级锁,会限制其他事务对整个表的访问。例如,原本多个事务可以同时对表中的不同行进行读取操作(基于行级共享锁的兼容性),但在锁升级为表级锁后,其他事务可能无法对表进行读取或写入操作,直到持有表级锁的事务完成,这会导致并发性能下降。
2. 例: 在一个多用户的在线购物系统中,有一个事务对订单表中的大部分行进行了操作,导致锁升级为表级锁。此时,其他用户想要查询自己的订单信息(原本只需要获取行级共享锁即可)就会被阻塞,直到这个事务完成,从而影响了系统的并发处理能力。
2.3.2 死锁可能性变化
1. 原理: 锁升级可能会改变锁的模式和持有情况,从而对死锁的可能性产生影响。一方面,如前面提到的,锁升级可能会避免一些潜在的死锁情况;另一方面,如果锁升级的策略不合理,也可能会导致新的死锁模式出现。
2. 例: 假设在一个数据库系统中,原本事务之间的行级锁竞争比较均衡,不会导致死锁。但由于锁升级策略导致某些事务频繁地获取表级锁,而其他事务又在等待这些表级锁的释放,可能会出现新的死锁场景,例如多个事务等待不同的表级锁,形成循环等待的情况。
3. 锁升级对数据库性能可能产生的影响
3.1 并发性能下降
3.1.1 行级锁到表级锁的转换
1. 原理: 锁升级过程中,从细粒度的行级锁转换为表级锁。在表级锁模式下,对整个表的并发访问受到限制。原本多个事务可以同时对表中的不同行进行操作,如在一个在线商城的数据库中,多个用户可以同时对商品表中的不同商品进行查询或购买操作(通过行级锁实现并发)。一旦锁升级为表级锁,这些并发操作就会被阻塞,因为其他事务不能访问被锁定的整个表,直到持有表级锁的事务完成。
2. 例: 假设有 10 个用户同时在商城中查询和购买不同商品,当一个事务对商品表进行大量操作导致锁升级后,这 10 个用户的操作都会被暂停等待,直到锁被释放,这会导致系统的响应时间变长,并发处理能力大幅下降。
3.1.2 共享锁与排他锁的相互影响
1. 原理: 在锁升级后,如果表级锁是排他锁,那么所有对该表的读取(共享锁)和写入(其他排他锁)操作都将被阻止。即使表级锁是共享锁,对于需要排他锁进行写入操作的事务也会被阻塞。这种相互影响会导致事务等待时间增加,系统的整体吞吐量降低。
2. 例: 在一个数据库中有一个报表生成事务需要对销售数据表进行读取操作(加共享锁),同时有一个数据更新事务需要对同一表进行写入操作(加排他锁)。如果因为某些原因锁升级为表级排他锁,那么报表生成事务就会被阻塞,无法进行读取操作,直到数据更新事务完成,这会降低系统的并发性能。
3.2 死锁风险增加(可能出现新的死锁模式)
3.2.1 锁模式改变导致的死锁
1. 原理: 锁升级可能会改变锁的持有模式和顺序。例如,原本事务之间通过行级锁可以按照一定的顺序访问数据,避免死锁。但锁升级后,表级锁的持有时间较长且范围广,可能会导致新的循环等待情况。当多个事务等待不同的表级锁释放时,就容易形成死锁。
2. 例: 假设有三个事务 T1、T2 和 T3,它们都需要访问表 A 和表 B。在没有锁升级时,它们通过行级锁可以有序地访问不同行的数据。但如果 T1 对表 A 进行了大量操作导致锁升级为表级锁,同时 T2 对表 B 进行操作也导致锁升级,T3 可能会同时等待 T1 释放表 A 的锁和 T2 释放表 B 的锁,T1 又可能在等待 T3 释放某个资源,从而形成死锁。
3.2.2 死锁检测和处理开销
1. 原理: 数据库系统需要不断地检测死锁情况。当死锁发生时,数据库要选择一个事务进行回滚来解除死锁,这个过程会消耗系统资源。随着锁升级导致死锁风险增加,死锁检测和处理的频率也会增加,从而占用更多的 CPU 时间和内存等资源。
2. 例: 在一个高并发的数据库系统中,如果频繁因为锁升级出现死锁,数据库会不断地执行死锁检测算法。这些算法需要遍历锁的信息、事务的等待链等,消耗大量的 CPU 资源。而且每次死锁处理时的回滚操作也会增加系统的负担,影响数据库的性能。
3.3 系统资源利用效率降低
3.3.1 内存资源
1. 原理: 在锁升级前,行级锁需要维护每行锁的相关信息,如锁的类型、持有者等。虽然单个行级锁的信息占用空间较小,但当行级锁数量众多时,也会占用一定的内存空间。然而,锁升级为表级锁后,数据库可能不会立即释放之前行级锁占用的内存空间,导致内存资源的浪费。同时,表级锁本身也需要占用一定的内存来记录锁的状态等信息。
2. 例: 一个数据库中有大量的小事务频繁地对一个大表进行行级锁操作,这些行级锁信息存储在内存的锁管理区域。当发生锁升级后,这些行级锁信息可能没有及时清理,并且还增加了表级锁的内存占用,使得内存中用于锁管理的区域膨胀,降低了内存资源的有效利用率。
3.3.2 CPU 资源
1. 原理: 锁升级过程本身需要消耗 CPU 资源来进行判断和转换操作。此外,升级后的表级锁可能会导致更多的事务等待,这些等待事务会不断地检查锁是否释放,这也会消耗 CPU 资源。同时,如前面提到的死锁检测等操作也会增加 CPU 的开销。
2. 例: 在一个数据库服务器中,当锁升级频繁发生时,CPU 需要花费时间来处理锁升级的逻辑,如判断是否满足升级条件、进行锁模式的转换等。而且大量被阻塞的事务会不断地轮询锁的状态,使得 CPU 的使用率增加,但实际有效的工作减少,导致系统资源利用效率降低。
4. 如何监控数据库中的锁升级情况
4.1 利用数据库系统的动态视图或系统表
4.1.1 SQL Server
1. sys.dm_tran_locks 视图: 这个视图提供了有关当前在数据库中活动的锁的详细信息。可以通过查询这个视图来观察锁的级别(行级、表级等)以及锁的状态变化,以判断是否发生了锁升级。例如,通过检查request_mode(锁模式)、resource_type(资源类型,如行或表)和request_status(请求状态)等列,可以了解锁的详细情况。
例:
SELECT request_session_id, resource_type, request_mode, request_status
FROM sys.dm_tran_locks;
- SQL Server 扩展事件(Extended Events): 可以使用扩展事件来捕获锁升级事件。通过创建一个扩展事件会话,定义一个事件来捕获lock_escalation事件,就可以收集锁升级相关的详细信息,包括发生锁升级的会话、对象和时间等。
例(创建扩展事件会话):
-- 创建扩展事件会话
CREATE EVENT SESSION [LockEscalationMonitoring] ON SERVER
ADD EVENT sqlserver.lock_escalation
ADD TARGET package0.event_file(SET filename = N'C:\temp\LockEscalation.xel')
WITH (MAX_MEMORY = 4096KB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY = 30 SECONDS, MAX_EVENT_SIZE = 0KB, MEMORY_PARTITION_MODE = NONE, TRACK_CAUSALITY = OFF, STARTUP_STATE = OFF);
-- 启动会话
ALTER EVENT SESSION [LockEscalationMonitoring] ON SERVER STATE = START;
4.1.2 Oracle
- V L O C K 视图 : 类似于 S Q L S e r v e r 的动态视图, V LOCK视图: 类似于SQL Server的动态视图,V LOCK视图:类似于SQLServer的动态视图,VLOCK视图用于查看数据库中的锁信息。可以通过检查锁的类型(如TM代表表级锁,TX代表事务锁)和相关的事务信息来判断是否有锁升级的情况。例如,如果看到大量原本应该是行级锁相关的事务(TX类型)突然被表级锁(TM` 类型)所取代,可能表示发生了锁升级。
例:
SELECT SID, TYPE, LMODE, ID1, ID2
FROM V$LOCK;
2. Oracle Trace 功能: 可以启用 Oracle 的跟踪功能(如 SQL Trace 或事件 10046 跟踪)来捕获详细的数据库操作信息,包括锁的获取、释放和升级情况。通过分析跟踪文件,可以确定锁升级发生的时间、涉及的事务和 SQL 语句等信息。
4.1.3 MySQL
1. Performance Schema: MySQL 的 Performance Schema 提供了很多关于数据库性能的信息,包括锁相关的数据。可以通过查询performance_schema.data_locks表来查看锁的详细信息。通过观察锁的范围(是行级还是表级)以及锁的持有时间等参数,来判断是否发生了锁升级。
例:
SELECT * FROM performance_schema.data_locks;
2. SHOW ENGINE INNODB STATUS 命令: 这个命令可以显示 InnoDB 存储引擎的状态信息,其中包含了关于锁的信息。虽然信息相对较简略,但可以快速查看是否有表级锁等待等可能与锁升级相关的情况。例如,查看TRANSACTIONS部分中关于锁等待的描述。
4.2 使用数据库管理工具
4.2.1 SQL Server Management Studio(SSMS)
1. 活动监视器(Activity Monitor): 在 SSMS 中,可以通过活动监视器来查看当前的数据库活动,包括锁相关的信息。它以图形化的方式展示了不同类型的锁以及持有锁的进程等内容。可以通过观察锁的数量和类型变化来发现锁升级的迹象。例如,如果看到表级锁的数量突然增加,而相应的行级锁数量减少,可能是发生了锁升级。
4.2.2 Oracle Enterprise Manager(OEM)
1. 性能中心(Performance Hub): OEM 提供了性能中心来监控数据库的各种性能指标。在这里,可以查看锁的活动情况,包括锁等待时间、锁的类型分布等。通过设置警报,可以在出现可能与锁升级相关的异常情况(如长时间的表级锁等待)时收到通知。
4.2.3 MySQL Workbench
1. 性能仪表板(Performance Dashboard): MySQL Workbench 的性能仪表板可以显示一些关于锁的基本信息。虽然它没有像前两者那样丰富的功能,但可以查看诸如当前锁等待的数量等信息,帮助初步判断是否有锁升级相关的问题。同时,可以通过执行自定义查询来深入挖掘 Performance Schema 中的锁信息。
5. 如何避免锁升级问题
5.1 优化事务设计
5.1.1 缩小事务范围
1. 原理: 减少事务中操作的数据量,可降低锁升级的触发几率。如果事务只涉及少量行的操作,数据库就不太可能因为大量行级锁而触发升级。
2. 例: 在一个库存管理系统中,不要在一个事务里更新所有商品的库存,而是将更新操作拆分成多个小事务,每次只更新一种或几种商品的库存。比如,将更新 1000 种商品库存的事务,拆分成 100 个每次更新 10 种商品库存的事务。
5.1.2 合理安排事务操作顺序
1. 原理: 避免事务之间出现交叉锁定相同数据的情况,降低死锁风险,从而减少因死锁预防而导致的锁升级。通过按照相同的顺序访问表和行,可以使锁的获取更加有序。
2. 例: 假设有两个事务,事务 A 和事务 B,都需要操作表 X 和表 Y 中的数据。如果事务 A 总是先操作表 X 再操作表 Y,事务 B 也遵循同样的顺序,就可以减少因相互等待对方释放锁而导致锁升级的情况。
5.2 调整数据库参数
5.2.1 调整锁升级阈值
1. 原理: 不同数据库系统有参数来控制锁升级的阈值。通过适当提高这个阈值,可以让数据库容忍更多的行级锁,减少不必要的锁升级。
2. 例: 在 SQL Server 数据库中,可以通过配置MAXDOP(最大并行度)和LOCK_ESCALATION等参数来控制锁升级。例如,将LOCK_ESCALATION设置为DISABLE可以完全禁止锁升级,但这需要谨慎使用,因为可能会增加系统资源的消耗。在 Oracle 数据库中,可以通过调整一些隐藏参数来影响锁升级行为,但这需要对数据库有深入的了解并且在测试环境充分验证后才能使用。
5.3 优化查询和索引使用
5.3.1 使用合适的索引
1. 原理: 索引可以加快数据访问速度,使事务能够更快地获取和释放行级锁。当查询和更新操作能够通过索引高效地定位数据时,就不需要对大量行进行扫描和加锁。
2. 例: 在一个员工信息数据库中,如果经常通过员工编号查询和更新员工工资,那么在员工编号列上建立索引。这样,当执行更新工资的事务时,如UPDATE employees SET salary = new_salary WHERE employee_id = 123,数据库可以通过索引快速定位到要更新的行,减少对其他行的不必要扫描和加锁,从而降低锁升级的可能性。
5.3.2 避免全表扫描
1. 原理: 全表扫描会导致数据库对表中的大量行进行访问和可能的加锁。通过优化查询,使用索引或者限制查询范围,避免全表扫描,可以减少行级锁的数量。
2. 例: 如果有一个查询SELECT * FROM orders WHERE order_date BETWEEN ‘2024-01-01’ AND ‘2024-02-01’,确保在order_date列上有索引,并且查询条件的范围是合理的,避免写成SELECT * FROM orders这样的全表扫描查询,从而减少锁升级的风险。
5.4 采用替代的并发控制机制(如果适用)
5.4.1 使用乐观并发控制(OCC)
1. 原理: 乐观并发控制假设事务在执行过程中很少发生冲突。在这种机制下,事务在读取数据时不会加锁,只有在提交时才会检查数据是否被其他事务修改。如果没有冲突,事务提交成功;如果有冲突,则回滚并重新执行。
2. 例: 在一个多人协作的文档编辑系统中,多个用户可以同时编辑文档的不同部分。采用乐观并发控制,用户在编辑过程中可以自由操作,当提交修改时,系统检查文档是否被其他用户修改。如果没有修改,提交成功;如果有修改,则可以提示用户合并修改或者重新编辑,这样就避免了因锁而导致的升级问题。
5.4.2 使用版本号或时间戳
1. 原理: 为每行数据添加版本号或时间戳,事务在更新数据时,通过比较版本号或时间戳来判断数据是否被其他事务修改。如果数据未被修改,更新操作成功;如果数据已经被修改,事务可以根据业务规则决定是放弃更新还是重新获取最新数据后再更新。
2. 例: 在一个产品信息管理系统中,为每个产品记录添加一个版本号。当一个事务想要更新产品价格时,它首先读取产品的版本号,在提交更新时,再次检查版本号是否改变。如果版本号不变,说明没有其他事务修改该产品信息,更新成功;如果版本号改变,事务可以重新获取最新的产品信息和版本号,然后决定是否继续更新。这种方式可以在一定程度上避免锁的使用和升级。
6. 后记
锁问题一直是事务处理和高并发编程的核心问题,大家一定要搞透彻明白才能写出高效的代码。
码字不易,宝贵经验分享不易,请各位支持原创,转载注明出处,多多关注作者,后续不定期分享DB基本知识和排障案例及经验、性能调优等。
相关文章:
深入探讨锁升级问题
1. 引言 本文深入探讨锁升级问题。 2. 锁升级问题概述 2.1 锁升级的概念 2.1.1 定义 锁升级是指数据库管理系统将较低粒度的锁(如行级锁)转换为较高粒度的锁(如表级锁)的过程。这种情况通常发生在事务对同一对象的多个较低粒…...
MySQL篇—通过官网下载linux系统下多种安装方式的MySQL社区版软件
💫《博主介绍》:✨又是一天没白过,我是奈斯,DBA一名✨ 💫《擅长领域》:✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux,也在扩展大数据方向的知识面✌️…...
6.824/6.5840(2024)环境配置wsl2+vscode
本文是经过笔者实践得出的最速の环境配置 首先,安装wsl2和vscode 具体步骤参见Mit6.s081环境配置踩坑之旅WSL2VScode_mit6s081-CSDN博客 接下来开始为Ubuntu(笔者使用的版本依然是20.04)配置go的相关环境 1、更新Ubuntu的软件包 sudo apt-get install build-es…...
【乐企文件生成工程】搭建docker环境,使用docker部署工程
1、自行下载docker 2、自行下载docker-compose 3、编写Dockerfile文件 # 使用官方的 OpenJDK 8 镜像 FROM openjdk:8-jdk-alpine# 设置工作目录 WORKDIR ./app# 复制 JAR 文件到容器 COPY ../lq-invoice/target/lq-invoice.jar app.jar # 暴露应用程序监听的端口 EXPOSE 1001…...
常见的数据结构---队列、树与堆的深入剖析
目录 一、队列 二、树 三、堆 在现代计算机科学与工程领域,队列、树和堆是三种极其重要的基础数据结构,它们各自具有独特的特点和应用。在日常开发中,合理选择和使用这些数据结构可以显著提高程序的效率和可维护性。它们不仅奠定了算法设计…...
leetcode--螺旋矩阵
LCR 146.螺旋遍历二维数组 给定一个二维数组 array,请返回「螺旋遍历」该数组的结果。 螺旋遍历:从左上角开始,按照 向右、向下、向左、向上 的顺序 依次 提取元素,然后再进入内部一层重复相同的步骤,直到提取完所有元…...
JavaScript(JS)的对象
目录 1.array 数组对象 2.String 字符串对象 3.JSON 对象(数据载体,进行数据传输) 4.BOM 浏览器对象 5.DOM 文档对象(了解) 1.array 数组对象 定义方式1:var 变量名 new Array(元素列表); 定义方式…...
基于BM1684的AI边缘服务器-模型转换,大模型一体机
介绍 我们属于SoC模式,即我们在x86主机上基于tpu-nntc和libsophon完成模型的编译量化与程序的交叉编译,部署时将编译好的程序拷贝至SoC平台(1684开发板/SE微服务器/SM模组)中执行。 注:以下都是在Ubuntu20.04系统上操…...
git推送多个仓库
在 Git 中,可以通过添加多个远程仓库来实现一次 git push 推送到多个仓库,比如同时推送到 Gitee 和 GitHub。以下是详细的设置步骤: 1. 添加多个远程仓库 假设你的项目已经有一个远程仓库(例如 GitHub),你…...
Matlab mex- setup报错—错误使用 mex,未检测到支持的编译器...
错误日志: 在使用mex编译时报错提示:错误使用 mex,未检测到支持的编译器。您可以安装免费提供的 MinGW-w64 C/C 编译器;请参阅安装 MinGW-w64 编译器。有关更多选项,请访问https://www.mathworks.com/support/compile…...
PostgreSQL认证培训需要什么条件
PostgreSQL认证培训通常没有严格的前置条件,但以下几点可以帮助你更好地准备和通过认证考试: 1、基础知识:具备基本的数据库知识和经验,特别是对SQL有一定的了解。如果你Oracle、MySQL等基础知识,对对你学习PostgreSQ…...
Oracle—系统包使用
文章目录 系统包dbms_redefinition 系统包 dbms_redefinition 功能介绍:该包体可以实现将Oracle库下的表在线改为分区结构或者重新定义; 说明:在检查表是否可以重定义和开始重定义的过程中,按照表是否存在主键,参数 o…...
【排序用法】.NET开源 ORM 框架 SqlSugar 系列
💥 .NET开源 ORM 框架 SqlSugar 系列 🎉🎉🎉 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列…...
【SpringBoot】整合篇
1、log4j2 第一步,导入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions><!-- 去掉springboot默认配置 --> <exclusion> <…...
写入json和读取json文件
/// <summary> ///写入文件 /// </summary> /// <param name"Stns"></param> /// <returns></returns> public ActionResult WriteJsonFile(string Stns) { strin…...
Vuex的理解及使用场景
Vuex 是 Vue.js 应用中一个专门为状态管理而设计的库,它基于 Fluts 和 Redux 的模式。Vuex 提供了一种集中式存储管理所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。以下是 Vuex 的理解及使用场景: Vuex 的理解 核心概…...
PostGis学习笔记
– 文本方式查看几何数据 SELECT ST_AsText(geom)FROM nyc_streets WHERE name ‘Avenue O’; – 计算紧邻的街区 SELECT name,ST_GeometryType(geom) FROM nyc_streets WHERE ST_DWithin( geom,ST_GeomFromText(‘LINESTRING(586782 4504202,586864 4504216)’,26918),0.1); …...
Qt 窗口类型、窗口标志和窗口属性
一、窗口类型 Qt 窗口标志枚举类型用于指定小部件的各种窗口系统属性。其中一些标志取决于底层窗口管理器是否支持它们。以下是窗口类型: Qt::QWidget:这是 QWidget 的默认类型。如果它们有父级,这种类型的部件是子部件,如果没有父控件,则为独立窗口。Qt::Window:通常具…...
相机学习笔记——工业相机的基本参数
0、相机分类 图像颜色不同可以分为黑白相机和彩色相机:相同分辨率下,黑白工业相机相比彩色工业相机精度更高,检测图像边缘时,黑白工业相机成像效果更好。 芯片类型不同可以分为CCD相机和CMOS相机:CCD工业相机具有体积小…...
MATLAB - ROS2 ros2genmsg 生成自定义消息(msg/srv...)
系列文章目录 前言 语法 ros2genmsg(folderpath)ros2genmsg(folderpath,Name=Value) 一、说明 ros2genmsg(folderpath) 通过读取指定文件夹路径下的 ROS 2 自定义信息和服务定义来生成 ROS 2 自定义信息。函数文件夹必须包含一个或多个 ROS 2 软件包。这些软件包包含 .msg 文…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
