MySQL怎样运行的-掘金小册读书笔记

实在不爱重新排版,我能看懂就行了吧。。。
声明:以下内容并非原创,来自掘金小册:MySQL是怎样运行的-从根上理解MySQL--https://juejin.im/book/6844733769996304392/section/6844733769945972749

一、重新认识MySQL
Mysqld
Mysql_safe
Mysql.server
多实例下:
mysqld_multi:
其实我们一台计算机上也可以运行多个服务器实例,也就是运行多个MySQL服务器进程。mysql_multi可执行文件可以对每一个服务器进程的启动或停止进行监控。这个命令的使用比较复杂,本书主要是为了讲清楚MySQL服务器和客户端运行的过程,不会对启动多个服务器程序进行过多唠叨。

Windows下注册mysql服务:
比如我的Windows计算机上mysqld的完整路径是:
C:Program FilesMySQLMySQL Server 5.7inmysqld
所以如果我们想把它注册为服务的话可以在命令行里这么写:
"C:Program FilesMySQLMySQL Server 5.7inmysqld" –install
在把mysqld注册为Windows服务之后,我们就可以通过下边这个命令来启动MySQL服务器程序了:
net start MySQL

Windows下以服务的方式运行服务器程序:
首先看看啥是个Windows 服务?如果无论是谁正在使用这台计算机,我们都需要长时间的运行某个程序,而且需要在计算机启动的时候便启动它,一般我们都会把它注册为一个Windows 服务,操作系统会帮我们管理它。把某个程序注册为Windows服务的方式挺简单,如下:
"完整的可执行文件路径" --install [-manual] [服务名]
命名管道和共享内存(服务器和客户端在同一台windows上)
是Windows操作系统中的两种进程间通信方式。
Unix域套接字文件(服务器和客户端在同一台linux上)
服务器进程和客户端进程都运行在同一台操作系统为类Unix的机器上的话,我们可以使用Unix域套接字文件来进行进程间通信。
如果我们在启动客户端程序的时候指定的主机名为localhost,或者指定了--protocol=socket的启动参数,那服务器程序和客户端程序之间就可以通过Unix域套接字文件来进行通信了。
SSL(安全套接字)的网络连接进行通信(服务器和客户端不在同一台上)(TCP/IP)
如果客户端程序和服务器程序不运行在一台计算机上,我们还可以采用使用了SSL(安全套接字)的网络连接进行通信,来保证数据传输的安全性。来保证数据传输的安全性。
MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除。
虽然查询缓存有时可以提升系统性能,但也不得不因维护这块缓存而造成一些开销,比如每次都要去查询缓存中检索,查询请求处理完需要更新查询缓存,维护该查询缓存对应的内存区域。从MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除。
查询优化
是服务器处理请求的过程中进行的一步;后面详细了解。
存储引擎负责的事情(表处理器)
我们知道表是由一行一行的记录组成的,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存储器上,这都是存储引擎负责的事情。它的功能就是接收上层传下来的指令,然后对表中的数据进行提取或写入操作。我们可以为不同的表设置不同的存储引擎,也就是说不同的表可以有不同的物理存储结构,不同的提取和写入方式。

MySQL server和存储引擎分工
为了管理方便,人们把连接管理、查询缓存、语法解析、查询优化这些并不涉及真实数据存储的功能划分为MySQL server的功能,把真实存取数据的功能划分为存储引擎的功能。各种不同的存储引擎向上边的MySQL server层提供统一的调用接口(也就是存储引擎API),包含了几十个底层函数,像"读取索引第一条内容"、"读取索引下一条内容"、"插入记录"等等。
所以,在MySQL server完成了查询优化后,只需按照生成的执行计划调用底层存储引擎提供的API,获取到数据后返回给客户端就好了。
Show engines;
XA列代表着该存储引擎是否支持分布式事务
Savepoints代表着该存储引擎是否支持部分事务回滚。

二、启动选项和配置文件——MySQL的调控按钮

每个MySQL程序都有许多不同的选项。
大多数程序提供了一个--help选项,你可以查看该程序支持的全部启动选项以及它们的默认值。例如,使用mysql --help可以看到mysql程序支持的启动选项,mysqld_safe --help可以看到mysqld_safe程序支持的启动选项。查看mysqld支持的启动选项有些特别,需要使用mysqld --verbose --help。
配置文件中应用不同的启动程序读不同的组;
配置文件中不同的选项组是给不同的启动命令使用的,如果选项组名称与程序名称相同,则组中的选项将专门应用于该程序。例如, [mysqld]和[mysql]组分别应用于mysqld服务器程序和mysql客户端程序。不过有两个选项组比较特别:
• [server]组下边的启动选项将作用于所有的服务器程序。
• [client]组下边的启动选项将作用于所有的客户端程序。
需要注意的一点是,mysqld_safe和mysql.server这两个程序在启动时都会读取[mysqld]选项组中的内容。为了直观感受一下,我们挑一些启动命令来看一下它们能读取的选项组都有哪些:
启动命令 类别 能读取的组
mysqld 启动服务器 [mysqld]、[server]
mysqld_safe 启动服务器 [mysqld]、[server]、[mysqld_safe]
mysql.server 启动服务器 [mysqld]、[server]、[mysql.server]
mysql 启动客户端 [mysql]、[client]
mysqladmin 启动客户端 [mysqladmin]、[client]
mysqldump 启动客户端 [mysqldump]、[client]
特定MySQL版本的专用选项组
我们可以在选项组的名称后加上特定的MySQL版本号,比如对于[mysqld]选项组来说,我们可以定义一个[mysqld-5.7]的选项组,它的含义和[mysqld]一样,只不过只有版本号为5.7的mysqld程序才能使用这个选项组中的选项。

同一个配置文件中多个组的优先级
我们说同一个命令可以访问配置文件中的多个组,比如mysqld可以访问[mysqld]、[server]组,如果在同一个配置文件中,比如~/.my.cnf,在这些组里出现了同样的配置项,比如这样:
[server]
default-storage-engine=InnoDB

[mysqld]
default-storage-engine=MyISAM
那么,将以最后一个出现的组中的启动选项为准,比方说例子中default-storage-engine既出现在[mysqld]组也出现在[server]组,因为[mysqld]组在[server]组后边,就以[mysqld]组中的配置项为准。
启动选项指定配置文件
注意defaults-extra-filedefaults-file的区别,使用defaults-extra-file可以指定额外的配置文件搜索路径(也就是说那些固定的配置文件路径也会被搜索)。
系统变量
查看:show variables like
设置:
在启动选项中设置,启动选项可以在命令行或者配置文件中添加。
在服务器程序运行过程中设置:看作用范围:
• GLOBAL:全局变量,影响服务器的整体操作。
• SESSION:会话变量,影响某个客户端连接的操作。(注:SESSION有个别名叫LOCAL)
SET [GLOBAL|SESSION] 系统变量名 = 值;
或者写成这样也行:
SET [@@(GLOBAL|SESSION).]var_name = XXX;
直接在客户端进行:SET default_storage_engine = MyISAM;表示在当前客户端生效;
注意:
小贴士: 如果某个客户端改变了某个系统变量在GLOBAL作用范围的值,并不会影响该系统变量在当前已经连接的客户端作用范围为SESSION的值,只会影响后续连入的客户端在作用范围为SESSION的值。

注意事项:
• 并不是所有系统变量都具有GLOBAL和SESSION的作用范围。
o 有一些系统变量只具有GLOBAL作用范围,比方说max_connections,表示服务器程序支持同时最多有多少个客户端程序进行连接。
o 有一些系统变量只具有SESSION作用范围,比如insert_id,表示在对某个包含AUTO_INCREMENT列的表进行插入时,该列初始的值。
o 有一些系统变量的值既具有GLOBAL作用范围,也具有SESSION作用范围,比如我们前边用到的default_storage_engine,而且其实大部分的系统变量都是这样的,
• 有些系统变量是只读的,并不能设置值。
比方说version,表示当前MySQL的版本,我们客户端是不能设置它的值的,只能在SHOW VARIABLES语句里查看。
启动选项和系统变量的区别:
启动选项是在程序启动时我们程序员传递的一些参数,而系统变量是影响服务器程序运行行为的变量,它们之间的关系如下:
• 大部分的系统变量都可以被当作启动选项传入。
• 有些系统变量是在程序运行过程中自动生成的,是不可以当作启动选项来设置,比如auto_increment_offset、character_set_client啥的。
• 有些启动选项也不是系统变量,比如defaults-file。

状态变量
为了让我们更好的了解服务器程序的运行情况,MySQL服务器程序中维护了好多关于程序运行状态的变量,它们被称为状态变量。
由于状态变量是用来显示服务器程序运行状况的,所以它们的值只能由服务器程序自己来设置,我们程序员是不能设置的。与系统变量类似,状态变量也有GLOBAL和SESSION两个作用范围的,所以查看状态变量的语句可以这么写:
SHOW [GLOBAL|SESSION] STATUS [LIKE 匹配的模式];
类似的,如果我们不写明作用范围,默认的作用范围是SESSION。

三、乱码问题—字符集和比较规则
Mysql中的utf8和utf8mb4
utf8字符集表示一个字符需要使用1~4个字节,但是我们常用的一些字符使用1~3个字节就可以表示了。而在MySQL中字符集表示一个字符所用最大字节长度在某些方面会影响系统的存储和性能,所以设计MySQL的大叔偷偷的定义了两个概念:
• utf8mb3:阉割过的utf8字符集,只使用1~3个字节表示字符。
• utf8mb4:正宗的utf8字符集,使用1~4个字节表示字符。
有一点需要大家十分的注意,在MySQL中utf8是utf8mb3的别名,所以之后在MySQL中提到utf8就意味着使用1~3个字节来表示一个字符,如果大家有使用4字节编码一个字符的情况,比如存储一些emoji表情啥的,那请使用utf8mb4。
为了让大家的印象更深刻,我把几个常用到的字符集的Maxlen列摘抄下来,大家务必记住:
字符集名称 Maxlen
ascii 1
latin1 1
gb2312 2
gbk 2
utf8 3
utf8mb4 4

字符集的查看:

比较规则的查看:

字符集和比较规则的应用:
各级别的字符集和比较规则
MySQL有4个级别的字符集和比较规则,分别是:
• 服务器级别
• 数据库级别
• 表级别
• 列级别
服务器级别:
两个系统变量表示服务器级别的字符集和比较规则:
Character_set_server 服务器级别的字符集
Collation_server 服务器级别的比较规则;
可以看到在我的计算机中服务器级别默认的字符集是utf8,默认的比较规则是utf8_general_ci。
我们可以在启动服务器程序时通过启动选项或者在服务器程序运行过程中使用SET语句修改这两个变量的值。比如我们可以在配置文件中这样写:
[server]
character_set_server=gbk
collation_server=gbk_chinese_ci
当服务器启动的时候读取这个配置文件后这两个系统变量的值便修改了。

数据库级别
我们在创建和修改数据库的时候可以指定该数据库的字符集和比较规则,具体语法如下:
CREATE DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];

ALTER DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];

需要注意的一点是:
character_set_database 和 collation_database 这两个系统变量是只读的,我们不能通过修改这两个变量的值而改变当前数据库的字符集和比较规则。
数据库的创建语句中也可以不指定字符集和比较规则,比如这样:
CREATE DATABASE 数据库名;
这样的话将使用服务器级别的字符集和比较规则作为数据库的字符集和比较规则。

表级别
我们也可以在创建和修改表的时候指定表的字符集和比较规则,语法如下:
CREATE TABLE 表名 (列的信息)
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]]

ALTER TABLE 表名
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]
Eg:
mysql> CREATE TABLE t(
-> col VARCHAR(10)
-> ) CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 0 rows affected (0.03 sec)

如果创建和修改表的语句中没有指明字符集和比较规则,将使用(继承)该表所在数据库的字符集和比较规则作为该表的字符集和比较规则。

列级别
需要注意的是,对于存储字符串的列,同一个表中的不同的列也可以有不同的字符集和比较规则。我们在创建和修改列定义的时候可以指定该列的字符集和比较规则,语法如下:

CREATE TABLE 表名(
列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],
其他列...
);

ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];

比如我们修改一下表t中列col的字符集和比较规则可以这么写:
mysql> ALTER TABLE t MODIFY col VARCHAR(10) CHARACTER SET gbk COLLATE gbk_chinese_ci;
Query OK, 0 rows affected (0.04 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>

对于某个列来说,如果在创建和修改的语句中没有指明字符集和比较规则,将使用该列所在表的字符集和比较规则作为该列的字符集和比较规则。
小贴士:
在转换列的字符集时需要注意,如果转换前列中存储的数据不能用转换后的字符集进行表示会发生错误。比方说原先列使用的字符集是utf8,列中存储了一些汉字,现在把列的字符集转换为ascii的话就会出错,因为ascii字符集并不能表示汉字字符。

仅修改字符集或仅修改比较规则:
由于字符集和比较规则是互相有联系的,如果我们只修改了字符集,比较规则也会跟着变化,如果只修改了比较规则,字符集也会跟着变化,具体规则如下:
• 只修改字符集,则比较规则将变为修改后的字符集默认的比较规则。
• 只修改比较规则,则字符集将变为修改后的比较规则对应的字符集。
• 9_AMQBq-
根据这个列的类型来确定存储数据时每个列的实际数据占用的存储空间大小
知道了这些规则之后,对于给定的表,我们应该知道它的各个列的字符集和比较规则是什么,从而根据这个列的类型来确定存储数据时每个列的实际数据占用的存储空间大小了。比方说我们向表t中插入一条记录:

mysql> INSERT INTO t(col) VALUES('我我');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM t;
+--------+
| s |
+--------+
| 我我 |
+--------+
1 row in set (0.00 sec)
首先列col使用的字符集是gbk,一个字符'我'在gbk中的编码为0xCED2,占用两个字节,两个字符的实际数据就占用4个字节。如果把该列的字符集修改为utf8的话,这两个字符就实际占用6个字节啦~
客户端和服务器通信中的字符集
编码和解码使用的字符集不一致的后果
编码和解码采用的字符集不一致,导致解码后的得到的结果乱码;
举例说明:
我们知道字符'我'在utf8字符集编码下的字节串长这样:0xE68891,如果一个程序把这个字节串发送到另一个程序里,另一个程序用不同的字符集去解码这个字节串,假设使用的是gbk字符集来解释这串字节,解码过程就是这样的:

  1. 首先看第一个字节0xE6,它的值大于0x7F(十进制:127),说明是两字节编码,继续读一字节后是0xE688,然后从gbk编码表中查找字节为0xE688对应的字符,发现是字符'鎴'
  2. 继续读一个字节0x91,它的值也大于0x7F,再往后读一个字节发现木有了,所以这是半个字符。
  3. 所以0xE68891被gbk字符集解释成一个字符'鎴'和半个字符。
    假设用iso-8859-1,也就是latin1字符集去解释这串字节,解码过程如下:
  4. 先读第一个字节0xE6,它对应的latin1字符为æ。
  5. 再读第二个字节0x88,它对应的latin1字符为ˆ。
  6. 再读第三个字节0x91,它对应的latin1字符为‘。
  7. 所以整串字节0xE68891被latin1字符集解释后的字符串就是'我'
    可见,如果对于同一个字符串编码和解码使用的字符集不一样,会产生意想不到的结果,作为人类的我们看上去就像是产生了乱码一样。
    MySQL中字符集的转换
    发送请求到返回结果这个过程中伴随着多次字符集的转换,在这个过程中会用到3个系统变量,我们先把它们写出来看一下:

    系统变量 描述
    character_set_client 服务器解码请求时使用的字符集
    character_set_connection 服务器处理请求时会把请求字符串从character_set_client转为character_set_connection
    character_set_results 服务器向客户端返回数据时使用的字符集
    这几个系统变量在我的计算机上的默认值如下(不同操作系统的默认值可能不同):

补充:
如果你查到你的服务端character_set_results 默认是null:
null就是服务器不对查询得到的结果进行字符集转换,直接发送给客户端。

1、客户端发送请求所使用的字符集
一般情况下客户端所使用的字符集和当前操作系统一致,不同操作系统使用的字符集可能不一样,如下:
• 类Unix系统使用的是utf8
• Windows使用的是gbk
例如我在使用的macOS操作系统时,客户端使用的就是utf8字符集。所以字符'我'在发送给服务器的请求中的字节形式就是:0xE68891
这里注意:
如果你使用的是可视化工具,比如navicat之类的,这些工具可能会使用自定义的字符集来编码发送到服务器的字符串,而不采用操作系统默认的字符集(所以在学习的时候还是尽量用黑框框比较好)。

2、服务器接收到客户端发送来的请求其实是一串二进制的字节,它会认为这串字节采用的字符集是character_set_client,然后把这串字节转换为character_set_connection字符集编码的字符。

由于我的计算机上character_set_client的值是utf8,首先会按照utf8字符集对字节串0xE68891进行解码,得到的字符串就是'我',然后按照character_set_connection代表的字符集,也就是gbk进行编码,得到的结果就是字节串0xCED2。

3、因为表t的列col采用的是gbk字符集,与character_set_connection一致,所以直接到列中找字节值为0xCED2的记录,最后找到了一条记录。

如果某个列使用的字符集和character_set_connection代表的字符集不一致的话,还需要进行一次字符集转换。
4、上一步骤找到的记录中的col列其实是一个字节串0xCED2,col列是采用gbk进行编码的,所以首先会将这个字节串使用gbk进行解码,得到字符串'我',然后再把这个字符串使用character_set_results代表的字符集,也就是utf8进行编码,得到了新的字节串:0xE68891,然后发送给客户端。

5、由于客户端是用的字符集是utf8,所以可以顺利的将0xE68891解释成字符我,从而显示到我们的显示器上,所以我们人类也读懂了返回的结果。

如果你读上边的文字有点晕,可以参照这个图来仔细分析一下这几个步骤:

从这个分析中我们可以得出这么几点需要注意的地方:
• 服务器认为客户端发送过来的请求是用character_set_client编码的。
假设你的客户端采用的字符集和 character_set_client 不一样的话,这就会出现意想不到的情况。比如我的客户端使用的是utf8字符集,如果把系统变量character_set_client的值设置为ascii的话,服务器可能无法理解我们发送的请求,更别谈处理这个请求了。
• 服务器将把得到的结果集使用character_set_results编码后发送给客户端。
假设你的客户端采用的字符集和 character_set_results 不一样的话,这就可能会出现客户端无法解码结果集的情况,结果就是在你的屏幕上出现乱码。比如我的客户端使用的是utf8字符集,如果把系统变量character_set_results的值设置为ascii的话,可能会产生乱码。
• character_set_connection只是服务器在将请求的字节串从character_set_client转换为character_set_connection时使用,它是什么其实没多重要,但是一定要注意,该字符集包含的字符范围一定涵盖请求中的字符,要不然会导致有的字符无法使用character_set_connection代表的字符集进行编码。比如你把character_set_client设置为utf8,把character_set_connection设置成ascii,那么此时你如果从客户端发送一个汉字到服务器,那么服务器无法使用ascii字符集来编码这个汉字,就会向用户发出一个警告。

知道了在MySQL中从发送请求到返回结果过程里发生的各种字符集转换,但是为啥要转来转去的呢?不晕么?

答:是的,很头晕,所以我们通常都把 character_set_client 、character_set_connection、character_set_results 这三个系统变量设置成和客户端使用的字符集一致的情况,这样减少了很多无谓的字符集转换。为了方便我们设置,MySQL提供了一条非常简便的语句:
SET NAMES 字符集名;
这一条语句产生的效果和我们执行这3条的效果是一样的:
SET character_set_client = 字符集名;
SET character_set_connection = 字符集名;
SET character_set_results = 字符集名; 这三个变量是session级别的!

注意:
如果你使用的是Windows系统,那应该设置成gbk。

另外,如果你想在启动客户端的时候就把character_set_client、character_set_connection、character_set_results这三个系统变量的值设置成一样的,那我们可以在启动客户端的时候指定一个叫default-character-set的启动选项,比如在配置文件里可以这么写:
[client]
default-character-set=utf8

比较规则的应用:

比较规则的作用通常体现比较字符串大小的表达式以及对某个字符串列进行排序中,所以有时候也称为排序规则。
在一个表中插入几列不同的字符串,然后将其排序,如果字符集的比较规则不同,得到的排序结果也是不同的。因为对应的比较规则转码后换算出来的十进制数字不同,自然排序也不一样。
所以 如果以后大家在对字符串做比较或者对某个字符串列做排序操作时没有得到想象中的结果,需要思考一下是不是比较规则的问题~
注意:《修改对应列的字符集才有用哦!修改表的不行。》

总结

  1. 字符集指的是某个字符范围的编码规则。
  2. 比较规则是针对某个字符集中的字符比较大小的一种规则。
  3. 在MySQL中,一个字符集可以有若干种比较规则,其中有一个默认的比较规则,一个比较规则必须对应一个字符集。
  4. 查看MySQL中查看支持的字符集和比较规则的语句如下:
  5. SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式];
  6. SHOW COLLATION [LIKE 匹配的模式];
  7. MySQL有四个级别的字符集和比较规则
    • 服务器级别
    character_set_server表示服务器级别的字符集,collation_server表示服务器级别的比较规则。
    • 数据库级别
    创建和修改数据库时可以指定字符集和比较规则:
    CREATE DATABASE 数据库名
    [[DEFAULT] CHARACTER SET 字符集名称]
    [[DEFAULT] COLLATE 比较规则名称];

ALTER DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];
character_set_database表示当前数据库的字符集,collation_database表示当前默认数据库的比较规则,这两个系统变量是只读的,不能修改。如果没有指定当前默认数据库,则变量与相应的服务器级系统变量具有相同的值。
• 表级别
创建和修改表的时候指定表的字符集和比较规则:
CREATE TABLE 表名 (列的信息)
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]];

ALTER TABLE 表名
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称];
• 列级别
创建和修改列定义的时候可以指定该列的字符集和比较规则:
CREATE TABLE 表名(
列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],
其他列...
);

ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];
6. 从发送请求到接收结果过程中发生的字符集转换:
o 客户端使用操作系统的字符集编码请求字符串,向服务器发送的是经过编码的一个字节串。
o 服务器将客户端发送来的字节串采用character_set_client代表的字符集进行解码,将解码后的字符串再按照character_set_connection代表的字符集进行编码。
o 如果character_set_connection代表的字符集和具体操作的列使用的字符集一致,则直接进行相应操作,否则的话需要将请求中的字符串从character_set_connection代表的字符集转换为具体操作的列使用的字符集之后再进行操作。
o 将从某个列获取到的字节串从该列使用的字符集转换为character_set_results代表的字符集后发送到客户端。
o 客户端使用操作系统的字符集解析收到的结果集字节串。
在这个过程中各个系统变量的含义如下:
系统变量 描述
character_set_client 服务器解码请求时使用的字符集
character_set_connection 服务器处理请求时会把请求字符串从character_set_client转为character_set_connection
character_set_results 服务器向客户端返回数据时使用的字符集
一般情况下要使用保持这三个变量的值和客户端使用的字符集相同。
7. 比较规则的作用通常体现比较字符串大小的表达式以及对某个字符串列进行排序中。

客户端发送请求时采用的编码字符集和
服务器接受请求时解码字符集。区分开。

三、InnoDB记录存储结构
InnoDB页:
InnoDB从磁盘读取到内存的机制
InnoDB采取的方式是:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB。也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中。
InnoDB行格式(记录在磁盘上的存放方式):
设计InnoDB存储引擎的大叔们到现在为止设计了4种不同类型的行格式:分别是Compact、Redundant、Dynamic和Compressed行格式。
Ascii字符集
ascii字符集只包括空格、标点符号、数字、大小写字母和一些不可见字符,所以我们的汉字是不能存到这个表里的。
1、 COMPACT行格式:

  1. 记录的额外的信息
  2. 变长字段的长度列表(逆序存放)(有这种列的表才有这个信息)
  3. 真正的数据内容
  4. 变长字段占用的字节数
  5. NULL值列表
  6. 记录头信息
  7. 记录的真实数据
    2、
原文地址:https://www.cnblogs.com/zhongyt0927/p/13922345.html