MySQL是怎样运行的
MySQL是怎样运行的
1 初识MySQL
1.1MySQL的C/S架构
根据我以往的经验,MySQL会启动一个服务,我们可以通过“客户端”链接到服务,进行对数据库的操作。
所以,它的执行步骤通常是这样的:
- 启动MySQL服务器程序
- 启动MySQL客户端程序,连接到服务器程序
- 在客户端程序输入命令语句,并将其作为请求(Http请求???)发送给服务器程序。服务器程序在收到这些请求后,根据请求的内容来操作具体的数据,并将结果返回给客户端。
代表MySQL服务器程序的进程称为MySQL数据库实例
1.1.3 启动
初次启动需要安装,使用mysqld --initialize-insecure
,使用console
选项可以将安装结果打印在控制台上
如果需要安装服务,使用mysqld --install
即可
2 启动选项和系统变量
2.1 启动选项和配置文件
2.1.1 命令行启动选项
在命令行中指定启动选项的格式如下:
mysqld --skip-networking
其中要注意的是启动选项全称前要使用--
,单词连接可以使用-
或者_
,且单词和值之间不要有空格
2.1.2 配置文件中使用选项
mysql程序在启动时会在多个路径下寻找配置文件,不过我们一般只需要在basedir
,也就是mysql安装目录下防止一份名为my.ini
或者my.cnf
的配置文件即可
3 字符集和比较规则
3.1 字符集介绍
……
3.2 MySQL中支持的字符集和比较规则
3.2.1 utf8和utf8mb4
由于4字节字符实在不常用(emoji等),所以MySQL默认了两个容易混淆的概念:
- utf8mb3:精简的UTF-8字符集,只能表示1~3字节的字符,在MySQL中,utf-8==utf8mb3
- utf8mb4:完整的UTF-8字符集能表示1~4字节的字符
所以,如果要在MySQL(版本低于8.0)中存储emoji,要修改MySQL字符集;版本大于8.0后,已经对字符集进行了优化,可以utf-8得以真正地等于utf-8,并且作为数据库的默认字符集出现
3.2.2 查看字符集
通过在控制台输入show charset
即可查看当前支持的字符集,可以看到这些字符集都为小写形式出现,值得我们注意的就是最后一列的Maxlen,即最大字符长度
+----------+-----------------------------+---------------------+--------+
| 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 |
+----------+-----------------------------+---------------------+--------+
40 rows in set (0.00 sec)
3.2.3 查看比较规则
使用show collation
命令查看比较规则,但所有字符集的比较规则太多,我们只查看utf8的,show collation where charset like 'utf8';
,结果如下,期中Default为Yes的就是该字符集默认的比较规则
+--------------------------+---------+-----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+--------------------------+---------+-----+---------+----------+---------+
| utf8_general_ci | utf8 | 33 | Yes | Yes | 1 |
| utf8_bin | utf8 | 83 | | Yes | 1 |
| utf8_unicode_ci | utf8 | 192 | | Yes | 8 |
| utf8_icelandic_ci | utf8 | 193 | | Yes | 8 |
| utf8_latvian_ci | utf8 | 194 | | Yes | 8 |
| utf8_romanian_ci | utf8 | 195 | | Yes | 8 |
| utf8_slovenian_ci | utf8 | 196 | | Yes | 8 |
| utf8_polish_ci | utf8 | 197 | | Yes | 8 |
| utf8_estonian_ci | utf8 | 198 | | Yes | 8 |
| utf8_spanish_ci | utf8 | 199 | | Yes | 8 |
| utf8_swedish_ci | utf8 | 200 | | Yes | 8 |
| utf8_turkish_ci | utf8 | 201 | | Yes | 8 |
| utf8_czech_ci | utf8 | 202 | | Yes | 8 |
| utf8_danish_ci | utf8 | 203 | | Yes | 8 |
| utf8_lithuanian_ci | utf8 | 204 | | Yes | 8 |
| utf8_slovak_ci | utf8 | 205 | | Yes | 8 |
| utf8_spanish2_ci | utf8 | 206 | | Yes | 8 |
| utf8_roman_ci | utf8 | 207 | | Yes | 8 |
| utf8_persian_ci | utf8 | 208 | | Yes | 8 |
| utf8_esperanto_ci | utf8 | 209 | | Yes | 8 |
| utf8_hungarian_ci | utf8 | 210 | | Yes | 8 |
| utf8_sinhala_ci | utf8 | 211 | | Yes | 8 |
| utf8_german2_ci | utf8 | 212 | | Yes | 8 |
| utf8_croatian_ci | utf8 | 213 | | Yes | 8 |
| utf8_unicode_520_ci | utf8 | 214 | | Yes | 8 |
| utf8_vietnamese_ci | utf8 | 215 | | Yes | 8 |
| utf8_general_mysql500_ci | utf8 | 223 | | Yes | 1 |
+--------------------------+---------+-----+---------+----------+---------+
27 rows in set (0.00 sec)
这其中的规律是:
- “utf8”前缀:表示规则所属的字符集
- 紧跟前缀:表示规则所应用的语言
- “ci”后缀:表示是否区分语言中的重音、大小写等
后缀 | 全称 | 含义 |
---|---|---|
_ai |
accent insensitive | 不区分重音 |
_as |
accent sensitive | 区分重音 |
_ci |
case insensitive | 不区分大小写 |
_cs |
case sensitive | 区分大小写 |
_bin |
binary | 以二进制方式比较 |
示例: utf8_spanish_ci
表示以西班牙语比较,且不区分大小写
3.3 字符集和比较规则的应用
3.3.1 各级别的字符集和比较规则
MySQL存在4个级别的字符集和比较规则,分别是服务器级别、数据库级别、表级别、列级别
1 服务器级别
MySQL通过两个系统变量来管理服务器级别的字符集和比较规则,通过show variables like 'character_set_server\collation_server';
查看这两个变量
系统标量 | 描述 |
---|---|
character_set_server |
服务器级别的字符集 |
collation_server |
服务器级别的字符集比较规则 |
可以通过在ini配置文件中配置这两个变量来制定具体的字符集和规则,
2 数据库级别
在创建和修改数据库时就可以制定该数据库的字符集和比较规则:
create database demo01
character set gb2312
collate gb2312_chinese_ci;
在创建完数据并选择中数据库后,可以使用
show variables like 'character_set_database';
show variables like 'collation_data%';
来查看这两个变量,但是,我们只能通过这两个变量来查看数据库级别的字符集和比较规则,而不能通过这两个变量进行修改
3 表级别
指定方式相同:
create table t(
col varchar(10)
)
character set utf8
collate utf8_general_ci;
既然是表的属性,自然可以通过alter
关键字进行修改
alter table t
character set gbk
collate gbk_chinese_ci;
alter table t
character set utf8
collate utf8_general_ci;
4 列级别
制定方式:
create table t(
col varchar(10) character set utf8 collate utf8_general_ci
);
修改方式:
alter table t modify col varchar(10) character set gbk collate gbk_chinese_ci;
要注意的是,在修改字符集和比较规则的时候,如果两个字符集的字符不能相互表示就会引起错误,比如将ASCⅡ的转换成utf8
5 仅修改字符集或者比较规则
- 只修改字符集,比较规则会自动变成字符集默认的比较规则
- 只修改比较规则,字符集会变成与之对应的
了解字符集和比较规则后,我们就能够清楚地判断一条记录的实际大小了
3.3.2 客户端和服务器通信过程中使用的字符集
对于同一个字符,如果编码和解码使用的字符集不一样就会产生不必要的误解,因此我们需要一套字符集转换的系统:即按照utf8字符集对0xE68891进行解码,随后按照GBK字符集编码成0XCED2,这样就完成了汉字“我”跨字符集的转换。在MySQL中,这样的转换时常发生
客户端发送请求
MySQL客户端种类繁多,默认的客户端(bin下的mysql程序)使用的字符集和操作系统一致,要查看操作系统的字符集:
- UNIX:LC_ALL、LC_CTYPE、LANG这三个环境变量依次决定了系统的字符集
- Windows:通过使用命令
chcp
查看
在Windows下,通过在ini或者在启动命令中指定default-character-set
的值来修改客户端默认字符集
服务器接收请求
本质上说,服务器接收到的请求就是一个字节序列,而它认为这个字节序列的编码就是character_set_client
对应的值(每个客户端有单独的值),如果改变这个值,将会产生意料之中的错误:
set character_set_client=ascii;
mysql> select '发达';
+--------+
| ?????? |
+--------+
| ?????? |
+--------+
mysql> set character_set_client=utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> select '发达';
+--------+
| 发达 |
+--------+
| 发达 |
+--------+
服务器处理请求
服务器使用character_set_client
指定的字符集来解析字节序列,但真正处理它们还需要将解析后的字节序列转换成由character_set_connection
指定的编码后进行。为什么要多加转换的一步呢?
mysql> select 'a' = 'A';
+-----------+
| 'a' = 'A' |
+-----------+
| 1 |
+-----------+
1 row in set (0.00 sec)
在上面这个例子中,服务器在接收到请求后无法判断这两个字符所处的字符集和比较规则,此时character_set_connection
就发挥了作用,上述情况是字符集制定为utf8的情况,下面这种就不一样了:
mysql> set character_set_connection=gbk;
Query OK, 0 rows affected (0.00 sec)
mysql> set collation_connection=gbk_bin;
Query OK, 0 rows affected (0.00 sec)
mysql> select 'a' = 'A';
+-----------+
| 'a' = 'A' |
+-----------+
| 0 |
+-----------+
1 row in set (0.00 sec)
可以看到,再将连接字符集和比较规则改变后,比较结果就发生了变化。那么问题又来了,客户端不是有一套字符集和比较规则嘛,直接用客户端的不就行了!可有些时候,你会拿字符串和表中的数据进行比较,这时候就需要连接字符集来进行统一了:
mysql> create table tt( c varchar(100)) engine=innodb charset=utf8;
select * from tt where c = '我';
表格中的数据是utf8编码的,而客户端发送的请求字节序列确实按照character_set_client
指定的,若这个变量的值为gbk,那么这两个字符比较起来就麻烦了,因此,需要统一地将他们转换成优先级更高的字符(在这里就是表中的utf8)
服务器生成响应
在读取到数据结果后,服务器会根据character_set_results系统变量对应的字符编集进行转换后返回给客户端
客户端收到响应
客户端会使用客户端默认的字符集来解释这个由服务器返回的字节序列,以下的例子中将返回结果字符集设置成了gbk,而客户端字符集为utf8,于是就产生了乱码!所以,暂且来看,client和result要保持一致
mysql> set character_set_results=gbk;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from tt;
+------+
| c |
+------+
| ÎÒ |
+------+
1 row in set (0.00 sec)
另外,可以通过set names charset_name;
来一键配置这三个变量,还可以在ini文件中配置default-character-set
来配置这些变量