数据库系列之MySQL数据库中内存使用分析

在实际系统环境中,MySQL实例的内存使用随着业务的增长缓慢增长,有些时候并没有及时的释放。本文简要介绍下MySQL数据库中和内存相关的配置,以及分析内存的实际使用情况,以进行应急和调优处理。


1、MySQL内存结构

在MySQL中内存的占用主要由两部分组成:全局共享缓存global buffers和所有线程独立缓存thread buffers。

  • Global buffers主要用于缓存数据页、索引页、数据字典等常用数据,这部分为常驻内存;
  • Thread buffers针对每个数据库连接会话会独立分配缓存,thread buffer与连接数成正比,连接数越高则总的thread buffers占用越高。这部分缓存通常会随着连接的释放而关闭。

MySQL中使用的内存大小等于全局共享缓存(Sharing+innodb_buffer_pool)和所有线程缓存之和,如下图所示:

在这里插入图片描述

1)global_buffers:包括Sharing buffers部分+InnoDB_Buffer_Pool

  • innodb_buffer_pool_size:InnoDB高速缓存,缓存innodb表的索引,数据,插入数据时的缓冲,以及事务锁、自适应哈希等。通过“show engine innodb status \G”和“show global status like ‘innodb_buffer_pool_%’”可以查看innodb_buffer_pool的表现。
  • innodb_log_buffer_size:InnoDB REDO日志缓冲,提高REDO日志写入效率。由于InnoDB在事务提交前,并不将改变的日志写入到磁盘中,因此在大事务中,可以减轻磁盘I/O的压力。
  • innodb_additional_mem_pool_size :用来存放Innodb的内部目录,由系统自动调整。
  • key_buffer_size:指定索引缓冲区的大小,它决定MyISAM表索引处理的速度,尤其是索引读的速度,只对MyISAM表起作用。即使不使用MyISAM表,但是内部的临时磁盘表是MyISAM表,也要使用该值。
  • query_cache_size:查询高速缓存,缓存查询结果,当打开时候,执行查询语句会进行缓存,读写都会带来额外的内存消耗,下次再次查询若命中该缓存会立刻返回结果。
  • table_open_cache:表空间文件描述符缓存,提高数据表打开效率。存放当前已经打开的表句柄,与表创建时指定的存储引擎相关。当把table_open_cache设置的过大时,如果系统处理不了这么多文件描述符,那么就会出现客户端失效、连接不上。
  • table_definition_cache:表定义文件描述符缓存,提高数据表打开效率。MySQL需要打开frm文件,并将其内容初始化为Table Share对象。这里存放与存储引擎无关的,独立的表定义相关信息。

2)all_thread_buffers:max_threads(当前活跃连接数) * (会话级内存分配总和)

  • read_buffer_size:顺序读缓冲,提高顺序读效率。MySQL读入缓冲区的大小,将对表进行顺序扫描的请求将分配一个读入缓冲区,MySQL会为它分配一段内存缓冲区,read_buffer_size变量控制这一缓冲区的大小,如果对表的顺序扫描非常频繁,并你认为频繁扫描进行的太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能。
  • read_rnd_buffer_size:随机读缓冲,提高随机读效率。MySQL的随机读缓冲区大小,当按任意顺序读取行时(列如按照排序顺序)将分配一个随机读取缓冲区,进行排序查询时,MySQL会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要大量数据可适当的调整该值,但MySQL会为每个客户连接分配该缓冲区所以尽量适当设置该值,以免内存开销过大。
  • sort_buffer_size:排序缓冲,提高排序效率。connection级参数,在每个connection第一次需要使用这个buffer的时候,一次性分配设置的内存。
  • join_buffer_size:表连接缓冲,提高表连接效率。MySQL在完成某些Join需求的时候(all/index join),为了减少参与Join的“被驱动表”的读取次数以提高性能,需要使用到Join Buffer来协助完成 Join操作。
  • binlog_cache_size:二进制日志缓冲,提高二进制日志写入效率为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存,作用是提高记录bin-log的效率。
  • tmp_table_size:内存临时表,提高临时表存储效率。当需要做类似group by操作生成的临时表大小,提高联接查询速度的效果,调整该值直到created_tmp_disk_tables/created_tmp_tables*100% <= 25%。
  • thread_stack:线程堆栈,暂时寄存SQL语句/存储过程、线程运行时的信息等。每个连接线程被创建时,MySQL给它分配的内存大小。当MySQL创建一个新的连接线程时,需要给它分配一定大小的内存堆栈空间,以便存放客户端的请求的Query及自身的各种状态和处理信息。
  • thread_cache_size:线程缓存,降低多次反复打开线程开销。当客户端断开之后,服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁(前提是缓存数未达上限)。
  • net_buffer_length:线程持连接缓冲以及读取结果缓冲。客户发出的SQL语句期望的长度,如果语句超过这个长度,缓冲区自动地被扩大,直到max_allowed_packet个字节。
  • bulk_insert_buffer_size:MyISAM表批量写入数据缓冲。如果进行批量插入,可以增加bulk_insert_buffer_size变量值的方法来提高速度,只对myisam表使用。

调整对应的配置后,相应的内存使用大小可以通过计算得到(参考网址http://www.mysqlcalculator.com/):

在这里插入图片描述

另外,也可以通过SQL语句获得各个配置的大小(假设最大连接为200),如下所示:

select VARIABLE_NAME,VARIABLE_VALUE/1024/1024 MB from performance_schema.global_variables WHERE VARIABLE_NAME in ('key_buffer_size','query_cache_size','tmp_table_size','innodb_buffer_pool_size','innodb_additional_mem_pool_size','innodb_log_buffer_size')
union all
SELECT 'sort_buffer_size',(v1.VARIABLE_VALUE*v2.vv) MB
FROM ( select 200 as VARIABLE_VALUE from performance_schema.global_variables WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,( SELECT VARIABLE_VALUE/1024/1024 vv FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'sort_buffer_size' ) AS v2 
union all
SELECT 'read_buffer_size',(v1.VARIABLE_VALUE*v2.vv) MB
FROM ( select 200 as VARIABLE_VALUE from performance_schema.global_variables WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,( SELECT VARIABLE_VALUE/1024/1024 vv FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'read_buffer_size' ) AS v2 
union all
SELECT 'read_rnd_buffer_size',(v1.VARIABLE_VALUE*v2.vv) MB
FROM ( select 200 as VARIABLE_VALUE from performance_schema.global_variables WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,( SELECT VARIABLE_VALUE/1024/1024 vv FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'read_rnd_buffer_size' ) AS v2 
union all
SELECT 'join_buffer_size',(v1.VARIABLE_VALUE*v2.vv) MB
FROM ( select 200 as VARIABLE_VALUE from performance_schema.global_variables WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,( SELECT VARIABLE_VALUE/1024/1024  vv FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'join_buffer_size' ) AS v2 
union all
SELECT 'thread_stack',(v1.VARIABLE_VALUE*v2.vv) MB
FROM ( select 200 as VARIABLE_VALUE from performance_schema.global_variables WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,( SELECT VARIABLE_VALUE/1024/1024 vv FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'thread_stack' ) AS v2 
union all
SELECT 'binlog_cache_size',(v1.VARIABLE_VALUE*v2.vv) MB
FROM ( select 200 as VARIABLE_VALUE from performance_schema.global_variables WHERE VARIABLE_NAME='MAX_CONNECTIONS' ) AS v1,( SELECT VARIABLE_VALUE/1024/1024 vv FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'binlog_cache_size' ) AS v2

对于连接配置,可以查看系统中历史最大连接情况进行评估

mysql> show global status like 'Max_used_connections';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Max_used_connections | 28    |
+----------------------+-------+
1 row in set (0.00 sec)
2、MySQL中内存相关表

在MySQL中有内存相关的表监控内存的使用情况

mysql> show tables like '%memory%';
+-----------------------------------------+
| Tables_in_performance_schema (%memory%) |
+-----------------------------------------+
| memory_summary_by_account_by_event_name |
| memory_summary_by_host_by_event_name |
| memory_summary_by_thread_by_event_name |
| memory_summary_by_user_by_event_name |
| memory_summary_global_by_event_name |
+-----------------------------------------+
5 rows in set (0.00 sec)

以上表的监控统计,分别统计帐户、主机、线程、用户和全局事件执行内存操作等信息。

1)memory_summary_by_account_by_event_name

按MySQL账户和事件名称分类的内存使用情况摘要,识别哪些账户正在使用最多的内存,以及这些内存是如何分配的,如查询、系统锁等特定事件。

select USER, HOST, EVENT_NAME, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_account_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc limit 10;

2)memory_summary_by_host_by_event_name

按连接到MySQL的主机和事件名称分类的内存使用情况摘要,用来识别识别哪些远程主机或IP地址正在消耗最多的内存。

select HOST, EVENT_NAME, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_host_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc limit 10;

3)memory_summary_by_thread_by_event_name

按MySQL线程ID和事件名称分类的内存使用情况摘要,对于特定的长时间运行查询或事务的内存使用情况特别有用,因为每个线程通常与一个特定的查询或事务相关联。

select thread_id, event_name, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_thread_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc limit 10;

得到thread_id后,查找performance_schema.threads表获得对应的processlist_id和processlist_info:

mysql> select * from performance_schema.threads where THREAD_ID=49\G
*************************** 1. row ***************************THREAD_ID: 49NAME: thread/sql/one_connectionTYPE: FOREGROUNDPROCESSLIST_ID: 10PROCESSLIST_USER: rootPROCESSLIST_HOST: tango-DB01PROCESSLIST_DB: tango
PROCESSLIST_COMMAND: QueryPROCESSLIST_TIME: 84PROCESSLIST_STATE: User sleepPROCESSLIST_INFO: select count(1),sleep(2000) from tango.t2 for updatePARENT_THREAD_ID: NULLROLE: NULLINSTRUMENTED: YESHISTORY: YESCONNECTION_TYPE: SSL/TLSTHREAD_OS_ID: 1657RESOURCE_GROUP: USR_default
1 row in set (0.00 sec)

也可以通过THREAD_ID,查找performance_schema.events_statements_current和performance_schema.events_statements_history获得对应的历史记录信息,定位到具体的SQL语句信息,以后续应急或优化。

4)memory_summary_by_user_by_event_name

按MySQL用户和事件名称分类的内存使用情况摘要,更侧重于基于用户名而不是完整的账户信息(包括主机)的内存使用。

select USER, EVENT_NAME, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_by_user_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc limit 10;

5)memory_summary_global_by_event_name

包括全局的、不按任何特定账户、主机、线程或用户分类的内存使用情况摘要,提供整个MySQL服务器内存使用的概览,并允许按事件名称来查看这些内存是如何分配的。

select event_name, SUM_NUMBER_OF_BYTES_ALLOC from performance_schema.memory_summary_global_by_event_name order by SUM_NUMBER_OF_BYTES_ALLOC desc LIMIT 10;
3、MySQL内存分配管理

MySQL的内存虽然划分为sharing buffers+innodb_buffer_pool和thread buffers,但实际上是按照Server层和innodb层进行内存管理,而且这两部分是按照不同的内存管理方式进行管理的。

  • InnoDB层则主要由Free List、LRU List、FLU List等多个链表来统一管理Innodb_buffer_pool。Innodb_buffer_pool内存初始化是通过「mmap()」方式直接向操作系统申请内存,最终会申请Innodb_buffer_pool_size大小的文件映射段动态内存。「mmap()」方式申请的内存会在文件映射段分配内存,而且在释放时会直接归还系统。这部分内存空间初始化后仅仅是虚拟内存,等真正使用时,才会分配物理内存。
  • Server层是由mem_root来进行内存管理,包括Sharing与Thead buffers。「mem_root」结构体使用内存分配管理器进行内存统一管理,避免频繁调用内存操作,提升性能,统一的分配和管理内存也可以防止发生内存泄漏。

MySQL首先通过「init_alloc_root」函数初始化一块较大的内存空间,实际上最终是「通过malloc函数向内存分配器申请内存空间」,然后每次再调用alloc_root函数在这块内存空间中分配出内存进行使用,其目的就是将多次零散的malloc操作合并成一次大的malloc操作,以提升性能。

在Linux中常用的内存分配管理器有三种:ptmalloc(Glibc)、tcmalloc(Google)、jemalloc(FreeBSD)。MySQL 默认使用的是glibc的ptmalloc作为内存分配器。

  • ptmalloc(glibc):ptmalloc是GNU C库(glibc)中的默认内存分配器,广泛用于Linux系统。它提供了一套标准的内存分配和释放函数,如malloc、free、realloc等。ptmalloc通过维护内存池来优化内存分配,并尝试减少内存碎片。然而,由于它是glibc的一部分,因此在某些情况下,其性能可能不如其他专为性能而设计的内存分配器。
  • tcmalloc(Google):tcmalloc用于多线程环境,并通过减少锁的竞争和内存碎片来提高性能。tcmalloc使用线程本地缓存(Thread-Caching Malloc)的概念,将内存分配的任务分散到不同的线程中,以减少对共享数据结构的竞争。此外,tcmalloc还采用了一些优化策略,如小对象合并、高效的分配器缓存等,以进一步提高性能。
  • jemalloc(FreeBSD):jemalloc是由FreeBSD社区开发的一款通用的内存分配器,并逐渐被其他系统广泛采用。jemalloc的设计目标是提供高度可扩展性和低碎片化的内存分配。它使用了一种称为arena的并发数据结构来管理内存,每个arena都有自己的内存池和缓存,以减少锁的竞争。jemalloc还采用了一种称为“大小类”(size classes)的机制来管理不同大小的内存分配请求。它将内存分配请求划分为不同的大小类,并为每个大小类维护一个独立的内存池和缓存。这种机制使得jemalloc在处理不同大小的内存分配请求时具有更高的灵活性和效率。

在这里插入图片描述

在实际生产系统中,遇到MySQL实例实际占用的内存比innodb_buffer_pool配置的高很多,但是没有及时释放的现象。大部分是因为内存分配管理器占用很多内存不释放,另一部分是因为内存碎片。另外在部分场景下,原生的MySQL使用的ptmalloc内存管理存在内存释放不及时的问题,所以在基于MySQL系列的国产数据库在内存管理上进行了部分优化,比如使用tcmalloc替代ptmalloc进行内存管理。通过以下命令,也可以查看实际使用的内存管理方式:

pt-mysql-summary  -S /tmp/mysql.sock --user root --password xxxxxx|grep -A 5 "Memory management"
# Memory management library ##################################
jemalloc is not enabled in mysql config for process with id 1339
# The End ####################################################

针对ptmalloc(glibc)内存管理的缺陷(调用glibc申请的内存使用完毕后,归还给OS时没有被正常回收,而变成了碎片,随着碎片的不断增长,就能看到mysqld进程占用的内存不断上升)。在测试环境,可以调用gdb函数主动回收释放内存碎片空间:

gdb --batch --pid `pidof mysqld` --ex 'call malloc_trim(0)'

以上是MySQL数据库内存配置和管理的相关知识。


参考资料:

  1. https://dev.mysql.com/doc/refman/8.0/en/memory-use.html
  2. https://blog.csdn.net/dc666/article/details/78901341
  3. https://blog.csdn.net/n88Lpo/article/details/126925517/
  4. https://zhuanlan.zhihu.com/p/264916825
  5. https://www.modb.pro/db/60336

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/13739.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL索引和视图

MySQL索引和视图是关系型数据库MySQL中的两个重要概念。索引用于优化数据库的查询性能&#xff0c;而视图用于提供一个逻辑上的表结构&#xff0c;方便用户查询和操作数据。 索引是一种数据结构&#xff0c;可以加速对数据库表中的数据进行查询的速度。通过创建索引&#xff0…

激光雷达SLAM算法综述

大家好呀&#xff0c;我是一个SLAM方向的在读博士&#xff0c;深知SLAM学习过程一路走来的坎坷&#xff0c;也十分感谢各位大佬的优质文章和源码。随着知识的越来越多&#xff0c;越来越细&#xff0c;我准备整理一个自己的激光SLAM学习笔记专栏&#xff0c;从0带大家快速上手激…

BEVFusion的相机工作流中,图像编码之后FPN+ADP网络的作用

在BEVFusion的相机工作流中&#xff0c;图像编码之后会经过一个FPNADP的网络,那么这个结构的作用是什么呢 FPN大家都很熟悉&#xff0c;就是特征金字塔。但是这里还是贴一些来自GPT的废话 在Bird’s Eye View (BEV) 算法中使用的特征金字塔网络&#xff08;FPN, Feature Pyrami…

视频监控管理平台LntonCVS监控视频汇聚融合云平台主要功能应用场景介绍

随着网络技术的不断发展和万物互联时代的到来&#xff0c;视频融合在一些系统集成项目及综合管理应用中变得日益重要。本文以LntonCVS视频融合云平台为案例&#xff0c;探讨视频融合的对象及其应用场景。 1. 视频监控设备 视频监控摄像设备是各种视频应用项目的基础部分。在视…

【Andoird开发】android获取蓝牙权限,beacon,android-beacon-library

iBeacon 最先是苹果的技术&#xff0c;使用android-beacon-library包可以在android上开发iBeacon 技术。 iBeacon的发明意义重大。它是一种基于蓝牙低功耗&#xff08;Bluetooth Low Energy, BLE&#xff09;技术的定位系统&#xff0c;通过向周围发送信号来标识其位置。这项技…

【NumPy】关于numpy.arange()函数,看这一篇文章就够了

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

AI--构建检索增强生成 (RAG) 应用程序

LLM 所实现的最强大的应用之一是复杂的问答 (Q&A) 聊天机器人。这些应用程序可以回答有关特定源信息的问题。这些应用程序使用一种称为检索增强生成 (RAG) 的技术。 典型的 RAG 应用程序有两个主要组件 索引&#xff1a;从源中提取数据并对其进行索引的管道。这通常在线下…

实时3D云渲染与汽车虚拟仿真的联系

汽车虚拟仿真是指利用计算机技术对汽车进行全方位的模拟&#xff0c;包括车身结构、发动机、转向系统、悬挂系统、制动系统等各个方面&#xff0c;以达到实现汽车设计验证、性能分析、安全评估和驾驶模拟等目的的一种技术手段。现如今&#xff0c;越来越多的汽车制造商采用虚拟…

K8s Service 背后是怎么工作的?

kube-proxy 是 Kubernetes 集群中负责服务发现和负载均衡的组件之一。它是一个网络代理&#xff0c;运行在每个节点上, 用于 service 资源的负载均衡。它有两种模式&#xff1a;iptables 和 ipvs。 iptables iptables 是 Linux 系统中的一个用户空间实用程序&#xff0c;用于…

Kroma宣布推出Spectrum:以太坊Layer-2的先进原生质押服务

Kroma宣布推出备受期待的Spectrum&#xff0c;这是一项先进的原生质押服务&#xff0c;旨在彻底改变以太坊 Layer-2格局。Spectrum将于2024年5月14日开始运营&#xff0c;为用户提供利用质押ETH、stETH和eETH的奖励机会&#xff0c;助力用户在去中心化金融&#xff08;DeFi&…

爆火!开源多模态大模型在手机端进行本地部署!

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型& AIGC 技术趋势、大模型& AIGC 落地项目经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了…

二叉树遍历操作详解

目录 一、思路详解 1.1 递归思路 1.2 递归分支图 1.3 递归栈帧图 二、C语言实现 2.1 前序遍历 2.2 中序遍历 2.3 后序遍历 三、查找值为x的结点 3.1 递归思路 3.2 C语言代码 一、思路详解 采用递归的思想解决问题&#xff0c;以高度为3的满二叉树为例。 1.1 递归思…

ClickHouse 几年内数据查询及细节

在 ClickHouse 中&#xff0c;查询三年内的时间数据可以使用以下方法&#xff1a; 1. 使用日期函数 可以使用 ClickHouse 支持的日期函数来筛选出三年内的数据。例如&#xff0c;使用 today() 函数获取当天日期&#xff0c;使用 toDate() 函数将日期转换为指定格式&#xff0…

【C++】学习笔记——map和set

文章目录 十五、map和set1. 关联式容器2. set的介绍3. set的使用4. multiset5. map的介绍6. map的使用7. multimap8. map中重载的operator[] 未完待续 十五、map和set 1. 关联式容器 我们已经接触过STL中的部分容器&#xff0c;比如&#xff1a;vector 、list 、deque 等&…

Golang | Leetcode Golang题解之第99题恢复二叉搜索树

题目&#xff1a; 题解&#xff1a; func recoverTree(root *TreeNode) {var x, y, pred, predecessor *TreeNodefor root ! nil {if root.Left ! nil {// predecessor 节点就是当前 root 节点向左走一步&#xff0c;然后一直向右走至无法走为止predecessor root.Leftfor pr…

OpenHarmony开发之MQTT讲解

相信MQTT这个名称大家都不陌生&#xff0c;物联网的开发必然会遇到MQTT相关知识的应用。那么什么是MQTT&#xff1f;它有什么特点&#xff1f;它能解决什么问题&#xff1f;它是如何工作的&#xff1f;OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;的物…

简单快捷的图片格式转换工具:认识webp2jpg-online

经常写博客或记笔记的朋友们可能会碰到图床不支持的图片格式或图片太大需要压缩的情况。通常&#xff0c;我们会在浏览器中搜索在线图片格式转换器&#xff0c;但这些转换器往往伴有烦人的广告或要求登录&#xff0c;并且支持的转换格式有限。最近&#xff0c;我在浏览 GitHub …

hls.js实现分片播放视频

前言&#xff1a;hls.js官网&#xff1a;hls.js - npm 一、demo——在HTML中使用 <audio id"audio" controls></audio><script src"https://cdn.jsdelivr.net/npm/hls.jslatest"></script> <script>document.addEventList…

upload-labs 通关方法

目录 Less-1&#xff08;JS前端验证&#xff09; Less-2&#xff08;MIME验证&#xff09; Less-3&#xff08;黑名单&#xff0c;特殊过滤&#xff09; Less-4&#xff08;黑名单验证&#xff0c;.htaccess&#xff09; Less-5&#xff08;黑名单&#xff0c;点空格点绕过…

Qt | QCalendarWidget 类(日历)

01、QCalendarWidget 类 1、QCalendarWidget 类是 QWidget 的直接子类,该类用于日历,见下图 02、QCalendarWidget 属性 ①、dateEditAcceptDelay:int 访问函数:int dateEditAcceptDelay()const; void setDateEditAcceptDelay(int) 获取和设置日期编辑器的延迟时间(以毫秒…