1、Mysql架构与历史
最上层是服务并不是Mysql所独有的,大多数基于网络的客户端/服务器的工具或者服务都有类似的架构,比如连接处理,授权认证,安全等。
第二层是Mysql比较有意思的部分。大多数Mysql的核心服务都在这一层,包括查询解析,分析,优化,缓存以及所有的内置函数,所有跨存储引擎的功能都在这一层实现:存储过程,视图,触发器等。
第三层包括了存储引擎,存储引擎负责Mysql中数据的存储和提取。服务器通过API与存储引擎进行通信,这些接口屏蔽了不同存储引擎之间的差异。存储引擎不会去解析sql,不同存储引擎之间也不会相互通信,只是简单地响应上层服务器的请求。
每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中执行,该线程只会轮流在某个CPU核心或CPU中运行。服务器只会负责缓存线程,因此不需要为每一个新建的连接创建或者销毁线程。
当客户端连接到Mysql服务器时,服务器需要对其进行认证,如果使用了安全套接字SSL的方式连接,还可以使用X.509证书认证。一旦客户端连接成功,服务器会继续验证该客户端1是否具有执行特定查询的权限。
Mysql会解析查询,并创建内部数据结构,然后对其进行各种优化,包括重写查询,决定表的读取顺序,以及选择合适的索引等。用户可以通过关键字提示优化器,也可以查询优化器过程(explain)。
优化器并不关心表使用的什么存储引擎,但存储引擎对于优化查询是有影响的。优化器会请求存储引擎提供容量或某个具体操作的开销信息,以及表数据的统计信息等。
无论何时,只要有多个查询需要再同一时刻修改数据,都会产生并发控制的问题,Mysql会在两个层面进行并发控制:服务器层与存储引擎层。
读锁是共享的,或者说是相互不阻塞的,多个客户在同一时刻可以同时读取同一个资源,而互不干扰。写锁则是排他的,也就是说一个写锁会阻塞其他的写锁和读锁,这是处于安全策略的考虑,只有这样,才能确保在给定的时间内,只有一个用户能执行写入,并防止其他用户读取正在写入的同一资源。
一种提高共享资源并发性的方式就是让锁对象更有选择性。尽量只锁定需要修改的部分数据,而不是所有的资源。更理想的方式是只对会修改的数据片进行精确的锁定。任何时候,在给定的资源上,锁定的数据量越少,则系统的并发程度越高,只要相互之间不发生冲突即可。
问题是加锁也需要消耗资源,锁的各种操作,包括获得锁,检查锁是否已经解除,释放锁等,都会增加系统的开销。如果系统花费大量的时候来管理锁,而不是存储数据,那么系统的性能可能会受到影响。
所谓锁策略就是在锁的开销和数据的安全性之间需求平衡,这种平衡当然也会影响到性能。一般都是在表上加行级锁,并以各种复杂的方式来实现,以便在锁较多的情况下尽可能低提供更好的性能。
Mysql提供了多种选择,每种Mysql存储引擎都可以实现自己的锁策略和锁粒度。下面介绍两种最重要的锁策略
表锁是Mysql中最基本的锁策略,并且是开销最小的策略。他会锁整张表,一个用户对表进行写操作前,需要先获取写锁,这会阻塞其他用户对该表的所有读写操作。只有没有写锁时,其他读取用户才能获取读锁,读锁之间是不相互阻塞的。
在特定场景中,表锁也可能有良好的性能,例如 READ LOCAL 表锁支持某些类型的并发写操作。另外写锁比读锁有更高的优先级,因此一个写锁请求可能会被插入到读锁队列的前面。
行级锁可以最大程度地支持并发处理,同时也带来了最大的锁开销。Mysql在InnoDB中实现了行级锁。行级锁只在存储引擎层实现,而Mysql服务器层没有实现,服务器层完全不了解存储引擎中的锁实现。
事务就是一组原子性的sql查询,或者说一个独立的工作单元。如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询。如果其中有任何一个语句因为崩溃或其他原因无法执行,那么所有的语句都不会执行。也就是说事务内的语句,要么全部执行成功,要么全部执行失败。
我们可以先了解一下事务的ACID概念。ACID表示原子性,一致性,隔离性和持久性。
原子性:一个事务必须被视为一个不可分割的最小工作单元,整个事务中所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是原子性操作。
一致性:数据库总是从一个一致性的状态转换到另外一个一致性的状态。
隔离性:通常来说,一个事务所做的修改在最终提交之前,对其他事务是不可见的。
在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。
READ UNCOMMITTED(未提交读):事务中的修改,即使没有提交,对其他事务也是可见的。事务可以读取未提交的数据,这也被称为脏读。
READ COMMITTED(已提交读):大多数数据库系统的默认隔离级别都是READ COMMITTED。该级别满足隔离级别的简单定义,一个事务开始时,只能看见已经提交的事务所做的修改。换句话说就是一个事务从开始到提交之前,所做的任何修改对其他事务都不可见。也叫不可重复读。
REPEATABLE READ(可重复读):,MYSQL默认隔离级别。该级别解决了脏读的问题。保证了在同一事务中多次读取同样记录的结果是一致的。但是理论上可重复读无法解决幻读的问题。所谓幻读就是说当某个事务在读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围内的记录时,会产生幻行。InnoDB等存储引擎通过多版本并发控制解决了幻读的问题。
SERIALIZABLE(可串行化):最高隔离级别,通过强制事务串行执行,避免了幻读的问题。简单来说就是给每行数据加上锁,所以可能会导致大量的超时和锁争用的问题。实际应用中很少用这个隔离级别。
隔离级别 | 脏读可能性 | 不可重复读可能性 | 幻读可能性 | 加锁读 |
---|---|---|---|---|
READ UNCOMMITTED | √ | √ | √ | × |
READ COMMITTED | × | √ | √ | × |
REPEATABLE READ | × | × | √ | × |
SERIALIZABLE | × | × | × | √ |
死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。当多个事务视图以不同的顺序锁定资源时,就可能会产生死锁。多个事务同时锁定同一个资源时,也会产生死锁。
InnoDB目前解决死锁的方法是将持有最少行级排他锁的事务进行回滚。
事务日志可以帮助提高事务的效率,使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久化的事务日志中,而不用每次都将修改的数据本身持久化到磁盘。事务日志使用追加的方式,因此写日志的操作时磁盘上一小块区域内的顺序IO,而不像随机IO需要再磁盘的多个地方移动磁头。事务日志持久化之后,内存中被修改的数据在后台可以慢慢的回刷到磁盘。
如果数据的修改已经记录到事务日志并持久化,但数据本身还没有写回磁盘,此时系统崩溃,存储引擎在重启时能够自动修复这部分修改的数据。
Mysql默认采用自动提交模式,也就是说如果不是显式地开始一个事务,则每个查询都被当做一个事务执行提交操作。
Mysql服务器层不管理事务,事务是由下层的存储引擎实现的。所以在同一个事务中,使用多个存储引擎是不可靠的。如果在事务中混合使用了事务型和非事务型的表,再正常提交的情况下不会有什么问题,但是如果需要回滚的话,非事务型的表上的修改就无法撤销从而导致数据不一致。
InnoDB采用的是两阶段锁定协议。在事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一时刻释放。InnoDB会根据隔离级别在需要的时候自动加锁。
SELECT ... LOCK IN SHARE MODE;
SELECT ... FOR UPDATE;
Mysql的大多数事务型存储引擎实现的都不是简单的行级锁,基于提升并发性能的考虑,一般都同时实现了多版本并发控制。MVCC是行级锁的一个变种,他在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。
MVCC的实现是通过保存数据在某个时间点的快照来实现的。也就是说不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务的开始时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。
不同的存储引擎MVCC的实现是不同的,典型有乐观并发控制和悲观并发控制。
InnoDB的MVCC是通过在每行记录后面保存两个隐藏的列来实现的。这两列,一个保存了行的创建时间,一个保存行的过期时间。当然存储的并不是实际的时间值而是系统版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号作为事务的版本号,用来和查询到的每行记录的版本号进行比较。下面我们来看看在 REAPEATABLE READ 隔离级别下。MVCC是如何操作的。
InnoDB值查找版本早于当前事务版本的数据行,这样就可以保证事务读取的行要么是事务开始前已经存在得,要么是事务自身修改过的。
行的删除版本要么未定义,要么大于当前事务版本号。确保事务读取到的行在事务开始之前未被删除。
INSERT:InnoDB为新插入的行保存当前系统版本号作为行版本号
DELETE:InnoDB为删除的每一行保存当前系统版本号作为行删除标识
UPDATE:InnoDB为新插入的行保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为删除标识
保存这两个系统版本号,使得大部分读操作都可以不用加锁,这样设计使得读取操作很简单,性能很好,并且也能保证只会读取到符合标准的行。不足之处就是每行记录都需要额外的存储空间。
MVCC只在 REPEATABLE READ 和 READ COMMITTED 两个隔离级别下工作。因为 READ UNCOMMITTED 总是读取最新的数据行而不是符合当前事务版本的数据行;而 SERIALIZABLE 则会对所有读取的行都加锁。
在文件系统中,Mysql将每个数据库保存为数据目录下的一个子目录。创建表时,Mysql会在数据库子目录下创建一个和表同名的.frm文件保存表的定义。可以使用SHOW TABLE STATUS 命令显式表的相关信息。
mysql> show table status like 'user' \G
*************************** 1. row ***************************Name: userEngine: InnoDBVersion: 10Row_format: DynamicRows: 9Avg_row_length: 1820Data_length: 16384
Max_data_length: 0Index_length: 0Data_free: 0Auto_increment: 14Create_time: 2023-09-24 17:34:24Update_time: NULLCheck_time: NULLCollation: utf8mb4_general_ciChecksum: NULLCreate_options:Comment:
1 row in set (0.00 sec)
Row_format:行的格式,对于InnoDB的表,常见的行格式类型有Compact、Redundant、Dynamic和Compressed。
Compact行格式是MySQL5.0中引入的,其目标是为了更高效的存储数据记录。其存储结构示意图如下:
从图中我们可以看出来,一条完整的记录其实可以被分为记录的额外信息和记录的真实数据两部分。
这部分信息是为了描述这条记录而不是额外添加的一些信息,这些额外信息分为三部分,分别是变长字段长度列表、NULL值列表和记录头信息;
MySQL支持一些变长的数据类型,比如VARCHAR(M)、 VARBINARY(M)、 TEXT类型、BLOB类型,这些数据类型修饰列称为变长字段。变长字段中存储多少字节的数据不是固定的,所以我们在存储真实数据的时候需要顺便把这些数据占用的字节数也存起来。也就是变长字段时占用了两部分空间来存储的,(1)真实的数据内容,(2)占用的字节数。
在Compact行格式中,把所有变长字段的真实数据占用的字节长度都存放在记录的开头部位,从而形成一个变长字段长度列表。
需要注意的是,这里面存储的变长长度和字段顺序是相反的。比如两个varchar字段在表结构的顺序是a(10), b(15),那么在变长字段长度列表中存储的长度顺序就是15,10,是反过来的。变长字段的长度列表不是一定存在的,如果表中没有变长类型的字段,或者该记录中所有的变长字段值均为NULL。
表中的某些列可能存储NULL值,如果把这些NULL值都放到记录的真实数据中存储则显的比较浪费空间,所以Compact行格式把这些值为NULL的列统一管理起来,存储到NULL值列表中。
如果表中有字段允许为NULL,InnoDB就会开辟一块空间来标识每个字段实际存储的数据是不是NULL,如果表中的字段都不允许为NULL,则NULL值列表也就不存在了。
每个允许存储NULL的列对应一个二进制位,二进制位按照列的逆序排列,二进制位表示的意义如下:
记录头信息用于描述该记录的,它是由固定的5个字节组成,即40个二进制位,不同的位代表不同的意思;
名称 | 大小(bit) | 描述 |
---|---|---|
预留位1 | 1 | 没有使用 |
预留位2 | 1 | 没有使用 |
delete_mask | 1 | 标记该记录是否被删除。0 - 没有被删除,1 - 记录被删除那么被删除的记录为什么还在页中存储呢?实际上记录并没有从磁盘消失。这些被删除的记录之所以不立即从磁盘上移除是因为移除它们之后其他的记录在磁盘上需要重新排列,导致性能消耗。所以只是打一个标记而已,所有被删除掉的记录都会组成一个所谓的垃圾链表,在这个链表中的记录占用的空间称之为可重用空间,之后如果有新纪录插入到表中的话,可能把这些被删除的记录占用的存储空间覆盖掉。 |
min_rec_mask | 1 | B+树的每层非叶子节点中的最小记录都会添加该标记,值为1。 0 - 表示不是B+树的非叶子节点中的最小记录 |
n_owned | 4 | 表示当前记录拥有的记录数 。页目录中每个组最后一条记录的头信息中会存储该组一共有多少条记录,作为n_owned字段 |
heap_no | 13 | 表示当前记录在本页中的位置信息,heap_no是没有值为0和1的。这是因为MySQL会自动给每个页里加两个记录,这两个记录并不是我们自己插入的,所以有时候也称为伪记录或者虚拟记录。这两个伪记录一个代表最小记录,一个代表最大记录。最小记录和最大记录的heap_no值分别是0和1,也就是说它们的位置最靠前。 |
record_type | 3 | 表示当前记录的类型:0 - 普通记录, 1- B+树非叶子节点记录,2 - 最小记录,3 - 最大记录 |
next_record | 16 | 表示下一条记录的相对位置,也就是从当前记录的真实数据到下一条记录的真实数据的地址偏移量。 |
记录的真实数据除了自定义的列的数据以外,MySQL还会为每条记录默认的添加一些列(也称为隐藏列),具体的列如下:
列名 | 是否必须 | 占用空间 | 描述 |
---|---|---|---|
DB_ROW_ID | 否 | 6字节 | 行ID,唯一标识一条记录 |
DB_TRX_ID | 是 | 6字节 | 事务ID |
DB_ROLL_PTR | 是 | 7字节 | 回滚指针 |
当用户未指定数据表的主键时,MySQL会选择非NULL的Unique列作为主键,而如果非NULL的Unique列也没有,这个时候MySQL就会向数据表添加DB_ROW_ID字段用来作为主键。记录的数据内容不包括字段值为NULL的数据内容。
redundant行格式是MySQL5.0之前的一种旧的格式,其结构与compact行格式大体还是比较相似的。
在MySQL8.0中,默认行格式就是Dynamic。Dynamic、Compressed行格式和Compact行格式挺像,只不过在处理行溢出数据时有分歧:
Compressed和Dynamic两种记录格式对于存放在BLOB中的数据采用了完全的行溢出的方式。在数据页中只存放20个字节的指针(溢出页的地址),实际的数据都存放在Off Page(溢出页)中。
Compact 和 Redundant两种格式会在记录的真实数据处存储一部分数据(存放768个前缀字节)。
Compressed行记录格式的另一个功能就是,存储在其中的行数据会以zlib的算法进行压缩,因此对于blob、text、varchar这类大长度类型的数据能够进行非常有效的存储。
Rows:表中的行数,InnoDB引擎该值是估计值,MyISAM引擎是精确值
Max_data_length:表数据的最大容量,该值和存储引擎有关
Data_free:对于MyISAM表,表示已分配但目前没有使用的空间。这部分空间包括了之前删除的行,以及后续可以被INSERT利用的空间
Auto_increment:下一个 AUTO_INCREMENT 的值
Check_time:使用 CHECK TABLE 命令或者 myisamchk 工具最后一次检查表的时间
InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级别。其默认级别是 REAPEATABLE READ,并且通过间隙锁策略防止幻读的出现。间隙锁使得InnoDB不仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻行的插入。
InnoDB表是基于聚簇索引建立的。InnoDB内部做了很多优化,包括从磁盘读取数据时采用的可预测性预读,能够自动在内存中创建hash索引以加速读操作的自适应哈希索引。
在Mysql5.1及之前的版本,MyISAM是默认的存储引擎。MyISAM提供了大量的特性,包括全文索引、压缩、空间函数等,但MyISAM不支持事务和行级锁,而且崩溃后无法完全恢复。
MyISAM会将表存储在两个文件中:数据文件和索引文件,分别以 .myd 和 .myi 为扩展名。Mysql会根据表的定义来决定采用哪种行格式。
MyISAM对整张表加锁,而不是针对行。读取时会对需要读到的所有表加共享锁,写入时则对表加排他锁。但是在表有读取操作的时候,也可以进行插入操作。
对于MyISAM表,Mysql可以手工或者自动执行检查和修复操作。执行表的修复可能会导致一些数据的丢失,而且修复操作非常慢。
对于MyISAM表即使是BLOB和TEXT等字段,也可以基于前500个字符创建索引。MyISAM也支持全文索引
创建MyISAM表的时候,如果指定了DELAY_KEY_WRITE 选项,在每次修改执行完成时,不会立刻将修改的索引数据写入磁盘。而是会写到内存中的键缓冲区,只有在清理键缓冲区或者关闭表时才会将对应的索引快写入磁盘。这种方式提高了写入性能但是在服务器崩溃的时候会造成索引损坏需要执行修复操作。
如果表在创建并导入数据以后不会再进行修改操作,那么这样的表适合采用MyISAM压缩表。
可以使用myisampack对MyISAM表进行压缩。压缩表是不能进行修改的,极大的减少磁盘空间占用,因此也减少磁盘IO,从而提升查询性能。
相关文章:

1、Mysql架构与历史
Mysql逻辑架构 最上层是服务并不是Mysql所独有的,大多数基于网络的客户端/服务器的工具或者服务都有类似的架构,比如连接处理,授权认证,安全等。 第二层是Mysql比较有意思的部分。大多数Mysql的核心服务都在这一层,…...

考试复习
选择20道 填空10道 判断10道 简答4-5道 编程题2道 一、选择题 1.js中更改一个input框的值: <input ida type"text" value"123456"> 通过a.value改变他的值 方法: 在script标签中通过id获得该输入框对象,然…...
使用Docker一键安装MySQL与Nginx脚本
在项目开发和部署过程中,使用Docker可以方便地快速搭建和管理数据库(MySQL)以及Web服务器(Nginx)。本教程将为你提供一份一键安装脚本。 安装Docker 首先,确保你的系统已经安装了Docker。如果没有安装&am…...
VMware系列:Vmware vSphere常见问题及解决办法
Vmware vSphere常见问题及解决办法 1. 虚拟机文件被锁,无法正常 power on故障状态:祸根:解决方法:2. 忽视掉ESXi/vCenter Server提示SSH事件的方法3. 尝试迁移一台带USB设备的VM失败故障状态:故障分析:解决方案:4. Convert Linux系统的Troublshooting过程5. vCenter Serv…...

基于web宠颐生宠物医院系统设计与实现
基于web宠颐生医院系统开发与实现 摘要:时代飞速发展,网络也飞速发展,互联网许多的行业都可以用互联网实现了,互联网已经成为了人们生活中重要的一部分,或多或少的影响着我们的生活,互联网在给我带了方便的…...

二、Gitee使用方法
目录 (1)首先可以注册一个 gitee 账号,注册很方便,自行注册 (2)登陆后进入你的主页 (3)创建仓库 (3)克隆 (4)代码提交 …...

【C++】string模拟
string讲解:【C】String类-CSDN博客 基本框架 #pragma once #include <iostream> using namespace std; namespace wzf {class string{public:// 默认构造函数string(): _str(new char[1]), _size(0), _capacity(0){_str[0] \0; // 在没有内容时仍要有终…...

python高级练习题库实验1(A)部分
文章目录 题目1代码实验结果题目2代码实验结果题目3代码实验结果题目4代码实验结果题目总结题目1 输入一个整数,用于控制输出*的个数,输入日期,按照特定格式输出 研究下面的例子,并编写一个与这些例子完全相同的程序。 代码 import datetime# ask user for length of b…...

数据库应用:MongoDB 数据备份与恢复
目录 一、实验 1.MongoDB 数据库备份与恢复 2.MongoDB 数据表备份与恢复 二、问题 1.MongoDB有哪些命令行工具实现数据备份与恢复 一、实验 1.MongoDB 数据库备份与恢复 (1)查看版本 rootnode1:~# mongo --version(2)准备…...

MySQL-函数
一、统计函数 CREATE TABLE student (id INT NOT NULL DEFAULT 1,name varchar(20) not null default ,chinese float not null default 0.0,english float not null default 0.0,math float not null default 0.0 );insert into student values (1,曹操,77,89,85);insert int…...
【12】Python函数专题(下)
文章目录 1. 高阶函数1.1 以函数为参数1.2 以函数为返回值1.3 以函数为 参数和返回值2. 闭包3. 装饰器3.1 装饰器的引入3.2. 装饰器的使用3.3 装饰器强化练习🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…...

国标GB28181协议/RTSP视频监控汇聚平台EasyCVR(V.3.4)页面UI大更新
为提高用户体验,增强平台功能,旭帆科技的Easy系列平台也在不断优化更新中。在最新的EasyCVR(V.3.4)中,其最显著的区别即为首页UI的调整。 其亮点是在【配置中心】-【基础配置】-【展示信息】中,首页UI可分…...

生成式AI与预测式AI的主要区别与实际应用
近年来,预测式人工智能(Predictive AI)通过先进的推荐算法、风险评估模型、以及欺诈检测工具,一直在推高着该领域公司的投资回报率。然而,今年初突然杀出的生成式人工智能(Generative AI)突然成…...

【JavaEE】多线程 -- 死锁问题
目录 1. 问题引入 2.死锁问题的概念和原因 3. 解决死锁问题 1. 问题引入 在学习死锁之前, 我们先观察下面的代码能否输出正确的结果: 运行程序, 能正常输出结果: 这个代码只管上看起来, 好像是有锁冲突的, 此时的 locker 对象已经是加锁的状态, 在尝试对 locker 加锁, 不应该…...

XTU OJ 1339 Interprime 学习笔记
链接 传送门 代码 #include<bits/stdc.h> using namespace std;const int N1e610; //78498 我计算了一下,6个0的范围内有这么多个素数,所以开这么大的数组存素数 //计算的代码是一个循环 int prime[80000]; int a[N],s[N];//s数组是前缀和数组b…...
【Web安全】xss攻击方式与绕过
xss攻击方式与绕过 文章目录 xss攻击方式与绕过XSS攻击方式1. script标签2. img标签3. input标签4. details标签5. svg标签6. select标签7. iframe标签8. video标签9. audio标签10. body标签11. textarea标签 常见绕过方式1. 空格过滤2. 引号过滤3. 括号过滤4. 关键词过滤5. 编…...

文件夹重命名技巧:用关键词替换文件夹名称指定内容的右侧文字
在日常生活中,经常要管理大量的文件夹,这时候掌握一些文件夹重命名的技巧就非常实用。例如文件夹重命名时,经常要将一些通用的文字替换成其他关键词,以便更好地标识和分类文件夹。而用关键词替换文件夹名称指定内容的右侧文字&…...

python pip安装第三方包时报错 error: Microsoft Visual C++ 14.0 or greater is required.
文章目录 1.问题2.原因3.解决办法 1.问题 pip install 的时候报错一大堆,其中有这么一段话 👇 error: Microsoft Visual C 14.0 or greater is required. Get it with "Microsoft C Build Tools": https://visualstudio.microsoft.com/visua…...

对 .NET程序2G虚拟地址紧张崩溃 的最后一次反思
一:背景 1. 讲故事 最近接连遇到了几起 2G 虚拟地址紧张 导致的程序崩溃,基本上 90% 都集中在医疗行业,真的很无语,他们用的都是一些上古的 XP,Windows7 x86,我也知道技术人很难也基本无法推动硬件系统和…...

HCIA-RS基础-静态路由协议
摘要:静态路由是一种在网络中广泛应用的路由选择方案,它以其简单的配置和低开销而备受青睐。本文将介绍静态路由的配置方法、默认路由的设置、路由的负载分担和备份策略。通过学习本文,希望可以你能够掌握静态路由的基本概念和在华为模拟器中…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...