MySQL是怎样运行的

05InnoDB数据页结构

学习《MySQL是怎样运行的》,感谢作者!

不同类型的页简介 #

页是InnoDB管理存储空间的基本单位,1个页的大小一般是16KB

InnoDB为了不同目的设计多种不同类型的页,包括存放表空间头部信息 的页、存放Change Buffer 信息的页、存放INODE信息的页、存放undo 日志信息的页

这里说的是存放表中记录的那种类型的页,这种存放记录的页称为索引页(INDEX页)

暂时称之为数据页

数据页结构快览 #

1个页有16KB,这部分存储空间被划分为了多个部分(7部分),不同部分有不同的功能
ly-20241212142155323

名称中文名占用空间大小
File Header文件头部38 字节页的一些通用信息
Page Header页面头部56 字节数据页专有的一些信息
Infimum + Supremum页面中的最小记录和最大记录26 字节两个虚拟的记录
User Records用户记录不确定用户存储的记录内容
Free Space空闲空间不确定页中尚未使用的空间
Page Directory页目录不确定某些记录的相对位置
File Trailer文件尾部8 字节校验页是否完整

记录在页中的存储 #

每插入一条记录,从Free Space申请一个记录大小的空间,并将这个空间划分到UserRecords部分。当FreeSpace部分的空间全部被UserRecords部分替代掉后,意味着该页用完。如果再插入,就需要申请新的页

ly-20241212142155485

记录头信息的秘密 #

mysql> CREATE TABLE page_demo(
      c1 INT,
      c2 INT,
      c3 VARCHAR(10000),
      PRIMARY KEY(c1)
      ) CHARSET=ascii ROW_FORMAT=COMPACT;
Query OK, 0 rows affected (0.03 sec)

ly-20241212142155528

...

04InnoDB记录存储结构

学习《MySQL是怎样运行的》,感谢作者!

问题 #

表数据存在哪,以什么格式存放,MySQL以什么方式来访问
存储引擎:对表中数据进行存储写入
InnoDB是MySQL默认的存储引擎,这章主要讲InnoDB存储引擎的记录存储结构

InnoDB页简介 #

注意,是简介
InnoDB:将表中的数据存储到磁盘上
真正处理数据的过程:内存中。所以需要把磁盘中数据加载到内存中,如果是写入修改请求,还需要把内存中的内容刷新到磁盘
获取记录:不是一条条从磁盘读,InnoDB将数据划分为若干个页,以作为磁盘内存之间交互的基本单位。页大小-> 一般是16KB
一般情况:一次最少从磁盘读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘

mysql>  SHOW VARIABLES LIKE 'innodb_page_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
1 row in set (0.00 sec)

只能在第一次初始化MySQL数据目录时指定,之后再也不能更改(通过mysqld –initialize初始化数据目录[旧版本])

InnoDB行格式 #

以记录为单位向表中插入数据,而这些记录在磁盘上的存放形式也被称为行格式或者记录格式
目前有4中不同类型的行格式:COMPACT、REDUNDANT、DYNAMIC和COMPRESSED

compact [kəmˈpækt]契约
redundant[rɪˈdʌndənt] 冗余的
dynamic[daɪˈnæmɪk]动态的
compressed [kəmˈprest] 压缩的

指定行格式的语法 #

CREATE TABLE 表名(列的信息) ROW_FORMAT=行格式名称
ALTER TABLE 表名 ROW_FORMATE=行格式名称
如下,在数据库xiaohaizi下创建一个表

CREATE TABLE record_format_demo(
      c1 VARCHAR(10),
      c2 VARCHAR(10) NOT NULL,
      c3 CHAR(10),
      c4 VARCHAR(10)
      ) CHARSET=ascii ROW_FORMAT=COMPACT;  
#回顾:ascii每个字符1字节即可表示,且只有空格标点数字字母不可见字符
#插入两条数据
INSERT INTO record_format_demo(c1,c2,c3,c4) VALUES('aaaa','bbb','cc','d'),('eeee','fff',NULL,NULL);

查询

...

03字符集和比较规则

学习《MySQL是怎样运行的》,感谢作者!

字符集 #

把哪些字符映射成二进制数据:字符范围
怎么映射:字符->二进制数据,编码;二进制->字符,解码
字符集:某个字符范围的编码规则
同一种字符集可以有多种比较规则

重要的字符集 #

ASCAII字符集:128个,包括空格标点数字大小写及不可见字符,使用一个字节编码
ISO 8859-1字符集:256个,ASCAII基础扩充128个西欧常用字符(包括德法),使用1个字节,别名Latin1
GB2312字符集:收录部分汉字,兼容ASCAII字符集,如果字符在ASCAII字符集中则采用1字节,否则两字节。即变长编码方式

区分某个字节,代表一个单独字符,还是某个字符的一部分
比如0xB0AE75,由于是16进制,所有两个代表1个字节。所以这里有三个字节,其中最后那个字节为7*16+5=117 < 127 所以代表一个单独字符。而AE=10 * 16 +15=175 >127 ,所以是某个字符的一部分

GBK字符集:对GB2312字符集扩充,编码方式兼容GB2312
UTF-8字符集:几乎收录所有字符,且不断扩充,兼容ASCAII字符集。变长:采用14字节
L->0x4C 1字节,啊->0xE5958A,两字节
UTF-8是Unicode字符集的一种编码方案,Unicode字符集有三种方案:UTF-8(1
4字节编码一个字符),UTF-16(2或4字节编码一个字符),UTF-32(4字节编码一个字符)

对于**“我”**,ASCLL中没有,UTF-8中采用3字节编码,GB22312采用2字节编码

MySQL中支持的字符集和比较规则 #

MySQL中,区分utf8mb3和utf8mb4,前者只是用13字节表示字符;后者使用14字节表示字符。MySQL中,utf8代表utf8mb3。

#查看当前MySQL支持的字符集(注意,是字符集,名称都是小写)
#Default collation 默认比较规则
mysql> SHOW CHARSET;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| dec8     | DEC West European               | dec8_swedish_ci     |      1 |
| cp850    | DOS West European               | cp850_general_ci    |      1 |
| hp8      | HP West European                | hp8_english_ci      |      1 |
| koi8r    | KOI8-R Relcom Russian           | koi8r_general_ci    |      1 |
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |  <---
| latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |  <---
| swe7     | 7bit Swedish                    | swe7_swedish_ci     |      1 |
| ascii    | US ASCII                        | ascii_general_ci    |      1 |  <---
| ujis     | EUC-JP Japanese                 | ujis_japanese_ci    |      3 |
| sjis     | Shift-JIS Japanese              | sjis_japanese_ci    |      2 |
| hebrew   | ISO 8859-8 Hebrew               | hebrew_general_ci   |      1 |
| tis620   | TIS620 Thai                     | tis620_thai_ci      |      1 |
| euckr    | EUC-KR Korean                   | euckr_korean_ci     |      2 |
| koi8u    | KOI8-U Ukrainian                | koi8u_general_ci    |      1 |
| gb2312   | GB2312 Simplified Chinese       | gb2312_chinese_ci   |      2 |  <---
| greek    | ISO 8859-7 Greek                | greek_general_ci    |      1 |
| cp1250   | Windows Central European        | cp1250_general_ci   |      1 |
| gbk      | GBK Simplified Chinese          | gbk_chinese_ci      |      2 |  <---
| latin5   | ISO 8859-9 Turkish              | latin5_turkish_ci   |      1 |
| armscii8 | ARMSCII-8 Armenian              | armscii8_general_ci |      1 |
| utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |  <---
| ucs2     | UCS-2 Unicode                   | ucs2_general_ci     |      2 |
| cp866    | DOS Russian                     | cp866_general_ci    |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak      | keybcs2_general_ci  |      1 |
| macce    | Mac Central European            | macce_general_ci    |      1 |
| macroman | Mac West European               | macroman_general_ci |      1 |
| cp852    | DOS Central European            | cp852_general_ci    |      1 |
| latin7   | ISO 8859-13 Baltic              | latin7_general_ci   |      1 |  
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_general_ci  |      4 |  <---
| cp1251   | Windows Cyrillic                | cp1251_general_ci   |      1 |
| utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |  <---
| utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
| cp1256   | Windows Arabic                  | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic                  | cp1257_general_ci   |      1 |
| utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |  <---
| binary   | Binary pseudo charset           | binary              |      1 |
| geostd8  | GEOSTD8 Georgian                | geostd8_general_ci  |      1 |
| cp932    | SJIS for Windows Japanese       | cp932_japanese_ci   |      2 |
| eucjpms  | UJIS for Windows Japanese       | eucjpms_japanese_ci |      3 |
| gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.00 sec)

字符集的比较规则(这里先看utf8的)

...

02启动选项和系统变量

学习《MySQL是怎样运行的》,感谢作者!

启动选项和配置文件 #

在程序启动时指定的设置项,也称之为启动选项startup option(可以在命令行中/配置文件中 指定)
由于在centos7中使用systemctl start mysqld启动mysql,所以好像没法用命令行指定启动选项了

程序(可能有些程序新版本已经没有了)的对应类别和能读取的组:
ly-20241212142154302

这里讲配置文件的方式设置启动选项:

#添加配置
vim /etc/my.cnf
[server]
skip-networking #禁止tcp网络连接
default-storage-engine=MyISAM #建表默认使用M有ISAM存储引擎


#效果
▶ mysql -h127.0.0.1 -uroot -p
Enter password: 
ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1' (111)

#去除tcp网络连接限制后新建一个表
▶ mysql -h127.0.0.1 -uroot -p #可以连接上
mysql> create table default_storage_engine_demo(i int);
Query OK, 0 rows affected (0.01 sec)
mysql> show create table default_storage_engine_demo;
+-----------------------------+----------------------------------------------------------------------------------------------------------------+
| Table                       | Create Table                                                                                                   |
+-----------------------------+----------------------------------------------------------------------------------------------------------------+
| default_storage_engine_demo | CREATE TABLE `default_storage_engine_demo` (
  `i` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |

如果多个配置文件都配置了某个选项,如/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf都配置了,则以最后一个配置的为主
如果同一个配置文件,比如[server]组和[mysqld]组都出现了default-storage-engine配置,则以后出现的组中的配置为准
如果一个启动选项既在命令行中出现,又在配置文件中配置,则以命令行中的为准

...

01初识MySQL

学习《MySQL是怎样运行的》,感谢作者!

原文 #

下载与安装 #

环境Centos7

添加MySQL5.7仓库

sudo rpm -ivh https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm

解决证书问题

rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022

查看是否添加成功

sudo yum repolist all | grep mysql | grep 启用   
mysql-connectors-community/x86_64   MySQL Connectors Community      启用:    213
mysql-tools-community/x86_64        MySQL Tools Community           启用:     96
mysql57-community/x86_64            MySQL 5.7 Community Server      启用:    642

MySQL安装

sudo yum -y install mysql-community-server

运行与密码修改 #

Centos7中安装目录查看,在/usr/bin中,与Max有所不同

whereis mysql
mysql: /usr/bin/mysql /usr/lib64/mysql /usr/share/mysql /usr/share/man/man1/mysql.1.gz
ls /usr/bin |grep mysql
mysql
mysqladmin
mysqlbinlog
mysqlcheck
mysql_config_editor
mysqld_pre_systemd
mysqldump
mysqldumpslow
mysqlimport
mysql_install_db
mysql_plugin
mysqlpump
mysql_secure_installation
mysqlshow
mysqlslap
mysql_ssl_rsa_setup
mysql_tzinfo_to_sql
mysql_upgrade

添加mysqld目录到环境变量中(这里可省略,因为mysqld默认在/usr/bin中了

...