Day06-数据库服务存储引擎

news2024/11/26 6:20:25

Day-06-数据库存储引擎知识

  • 1、数据库联合索引应用
  • 2、数据库索引扩展信息(扩展列信息说明)
  • 3、数据库索引应用总结
  • 4、数据库存储引擎概述
  • 5、数据库存储引擎种类
  • 6、数据库存储引擎特性(Innodb)Innodb vs MyISAM
  • 7、数据库存储引擎应用
  • 8、数据库存储引擎结构

01.数据库联合索引应用
02.数据库索引扩展信息
03.数据库索引应用总结(索引引擎知识补充-菜单)
04.数据库存储引擎概述
05.数据库存储引擎种类 MyISAM Innodb
06.数据库存储引擎特性
07.数据库存储引擎应用
08.数据库存储引擎结构(磁盘结构部分–表空间–一大波名词知识–底层原理知识)

1、数据库联合索引应用

作业题目:
01 利用子查询,实现以下效果

#建表语句
CREATE TABLE empsalary(
    `depname` varchar(20),
    `empno` bigint(20),
    `salary` int(10),
    `enroll_date` date
    );
    
#插入测试数据
INSERT INTO empsalary VALUES('develop',10,5200,'2007/08/01');
INSERT INTO empsalary VALUES('sales',1,5000,'2006/10/01');
INSERT INTO empsalary VALUES('personnel',5,3500,'2007/12/10');
INSERT INTO empsalary VALUES('sales',4,4800,'2007/08/08');
INSERT INTO empsalary VALUES('sales',6,5500,'2007/01/02');
INSERT INTO empsalary VALUES('personnel',2,3900,'2006/12/23');
INSERT INTO empsalary VALUES('develop',7,4200,'2008/01/01');
INSERT INTO empsalary VALUES('develop',9,4500,'2008/01/01');
INSERT INTO empsalary VALUES('sales',3,4800,'2007/08/01');
INSERT INTO empsalary VALUES('develop',8,6000,'2006/10/01');
INSERT INTO empsalary VALUES('develop',11,5200,'2007/08/15');

# 查询数据信息;
mysql> select * from empsalary;
+-----------+-------+--------+-------------+
| depname   | empno | salary | enroll_date |
+-----------+-------+--------+-------------+
| develop   |    10 |   5200 | 2007-08-01  |
| sales     |     1 |   5000 | 2006-10-01  |
| personnel |     5 |   3500 | 2007-12-10  |
| sales     |     4 |   4800 | 2007-08-08  |
| sales     |     6 |   5500 | 2007-01-02  |
| personnel |     2 |   3900 | 2006-12-23  |
| develop   |     7 |   4200 | 2008-01-01  |
| develop   |     9 |   4500 | 2008-01-01  |
| sales     |     3 |   4800 | 2007-08-01  |
| develop   |     8 |   6000 | 2006-10-01  |
| develop   |    11 |   5200 | 2007-08-15  |
+-----------+-------+--------+-------------+

# 想要的结果
# 实现要求如下
+-------+-----------+-----------+-------+--------+-------------+
| sum   | avg       | depname   | empno | salary | enroll_date |
+-------+-----------+-----------+-------+--------+-------------+
| 25100 | 5020.0000 | develop   |    10 |   5200 | 2007-08-01  |
| 25100 | 5020.0000 | develop   |     7 |   4200 | 2008-01-01  |
| 25100 | 5020.0000 | develop   |     9 |   4500 | 2008-01-01  |
| 25100 | 5020.0000 | develop   |     8 |   6000 | 2006-10-01  |
| 25100 | 5020.0000 | develop   |    11 |   5200 | 2007-08-15  |
|  7400 | 3700.0000 | personnel |     5 |   3500 | 2007-12-10  |
|  7400 | 3700.0000 | personnel |     2 |   3900 | 2006-12-23  |
| 20100 | 5025.0000 | sales     |     1 |   5000 | 2006-10-01  |
| 20100 | 5025.0000 | sales     |     4 |   4800 | 2007-08-08  |
| 20100 | 5025.0000 | sales     |     6 |   5500 | 2007-01-02  |
| 20100 | 5025.0000 | sales     |     3 |   4800 | 2007-08-01  |
+-------+-----------+-----------+-------+--------+-------------+

方法一:左外连接

select aa.sum,aa.avg,b.depname,b.empno,b.salary,b.enroll_date 
from empsalary b
left join
( select t.depname,sum(salary) sum,count(1) cn,sum(salary)/count(1) avg
 from empsalary t
 group by t.depname) aa
on b.depname=aa.depname order by aa.sum desc;

方法二:内连接

select * from
(select sum(salary),avg(salary),depname
 from oldboy.empsalary
 group by depname) as b ,oldboy.empsalary as c
 where b.depname=c.depname;

方法三:(PostgreSQL解题方法)

select sum(salary) OVER (PARTITION BY depname) as sum,avg(salary) OVER (PARTITION By depname) as avg ,depname,empno,salary,enroll_date from empsalary;
-- partition by与分组函数 group by的区别在于
group by        会合并聚合分组信息
partition by    不会合并聚合分组信息,结合开窗函数over会对应字段重复显示


  • 联合索引部分覆盖
    • 需要满足最左原则;
    • 需要定义条件信息时,将所有联合索引条件部分引用;

情况一:联合索引列没有全部用上

mysql> desc select * from t100w where num=339934;

image-20240813172444657

– 联合索引列只应用了部分信息

说明:进行联合索引覆盖查询时,区间范围列不是最后一列,索引查询匹配只统计到区间范围匹配(不等值)列,也属于部分覆盖;

desc select * from t100w where num=339934  and k2='ej';

1668233771781

说明:进行联合索引覆盖查询时,查询索引列是不连续的,索引查询匹配只统计到缺失列前,也属于部分覆盖;

– 联合索引列应用有缺失,也会出现部分覆盖

情况二:联合索引中间列,应用了范围或模糊查询

mysql > desc  select * from t100w where num=339934 and k1<'yb' and k2='nokl';

1668230013096

  • 联合索引全不覆盖
    • 需要定义条件信息时,将所有联合索引条件都不做引用;

情况一:查询数据没有应用联合索引列;

mysql> desc select * from t100w;

情况二:联合索引最左列应用了范围查询;

mysql> desc select * from t100w where num<339934 ;

说明:进行联合索引全不覆盖查询时,区间范围列出现在了第一列,也属于全不覆盖索引

情况三:联合索引最左列没有应用,但是应用了其它列信息;

mysql> desc select * from t100w where k2='ej';

说明:进行联合索引全不覆盖查询时,缺失最左列索引条件信息时,也属于全不覆盖索引

2、数据库索引扩展信息(扩展列信息说明)

Extar:在此列会显示索引优化功能是否使用,显示是否应用临时表,显示排序信息

PS:一旦出现排序信息,就会对CPU资源有消耗,

哪些查询语句情况涉及到排序操作:

  • 情况一:查询语句中含有 order by ,表示触发式的排序;
  • 情况二:查询语句中含有 group by,表示隐藏式的排序;
  • 情况三:查询语句中含有 DISTINCT,表示会先进行排序后再取消重复;
mysql> desc select * from city where countrycode='CHN' order by population;
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra                                 |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+
|  1 | SIMPLE      | city  | NULL       | ref  | CountryCode   | CountryCode | 12      | const |  363 |   100.00 | Using index condition; Using filesort |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+
1 row in set, 1 warning (0.00 sec)

# 如何解决排序问题
mysql> alter table city add index idx_co_po(countrycode,population);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc select * from city where countrycode='CHN' order by population;
+----+-------------+-------+------------+------+-----------------------+-----------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys         | key       | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+-----------------------+-----------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | city  | NULL       | ref  | CountryCode,idx_co_po | idx_co_po | 12      | const |  363 |   100.00 | Using index condition |
+----+-------------+-------+------------+------+-----------------------+-----------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

# 特殊情况说明:在order by信息出现在group by之后,是无法实现索引优化处理的

3、数据库索引应用总结

01 建立索引原则规范(DBA运维规范)

  • 数据表中必须要有主键索引(创建表时指定),建议是与业务无关的自增列;
  • 数据表中某些列若经常作为 where/order by/group by/join on/distinct条件信息,最好将相应列设置索引(产品功能/用户行为)
  • 数据表中最好使用唯一值多的列作为索引,如果索引列重复值较多,可以考虑使用联合索引;(最左列-减少回表次数 - 减少磁盘IO)
  • 数据表中列值长度较长的索引列,建议可以使用前缀索引;(防止索引树层次过高)
  • 数据表中不建议建立大量索引,最好降低索引条目,不要创建无用索引,不常用的索引要定期清理(percona toolkit)
  • 数据表中的索引信息做调整维护时,尽量避开业务繁忙期,或者通过软件工具做调整维护(pt-ost)
  • 数据表中的联合索引创建过程要遵循索引最左原则;

02 索引应用失效情况(开发工作规范)

  • 数据表信息查询时,没有设置查询条件信息;
  • 数据表信息查询时,查询的条件没有建立索引;
select * from t1;
select * from t1 where id=1001 or 1=1;   -- 执行SQL注入语句问题

03 查询结果规范要求

当查询结果集数据是原表中的大部分数据,超过了总行数的25%,优化器便自动判断没必要走索引了,因为可以借助预读功能获取数据

可以通过精细查找指定数据的范围,从而达到优化的效果;(read_head预读相关参数)

04 索引失效情况处理

当频繁的对数据表中索引列值做修改、删除等操作时,会导致索引统计信息过旧或不真实,最终造成索引功能失效;

本身索引是有自我维护的机制能力,但并不是实时调整更新的,需要有一定的间隔时间做调整;

一般索引失效的表现情况为:select查询语句平常查询时很快,但突然某天执行就变慢了,就是索引失效了,统计数据不真实;

索引统计的信息存储位置:

innodb_index_stats
innodb_table_stats
-- mysql库中的相应表

当索引失效时,可以使用命令重新进行统计信息获取,使索引功能再次生效:

mysql > analyze table world.city;   -- 手动重新构建索引树
-- 表示立即更新过久的统计信息(也可以将索引删除重建)

在查询条件过程中,使用了函数信息在索引列上,或者对索引进行了运算(+ - * / !等),都会导致索引功能失效,建议尽量避免;

# 错误举例:
select * from test where id-1=9;

# 正确举例:
select * from test where id=10;
-- 总之尽量避免条件信息出现 算数运算  函数运算  子查询

# 子查询补充:
# 子查询指一个查询语句嵌套在另一个查询语句内部的查询
# SQL 中子查询的使用大大增强了 SELECT 查询的能力,因为很多时候查询需要从结果集中获取数据
# 查询中国城市人口大于北京人口数量的城市信息
查询01:查询中国 北京的人口数量
select population from city where countrycode='CHN' and name='Peking';
查询02:查询中国 基于北京人口数量 大于北京人口数量城市
select * from city where countrycode='CHN'  and population > 'xxx'

mysql> select * from city where CountryCode='CHN' and population > (select population from city where CountryCode='CHN' and name='Peking');

在查询数据信息过程中,出现了隐式转换也会导致索引失效;

# 创建测试数据表
mysql> create table test (id int,name varchar(20),telno char(11));
mysql> insert into test values (1,'a','110'),(2,'b','123'),(3,'c','120'),(4,'d','119'),(5,'e','130');

# 创建索引信息
mysql> alter table test add index idx(telno);

# 查询数据信息
mysql> select * from test where telno='110';
mysql> select * from test where telno=110;
-- 上面两条语句都能查看到结果信息,但是有一条语句是没有走索引的

在查询条件过程中,应用了特殊数据匹配方法时,也会导致索引失效,一般是辅助索引失效;

<> , not in , like "%_" 
-- 应用以上特殊符号信息,也会导致辅助索引失效

索引失效情况:
情况一:有大量的更新或删除操作,会导致索引失效

analyze table world.city;--手动重新构建索引树

情况二:条件中应用了运算符或者 应用了函数信息

参考文档资料

数据库索引知识补充-彩蛋:

01 数据库服务索引功能特性 8.0

  • 在新的数据库服务中,支持不可见索引功能

应用场景

案例:企业中某个业务的表结构做了调整(添加列)-> 创建索引 -> 批量修改操作 (操作一半报错中断了);

​ 触发索引锁机制

设置方法:

# 在创建索引或修改索引时,可以设置不可见或可见索引(默认)
mysql> alter table test alter index idx invisible/visible;
-- 已经有索引了,进行调整
mysql> alter table test add index idx1(name) invisible/visible;
-- 创建索引时,设置索引可见功能
-- 在做批量数据导入时,辅助索引信息可以设置为不可见,优化器就不会加载识别索引信息

mysql> alter table city alter index CountryCode invisible;
  • 索引倒序

在早期数据库中,所有索引列创建索引信息,都是按照从小到大顺序进行排序,在最新数据库中,可以灵活调整索引排序方式;

mysql> alter table xiaoQ add index idx01(k1,k2 desc,k3);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc select * from xiaoQ order by k1,k2 desc,k3;
+----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key   | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | xiaoQ | NULL       | index | NULL          | idx01 | 15      | NULL |    4 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

02 数据库服务自主优化能力

  • 自主优化功能一:AHI(索引的索引)

AHI全称(中文名称)为自适应的hash索引/散列索引,用于在内存中建立索引,快速锁定内存中的热点数据索引页位置;

正常情况下,所有数据都是存储在磁盘中的,如果想访问读取相应磁盘的数据信息,都是会将磁盘数据调取存放在内存中,即消耗IO;

对于数据库服务而言,想要读取数据信息,也是会从磁盘中读取存储页,在放入内存中被数据库服务进行访问,索引访问也是一样的;

但是当数据页大量的被存放在内存中后,从大量内存中的数据页找到想要的,也是比较困难的事情;

因此,可以对内存中经常被访问数据索引页建立一个hash索引,从而可以帮助数据库服务快速定位内存中想要找的索引数据页;

作用说明:

给索引创建索引;

1675276929767

配置参数:

mysql> show variables like 'innodb_adaptive_hash_index';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_adaptive_hash_index | ON    |
+----------------------------+-------+
1 row in set (0.05 sec)

  • 自主优化功能二:CHANGE BUFFER

作用说明:

临时缓存变化索引数据信息

配置参数:

mysql> show variables like '%change_buffer%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| innodb_change_buffer_max_size | 25    |    -- 设置缓冲区大小
| innodb_change_buffering       | all   |    -- none 关闭
+-------------------------------+-------+
2 rows in set (0.01 sec)
-- all:    默认值。开启buffer inserts、delete-marking operations、purges
-- none: 不开启change buffer
  • 自主优化功能三:ICP (索引下推)

作用说明:

索引下推功能:主要在查询数据时,用于减少IO消耗,减少回表次数

配置参数:

mysql> show variables like '%switch%';
mysql> set global optimizer_switch='index_condition_pushdown=off/on';
-- 实现测试练习完,需要恢复开启(操作可以省略)


# 测试练习
mysql> select * from t100w where k1='qj' and k2 like '%v%';
mysql> desc select * from t100w where k1='qj' and k2 like '%v%';
-- extra列显示using index condition信息,表示应用了索引下推

# 进行压测
mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='oldboy' --query="select * from t100w where k1='qj' and k2 like '%v%" engine=innodb --number-of-queries=20000 -uroot -p123456 -h192.168.30.101 -verbose
  • 自主优化功能四:MRR

MRR,全称(Multi-Range Read Optimization 多范围读取操作);

简单来说:MRR 通过把「随机磁盘读」,转化为「顺序磁盘读」,从而提高了索引查询的性能。

描述说明中涉及到的问题:

① 为什么要把随机读转换为顺序读? 减少磁盘压力

② 为什么顺序读就能提升读取性能?

③ 如何将随机读去转换为顺序读取? MRR

MRR功能配置信息:

mysql > set optimizer_switch='mrr=on';
mysql > set global optimizer_switch='mrr_cost_based=off/on';
-- 用来告诉优化器,要不要基于使用 MRR的成本,考虑使用MRR是否值得(cost-based choice)

对于只返回一行数据的查询,是没有必要 MRR 的,而如果你把 mrr_cost_based 设为 off,那优化器就会通通使用 MRR,这在有些情况下是很傻的,所以建议这个配置还是设为on,毕竟优化器在绝大多数情况下都是正确的。

1675369639191

4、数据库存储引擎概述

作用:数据库存储引擎主要负责数据信息有序存储和调取(类似文件系统)

存储引擎结构

  • 存储数据角度-段区页 - 磁道 - block - 扇区
  • 存储架构角度-表空间信息 - 各种表空间文件

5、数据库存储引擎种类

在各种版本的数据库服务中,是有多种存储引擎可以应用的,以MySQL数据库服务为例,可以使用命令查看可以应用存储引擎:

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------
| Engine             | Support | Comment                                                        | Transac
+--------------------+---------+----------------------------------------------------------------+--------
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL   
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO     
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES    
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO     
| MyISAM             | YES     | MyISAM storage engine                                          | NO     
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO     
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO     
| CSV                | YES     | CSV storage engine                                             | NO     
| ARCHIVE            | YES     | Archive storage engine                                         | NO     
+--------------------+---------+----------------------------------------------------------------+--------
9 rows in set (0.00 sec)

在实际场景中,99.9%都是使用innodb存储引擎,并且在最新版8.0数据库中,所有mysql数据库中的表对应的引擎也都改为了innodb;

如果在面试环节中,面试官询问你:

  • 列举出mysql中支持的存储引擎种类:InnoDB、MyISAM、CSV、MEMORY;

  • 列举出mysql分支产品的存储引擎种类:在percone、mariadb数据库中,可能还会应用TokuDB MyRocks Rocksdb存储引擎

    从特点上可以支持innodb引擎的特性(支持事务),并且数据压缩比比较高(15倍),数据插入性能比较强(5~6倍);

    以上存储引擎就比较适合于zabbix监控类的平台,归档数据、历史数据存储业务等,数据量级比较大的情况;

    监控服务部署tokuDB存储引擎参考链接:https://www.cnblogs.com/oldboy-heqing/articles/16891210.html

6、数据库存储引擎特性(Innodb)Innodb vs MyISAM

在数据库服务领域,大部分场景下都会使用innodb存储引擎,是因为innodb存储引擎具有一定优秀特性:

序号特性解释说明
01数据访问特性支持多版本并发控制特性(MVCC),支持行级锁控制并发
02数据索引特性支持聚簇索引/辅助索引特性,可以组织存储数据和优化查询(IOT)
03数据事务特性支持事务概念特性,可以实现数据的安全保证
04数据缓冲特性支持多缓冲区功能,自适应hash索引(AHI)
05数据迁移特性支持复制数据中的高级功能特性,支持数据备份恢复的热备
06服务自愈特性支持自动故障恢复(CR-Crash Recovery)
07数据存储特性支持数据双写机制(Double write) 数据存储有关的安全机制

如果在面试环节中,面试官询问你:

  • InnoDB核心特性有哪些,以及与MyISAM存储引擎之间的区别:

    InnoBD支持:事务、mvcc、聚簇索引、外键、缓冲区、AHI、DW;MyISAM均不支持

    InnoDB支持:行级锁,MyISAM只支持表级锁;

    InnoDB支持:数据热备,可以保证业务正常运行,对业务影响低,MyISAM只支持温备份,需要锁表备份;

    InnoDB支持:支持CR自动故障恢复,宕机自动恢复,数据安全和一致性可以得到保证;MyISAM不支持,宕机可能丢失当前数据;

企业实际场景案例分析说明:

案例说明01:某期学员负责运维+MySQL相关工作;

平台环境:zabbix 3.2 + centos 7.3 + mariadb 5.5(InnoDB引擎),利用监控平台,监控了2000多个节点服务;

问题现象:每隔一段时间zabbix服务就会运行操作很卡,每隔3-4个月,都要重新部署zabbix,存储空间经常爆满(ibdata1 400~500G);ibdate1 ibdata1-01

异常分析:

  • zabbix版本过低,建议将zabbix程序进行升级更新;
  • zabbix使用的数据版本过低,建议将数据库版本进行升级,因为新版本数据库的原生态环境就比旧版本好些;
  • 在数据库5.5版本中,在没有做数据存储调配时,数据库所有数据都会保存到ibdata1文件中;
  • 在ibdata1文件中的数据空间,不会因为数据库中的数据删除,产生数据回缩的效果,即空间不释放;

优化建议:

  • 数据库版本升级到percona 5.7+(mariadb 10.x+),zabbix软件升级更高版本;
  • 数据库服务存储引擎改为tokudb;
  • 监控数据最好按月份进行数据切割(二次开发zabbix程序,数据保留机制功能重写,并且数据库分表存储)
  • 将数据库服务的binlog功能关闭(双1);
  • 数据库服务相关内存优化参数调整;

优化思路:

  • zabbix程序原生态支持TokuDB,经过压力测试,5.7要比5.5数据库版本性能高出 2~3倍;
  • 使用TokuDB作为数据库存储引擎,insert数据比innodb要快的多,数据压缩比也要比Innodb高;
  • 监控数据按月份进行切割(分区),为了能够truncate每个分区表,以便立即释放存储空间;
  • 将数据库服务binlog关闭,是为了减少无关日志的记录,避免磁盘IO的消耗,以及节省磁盘空间的使用;
  • 参数优化调整,主要是对安全性参数或内存相关参数调整,提高数据库服务运行性能;

企业案例资料参考:

https://mariadb.com/kb/en/installing-tokudb

https://docs.percona.com/percona-server/5.7/tokudb/tokudb_intro.html

https://www.percona.com/doc/percona-server/5.7/tokudb/tokudb_installation.html

案例说明02:企业客户实际数据库需求

平台环境:centos 5.8+mysql 5.0版本,MyISAM存储引擎+网站架构LNMP,数据量50G左右

问题现象:业务并发压力大的时候,整体网站访问非常卡,还会出现数据库服务宕机情况,造成部分数据丢失

问题分析:

  • MyISAM存储引擎具有表级锁,在高并发访问时,会频繁出现锁等待情况;
  • MyISAM存储引擎不支持事务机制,在断电或宕机时,会有可能丢失数据信息;

优化建议:

  • 数据库服务版本进行升级,从5.0升级到更高的版本;ok
  • 数据库服务升级后,迁移所有表数据到新环境(表空间迁移),调整存储引擎为InnoDB;
  • 数据库服务开启双1安全参数;
  • 数据库服务进行重构主从架构

7、数据库存储引擎应用

命令操作:

存储引擎设置:

# 永久修改存储引擎配置
[root@xiaoQ-01 ~]# vim /etc/my.cnf
[mysqld]
default_storage_engine=InnoDB
-- 重启数据库服务生效

存储引擎查看:

# 查看数据库可用存储引擎
mysql> show engines;

# 查看数据库默认存储引擎
mysql> select @@default_storage_engine;
+--------------------------+
| @@default_storage_engine |
+--------------------------+
| InnoDB                   |
+--------------------------+
1 row in set (0.00 sec)

数据表存储引擎配置修改:(具体表的存储引擎)

# 创建表时设置存储引擎
mysql > create table xxx (id int) engine=innodb charset=utf8mb4;
-- 常见表信息时,单独设置存储引擎

# 修改表示设置存储引擎
mysql > alter table world.xxx engine=myisam;
mysql > alter table world.xxx engine=innodb;
-- 修改表中存储引擎信息

数据表存储引擎信息查看:(具体表的存储引擎)

# 查看建表语句获取存储引擎信息
mysql > show create table city;

# 查看information_schema数据库获取存储引擎信息
mysql > select table_schema,table_name,engine from information_schema.tables where table_schema not in('sys','mysql','information_schema','performance_schema')

8、数据库存储引擎结构

什么是表空间:

表空间概念是出自于Oracle数据库机制,主要利用表空间可以灵活扩容存储数据

不同版本演变过程:了解

数据库服务存储引擎结构的介绍,可以依据官方图示参考说明:

https://dev.mysql.com/doc/refman/8.0/en/innodb-architecture.html

1 On-Disk Structures(磁盘结构部分)

在磁盘存储结构中,会使用表空间模式进行数据信息的管理,经常提到的段 区 页概念也是属于表空间的逻辑结构;

表空间的概念源于oracle数据库,最初的目的是为了能够更好的做存储的扩容;因此数据库的表空间技术类似磁盘管理的LVM技术;

在数据库服务中所使用的表空间也被划分出几种种类:

类型一:共享(系统)表空间

属于数据库服务5.5版本时默认的表空间应用,具体数据存储数据方式为:ibdata1~ibdataN

ibdata共享表空间在各个版本之间的作用区别:

数据库版本存储数据解释说明
MySQL 5.5版本系统相关数据全局数据字典信息(表基本结构信息、状态系统参数、属性)、undo回滚日志(记录撤销操作); Double write buffer信息、临时表信息、changer buffer
用户相关数据业务表数据行、表的索引数据均统一存储在ibdata1中,实现集中管理 数据表中数据清理后,ibdata1也不会释放磁盘空间
MySQL 5.6版本系统相关数据全局数据字典信息(表基本结构信息、状态系统参数、属性)、undo回滚日志(记录撤销操作); Double write buffer信息、临时表信息、changer buffer
用户相关数据共享表空间只存储系统数据,用户相关数据被独立管理了(独立表空间管理)
MySQL 5.7版本系统相关数据全局数据字典信息 undo回滚日志 Double write buffer信息、changer buffer 临时表信息被独立出来了,undo也可以设定为独立
用户相关数据共享表空间只存储系统数据,用户相关数据被独立管理了(独立表空间管理)
MySQL 8.0.11系统相关数据Double write buffer信息、changer buffer undo回滚日志信息被独立出来了,数据字典信息也不再集中存储管理了
用户相关数据共享表空间只存储系统数据,用户相关数据被独立管理了(独立表空间管理)
MySQL 8.0.20系统相关数据changer buffer Double write buffer信息被独立出来了

结构一:共享表空间中(ibdata1 ibdata2 ibdata)

对应的文件信息:ibdata1

早期:所有数据库有关的数据统一存储在共享表空间文件中

目前:共享表空间中数据已经做了拆分,此时只保留change buffer数据信息进行保存

  • 扩容共享表空间操作:

扩容前共享表空间信息查看:

mysql> select @@innodb_data_file_path;
+-------------------------+
| @@innodb_data_file_path |
+-------------------------+
| ibdata1:12M:autoextend  |
+-------------------------+
1 row in set (0.00 sec)
-- 可以在初始安装好数据库服务后,进行修改配置为两个ibdate文件,每个共享表空间文件占用2G,总共占用4个G空间

mysql> select @@innodb_autoextend_increment;
+-------------------------------+
| @@innodb_autoextend_increment |
+-------------------------------+
|                            64 |
+-------------------------------+
1 row in set (0.00 sec)
-- 查看参数信息说明:ibdata1文件,默认初始大小12M,不够用会自动扩展,默认每次扩展64M

共享表空间的扩容操作方法:

# 编写数据库配置文件信息
vim /etc/my.cnf
[mysqld]
innodb_data_file_path=ibdata1:12M;ibdata2:100M;ibdata3:100M:autoextend
-- 需要注意的是ibdata1文件大小必须和实际数据库要存储的数据相匹配,否则会出现如下报错信息
 [ERROR] [MY-012264] [InnoDB] The innodb_system data file './ibdata1' is of a different size 768 pages (rounded down to MB) than the 4864 pages specified in the .cnf file!
-- 表示ibdate1指定大小超过了原有ibdata1实际的大小尺寸

# 查看配置信息是否生效
mysql> select @@innodb_data_file_path;
+---------------------------------------------------------------------+
| @@innodb_data_file_path                                                  |
+---------------------------------------------------------------------+
| ibdata1:12M;/data02/ibdata2:100M;/data03/ibdata3:100M:autoextend      |
+---------------------------------------------------------------------+
1 row in set (0.00 sec)

数据库初始化时设置共享表空间容量建议:

序号版本信息建议说明
01MySQL 5.7设置共享表空间2~3个,大小建议512M或1G,最后一个指定为自动扩展
02MySQL 8.0设置共享表空间1个即可,大小建议512M或1G

共享表空间的初始设置方法:

# 模拟初始化清理数据
[root@xiaoQ-01 ~]# /etc/init.d/mysqld stop
[root@xiaoQ-01 ~]# rm -rf /data/3306/data/*

# 模拟初始化配置文件
[root@xiaoQ-01 ~]# vim /etc/my.cnf
[mysqld]
innodb_data_file_path=ibdata1:100M;ibdata2:100M;ibdata3:100M:autoextend

# 模拟初始化操作命令
[root@xiaoQ-01 ~]# mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/3306/data

# 模拟初始化重启服务
[root@xiaoQ-01 ~]#  /etc/init.d/mysqld start

结构二:独立表空间

对应文件信息:表名.ibd

作用:主要用于存储表的结构和数据信息

在数据库服务5.6版本中,针对用户数据,可以进行单独的存储管理,存储表的数据行和索引等相关信息;

独立表空间在各个版本之间的作用区别:

  • 在数据库服务8.0版本前

用户表包含三个部分组成(表.ibd 表.frm ibdata1-全局数据字典信息存储);

所以在8.0之前,如果想修改表数据结构信息(元数据修改),都会修改frm和ibdata文件信息,每次更新都会锁表(元数据锁);

因为要保证数据一致性,并且两个表均更新完,才能释放解锁,因此在8.0前修改元数据信息,要避开业务繁忙时间段;

  • 在数据库服务8.0版本后

用户表数据进行统一存储(表.ibd); 如果想修改表数据结构信息(元数据修改),只会修改ibd文件信息;

此时不需要对两个表文件均更新,只要更新一个文件即可,因此对文件锁的代价降低了,降低了对业务的影响;

独立表空间管理:

  • 表空间配置参数信息查看
mysql > select @@innodb_file_per_table;
+---------------------------------+
| @@innodb_file_per_table |
+---------------------------------+
|                                            1 |
+---------------------------------+
1 row in set (0.00 sec)
-- 表示每个表就是一个独立文件,进行数据信息的独立存储,不建议进行修改,如果改为0就是所有数据统一存储在共享表空间
-- 当默认设置为1表示所有用户数据,单独存储到ibd文件中/ 当设置为0,会将数据信息存储到ibdata文件

[root@db01 school]# file sc.ibd 
sc.ibd: data
[root@db01 school]# ibd2sdi sc.ibd
-- 可以查看独立表空间文件信息(表结构信息)
["ibd2sdi"
,
{
	"type": 1,
	"id": 393,
	"object":
		{
    "mysqld_version_id": 80026,
    "dd_version": 80023,
    "sdi_version": 80019,
    "dd_object_type": "Table",
    "dd_object": {
......
-- 可以看到文件中存储的元数据信息(数据字典信息),并且数据库8.0之后不再有表对应的frm文件信息了
-- 在数据库5.7环境中,每个表数据信息会存储生成两个表 frm ibd
-- frm文件中存储数据表的数据字典信息(元数据信息)
-- ibd文件中存储数据行信息和索引信息
  • 表空间配置参数信息修改
mysql > set global innodb_file_per_table=0
-- 设置为0表示利用共享表空间存储用户数据 1表示利用独立表空间存储用户数据

独立表空间文件作用:备份-1天 恢复-1天

01 可以实现快速迁移数据 1000w数据 1行1M 1000w*1M

数据库服务器A oldboy大表 ----- 数据库服务器B oldboy大表

02 当服务程序异常时,可以利用表空间文件修复数据

数据库备份恢复(物理备份-热备/冷备 逻辑备份-mysqldump-热备)

PS:要恢复数据的表结构需要清楚 ibd数据 – 创建好表

实践操作:

步骤一:环境准备

部署两个数据库服务(3306 3307 – 8.0.26)

步骤二:在3306实例中创建数据信息

将t100w数据恢复

获取表结构信息:

CREATE TABLE `t100w` (
`id` int DEFAULT NULL,
`num` int DEFAULT NULL,
`k1` char(2) DEFAULT NULL
`k2` char (4) DEFAULT NULL,
`dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

步骤三:在3307实例中创建相同表信息(空表)

CREATE TABLE `t100w` (
`id` int DEFAULT NULL,
`num` int DEFAULT NULL,
`k1` char(2) DEFAULT NULL
`k2` char (4) DEFAULT NULL,
`dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

步骤四:在3307实例中,需要解除自己的独立表空间的关系

mysql> alter table oldboy.t100w discard tablespace;
-- 删除t100w表的ibd数据文件信息,但是保留t100w的frm,ibdata1中关于t100w的系统数据

步骤五:将3306实例中独立表空间文件做迁移

cp /data/3306/data/oldboy/t100w.ibd /data/3307/data/oldboy/
chown -R mysql.mysql /data/*

步骤六:在3307实例中,加载迁移后的独立表空间文件

mysql> alter table oldboy.t100w import tablespace;
-- 在目标端加载识别迁移过来的数据文件信息
mysql> select count(*) from t100w;
+----------+
| count(*) |
+----------+
|  1000000 |
+----------+
1 row in set (0.04 sec)
-- 查看数据表中是否有迁移古来的数据信息

案例02:利用表空间迁移功能实现数据损坏恢复

说明:操作系统突然断电了,启动完成后 / 变为只读了,fsck修复文件系统,系统再次重新启动后,mysql启动不了了

结果:造成confulence库在、jira库不见了(备份没有 日志也没开)

服务:jira(bug追踪)、confluence(内部知识库) 、mysql 5.6.33(innodb引擎 使用独立表空间) – LNMT架构

硬件:联想服务器(8核 16G内存 500G存储空间 没有raid),centos 6.8系统

对话描述:

学生:这种情况怎么恢复?

老师:有备份吗?

学生:连二进制日志都没有,没有备份,没有主从

老师:jira数据库数据没什么办法了,只能进行硬盘数据恢复了

学生:jira数据库数据先不用关注,数据磁盘已经拉到中关村处理了

​ 主要是confulence库还想使用,但将生成中的库目录,导入到其他主机上(var/lib/mysql),无法直接访问数据库中数据? /data/3306/data/confulence

​ 老师有没有工具能直接读取数据库目录中的ibd文件内容

老师:我查查,最后发现没有

​ 我们可以尝试下独立表空间迁移

​ create table xx

​ alter table coufulence.t1 discard tablespace;

​ alter table coufulence.t1 import tablespace;

​ 虚拟环境测试可行

问题:confulence库中总共有107张表

困惑:如何创建107张和原来一模一样的表

解决:学生环境中有2016年的历史库,让学生利用mysqldump命令备份confulence历史库

​ mysqldump -uroot -ppassw0rd -B confulence --no-date > test.sql 只获取所有表结构信息

​ 如果是自研数据库,没有备份怎么办

​ mysql工具包中,拥有mysqlfrm工具也可以读取frm文件获取表结构

操作步骤一:备份历史数据库的所有表结构信息,并进行恢复

[root@xiaoQ-01 ~]# mysqldump -uroot -ppassw0rd -B confulence --no-date > test.sql 
mysql > create database confulence
mysql > source test.sql

操作步骤二:删除空表的独立表空间

select concat("alter table ",table_schema,".",table_name," discard tablespace;") from information_schema.tables where table_schema='confulence'; into outfile '/tmp/discard.sql';
source /tmp/discard.sql

实际执行过程发现,有20-30张表无法成功,主外键关系问题,如果一个表一个表分析表结构,处理外键关系很痛苦

set foreign_key_checks=0
-- 跳过外键检查,从而把有问题的20-30张表的独立表空间也删除了

操作步骤三:拷贝生成中confulence库下的所有表的ibd文件到准备好的环境中并加载识别

select concat("alter table ",table_schema,".",table_name," import tablespace;") from information_schema.tables where table_schema='confulence' into outfile '/tmp/import.sql';
source /tmp/import.sql

操作步骤四:进行数据信息验证

表都可以访问了,数据挽回了出现问题时刻的状态

案例03:mysql 5.7中误删除了ibdata1数据文件,导致数据库服务无法启动;(作业)

说明:如何恢复t100w表中数据,并且假设库中有100张表,而且表结构无法通过show create table获得;

提示:有可能是自研数据库,并且没有数据备份

思路:先获取表结构信息,然后重新建表,删除空表的独立表空间,导入表的数据文件,加载识别表数据信息

操作步骤一:mysql工具包中含有mysqlfrm工具,可以读取frm文件获得表结构;

[root@xiaoQ-01 ~]# ./mysqlfrm /data/3306/data/test/t100w.frm --diagnostic

操作步骤二:将新库中所有独立表空间进行删除

select concat('alter table ',table_schema,'.'table_name,' discard tablespace;') from informatin_schema.tables where table_schema='confluence' into outfile '/tmp/discard.sql';
source /tmp/discard.sql

表空间企业应用案例:

案例01:利用独立表空间进行快速数据迁移(源端 3306/test/t100w --> 目标端 3307/test/t100w)

说明:可以在需要某个表中的数据信息时,可以将数据表的独立表空间数据信息做迁移,在另一个数据库中进行恢复即可

e库下的所有表的ibd文件到准备好的环境中并加载识别**

select concat("alter table ",table_schema,".",table_name," import tablespace;") from information_schema.tables where table_schema='confulence' into outfile '/tmp/import.sql';
source /tmp/import.sql

操作步骤四:进行数据信息验证

表都可以访问了,数据挽回了出现问题时刻的状态

案例03:mysql 5.7中误删除了ibdata1数据文件,导致数据库服务无法启动;(作业)

说明:如何恢复t100w表中数据,并且假设库中有100张表,而且表结构无法通过show create table获得;

提示:有可能是自研数据库,并且没有数据备份

思路:先获取表结构信息,然后重新建表,删除空表的独立表空间,导入表的数据文件,加载识别表数据信息

操作步骤一:mysql工具包中含有mysqlfrm工具,可以读取frm文件获得表结构;

[root@xiaoQ-01 ~]# ./mysqlfrm /data/3306/data/test/t100w.frm --diagnostic

操作步骤二:将新库中所有独立表空间进行删除

select concat('alter table ',table_schema,'.'table_name,' discard tablespace;') from informatin_schema.tables where table_schema='confluence' into outfile '/tmp/discard.sql';
source /tmp/discard.sql

表空间企业应用案例:

案例01:利用独立表空间进行快速数据迁移(源端 3306/test/t100w --> 目标端 3307/test/t100w)

说明:可以在需要某个表中的数据信息时,可以将数据表的独立表空间数据信息做迁移,在另一个数据库中进行恢复即可

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

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

相关文章

Web前端入门

文章目录 前言1 Web前端概述1.1 网站和网页1.2 HTML语言1.3 网页的形成1.4 常用浏览器1.5 浏览器内核&#xff08;渲染引擎)1.6 web标准 2 HTML标签2.1 开发工具2.2 HTML语法规则2.3 标签的关系2.4 HTML注释标签2.5 结构标签 3 常用标签3.1 标题标签3.2 段落标签3.3 换行标签3.…

开源城市运动预约的工具类小程序源码

运动场馆预约小程序是一款主要针对城市运动预约的工具类程序&#xff0c; 产品主要服务人群为20-45岁运动爱好者&#xff0c; 程序前后端完整代码&#xff0c;包括场馆动态&#xff0c;运动常识&#xff0c;羽毛球场地预约&#xff0c;足球场地预约&#xff0c;篮球场地预约&a…

【C语言】常见概念

文章目录 库函数关键字字符和ASCll编码字符串与\0转义字符语句和语句分类注释 库函数 为了不再重复实现常见的代码&#xff0c;让程序员提升开发效率&#xff0c;C语言标准规定了一组函数&#xff0c;这些函数再由不同的编译器厂商根据标准进行实现&#xff0c;提供给程序员使…

DAY4 程序流程控制

程序执行顺序 顺序结构、分支结构&#xff08;if switch&#xff09;、循环结构(for while do-while) 分支结构 IF SWITCH 表达式类型只能是byte、short、 int、 char&#xff0c;JDK5开始支持枚举&#xff0c;JDK7开始支持String、不支持double、 float、Long。 case给出的…

基于Qt实现(PC)学生信息管理系统

学生信息管理系统 一、系统指南 本系统为表格式的学生信息管理系统&#xff0c;提供了文件新建、打开及保存功能&#xff0c;还可在表格中对数据进行增加、删除、修改、搜索&#xff0c;下面将一一介绍这些功能 1、新建文件 新建文件将会产生一个全新的空表格&#xff0c;…

【Redis入门到精通十】Redis哨兵

目录 哨兵&#xff08;Sentinel&#xff09; 1.哨兵的由来 2.哨兵的基本概念 3.基于docker安装配置Redis哨兵 4.哨兵选取主节点的原理 1.主观下线 2.客观下线 3.选举出哨兵的leader 4.leader挑选出合适的slave成为新的master 哨兵&#xff08;Sentinel&#xff09; Red…

2-117 基于matlab的共振峰估计

基于matlab的共振峰估计&#xff0c;共振峰参数包括共振峰频率和频带的宽度&#xff08;带宽&#xff09;。共振峰信息主要包含在语音频谱的包络中&#xff0c;其关键是估计自然语音频谱包络&#xff0c;通过倒谱法、LPC内插法、LPC求根法实现共振峰估计。程序已调通&#xff0…

Spark_累加器

分布式共享只写变量 实现原理&#xff1a;  累加器用来把Executor端变量信息聚合到Driver端&#xff0c;在Driver程序中定义的变量&#xff0c;在Executor端的每个Task都会得到这个变量的一份新的副本&#xff0c;每个task更新这些副本的值后&#xff0c;传回Driver端进行mer…

计算机视觉的应用36-人工智能时代计算机视觉技术在电力系统中的应用

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用36-人工智能时代计算机视觉技术在电力系统中的应用。本文综述了人工智能时代计算机视觉技术在电力系统中的应用。文章首先介绍了项目背景&#xff0c;随后详细阐述了计算机视觉技术的模型、技术原理…

轻松实现本地部署:任何人都能安装顶尖开源模型 LLaMA3!

引言 LLaMA3 在 2024年4月18 日正式发布了&#xff0c;作为开发人员怎么能不蹭一下热度&#xff0c;体验一下可以在个人电脑端部署的大语言模型呢&#xff1f;文末领取安装包和安装文档&#xff01; LLaMA3 LaMA3 是一个自回归语言模型&#xff0c;使用了优化的 Transformer …

Java后端面试题(day16)

目录 java常见的引用类型java中深拷贝和浅拷贝如何设计一个秒杀系统?谈一下对高并发的理解&#xff0c;平时怎么处理高并发问题?Comparable和Comparator区别&#xff1f;解决hash冲突有哪些方法&#xff1f;Synchronized锁的升级过程 java常见的引用类型 java的引用类型一般分…

【数据结构与算法】简单聊聊图数据的存储

文章目录 1. 邻接矩阵&#xff08;Adjacency Matrix&#xff09;2. 邻接表&#xff08;Adjacency List&#xff09;3. 邻接多重表4. 十字链表5. 图数据库&#xff08;Graph Database&#xff09; 存储图数据的方法主要有几种&#xff0c;每种方法都有其特定的应用场景和优缺点。…

【工具】前端js数字金额转中文大写金额

【工具】前端js数字金额转中文大写金额 代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>金额转…

快递批量查询物流追踪只揽收无物流信息的单号

在电子商务和物流领域&#xff0c;快递单号的追踪是确保货物顺利送达的关键环节。然而&#xff0c;在实际操作中&#xff0c;经常会遇到一些只显示揽收信息而没有后续物流更新的单号&#xff0c;这给商家和买家都带来了不小的困扰。本文将介绍如何通过快递批量查询物流的方法&a…

jdk多版本来回切换不生效

本人电脑安装了两个jdk1.8跟17 但是安装完17后发现怎么切换版本都是17&#xff0c;如图 解决思路也很简单&#xff0c;就是找到path 将%JAVA_HOME%/bin提到最前头&#xff0c;就解决了 但是需要注意的是jdk11以上就没有jre了

YOLO11改进|注意力机制篇| 引入SpatialGroupEnhance注意力机制

目录 一、【 SpatialGroupEnhance】注意力机制1.1【 SpatialGroupEnhance】注意力介绍1.2【SpatialGroupEnhance】核心代码 二、添加【SpatialGroupEnhance】注意力机制2.1STEP12.2STEP22.3STEP32.4STEP4 三、yaml文件与运行3.1yaml文件3.2运行成功截图 一、【 SpatialGroupEnh…

leetcode:反转字符串II

题目链接 string reverse(string s1) {string s2;string::reverse_iterator rit s1.rbegin();while (rit ! s1.rend()){s2 *rit;rit;}return s2; } class Solution { public:string reverseStr(string s, int k) {string s1;int i 0;//标记字符串下标int j 0;int length …

程序员在AI时代扮演着多重角色:不仅是AI技术的创造者,也是使用者,更是AIGC的贡献者

程序员在AI时代扮演着多重角色&#xff1a;不仅是AI技术的创造者&#xff0c;也是使用者&#xff0c;更是AIGC的贡献者 引言 大家好&#xff0c;我是猫头虎&#xff0c;在当下的AI时代&#xff0c;程序员不仅是AI技术的推动者&#xff0c;更在这个生态中扮演着多重角色&#…

ARM base instruction -- sdiv

有符号除法运算 Signed Divide divides a signed integer register value by another signed integer register value, and writes the result to the destination register. The condition flags are not affected. 将一个有符号整数寄存器值除以另一个有符号整数寄存器值&am…

YOLOv11训练自己数据集_笔记1

一、前言 官网yolov11-main yolov11代码地址 分析YOLO11的关键改进点 YOLO11 相比之前版本&#xff0c;带来了五大关键改进&#xff1a; 增强特征提取&#xff1a;通过改进Backbone和Neck架构&#xff0c;新增了C3k2和C2PSA等组件&#xff0c;提升了目标检测的精度。 优化效率…