MySQL架构篇
一、进阶学习环境说明
1.1 MySQL服务器环境
Linux虚拟机:CentOS 7
MySQL:MySQL5.7.30
在Linux服务器中安装MySQL:
ps.如果有自己的云服务器,可忽略前两步,直接进行第三步
1.2 服务器日志文件说明
MySQL是通过文件系统对数据和索引进行存储的。MySQL从物理结构上可以分为日志文件和数据与索引文件。MySQL在Linux中的数据索引文件和日志文件通常放在/var/lib/mysql目录下。
MySQL通过日志记录了数据库操作信息和错误信息。常用的日志文件包括:
- 错误日志
- 二进制日志
- 查询日志
- 慢查询日志
- 事务Redo日志
- 中继日志
- …
可以通过命令查看当前数据库中的日志使用信息:
mysql> show variables like ‘log_%’;
1.2.1 错误日志:error log
默认开启,从5.5.7以后无法关闭错误日志,错误日志记录了运行过程中遇到的所有严重的错误信息,以及MySQL每次启动和关闭的详细信息。错误日志所记录的信息是可以通过log_error和log_warnings来定义的
log_error:是否启用错误日志功能,指定错误日志存储位置
log-warnings:是否将警告信息输出到错误日志中。
log_error=/var/log/mysql-error.log
log_warnings=2
log_warnings 为0, 表示不记录告警信息。
log_warnings 为1, 表示告警信息写入错误日志。
log_warnings 大于1, 表示各类告警信息,例如有关网络故障的信息和重新连接信息写入错误日志。
1.2.2 二进制日志:bin log
默认关闭,需要通过以下配置进行开启。binlog记录了数据库所有的ddl语句和dml语句,但不包括select语句内容,语句以事件的形式保存,描述了数据的变更顺序,binlog还包括了每个更新语句的执行时间信息。如果是DDL语句,则直接记录到binlog日志,而DML语句,必须通过事务提交才能记录到binlog日志中。binlog主要用于实现mysql主从复制、数据备份、数据恢复。配置中mysql-bin是binlog日志文件的basename,binlog日志文件的完整名称:mysql-bin.000001。
server_id=42
log-bin=mysql-bin
1.2.3 通用查询日志:general query log
默认关闭,由于通用查询日志会记录用户的所有操作,其中还包含增删查改等信息,在并发操作大的环境下会产生大量的信息从而导致不必要的磁盘IO,会影响mysql的性能的。如若不是为了调试数据库的目的建议不要开启查询日志。
mysql> show global variables like ‘general_log’;
开启方式:
#启动开关
general_log={ON|OFF}
#日志文件变量,而general_log_file如果没有指定,默认名是host_name.log
general_log_file=/PATH/TO/file
#记录类型
log_output={TABLE|FILE|NONE}
1.2.4 慢查询日志:slow query log
默认关闭,通过以下设置开启。记录执行时间超过long_query_time秒的所有查询,便于收集查询时间比较长的SQL语句。
查看阈值
SHOW GLOBAL STATUS LIKE ‘%Slow_queries%’;
show variables like ‘%slow_query%’;
show variables like ‘long_query_time%’;
配置慢查询开启
#开启慢查询日志
slow_query_log=ON
#慢查询的阈值
long_query_time=10
#日志记录文件如果没有给出file_name值, 默认为主机名,后缀为-slow.log。如果给出了文件名,
但不是绝对路径名,文件则写入数据目录。
slow_query_log_file=slow_query_log.log
1.3 服务器数据文件说明
查看MySQL数据文件:
SHOW VARIABLES LIKE ‘%datadir%’;
ibdata文件:使用共享表空间存储表数据和索引信息,所有表共同使用一个或者多个ibdata文件。
InnoDB存储引擎的数据文件
&.frm文件:主要存放与表相关的数据信息,主要包括表结构的定义信息
&.ibd:使用独享表空间存储表数据和索引信息,一张表对应一个ibd文件。
MyIsam存储引擎的数据文件
&.frm文件:主要存放与表相关的数据信息,主要包括表结构的定义信息
&.myd文件:主要用来存储表数据信息。
&.myi文件:主要用来存储表数据文件中任何索引的数据树。
二、数据库基础概念
2.1 OLTP与OLAP
当今的数据处理大致可分为两大类
- 联机事务处理 OLTP (On-Line Transaction Processing)
OLTP 是传统关系型数据库的主要应用场景,用来执行一些基本的、日常的事务处理, 比如数据库记录的增、删、改、查等等。不适合海量数据的存取与处理- 联机分析处理 OLAP (On-Line Analytical Processing)
OLAP 是分布式数据库的主要应用场景,它对实时性要求不高,但处理的数据量大,通常应用于复杂的动态报表系统上。
2.2 行式存储与列式存储
行式存储法(Row-based):数据一行行存储传统的关系型数据库,如 Oracle、DB2、MySQL、SQL SERVER 等采用行式存储法(Row-based)
在基于行式存储的数据库中, 数据是按照行数据为基础逻辑存储单元进行存储的, 一行中的数据在存储介质中以连续存储形式存在。
列式存储(Column-based):数据一列列存储列式是相对于行式存储来说的,新兴的 Hbase、HP Vertica、EMC Greenplum 等分布式数据库均采用列式存储。
在基于列式存储的数据库中, 数据是按照列为基础逻辑存储单元进行存储的,一列中的数据在存储介质中以连续存储形式存在。
ElasticSearch、MongoDB、Solr、Splunk…
Redis(K/V)
ps:MongoDB,属于文档存储,存储一个JSON(BSON)文档、或者一个文本(二进制)文档。类似的有:elasticserach,solr,oss……
2.3 适用场景
行式存储
适合随机的增删改查操作;
需要在行中选取所有属性的查询操作;
需要频繁插入或更新的操作,其操作与索引和行的大小更为相关。
行式存储实操中,我们会发现行式数据库在读取数据时存在一个固有的“缺陷”。这个"缺陷"是什么?
不擅长在海量数据中找数据。
列式存储
&低延迟:查询过程中,可针对各列的运算并发执行,最后在内存中聚合完整记录集,最大可能降低查询响应时间;
&查找数据高效:无需维护索引,查询过程中能够尽量减少无关IO,避免全表扫描
&节省空间:因为各列独立存储,且数据类型已知,可以针对该列的数据类型、数据量大小等因素动态选择压缩算法,以提高物理存储利用率;如果某一行的某一列没有数据,那在列存储时,就可以不存储该列的值,这将比行式存储更节省空间。当然,跟行数据库一样,列式存储也有不太适用的场景,这个场景是什么?
数据需要频繁更新的交易场景,表中列属性较少的小量数据库场景,不适合做含有删除和更新的实时操作
2.4 行存储 vs 列存储
2.4.1 读取数据分析
假设:从2^30行中取出100001 ~ 200000行的name, status列
行存储成本分析:
场景:读取10W行数据的2列
先取行,再取列:从连续的空间取出10w行,从10w行结果集合中取出name和status列
1行平均10KB:10W行=10W * 10kb ≈ 1G数据
Buffer如何是4M,将进行256次读取10W过滤操作
列存储成本分析:
场景:读取10W行数据的2列
先取列,再取行:从2列中取出10w条
1列的一个条目平均20Byte,10W行的两列=20 byte * 10W ≈ 2M
Buffer如何是4M,将进行1次读取
不需要更多的过滤操作
2.4.2 更新一行多个值分析
行存储:一行数据
列存储:多列数据(次数多)
2.4.3 添加一行数据分析
行存储:一行数据
列存储:多列数据(次数多)
2.4.4 事务操作分析
行存储:锁一行数据
列存储:锁对应的列(范围大)
.
三、MySQL架构图
3.1 逻辑架构图
Connectors:连接器,负责跟客户端建立连接、获取权限、维持和管理连接。
Management Serveices & Utilities:系统管理和控制工具
Connection Pool: 连接池,管理用户连接,负责监听对 MySQL Server 的各种请求,接收连接请求,转发所有连接请求到线程管理模块。
SQL Interface: SQL接口,接受用户的SQL命令,并且返回用户需要查询的结果。
Parser: 解析器:SQL命令传递到解析器的时候会被解析器验证和解析。
Optimizer: 查询优化器:SQL语句在查询之前会使用查询优化器对查询进行优化。explain语句查看的SQL语句执行计划,就是由查询优化器生成的。
Cache和Buffer: 查询缓存,在MySQL5.7中包含缓存组件。在MySQL8中移除了
Pluggable Storage Engines:存储引擎,存储引擎就是存取数据、建立与更新索引、查询数据等技术的实现方法。
3.2 一条SQL语句的完整执行流程
Sql语句执行流程
分析SQL语句如下:
select c_id,first_name,last_name from customer where c_id=14;
大体来说,MySQL 可以分为 Server 层和存储引擎层两部分:
- Server层
包括连接器、查询缓存、分析器、优化器、执行器等
涵盖 MySQL 的大多数核心服务功能
所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实
现,比如存储过程、触发器、视图等。
- 存储引擎层:
负责数据的存储和提取
其架构模式是插件式的支持 InnoDB、MyISAM、Memory 等多个存储引擎。
现在最常用的存储引擎是 InnoDB,从 MySQL 5.5.5 版本开始成为了默认存储引擎。
第一步:连接到数据库
首先会连接到这个数据库上,这时候接待你的就是连接器。
连接命令一般这么写的: mysql -hip−Pip -Pip−Pport -u$user -p
连接完成后,如果你没有后续的动作,这个连接就处于空闲状态。客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数wait_timeout 控制的,默认值是 8 小时。
mysql> show processlist;
其中的 Command 列显示为“Sleep”的这一行,就表示现在系统里面有一个空闲连接。
第二步:查缓存
MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句hash之后的值,value是查询的结果。
如果你的查询语句在缓存中,会被直接返回给客户端。
如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。
如果查询命中缓存,MySQL 不需要执行后面的复杂操作就可以直接返回结果,效率会很高!但是不建议使用MySQL的内置缓存功能
第三步:分析SQL语句
如果查询缓存没有命中,接下来就需要进入正式的查询阶段了。客户端程序发送过来的请求,实际上只是一个字符串而已,所以MySQL服务器程序首先需要对这个字符串做分析,判断请求的语法是否正确,然后从字符串中将要查询的表、列和各种查询条件都提取出来,本质上是对一个SQL语句编译的过程,涉及词法解析、语法分析、语义分析等阶段。
词法分析:词法分析就是把一个完整的 SQL 语句分割成一个个的字符串
语法分析:根据词法分析的结果,语法分析器会根据语法规则做语法检查,判断你输入的这个 SQL语句是否满足 MySQL 语法。
预处理器:预处理器则会进一步去检查解析树是否合法,比如表名是否存在,语句中表的列是否存在等等,在这一步MySQL会检验用户是否有表的操作权限。
(1)词法分析:
词法分析就是把一个完整的 SQL 语句分割成一个个的字符串
比如:这条简单的SQL语句,会被分割成10个字符串
#分隔前
select c_id,first_name,last_name from customer where c_id=14;
#分隔后
select,c_id,first_name,last_name,from,customer,where,c_id,=,14
MySQL 同时需要识别出这个SQL语句中的字符串分别是什么,代表什么。
把"select"这个关键字识别出来,这是一个查询语句把“customer”识别成“表名 customer” 把“c_id识别成“列 c_id”。
(2)语法分析:
分析器第二步是根据词法分析的结果,语法分析器做语法检查。判断 SQL 语句是否满足 MySQL 语法。
“You have an error in your SQL syntax”错误提醒就是在这个位置出现的。如果语法正确就会根据 MySQL语法规则与SQL 语句生成一个数据结构,这个数据结构我们把它叫做解析树。
比如:下面这个语句 select 少打了开头的字母“s”。
mysql> elect c_id,first_name,last_name from customer where c_id=14;
#ERROR 1064 (42000): You have an error in your SQL syntax; check the manualthat corresponds to your MySQL server version for the right syntax to usenear ‘elect * from customer where c_id=14’ at line 1
解析树举例:
(3)预处理器:
预处理器则会进一步去检查解析树是否合法,比如表名是否存在,语句中表的列是否存在等等,在这一步MySQL会检验用户是否有表的操作权限。预处理之后会得到一个新的解析树。
第四步:优化SQL语句
优化器顾名思义就是对查询进行优化。作用是根据解析树生成不同的执行计划,然后选择最优的执行计划。
MySQL 里面使用的是基于成本模型的优化器,哪种执行计划执行时成本最小就用哪种。而且它是io_cost和cpu_cost的开销总和,它通常也是我们评价一个查询的执行效率的一个常用指标。
#查看上次查询成本开销
show status like ‘Last_query_cost’;
优化器可以做哪些优化呢?
- 当有多个索引可用的时候,决定使用哪个索引;
- 在一个语句有多表关联(join)的时候,决定各个表的连接顺序,以哪个表为基准表。
举个栗子:
(1)比如hello数据库中表customer上执行下面的语句,这个语句用到了两个索引last_name和address_id。
#hello数据库中表customer
explain select * from customer where last_name=‘热巴’ and address_id=18;
既可以使用last_name索引查询,然后过滤列address_id
也可以使用address_id索引查询,然后过滤列last_name。
两种执行计划的结果是一样的,但是执行效率会有所不同,而优化器的作用就是决定选择使用哪一个方案。
使用explain工具可以查看优化器的执行计划
注意:优化器最多就是辅助,作用很有限,我们的SQL语句不能依赖于MySQL的优化器去调优!如果SQL语句垃圾,则没有优化的空间。优化SQL的根本,在于掌握MySQL分析与调优技能。
第五步:执行SQL语句
(1)判断执行权限
开始执行的时候,要先判断一下你对这个表customer有没有执行查询的权限,如果没有,就会返回没有权限的错误。
(2)调用存储引擎接口查询
如果有权限,就使用指定的存储引擎打开表开始查询。执行器会根据表的引擎定义,去使用这个引擎提供的查询接口,提取数据。
c_id是主键执行流程:
&调用 InnoDB 引擎接口,从主键索引中检索c_id=14的记录。
&主键索引等值查询只会查询出一条记录,直接将该记录返回客户端。
&至此,这个语句就执行完成了。
c_id不是主键执行流程:全表扫描
&调用 InnoDB 引擎接口取这个表的第一行,判断c_id 值是不是 14,如果不是则跳过,如果是则将这行缓存在结果集中;
&调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
&执行器将上述遍历过程中所有满足条件的行组成的结果集返回给客户端。
&至此,这个语句就执行完成了。
举个栗子:
比如我们新建一个用户lesson1_test,只有表actor的查询权限,没有表customer的查询权限。
CREATE USER `mysql_user`@`localhost` IDENTIFIED BY '123456';
GRANT Select ON TABLE `hello`.`test` TO `mysql_user`@`localhost`;
使用这个用户lesson1_test连接mysql,执行下面的查询语句,就会返回没有权限的错误。
mysql -umysql_user -p123456
mysql> select * from customer where c_id=14;
3.3 案例
查询缓存案例
查询缓存默认是关闭的状态
1)查看是否开启缓存
mysql> show variables like ‘query_cache_type’;
2)查看缓存的命中次数:
mysql> show status like ‘qcache_hits’;
3)开启缓存
在/etc/my.cnf文件中修改“query_cache_type”参数
值为0或OFF
会禁止使用缓存。
值为1或ON
将启用缓存,但以SELECT SQL_NO_CACHE
开头的语句除外。
值为2或DEMAND
时,只缓存以SELECT SQL_CACHE
开头的语句。
修改配置文件 my.cnf ,在文件中增加如下内容开启缓存:
query_cache_type=2
清空查询缓存
可以使用下面三个SQL来清理查询缓存:
FLUSH QUERY CACHE; # 清理查询缓存内存碎片。
RESET QUERY CACHE; # 从查询缓存中移出所有查询。
FLUSH TABLES; # 关闭所有打开的表,同时该操作将会清空查询缓存中的内容。
注意:MySQL 8.0 版本直接将查询缓存的整块功能删掉了,也就是说 8.0 开始彻底没有这个功能了。
多数情况下,不建议使用MySQL查询缓存,为什么呢?
因为查询缓存往往弊大于利。
成本高:查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。因此很可能你费劲地把结果存起来,还没使用呢,就被一个更新全清空了。
命中率不高:对于更新压力大的数据库来说,查询缓存的命中率会非常低。除非你的业务就是有一张静态表,很长时间才会更新一次。比如,一个系统配置表,那这张表上的查询才适合使用查询缓存。
功能并不如业的缓存工具更好:redis、memcache、ehcache…
好在 MySQL 也提供了这种“按需使用”的方式。你可以将参数query_cache_type 设置成 DEMAND,这样对于默认的 SQL 语句都不使用查询缓存。而对于你确定要使用查询缓存的语句,可以用 SQL_CACHE显式指定,像下面这个语句一样:
mysql> select sql_cache * from city where city_id = 1;
MySQL查看配置和状态信息命令
查看配置参数:
show variables like ‘%%’;
#查看状态信息、计数器信息:
show status like ‘%%’;
存储引擎案例
在mysql中可以使用不同的存储引擎
查看支持的存储引擎
show engines
只有InnoDB引擎支持事务、行锁、外键。在选择引擎时尽可能使用InnoDB引擎。
MyIsam:早期版本默认的引擎。
Memory:所有的数据都是保存在内存中。
使用其他引擎,在mysql中默认使用InnoDB引擎,一个数据库中不同的表可以使用不同的引擎。
create table t_myisam(a int primary key, b int) engine=myisam;
四、MySQL的存储引擎之InnoDB
4.1 存储引擎种类
存储引擎 说明 MyISAM 高速引擎,拥有较高的插入,查询速度,但不支持事务 InnoDB 5.5版本后MySQL的默认数据库,支持事务和行级锁定,比MyISAM处理速度稍慢 ISAM MyISAM的前身,MySQL5.0以后不再默认安装 MRG_MyISAM 将多个表联合成一个表使用,在超大规模数据存储时很有用 Memory 内存存储引擎,拥有极高的插入,更新和查询效率。但是会占用和数据量成正比的内存空间。只在内存上保存数据,意味着数据可能会丢失 Falcon 一种新的存储引擎,支持事物处理,传言可能是InnoDB的替代者 Archive 将数据压缩后进行存储,非常适合存储大量的独立的,作为历史记录的数据,但是只能进行插入和查询操作 CSV CSV 存储引擎是基于 CSV 格式文件存储数据(应用于跨平台的数据交换)
查看存储引擎:
mysql> show engines;
引擎怎么选择?大部分情况下,InnoDB都是正确的选择。对于如何选择MySQL引擎这件事上可以归纳为一句话:除非需要用到某些InnoDB不具备的特性,并且没有其他办法可以替代,否则都应该选择InnoDB引擎。
InnoDB和MyISAM存储引擎区别:
>比较项 | Innodb | Myisam |
---|---|---|
存储文件 | .frm表定义文件 .ibd 数据文件和索引文件 | .frm 表定义文件 .myd 数据文件 .myi索引文件 |
锁 | 表锁、行锁 | 表锁 |
事务 | 支持 | 不支持 |
CRDU | 读、写 | 读多 |
索引结构 | B+ Tree | B+ Tree |
4.2 InnoDB架构图
上图详细显示了InnoDB存储引擎的体系架构,从图中可见,InnoDB存储引擎由内存池,后台线程和磁盘文件三大部分组成。
4.4 内存结构
InnoDB 内存结构主要分为如下四个区域:
- Buffer Pool 缓冲池
- Change Buffer 修改缓冲
- Adaptive Hash Index 自适应索引
- Log Buffer 日志缓冲
1)缓冲池(Buffer Pool)
缓冲池Buffer Pool 用于加速数据的访问和修改,通过将热点数据缓存在内存的方法,最大限度地减少磁盘 IO,加速热点数据的读和写。
Buffer Pool 中数据以页为存储单位,其实现数据结构是以页为单位的单链表。默认大小为128M
由于内存的空间限制,Buffer Pool 仅能容纳最热点的数据。Buffer Pool 使用最近最少使用算法(Least Recently Used,LRU)算法淘汰非热点数据页。
对于 Buffer Pool 中数据的查询,InnoDB 直接读取返回;对于 Buffer Pool 中数据的修改,InnoDB 直接在 Buffer Pool 中修改,并将修改写入 redo Log 中,当数据页被 LRU 算法淘汰时写入磁盘,若持久化前系统崩溃,则在重启后使用 redo Log 进行恢复。
show variables like ‘innodb_buffer_pool_size’;
2)修改缓冲(Change Buffer)
Change Buffer(在 MySQL 5.6 之前叫 insert buffer,简称 ibuf )是 InnoDB 5.5 引入的一种优化策略。Change Buffer 用于加速非热点数据中二级索引的写入操作。由于二级索引数据的不连续性,导致修改二级索引时需要进行频繁的磁盘 IO 消耗大量性能,Change Buffer 缓冲对二级索引的修改操作,同
时将写操作录入 redo log 中,在缓冲到一定量或系统较空闲时进行 merge 操作将修改写入磁盘中,从而达到减少磁盘 I/O 的目的。Change Buffer 在系统表空间中有相应的持久化区域。
Change Buffer 大小默认占 Buffer Pool 的 25%,最大50%,在引擎启动时便初始化完成。其物理结构为一棵名为 ibuf 的 B Tree。
二级索引就是辅助索引,除了聚簇索引之外的所有索引都是二级索引。
聚簇索引是也叫聚集索引,有的也叫索引组织表,指的是一种数据存储方式,指数据与索引的数据结构存储在一起。如 InnoDB 的主键索引中所有叶子节点都存储了对应行的数据。因为数据肯定只是存储在一个地方,所以一个表只能有一个聚集索引。
周期性合并二级索引页
周期性净化磁盘中二级索引页
3)自适应哈希索引(AHI)
自适应哈希索引(Adaptive Hash Index,AHI)用于实现对于热数据页的一次查询。是建立在索引之上的索引!使用聚簇索引进行数据页定位的时候需要根据索引树的高度从根节点走到叶子节点,通常需要3 到 4 次查询才能定位数据。InnoDB 根据对索引使用情况的分析和索引字段的分析,通过自调优Self-tuning的方式为索引页建立或者删除哈希索引。
AHI 的大小为 Buffer Pool 的 1/64,在 MySql 5.7 之后支持分区,以减少对于全局 AHI 锁的竞争,默认分区数为 8。
AHI 所作用的目标是频繁查询的数据页和索引页,而由于数据页是聚簇索引的一部分,因此 AHI 是建立在索引之上的索引,对于二级索引,若命中 AHI,则将直接从 AHI 获取二级索引页的记录指针,再根据主键沿着聚簇索引查找数据;若聚簇索引查询同样命中 AHI,则直接返回目标数据页的记录指针,此时就可以根据记录指针直接定位数据页。
#查看自适应哈希状态信息
mysql> show engine innodb status
#查看是否开启自适应哈希配置,默认是开启的
mysql> show variables like ‘innodb_adaptive_hash_index’;
4)日志缓冲(Log Buffer)
InnoDB 使用 Log Buffer 来缓冲日志文件的写入操作。内存写入加上日志文件顺序写的特点,使得InnoDB 日志写入性能极高。
对于任何修改操作,都将录入诸如 redo log 与 undo log 这样的日志文件中,因此日志文件的写入操作非常频繁,却又十分零散。这些文件都存储在磁盘中,因此日志记录将引发大量的磁盘 IO。Log Buffer将分散的写入操作放在内存中,通过定期批量写入磁盘的方式提高日志写入效率和减少磁盘 IO。
注意:这种将分散操作缓冲 改为 批量操作的优化方式将增加数据丢失的风险!
事务提交的时候必须将操作写入日志中,此时日志文件若未落盘而系统崩溃,则相关操作将丢失而无法恢复。而使用 write 方式将 Log Buffer 写入日志文件时,操作系统会将写入操作先写入 OS缓冲区中,需要调用 flush 指令将缓冲区数据刷入文件中,若操作系统在未刷入前崩溃,则同样将导致数据丢失不可恢复。
InnoDB 提供三种 Log Buffer 数据落盘方式
0:按秒写,按秒刷。每秒调用 write() 写入 OS Buffer 并调用 flush() 刷入磁盘。
1:实时写,实时刷。每次事务提交都调用 write() 写入 OS Buffer 并调用 flush() 刷入磁盘。
2:实时写,延迟刷。每次事务提交都调用 write() 写入 OS Buffer,但每秒调用 flush()刷入磁盘。
4.3 磁盘文件之表空间
在磁盘中,InnoDB 将所有数据都逻辑地存放在一个空间中,称为表空间(Tablespace)。表空间由段(Segment)、区(extent)、页(Page)组成。如果开启了独立表空间innodb_file_per_table=1,每张表的数据都会存储到一个独立的表空间,即一个单独的.ibd文件。如果设置了参innodb_file_per_table=0,关闭了独占表空间,则所有基于InnoDB存储引擎的表数据都会记录到系统表空间。
表空间是 InnoDB 物理存储中的最高层,目前的表空间类别包括:
系统表空间(System Tablespace)
独立表空间(File-per-table Tablespace)
通用表空间(General Tablespace)
回滚表空间(Undo Tablespace)
临时表空间(The Temporary Tablespace)
1)系统表空间
系统表空间是 InnoDB 数据字典、双写缓冲、修改缓冲和回滚日志的存储位置,如果关闭独立表空间,它也将存储所有表数据和索引。
它默认下是一个初始大小 10MB、名为 ibdata1 的文件,系统表空间所对应的文件由innodb_data_file_path 定义。指定系统表空间文件自动增长后,其增长大小由 innodb_autoextend_increment 设置(默认为8MB)且不可缩减,即使删除系统表空间中存储的表和索引,此过程释放的空间仅仅是在表空间文件中标记为已释放而已,并不会缩减其在磁盘中的大小。
数据字典(Data Dictionary): 数据字典是由各种表对象的元数据信息(表结构,索引,列信息等)组成的内部表。
双写缓冲(Doublewrite Buffer)双写缓冲用于保证写入磁盘时页数据的完整性,防止发生部分写失效问题,Doublewrite Buffer 同时存在于磁盘与内存中,大小都为 2MB。由于操作系统的存储单元页大小为 4K,而 InnoDB 默认存储单元页大小为 16K,在数据从Buffer 中写入磁盘时可能会出现页未写完全但系统崩溃的问题。InnoDB 在数据从 Buffer 刷写入磁盘前,先将数据保存于内存的双写缓冲中,达到 16K 后写入磁盘的双写缓冲中,再写入表数据文件,因此数据文件的写入总是按照 16K 单页递增,出现崩溃数据丢失时使用 redo log 恢复,以此保证数据完整性。
修改缓冲(Change Buffer): 内存中 Change Buffer 对应的持久化区域,同样为了数据完整性而设置。
回滚日志(Undo Log):Undo Log 存放在 Undo Segment 中,undo log 是记录数据修改前状态的逻辑日志,保存所有被更新的数据行逻辑状态的历史版本。Undo log 主要是这两个功能:实现事务进行 Rollback 操作时对数据的恢复,和根据数据的历史版本实现多版本并发控制(MVCC)功能。
2)独立表空间
独立表空间用于存放每个表的数据、索引和插入缓冲 Bitmap 页。开启独立表空间(File-per-table TableSpace)( innodb_file_per_table=ON )之后,InnoDB 会为每个数据库单独创建子文件夹,数据库文件夹内为每个数据表单独建立一个表空间文件 table.ibd 。同时创建一个 table.frm 文件用于保存表结构信息。
其他类型的信息,如回滚信息、插入缓冲索引页、系统事务信息、二次写缓冲等仍存放于系统表空间
内。因此即使使用独立表空间,系统表空间也会不断增长。
每个独立表空间的初始大小是 96KB。
3)其他
- 通用表空间
通用表空间(General Tablespace)是一个由 CREATE TABLESPACE 命令创建的共享表空间,创建时必须指定该表空间名称和 ibd 文件位置,ibd 文件可以放置于任何 MySql 实例有权限的地方。该表空间内可以容纳多张数据表,同时在创建时可以指定该表空间所使用的默认引擎。通用表空间存在的目的是为了在系统表空间与独立表空间之间作出平衡。系统表空间与独立表空间中的表可以向通用表空间移动,反之亦可,但系统表空间中的表无法直接与独立表空间中的表相互转化。- 共享表空间
共享表空间(Shared Tablespace)包括系统表空间和通用表空间。InnoDB 从 MySQL 5.7.24 开始不推
荐在共享表空间中放置表分区,后面的版本已经将它删除了。- Undo 表空间
Undo TableSpace 用于存放一个或多个 undo log 文件。默认 undo log 存储与系统表空间中,MySql 5.6 以后支持自定义 Undo log 表空间并存储所有 undo log。一旦用户定义了 Undo Tablespace,则系统表空间中的 Undo log 区域将失效。对于 Undo Tablespace 的启用必须在 MySql 初始化前设置,
Undo Tablespace 默认大小为 10MB。Undo Tablespace 中的 Undo log 表可以进行 truncate 操作。- 临时表空间
MySql 5.7 之前临时表存储在系统表空间中,极大加剧了 ibdata 文件贪婪的增长性,5.7 版本之后InnoDB 引擎从系统表空间中抽离出临时表空间(Temporary Tablespace),用于独立保存临时表数据及其回滚信息。该表空间文件路径由 innodb_temp_data_file_path 指定,但必须继承innodb_data_home_dir 。
4.5 磁盘文件之存储结构
1)段
表空间由各个段(Segment)组成,创建的段类型分为数据段、索引段、回滚段等。由于 InnoDB 采用聚簇索引与 B+ 树的结构存储数据,所以事实上数据页和二级索引页仅仅只是 B+ 树的叶子节点,因此数据段称为 Leaf node segment,索引段其实指的是 B+ 树的非叶子节点,称为 Non-Leaf node
segment。一个段会包含多个区,至少会有一个区,段扩展的最小单位是区。
数据段称为 Leaf node segment
索引段称为 Non-Leaf node segment
2)区【Extent】
区(Extend)是由连续的页组成的空间,大小固定为 1MB,由于默认页大小为 16K,因此一个区默认存储 64 个连续的页。如果页大小调整为 4K,则 256 个连续页组成一个区。为了保证页的连续性,InnoDB 存储引擎会一次从磁盘申请 4 ~ 5 个区。对于新创建的独立表空间,其大小默认是 96K 而不是 1MB,这是因为在每个段开始都会使用 32个页大小的碎片页Fragement page来存放数据,当碎片页写满了在进行 Extend 的申请,以节省磁盘容量的开销。
3)页【Page】
页(Page)是 InnoDB 的基本存储单位,每个页大小默认为 16K,从 InnoDB1.2.x 版本开始,可通过
设置 innodb_page_size 修改为 4K、8K、16K。InnoDB 首次加载后便无法更改。
#查看MySQL页大小
show global variables like ‘innodb_page_size’;
索引树上一个节点就是一个页,MySQL规定一个页上最少存储2个数据项。如果向一个页插入数据时,这个页已将满了,就会从区中分配一个新页。如果向索引树叶子节点中间的一个页中插入数据,如果这个页是满的,就会发生页分裂。
操作系统管理磁盘的最小单位也是页,是操作系统读写磁盘最小单位,Linux中页一般是4K,可以通过命令查看。
#默认 4096 4K
getconf PAGE_SIZE
所以InnoDB从磁盘中读取一个数据页时,操作系统会分4次从磁盘文件中读取数据到内存。写入也是一样的,需要分4次从内存写入到磁盘中。
4)行【Row】
InnoDB的数据是以行为单位存储的,1个页中包含多个行。在MySQL5.7中,InnoDB提供了4种行格式:Compact、Redundant、Dynamic和Compressed行格式,Dynamic为MySQL5.7默认的行格式。
InnoDB行格式官网:https://dev.mysql.com/doc/refman/5.7/en/innodb-row-format.html创建表时可以指定行格式:
CREATE TABLE t1 (c1 INT) ROW_FORMAT=DYNAMIC;
#修改表的行格式
ALTER TABLE tablename ROW_FORMAT=行格式名称;
#修改默认行格式
SET GLOBAL innodb_default_row_format=DYNAMIC;
#查看表行格式
SHOW TABLE STATUS LIKE 't1';
4.6 内存数据落盘
1)整体思路分析
在数据库中进行读取操作,将从磁盘中读到的页放在缓冲池中,下次再读相同的页时,首先判断该页是否在缓冲池中。若在缓冲池中,称该页在缓冲池中被命中,直接读取该页。否则,读取磁盘上的页。
对于数据库中页的修改操作,则首先修改在缓冲池中的页,然后再以一定的频率刷新到磁盘上。页从缓冲池刷新回磁盘的操作并不是在每次页发生更新时都触发,而是通过一种称为CheckPoint的机制刷新回磁盘。
内存数据落盘要考虑的核心问题:高性能写入数据,同时要保证数据的绝对安全性!
数据库灵魂三问:
①写入性能如何保证?
分散写入操作放在内存中,通过定期批量写入磁盘的方式提高写入效率减少磁盘 IO。
②如何持久化?也就是修改后的数据如何到磁盘中去。内存里缓冲池中的数据页要完成持久化通过两个流程来完成
脏页落盘
预写redo log落盘
③数据安全性怎么保证?
记录操作日志:Force Log at Commit机制与Write Ahead Log(WAL)策略
检查点机制CheckPoint
双写机制Double Write
2)脏页落盘
什么是脏页?
对于数据库中页的修改操作,则首先修改在缓冲池中的页,缓冲池中的页与磁盘中的页数据不一致,所以称缓冲池中的页为脏页。然后再以一定的频率将脏页刷新到磁盘上。页从缓冲池刷新回磁盘的操作并不是在每次页发生更新时触发,而是通过一种称为CheckPoint的机制刷新回磁盘。
为什么不是每次更新直接写入磁盘呢?
如果每次一个页发生变化就进行落盘,每次落盘一个页,必然伴随着4次IO操作,那么性能开销会非常大。而且这个开销是随着写入操作的增加指数级增长的!如果数据长期在内存中保存,那么数据就存在安全性风险!
InnoDB采用了Write Ahead Log(WAL)策略和Force Log at Commit机制实现事务级别下数据的持久性。
Force Log at Commit机制:要求当一个事务提交时,所有产生的日志都必须刷新到磁盘上。如果日志刷新成功后,缓冲池中的数据刷新到磁盘前数据库发生了宕机,那么重启时,数据库可以从日志中恢复数据。这样可以保证数据的安全性
Write Ahead Log(WAL)策略:要求数据的变更写入到磁盘前,首先必须将内存中的日志写入到磁盘;InnoDB 的 WAL(Write Ahead Log)技术的产物就是 redo log,对于写操作,永远都是日志先行,先写入 redo log 确保一致性之后,再对修改数据进行落盘。
说白了,保证数据的持久性与安全性我们采用记录日志的方式,那么也就是说,日志安全了,数据就安全了!
怎么确保日志就能安全的写入系统呢?
为了确保每次日志都写入到redo日志文件,在每次将redo日志缓冲写入redo日志后,调用一次fsync操作,将缓冲文件从文件系统缓存中真正写入磁盘。
这样做不就等同于数据直接写入磁盘吗?
日志是顺序写入,而数据是随机写入。顺序写入效率更高
日志也不是改一条写一条,而是采用redo 日志落盘策略来兼顾安全性与性能!
可以通过 innodb_flush_log_at_trx_commit 来控制redo日志刷新到磁盘的策略。接下来我们看redo日志如何落盘。
3)redo日志落盘
Log Buffer写入磁盘的时机由参数 innodb_flush_log_at_trx_commit 控制,默认1表示事务提交后立即落盘。 InnoDB的该属性可以控制每次事务提交时InnoDB的行为。是InnoDB性能调优的一个基础参数,涉及InnoDB的写入性能和数据安全性。
#查看写入时机参数配置
show VARIABLES like ‘innodb_flush_log_at_trx_commit’;
innodb_flush_log_at_trx_commit 配置详解:
为0时:事务提交时,不会立即把 log buffer里的数据写入到redo log日志文件的。而是等待主线程每秒写入一次。如果MySQL崩溃或者服务器宕机,此时内存里的数据会全部丢失,最多会丢失1秒的事务。写入效率最高,但是数据安全最低;
为1时:每次事务提交时,会将数据将从log buffer写入redo日志文件与文件系统缓存,并同时fsync刷新到磁盘中。系统默认配置为1,MySQL崩溃已经提交的事务不会丢失,要完全符合ACID必须使用默认设置1。写入效率最低,但是数据安全最高;
为2时:事务提交时,也会将数据写入redo日志文件与文件系统缓存,但是不会调用fsync,而是让操作系统自己去判断何时将缓存写入磁盘。事务提交都会将数据刷新到操作系统缓冲区,可以认为是已经持久化到磁盘,但没有真正意义上持久化到磁盘。如果MySQL崩溃已经提交的事务不会丢失。但是如果服务器宕机或者意外断电,操作系统缓存内的数据会丢失,所以最多丢失1秒的事务。
Tips. 用户程序写入数据到磁盘文件时,需要调用操作系统的接口,操作系统本身是有缓冲区的,之后依赖操作系统机制不时的将缓存中刷新到磁盘文件中。用户程序可以执行fsync操作将操作系统缓冲区的数据刷入到磁盘文件中。只有设置为1是最安全但是性能消耗的方式,可以真正地保证事务的持久性,但是由于MySQL执行刷新操作 fsync() 是阻塞的,直到完成后才会返回,我们知道写磁盘的速度是很慢的,因此 MySQL 的性能会明显地下降。0的性能最好的模式,但安全性却很差。2是一个折中的选择。在配置时,需综合安全性和性能等因素。
4)CheckPoint检查点机制
- 什么是CheckPoint?
讲到目前为止,数据还没有进入到磁盘!
思考一下这个场景:
如果redo日志可以无限地增大,同时缓冲池也足够大,那么是不需要将缓冲池中页的新版本数据页刷新回磁盘。当发生宕机时,完全可以通过redo日志来恢复整个数据库系统中的数据到宕机发生的时刻。
这么做的前提条件:
缓冲池可以缓存数据库中所有数据;
redo日志可以无限增大
显然这是不可能的,因此Checkpoint(检查点)技术就诞生了,目的是解决以下几个问题:
- 缩短数据库的恢复时间:当数据库发生宕机时,数据库不需要重做所有的日志,因为Checkpoint之前的页都已经刷新回磁盘。数据库只需对Checkpoint后的redo日志进行恢复,这样就大大缩短了恢复的时间。
- 缓冲池不够用时,将脏页刷新到磁盘:当缓冲池不够用时,根据LRU算法会溢出最近最少使用的页,若此页为脏页,那么需要强制执行Checkpoint,将脏页也就是页的新版本刷回磁盘。
- redo日志不可用时,刷新脏页:当redo日志出现不可用时,Checkpoint将缓冲池中的页至少刷新到当前redo日志的位置
1). 数据库系统对redo日志的设计都是循环使用的,并不是让其无限增大的。如果当数据库宕机恢复操作时,不需要redo日志中的部分redo日志,这部分就可以被覆盖重用。
2). InnoDB通过LSN(Log Sequence Number)来标记日志刷新的版本。LSN是8字节的数字,每个页有LSN,redo日志中也有LSN,Checkpoint也有LSN。
可以通过命令 SHOW ENGINE INNODB STATUS 来观察:
Checkpoint发生的时间、条件及脏页的选择等都非常复杂。而Checkpoint所做的事情无外乎是将缓冲池中的脏页刷回到磁盘,不同之处在于每次刷新多少页到磁盘,每次从哪里取脏页,以及什么时间触发Checkpoint。
- Checkpoint分类
在InnoDB存储引擎内部,有两种Checkpoint,分别为:Sharp Checkpoint、Fuzzy Checkpoint
sharp checkpoint:在关闭数据库的时候,将buffer pool中的脏页全部刷新到磁盘中。
fuzzy checkpoint:数据库正常运行时,在不同的时机,将部分脏页写入磁盘。仅刷新部分脏页到磁盘,也是为了避免一次刷新全部的脏页造成的性能问题。
Fuzzy Checkpoint:默认方式,只刷新一部分脏页,不是刷新所有脏页;主要有以下几种情况:
- Master Thread Checkpoint;
- FLUSH_LRU_LIST Checkpoint;
- Async/Sync Flush Checkpoint;
- Dirty Page too much Checkpoint
1、Master Thread Checkpoint :在Master Thread中,会以每秒或者每10秒一次的频率,将部分脏页从内存中刷新到磁盘,这个过程是异步的。正常的用户线程对数据的操作不会被阻塞。
2、FLUSH_LRU_LIST Checkpoint:缓冲池不够用时,根据LRU算法会淘汰掉最近最少使用的页,如果该页是脏页的话,会强制执行CheckPoint,将该脏页刷回磁盘(由Page Cleaner Thread完成);
3、Async/Sync Flush Checkpoint:重做日志不可用的情况,需要强制从脏页列表中选取一些脏页刷新磁盘到缓存(由Page Cleaner Thread完成)。由于磁盘是一种相对较慢的存储设备,内存与磁盘的交互是一个相对较慢的过程。innodb_log_file_size定义的是一个相对较大的值,正常情况下,由前面两种checkpoint刷新脏页到磁盘,在前面两种checkpoint刷新脏页到磁盘之后,脏页对应的redo log空间随即释放,一般不会发生Async/Sync Flush checkpoint。
4、Dirty Page too much:即脏页数量太多,导致强制进行Checkpoint。由参数innodb_max_dirty_pages_pt 来控制,默认75(即75%)。当脏页数量占据75%缓冲池时,刷新一部分脏页到磁盘。(由Page Cleaner Thread完成)
show variables like ‘innodb_max_dirty_pages_pct’;
5)Double Write双写
- 脏页落盘出现的问题
我们知道脏页会在某些场景下进行刷盘,将缓冲池内的脏页数据落地到磁盘。因为存储引擎缓冲池内的数据页大小默认为16KB,而文件系统一页大小为4KB,所以在进行刷盘操作时,就有可能发生如下场景:
如图所示,数据库准备刷新脏页时,需要四次IO才能将16KB的数据页刷入磁盘。但当执行完第二次IO时,数据库发生意外宕机,导致此时才刷了2个文件系统里的页,这种情况被称为写失效(partial pagewrite)。此时重启后,磁盘上就是不完整的数据页,就算使用redo log也是无法进行恢复的。
注意:redo log无法恢复数据页损坏的问题,恢复必须是数据页正常并且redo log正常。这里要知道一点,redo log中记录的是对页的物理操作,如偏移量600,写’xxxx’记录。如果这个页本身已经发生了损坏,再对其进行重做是没有意义的
2. 该怎么解决这个问题?
在数据库进行脏页刷新时,如果此时宕机,有可能会导致磁盘数据页损坏,丢失我们重要的数据。此时就算重做日志也是无法进行恢复的,因为重做日志记录的是对页的物理修改。其实就是在重做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是double write。
如图,其实Double Write 分为了两个组成部分:
内存中的double write buffer物理磁盘上共享表空间中连续的128个页,即2个区(extent),大小同样为2MB可以看出,有了Double write后的脏页刷新流程就是多了几步操作:
- 在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是会通过memcpy函数将脏页先复制到内存中的Double write buffer
- 通过Double write buffer再分两次,每次1MB顺序地写入共享表空间的物理磁盘上,然后马上调用fsync函数,同步磁盘。这样做可以避免缓冲写带来的问题
- Double write崩溃恢复
如图,如果操作系统在将页写入磁盘的过程中发生了崩溃,在恢复过程中,InnoDB存储引擎可以从共享表空间中的Double write中找到该页的一个副本,将其复制到表空间文件,再应用重做日志。
下面显示了一个由Double write进行恢复的情况:
090923 12:36:32 mysqld restarted
090923 12:26:33 InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.
InnoDB: Reading tablespace information from the .ibd files…
InnoDB: Crash recovery may have faild for some .ibd files!
InnoDB: Restoring possible half-written data pages from the doublewrite.
InnoDB: buffer…
小结
- 当commit 一个修改语句时,如果redo log有空闲区域,直接写redo log,如果redo log没有空闲区域,那么需要把被覆盖的redo log对应的数据页刷新到data file 中,最后改pool buffer中的记录
- innodb的redo log 不会记录完整的一页数据,因为这样日志太大,它只会记录那次(sequence)如何操作了(update,insert)哪页(page)的哪行(row)
- 因为数据库使用的页(page,默认16KB)大小和操作系统对磁盘的操作页(page,默认4KB)不一样,当提交了一个页需要刷新到磁盘,会有多次IO, 此时刷了前面的8k时异常发生宕机。在系统恢复正常后,如果没有double write机制,此时数据库磁盘内的数据页已损坏,无法使用redo log进行恢复。
- 如果有double write buffer,会检查double writer的数据的完整性,如果不完整直接丢弃doublewrite buffer内容,重新执行那条redo log,如果double write buffer的数据是完整的,用double writer buffer的数据更新该数据页,跳过该redo log。
相关文章:
MySQL架构篇
一、进阶学习环境说明 1.1 MySQL服务器环境 Linux虚拟机:CentOS 7 MySQL:MySQL5.7.30 在Linux服务器中安装MySQL: ps.如果有自己的云服务器,可忽略前两步,直接进行第三步 1.2 服务器日志文件说明 MySQL是通过文件系统对…...
Redhat7.6安装weblogic10.3.6(超详细,有图文)
一、环境 linux版本:Redhat 7.6 weblogic版本:WLS10.3.6 jdk版本:jdk1.8.0 下载网址:https://www.oracle.com/technetwork/middleware/weblogic/downloads/index.html 1.安装vsftpd服务,将部署环境使用JDK文件和wls服务文件…...
dashboard疏散主机提示报错:无法疏散主机...处理方法、openstack虚拟机状态卡在重启处理方法、openstack在数据库修改虚拟机状态的方法
文章目录dashboard疏散主机提示报错:无法疏散主机...处理方法报错说明【状态卡在reboot状态】解决方法【登录nova数据库修改虚拟机信息】首先获取nova数据库的密码登录nova数据库并做修改验证信息是否修改成功再次迁移并验证报错说明【虚拟机状态error也会导致疏散失…...
力扣:轮转数组(详解)
前言:内容包括:题目,代码实现,大致思路,代码解读 题目: 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3…...
Vue计算属性Computed
30. Vue计算属性Computed 1. 定义 Computed属性是Vue中的一个计算属性,是一种基于其它属性值计算而来的属性值,具有缓存机制,在依赖的属性值发生变化时会重新计算。 使用computed属性可以避免在模板中书写过多的计算逻辑,提高代…...
实验四:搜索
实验四:搜索 1.填格子 题目描述 有一个由数字 0、1 组成的方阵中,存在一任意形状的封闭区域,封闭区域由数字1 包围构成,每个节点只能走上下左右 4 个方向。现要求把封闭区域内的所有空间都填写成2 输入要求 每组测试数据第一…...
本地开发vue项目联调遇到访问接口跨域问题
本地开发vue项目联调遇到访问接口跨域问题 修改本地的localhost 一:按winr打开运行窗口,输入drivers ,然后回车 二:打开etc文件夹,然后用记事本的方式打开里面的hosts文件, 三:这时我们就可…...
Vue键盘事件的使用
前言 在vue中,我们经常会用到键盘事件,不管是我们按下某个键,其实都是一次键盘事件的调用,下面就介绍下Vue中的键盘事件 先写一段代码,这里我选择的键盘事件是keyup,当然用keydown也是没问题的 问题来了,…...
抓包工具fiddler详细使用教程
各位做测试的同学想必对抓包工具fiddler并不陌生,但是很多同学可能没有总结过它的用法,下面我总结了fiddler一些常用的用法。 Web端抓包配置 打开Fiddler,Tools -> Fiddler Options -> HTTPS 配置完后记得要重启Fiddler 选中Decrpt …...
raspberry Pi 连接蓝牙(小爱同学)
参数valueraspberry pi MOdel4B,4Gbbluetooth MOdel小爱同学writeTime2023年 2月11日 下午13:14分raspberry System ModelLinux raspberrypi 5.15.61-v8 #1579 SMP PREEMPT Fri Aug 26 11:16:44 BST 2022 aarch64 GNU/Linux 连接蓝牙 请在小爱同学app上…...
解决launch:program .exe does not exist
二. 程序的运行和调试 1.launch.json 复制下列代码至launch.json,并根据指导做出相对/绝对路径修改 用 IntelliSense 了解相关属性。 {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息,请访问: https://go.micros…...
ETL --事实表
每一个事实表通过表的粒度来定义。事实表的粒度是事件度量的定义。我们必须至始至终按照度量如何在 现实世界中理解来规定事实表的粒度。 所有的事实表包含了一组关联到维表的外键,而这些维表提供了事实表度量的上下文。大多数的事实表还 包括了一个或者多个数值型…...
手工数据采集耗时耗力?Smartbi数据填报实现数据收集分析自动化
企业在日常经营管理过程中,往往需要收集很多内外部的信息,清洗整理后再进行存储、分析、呈现、决策支持等各种作业,如何高效收集结构化数据是企业管理者经常要面对的问题。传统手工的数据采集方式不仅耗费了大量人力时间成本,还容…...
应用实战|微信小程序开发示例--多人聊天互动空间
“超能力”数据库~拿来即用,应用开发人员再也不用为撰写API而发愁。MemFire Cloud 为开发者提供了简单易用的云数据库(表编辑器、自动生成API、SQL编辑器、备份恢复、托管运维),很大地降低开发者的使用门槛。 本示例是…...
css:使用filter和backdrop-filter实现高斯模糊效果
背景 今天接到一个需求是,使用高斯模糊的效果对一个页面进行模糊处理,正好借这个机会来整理一下 css3 中高斯模糊的两个 API API介绍 filter 说明: 该 API 是一个过滤器,不仅能实现高斯模糊,还有很多比如颜色偏移、…...
科技大势怎么看 2023怎么干?
2023年,科技的走向依旧是世界各国的关注重点,各国在纷纷设立自己的科技战略目标外,还在潜心研究不同技术领域的科技趋势,试图通过科技占据国际竞争的制高点。 随着我国深入实施创新驱动发展战略,推动产业结构优化升级&…...
盘点曾经很火但消失了的8个软件
目录 1、飞信 3、暴风影音 4、千千静听 5、虾米音乐 6、快车下载 7、人人网 8、QQ农场 今天小编给大家分享曾经很火但消失了的8个软件,你都用过吗? 1、飞信 飞信是中国移动通信集团公司推出的一款短信、语音、视频通信应用程序。它于2007年推出&a…...
安卓 Frament + ViewPager使用示例
1. 组成架构 整个架构被包在一个外部Fragment之中,也可以放在一个Activity之中,随意。外部的fragment包含了两个组件,即途中的ViewPager和TabLayoutViewPager要套上一个FragmentStatePagerAdapter ,适配器负责new出一个个fragment…...
【银行测试】必看的四类题型:这可是最经典的一套题目了
目录:导读 一、根据题目要求写出具体LINUX操作命令 二、JMETER题目 三、根据题目要求写出具体SQL语句 四、测试案例设计题 金三银四面试面对大厂面试官提问,如何回答:花3天背完这100道软件测试面试题!银行测试的offer还不是手…...
跨源资源共享(CORS)-亲测理解,以及对http的状态,参数的理解和使用,对预检请求的触发和解决
跨源资源共享(CORS)-亲测理解,以及对http的状态,参数的理解和使用 跨源资源共享(CORS,或通俗地译为跨域资源共享)是一种基于HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的…...
学生使用的台灯该怎么选择?2023适合学生房间的灯推荐
随着社会的进步发展,我们的生活水平越来越高,很多家庭的孩子都开始使用台灯这种家居产品,对于学习任务繁重的他们来说,台灯确实可以起到保护眼睛、提高学习专注度的作用。那么不知道朋友们是否了解过,台灯该怎么选择呢…...
23种设计模式-桥接模式(安卓应用场景介绍)
概念 桥接模式是一种结构型设计模式,它通过将抽象与其实现分离来解耦。它使用接口(抽象类)作为桥梁,将一个抽象类与其实现类的代码分别独立开来,从而使它们可以各自独立地变化。桥接模式的核心思想是“组合优于继承”…...
2021牛客OI赛前集训营-提高组(第四场) T3快速访问
2021牛客OI赛前集训营-提高组(第四场) 题目大意 有一棵n1n1n1个节点的树,根节点为0。给你一个kkk,定义集合Si{j∈Z∣max(1,i−k)≤j<i}∪{0}S_i\{j\in Z|\max(1,i-k)\leq j<i\}\cup\{0\}Si{j∈Z∣max(1,i−k)≤j<i…...
【大数据是什么】
大数据是什么大数据是做什么的?大数据主要有哪些职位 ?大数据运维工程师数据仓库开发工程师ETL工程师大数据开发工程师BI工程师算法工程师大数据平台开发工程师大数据架构师讲述一下自己的大数据学习之路大数据是做什么的? 2014年,…...
大数据 | centos7图形界面无法执行yum命令
大家好,今天是三八女神节了! 你知道吗?世界上第一位电脑程序设计师是名女性,Ada Lovelace (1815-1852)。 她是一位英国数学家兼作家,第一位主张计算机不只可以用来算数的人,也发表了第一段分析机用的演算…...
三维人脸实践:基于Face3D的渲染、生成与重构 <一>
face3d: Python tools for processing 3D face git code: https://github.com/yfeng95/face3d paper list: PaperWithCode 该方法广泛用于基于三维人脸关键点的人脸生成、属性检测(如位姿、深度、PNCC等),能够快速实现人脸建模与渲染。推荐…...
Javascript 设计模式
设计模式的五大设计原则(SOLID)单一职责:一个程序只需要做好一件事。如果功能过于复杂就拆分开,保证每个部分的独立开放封闭原则:对扩展开放,对修改封闭。增加需求时,扩展新代码,而不是修改源代码。这是软件设计的终极…...
JAVA-文档工具screw-gui
前言 为什么萌生了写文档工具得想法,因为在项目开发得过程中,经常需要补充一些文档,比如数据库文档、详细设计文档等等,文档与项目相绑定,在项目需求新增或变更时,文档也需要反反复复得修改。 1. 数据库…...
开源鸿蒙南向嵌入学习笔记——NAPI框架学习(一)
开源鸿蒙南向嵌入学习笔记——NAPI框架学习(一) 前言——系列介绍 本系列文章主要是记录笔者在鸿蒙南向的学习与工作中的知识点笔记记录,其中不止会针对鸿蒙中的学习问题进行思考与记录,也会对涉及到的一些嵌入式等其他领域知识&…...
Spring - Spring框架概述面试题总结
文章目录01. 什么是Spring?02. Spring框架的设计目标,设计理念,和核心是什么?03. Spring的优点是什么?04. Spring框架中都用到了哪些设计模式?05. Spring有哪些应用场景?06. Spring由哪些模块组成…...
兰州市住房和城乡建设厅官方网站/百度资源搜索引擎
域名历史信息和搜索引擎权重的关系 上几节我们提到买一个权重高的域名有利于做SEO,但是域名一行业内,不是看起来那么简单。在购买以前我们最好查询这域名到底转手了多少次,历次转手中是否用人拿来专门做垃圾站?或者于垃圾站有着密…...
做网站底色怎么选/百度首页推广广告怎么做
一、默认允许上传4M的文件。 修改 Machine.config 文件,改动 MaxRequestLength 参数的值。在c:"winnt"microsoft.net 目录下搜索该文件. 需要注意的是:在保存文件时,您应该确保指定文件的完整路径(例如,&quo…...
唯品会网站开发/合肥最新消息今天
...
论述网站建设整个流程/长沙本地推广联系电话
网络:简述路由算法之动态路由算法在计算机网络中,路由器的一个很重要责任就是要在端对端的节点中找出一条最佳路径出来,通过自己与相邻节点之间的信息,来计算出从自己位置到目的节点之间的最佳线路,这种算法我们可以理…...
内蒙古生态文明建设相关网站/常州网络推广平台
title: creator-泄漏检测之js篇 categories: Cocos2dx tags: [creator, 优化, 泄漏, 内存] date: 2023-03-28 16:16:49 comments: false mathjax: true toc: true creator-泄漏检测之js篇 前篇 其实方法和之前的 egret_内存分析-泄漏.md 是一样的 一下使用 ui 作为测试, 正常…...
高端网站开发平台/实时seo排名点击软件
前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 前言 本文以一个 app 为例,演示对 app脱壳,然后分析其 协议加密和签名方法,然后编写 burp 脚本以方便后面的测试。 文中涉及的文件&#…...