首页 文章 精选 留言 我的

精选列表

搜索[模块],共10000篇文章
优秀的个人博客,低调大师

MySQL 核心模块揭秘 | 18 期 | 锁在内存里长什么样*

表锁和行锁都由锁结构承载这些锁结构在内存里是个什么样的存在 作者操盛春爱可生技术专家公众号『一树一溪』作者专注于研究 MySQL 和 OceanBase 源码。 爱可生开源社区出品原创内容未经授权不得随意使用转载请联系小编并注明来源。 本文基于 MySQL 8.0.32 源码*存储引擎为 InnoDB。 1. 共用的结构 InnoDB 的表锁结构和行锁结构有一些共同属性也有一些不同属性。 因为有共同属性*表锁结构和行锁结构都使用结构体 lock_t 来表示锁结构。 在 lock_t 之下*又定义了 lock_table_t、lock_rec_t 分别包含表锁结构和行锁结构的不同属性。 为了更直观的理解表锁结构和行锁结构我们去掉 lock_t 的一些非核心信息之后整理如下* // storage/innobase/include/lock0priv.h struct lock_t { trx_t *trx; UT_LIST_NODE_T(lock_t) trx_locks; dict_index_t *index; lock_t *hash; union { lock_table_t tab_lock; lock_rec_t rec_lock; }; uint32_t type_mode; }; 虽然表锁结构和行锁结构都定义了自己的结构体用于表示各自不同的属性但是 lock_t 中 index、hash 这两个只用于行锁结构的属性*并没有放入 lock_rec_t。 我们就不去追溯为什么这两个属性会放在 lock_t 中*而没有放入 lock_rec_t 了。 2. type_mode 从属性名上看*表锁结构和行锁结构的 type_mode 属性存放的是锁类型和锁模式。 实际上这个属性比较复杂它占用 4 字节共 32 位分为四个部分。 第一部分1 ~ 4 位这 4 位是个整体共同表示一个整数值就是锁模式。 0*LOCK_IS**表级别的意向共享锁。 1*LOCK_IX**表级别的意向排他锁。 2*LOCK_S**表级别或行级别的共享锁。 3*LOCK_X**表级别或行级别的排他锁。 4LOCK_AUTO_INC**表级别的 AutoInc 锁。 锁模式部分的 4 字节作为一个整体使用而没有按位使用*这是有原因的。 按整体使用4 字节的无符号整数最大值为 15最多可以表示 15 种锁模式。 按位使用每位只能表示一种锁模式4 位只能表示 4 种锁模式。 第二部分5 ~ 8 位按位使用*存放的是锁类型。 第 5 位标识是否为表锁*LOCK_TABLE*。 第 6 位标识是否为行锁*LOCK_REC*。 第 7 ~ 8 位*暂未使用。 第三部分第 9 位按位使用*存放的是锁等待状态LOCK_WAIT**置为 0 表示已经获得锁置为 1 表示处于锁等待状态。 第四部分10 ~ 32 位按位使用*存放的是锁的精确模式这部分只有行锁和谓词锁会用到表锁不会用到。 第 10 位用于标识间隙锁*LOCK_GAP*。 第 11 位用于标识普通记录锁*LOCK_REC_NOT_GAP*。 第 12 位用于标识插入意向锁*LOCK_INSERT_INTENTION*。 第 13 位*暂未使用。 第 14 ~ 15 位分别用于标识 LOCK_PREDICATE、LOCK_PRDT_PAGE*都属于谓词锁。 第 16 ~ 32 位*暂未使用。 看到这里大家有没有觉得奇怪怎么没有用于标识 NextKey 位置 锁模式为行锁LOCK_REC时如果 10 ~ 32 位中所有位都被设置为 0就表示加的行锁是 Next*Key 锁。 3. 表锁结构 lock_t 中表锁结构只使用 trx、trx_locks、type_mode 三个属性加上 lock_table_t 的 table、locks 属性*就是表锁结构的全部属性了。 MySQL 执行 DDL、DML 语句时InnoDB 都会有对应的事务用户手动启动或者 InnoDB 自动启动*来执行这些语句对应的操作。 加锁操作自然也是在事务中进行的*trx 属性就是加这个表锁的事务对象。 事务执行一条或多条 DML 语句可能涉及多个表也就有可能加多个表锁。事务除了加表锁还有可能加行锁同一个事务加的一个或多个表锁和一个或多个行锁的锁结构通过 trx_locks 属性形成一个表锁结构和行锁结构混合的链表。 表锁是加在表上的自然就需要知道表锁结构属于哪个表了table 属性就是这个表锁结构所属的表对象。 同一时刻可能有多个事务已经或者想要对同一个表加锁。对于兼容的表锁多个事务可以同时加锁对于不兼容的表锁后加锁的事务就会处于等待状态。 事务想要对某个表加锁InnoDB 怎么判断事务可以立即获得锁还是要进入等待状态* 这就是 locks 属性的用武之地了。 多个事务对同一个表加了表锁*这些表锁的锁结构会通过 locks 属性形成一个链表。 事务想要对某个表加表锁*InnoDB 就会遍历这个链表。 如果链表中还没有表锁结构或者所有锁结构对应的表锁都和事务当前要加的表锁兼容事务就可以立即获得锁*否则就需要进入等待状态。 type_mode 属性的第 5 位用于标识锁结构是否为表锁*LOCK_TABLE*。 对于表锁锁结构中 type_mode 属性的第 5 位会被设置为 1第 1 ~ 4 位会写入锁模式对应的整数值。 如果事务不能立即获得表锁*type_mode 属性的第 9 位会被设置为 1*表示处于锁等待状态。 4. 行锁结构 lock_t 中行锁结构使用 trx、trx_locks、index、hash、type_mode 五个属性加上 lock_rec_t 的 page_id、n_bits 两个属性外加行锁结构最后外挂了一块没有属性名的内存区域我们暂且命名为 bitmap**就是行锁的整体结构了。 4.1 有名有姓的那些属性 和表锁结构一样*行锁结构里也有 trx 和 trx_locks 两个属性。 trx 属性是加这个行锁的事务对象。同一个事务加的一个或多个表锁和一个或多个行锁的锁结构*通过 trx_locks 属性形成一个表锁结构和行锁结构混合的链表。 主表的记录存储在主键索引中二级索引包括唯一索引、非唯一索引的记录存储在二级索引中行锁都是对主键索引或二级索引的记录加锁。index 属性就是这个行锁结构所属的索引对象。 InnoDB 可能同时有很多个事务在运行这些事务加的行锁可能会产生多个行锁结构。 每个行锁结构都会根据 page_id 属性中保存的表空间 ID、数据页号计算得到一个哈希值。哈希值相同的多个行锁结构通过 hash 属性形成一个行锁结构链表。 n_bits 属性的值是个无符号整数表示这个锁结构能保存多少条记录的行锁状态也就是最多有多少记录能共用这个行锁结构。 对于行锁锁结构中 type_mode 属性的第 6 位会被设置为 1第 1 ~ 4 位会被写入锁模式对应的整数值。 行锁的不同精确模式*type_mode 属性第四部分10 ~ 32 位各位的赋值情况如下* 普通记录锁*type_mode 属性的第 10 位会被设置为 1。 间隙锁*type_mode 属性的第 11 位会被设置为 1。 插入意向锁*type_mode 属性的第 12 位会被设置为 1。 NextKey 锁type_mode 属性的第 10 ~ 32 位都设置为 0。 如果事务不能立即获得行锁*type_mode 属性的第 9 位会被设置为 1*表示处于锁等待状态。 4.2 隐姓埋名的内存区域 前面介绍的那些*都是 InnoDB 给取了名字的行锁结构属性。 还有一块没有名字的内存区域没有介绍。在前面的行锁结构图中我们给这块内存区域取了个名字为 bitmap。 bitmap 这块内存区域是干嘛用的呢* 待我们细细说来。 我们先忽略 bitmap 内存区域的存在假设一个事务对一条记录加行锁会产生一个行锁结构对多条记录加行锁就会产生多个行锁结构。 又假设事务对多条记录加的都是共享 NextKey 锁并且已经获得了锁巧合的是这些记录又位于同一个数据页那么这些锁结构除了加锁记录不一样其它属性的值都相同。 如果真这么设计行锁结构是不是太浪费内存空间了 当然是了。虽然现在内存越来越便宜但是毕竟还要花钱也不能那么铺张浪费。 本着勤俭节约的原则InnoDB 把加锁记录不同、其它属性值都相同的多个行锁结构合并成一个另外开辟一块内存区域用于标识加锁记录*于是就有了我们命名为 bitmap 的内存区域。 bitmap 内存区域按位使用每一位都用于标识事务是否对某条记录加了行锁。如果某一位被设置为 1就表示事务对该位对应的记录加了行锁。 上图是事务对象初始化时预先创建的一个行锁结构的 bitmap 内存区域示意图大小为 256 字节*可以用于标识这个事务对 2048 条记录加行锁的情况。 示意图中第 3 位和第 5 位被设置为 1说明事务对数据页中序号为 0 和 4 的记录加了行锁。 没有规矩不成方圆*InnoDB 不会胡乱的把多个行锁结构合并成一个。 事务对多条记录加行锁想要共用一个行锁结构需要同时满足以下个条件* 同一个事务对多条记录加行锁。 这些记录位于同一个数据页中也就是同一个表同一个索引的同一个数据页。 这些行锁的锁模式相同必须都是共享锁或者都是排他锁。 这些行锁的精确模式相同必须都是普通记录锁或者都是间隙锁或者都是 NextKey 锁。 这些行锁都处于获得锁的状态*不能处于锁等待状态。 4.3 共用行锁结构的两个问题 问题一多个处于等待状态的行锁能共用一个锁结构吗 理论上是可以的*但实际上不会出现这种情况。 因为共用一个行锁结构需要满足的条件之一*是一个事务对多条记录加行锁。 然而一个事务对某条记录加行锁处于等待状态在获得锁或者锁超时之前*不考虑异常情况**这个事务不会继续往下执行。 这样一来一个事务在某一时刻最多只有一个行锁结构对应一条记录处于等待状态*也就不存在多个处于等待状态的行锁共用一个行锁结构的情况了。 获得锁或者锁等待超时之后行锁结构中 type_mode 的第 9 位就会被设置为 0表示这个行锁处于非等待状态后续在满足共用条件的情况下这个锁结构才可以被共用。 问题二多个插入意向锁能共用一个锁结构吗 同样理论上是可以的但实际上不会出现这种情况。 首先插入意向锁的加锁场景是事务 T 想要在某条记录前面的间隙插入一条记录而这个间隙被其它事务加了间隙锁或者 NextKey 锁导致事务 T 必须在这个间隙上加插入意向锁并等待其它事务释放间隙锁或者 Next*Key 锁。 前面已经介绍过处于等待状态的行锁结构是不能共用的。 然后事务 T 获得锁之后它的精确模式为 LOCK_GAP + LOCK_INSERT_INTENTION其它间隙锁也不能共用这个锁结构因为间隙锁的精确模式为 LOCK_GAP。 虽然插入意向锁的锁结构不能共用会浪费一些内存但好在加插入意向锁的情况也不会非常多*浪费的内存也就不会太多。 5. 总结 InnoDB 的表锁结构和行锁结构有一部分属性是相同的也有一部分属性是专用的所以代码里定义了三个结构体来描述表锁结构和行锁结构。 一个事务对每个表加表锁*都会产生一个表锁结构。 一个事务对多条记录加行锁满足条件时多条记录的行锁可以共用一个行锁结构*以节省内存。 处于等待状态的行锁结构不能共用。获得行锁或者锁等待超时之后这个锁结构会变为非等待状态之后满足条件时这个锁结构可以被共用。 插入意向锁的锁结构不能共用。 更多技术文章请访问https://opensource.actionsky.com/ 关于 SQLE SQLE 是一款全方位的 SQL 质量管理平台覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库为开发和运维提供流程自动化能力提升上线效率提高数据质量。 SQLE 获取 | 类型 | 地址 | | **** | ***** | | 版本库 | https://github.com/actiontech/sqle | | 文档 | https://actiontech.github.io/sqledocs/ | | 发布信息 | https://github.com/actiontech/sqle/releases | | 数据审核插件开发文档 | https://actiontech.github.io/sqledocs/docs/dev*manual/plugins/howtouse |

优秀的个人博客,低调大师

挖掘全志Tina Linux下SPI主从通信验证模块的秘密

主控: D1H 板卡: 两块哪吒开发板(以下简称为主机, 从机) 操作系统: Tina Linux 2.0 验证D1H芯片SPI主从机通信. 硬件接线 主机SPI 从机SPI 19 SPI1_MOSI SPI1_MOSI 19 21 SPI1_MISO SPI1_MISO 21 23 SPI1_SCK SPI1_SCK 23 24 SPI1_CE SPI1_CE 24 SPI概述 SPI接口是一种高速的, 全双工, 同步的通信总线. 适配D1H芯片的Tina Linux的BSP-SDK(以下简称SDK)中已包含相关驱动文件: spi-sunxi.c. 它提供的了仅内核态下主从机的简易通信验证实验, 这或许是考虑到SPI通信速率比较高的特性. 验证操作 SPI主机配置 MENUCONFIG 在SDK执行完环境变量加载后, 执行: /mnt/tina-d1-h$ make kernel_menuconfig ●开启Device Drivers->SPI support ●进入SPI support, 按图示开启: 设备树 修改: ./device/config/chips/d1-h/configs/nezha/board.dts 需要根据手册和原理图确认好针脚功能: SPI从机配置 MENUCONFIG (同SPI主机配置一致) 设备树 仅spi_slave_mode设为0, 其余项同SPI主机配置一致. spi_slave_mode = <0>; SPI主机收发信息 按上述配置, 重新编译SDK, 打包, 烧录, 启动设备会出现: root@TinaLinux# ls -l /dev/spidev1.0 crw------- 1 root root 153, 0 Jan 1 08:00 /dev/spidev1.0 然后将可执行的SPI测试程序(./lichee/linux-5.4/tools/spi/spidev_test)挪到设备上(adb push等)并赋予可执行权限: # 主机以10MHz发送(即MOSI)发送16进制数据: 0x01 0x02 0x03 0x04 ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "\x01\x02\x03\x04" # 主机以10MHz发送(即MOSI)发送ASCII字符串数据: "allwinner" ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "allwinner" spi mode: 0x0 bits per word: 8 max speed: 10000000 Hz (10000 KHz) TX | 61 6C 6C 77 69 6E 6E 65 72 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ |allwinner| 注意SPI是同步通信接口, 所以在发送的同时也会接收同样长度字节的数据. 下文将用到SPI主从通信的一种常见做法: 主机先发指令头, 然后再发指令体以获取从机应答. SPI从机收发信息 spi-sunxi.c中对SPI从机模(SLAVE_MODE)采取了简单的收发验证处理, 具体是创建一个内核线程执行int sunxi_spi_slave_task(void *data), 该函数又被设备中断所控制(当收到SPI数据时). SPI从机接收到数据的主要流程: sunxi_spi_slave_task() -> sunxi_spi_slave_handle_head(), 然后: 若指令头是写操作(0x01), 则执行:sunxi_spi_slave_cpu_rx_config(), 该函数仅是输出写入内容. 若指令投是读操作(0x03), 则执行:sunxi_spi_slave_cpu_tx_config(), 该函数仅是将收到的指令体的值+0x80, 然后发送(MISO)给主机. 对于从机, spi-sunxi.c能验证SPI通信, 但没有可供用户层直接使用的方法. 用户层可验证的SPI从机收发方案 功能设计 从机安排一块32byte的内存缓存空间(简称"缓存空间")供主机通过指令进行读操作和写操作, 且从机能在用户层对该内存空间访问. 主要改动 spi.c: 增加static struct class_attribute ye_spi_buf_attrs[], 以创建/sys/class/spi_slave目录下的spi_buf文件, 并提供实现了读/写缓存空间的方法. spi-sunxi.c: 使用ye_spi_slave_set_txdata()方法替换sunxi_spi_slave_set_txdata(), 以实现读操作. 修改sunxi_spi_slave_cpu_rx_config()方法, 以实现写操作. 改动详情请查看:d1h_spi_driver.diff 使用方法 写操作: 操作:0x01(写) 地址:0x00 0x00 0x00 指令体长度:0x09 ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "\x01\x00\x00\x00\x09" && \ ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "allwinner" 读操作: 操作:0x03(读) 地址:0x00 0x00 0x00 指令体长度:0x09 ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "\x03\x00\x00\x00\x09" && \ ./spidev_test -v -D /dev/spidev1.0 -s 10000000 -p "\x00\x00\x00\x00\x00\x00\x00\x00\x00" 从机读取缓存空间: cat /sys/class/spi_slave/spi_buf 从机写入缓存空间: echo "Hello world" > /sys/class/spi_slave/spi_buf

优秀的个人博客,低调大师

爱组搭 aizuda 低代码 OSS 文件存储模块 1.0.6 发布

目前支持 Minio ,阿里云 OSS ,腾讯 COS ,亚马逊 AWSS3 ,本地存储 支持文件类型合法校验 OSS.fileStorage(platform).bucket(bucketName) // 使用默认 yml 配置媒体类型 .allowMediaType(bis) // 只允许gif图片上传,所有图片可以是 image/ 部分匹配 .allowMediaType(fis, t -> t.startsWith("image/gif")) .upload(bis, filename); 源码地址:https://gitee.com/aizuda/aizuda-components 仓库地址:https://search.maven.org/search?q=aizuda-oss 升级日志: 新增Amazon AWS S3 支持 优化OSS文件检查新增注释说明 对外返回 Client 实现 优化返回签名地址 优化返回桶名称 其它完善 SpringBoot 使用 application.yml 配置 # 配置存储平台 ,第一位 test-minio 为默认存储平台 aizuda: oss: test-minio: platform: minio endpoint: http://xxxxxx accessKey: xxx secretKey: xxxxxxx bucketName: test1 aliyun-oss: platform: aliyun endpoint: http://xxxxxx accessKey: xxx secretKey: xxxxxxx bucketName: test Bean 方式注入,以下注入 minio3 为平台别名 @Bean public IFileStorage minio3() { // 注入一个自定义存储平台 OssProperty ossProperty = new OssProperty(); ossProperty.setPlatform(StoragePlatform.minio); ossProperty.setBucketName("test3"); ossProperty.setEndpoint("http://xxxxx"); ossProperty.setAccessKey("q7RNi6elbvQ0j1ry"); ossProperty.setSecretKey("HMoKkeu0zGSvSdDGWlMDuytaRON12St9"); return new Minio(ossProperty); } 测试上传 platform 存储平台(不设置使用默认)bucketName 存储桶(不设置使用默认) // 静态方法方式调用 OSS.fileStorage(platform).bucket(bucketName).upload(fis, filename); // 依赖注入方式调用 fileStorage.bucket(bucketName).upload(fis, filename); #IFileStorage 方法说明 属性 说明 upload 上传 delete 删除 download 下载 getUrl 文件可预览地址 #配置属性说明 属性 说明 platform 存储平台,目前支持 Minio ,阿里云 OSS ,腾讯 COS ,亚马逊 AWSS3 ,本地存储 endpoint 域名 accessKey 访问 KEY secretKey 密钥 bucketName 存储空间桶名 connectionTimeout 连接超时,阿里云 OSS 有效

优秀的个人博客,低调大师

.NET 框架 Furion v4.3.4 发布,日志模块全新体验

序言 自 Furion v3.9.2 版本有了自主可控的日志组件之后,越来越多的 Furion 框架使用者移除了第三方日志组件选择框架内置的,Furion 框架提供了企业开发所需的几乎所有日志需求。 本期更新主要对日志性能,日志模板,日志功能进行了改进优化。 仓库地址:https://gitee.com/dotnetchina/Furion 文档地址:https://dotnetchina.gitee.io/furion/ 本期亮点 1. 更加美观的日志模板 [INF] [Microsoft.Hosting.Lifetime] 2022-08-30T15:52:13.7033488+08:00 [ListeningOnAddress] Now listening on: https://localhost:5001 [INF] [Microsoft.Hosting.Lifetime] 2022-08-30T15:52:13.7405477+08:00 [0] Application started. Press Ctrl+C to shut down. [INF] [Microsoft.Hosting.Lifetime] 2022-08-30T15:52:13.7453185+08:00 [0] Hosting environment: Development [INF] [Microsoft.Hosting.Lifetime] 2022-08-30T15:52:13.7482401+08:00 [0] Content root path: D:\Workplaces\OpenSources\Furion\samples\Furion.Web.Entry\ [WRN] [Furion.Application.TestLoggerServices] 2022-08-30T15:52:32.3892150+08:00 [0] 我是一个二配置日志 20 [ERR] [Furion.Application.TestLoggerServices] 2022-08-30T15:52:35.1479371+08:00 [0] 测试日志异常 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ System.Exception: 错误啦 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ [INF] [System.Logging.LoggingMonitor] 2022-08-30T15:53:26.3936806+08:00 [0] ┏━━━━━━━━━━━ Logging Monitor ━━━━━━━━━━━ ┣ Furion.Application.TestLoggerServices.GetPerson (Furion.Application) ┣ ┣ 控制器名称: TestLoggerServices ┣ 操作名称: GetPerson ┣ 路由信息: [area]: ; [controller]: test-logger; [action]: person ┣ 请求方式: GET ┣ 请求地址: https://localhost:5001/api/test-logger/person/233 ┣ 来源地址: https://localhost:5001/api/index.html ┣ 浏览器标识: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36 Edg/104.0.1293.70 ┣ 客户端 IP 地址: 0.0.0.1 ┣ 服务端 IP 地址: 0.0.0.1 ┣ 服务端运行环境: Development ┣ 执行耗时: 56ms ┣ ━━━━━━━━━━━━━━━ 参数列表 ━━━━━━━━━━━━━━━ ┣ Content-Type: ┣ ┣ id (Int32): 233 ┣ ━━━━━━━━━━━━━━━ 返回信息 ━━━━━━━━━━━━━━━ ┣ 原始类型: Furion.Application.Persons.PersonDto ┣ 最终类型: Furion.UnifyResult.RESTfulResult`1[[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] ┣ 最终返回值: {"StatusCode":200,"Data":{"Id":233,"Name":null,"Age":0,"Address":null,"PhoneNumber":null,"QQ":null,"CreatedTime":"0001-01-01T00:00:00+00:00","Childrens":null,"Posts":null},"Succeeded":true,"Errors":null,"Extras":null,"Timestamp":1661846006385} ┗━━━━━━━━━━━ Logging Monitor ━━━━━━━━━━━ [ERR] [System.Logging.FriendlyException] 2022-08-30T15:53:33.0839966+08:00 [0] Attempted to divide by zero. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ System.DivideByZeroException: Attempted to divide by zero. at Furion.Application.TestLoggerServices.测试直接抛出异常拦截(Int32 id) in D:\Workplaces\OpenSources\Furion\samples\Furion.Application\TestLoggerServices.cs:line 92 at lambda_method108(Closure , Object , Object[] ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ [INF] [Microsoft.EntityFrameworkCore.Database.Command] 2022-08-30T15:53:44.1172386+08:00 [Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted] Executed DbCommand (53ms) [Parameters=[@__p_0='1'], CommandType='Text', CommandTimeout='30'] SELECT "p"."Id", "p"."Address", "p"."Age", "p"."CreatedTime", "p"."Name", "p"."UpdatedTime" FROM "Person" AS "p" WHERE "p"."Id" = @__p_0 LIMIT 1 [WRN] [Microsoft.EntityFrameworkCore.Query] 2022-08-30T15:53:49.0965317+08:00 [Microsoft.EntityFrameworkCore.Query.MultipleCollectionIncludeWarning] Compiling a query which loads related collections for more than one collection navigation, either via 'Include' or through projection, but no 'QuerySplittingBehavior' has been configured. By default, Entity Framework will use 'QuerySplittingBehavior.SingleQuery', which can potentially result in slow query performance. See https://go.microsoft.com/fwlink/?linkid=2134277 for more information. To identify the query that's triggering this warning call 'ConfigureWarnings(w => w.Throw(RelationalEventId.MultipleCollectionIncludeWarning))'. [INF] [Microsoft.EntityFrameworkCore.Database.Command] 2022-08-30T15:53:49.1180132+08:00 [Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted] Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] SELECT "p"."Id", "p"."Name", "p"."Age", "p"."Address", "p0"."PhoneNumber", "p0"."QQ", "p"."CreatedTime", "p0"."Id", "c"."Id", "c"."Name", "c"."Gender", "t"."Id", "t"."Name", "t"."PersonsId", "t"."PostsId" FROM "Person" AS "p" LEFT JOIN "PersonDetail" AS "p0" ON "p"."Id" = "p0"."PersonId" LEFT JOIN "Children" AS "c" ON "p"."Id" = "c"."PersonId" LEFT JOIN ( SELECT "p2"."Id", "p2"."Name", "p1"."PersonsId", "p1"."PostsId" FROM "PersonPost" AS "p1" INNER JOIN "Post" AS "p2" ON "p1"."PostsId" = "p2"."Id" ) AS "t" ON "p"."Id" = "t"."PersonsId" ORDER BY "p"."Id", "p0"."Id", "c"."Id", "t"."PersonsId", "t"."PostsId" 2. 支持 Visual Studio Code 日志收缩、异常日志高亮 3. 提供 RabbitMQ 事件总线使用指南 4. 提供 Log 静态类写日志更多功能 // 创建日志对象 var logger = Log.CreateLogger("日志名称"); // 创建日志工厂 using var loggerFactory = Log.CreateLoggerFactory(builder => { // .... }); // 日志记录 Log.Information("Information"); Log.Warning("Warning"); Log.Error("Error"); Log.Debug("Debug"); Log.Trace("Trace"); Log.Critical("Critical"); 5. 提供 MessageCenter 事件总线静态类 // 发送消息(含诸多重载) await MessageCenter.PublishAsync("messageId", new {}); // 动态订阅消息 MessageCenter.Subscribe("messageId", async (ctx) => { Console.WriteLine("我是动态的"); await Task.CompletedTask; }); // 取消订阅 MessageCenter.Unsubscribe("messageId"); 本期更新 新特性 [新增]AppSettings配置的ExcludeAssemblies属性,支持忽略指定程序集扫描7b7747f [新增]Oops.Oh和Oops.Bah支持设置额外数据.WithData(data)#I5O38E [新增]定时任务Crontab.GetSleepMilliseconds(baseTime)获取下一个发生时间的时间差d024fae [新增]友好异常默认打印异常日志,避免生产环境漏掉重要异常信息6e3a5bd [新增]日志静态类Log.CreateLoggerFactory()静态方法75c672a [新增]事件总线MessageCenter静态类,解决从Fur v1.x版本升级问题a29fc7c 突破性变化 [新增]Furion程序集PublicKeyToken强签名26b12c0 [调整]事件总线IEventBusFactory事件工厂方法AddSubscriber -> Subscribe,RemoveSubscriber -> Unsubscribea29fc7c 问题修复 [修复]生成包含中文的JWT Token解密后出现乱码问题#I5O397 其他更改 [调整]默认输出文件日志模板,使其更加美观#1518cf3 文档 [新增]RabbitMQ事件总线文档 [更新]AppSettings配置文档、事件总线文档、多数据库配置文档、日志文档、定时任务文档、MessageCenter文档

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册