目录
往文件中存储数据是要指明编码格式的,这样未来读文件中的数据时才能根据相同的编码格式进行解码读取,才能在读数据时不会读出来一堆乱码。对于本段内容,更具体的说明如下:
问题:那什么是字符集和校验规则呢?为什么在已经有了字符集的存在的情况下,还要有校验规则的存在呢?答案如下:
对于以上内容,我们可以粗略理解成:字符集就是往数据库中存储数据前需要指定的编码格式,而校验规则就是从数据库中读取数据前需要指定的编码格式,这样一来,存数据的时候按照字符集将字符转码成二进制序列,取数据的时候按照校验规则将二进制数据转码成字符序列,所以编码集和校验规则必须匹配,不然读取数据时就会乱码。
查看MySQL数据库支持的字符集和校验规则
如下图所示,使用show charset语句即可查看数据库支持的字符集。下图中的Charset这一列就表示字符集;Description表示该字符集(本质就是一种编码格式)能将哪些国家的语言(即字符)和二进制序列互相转化;Default collation表示该字符集对应的默认校验规则,注意,我们在给MySQL设置字符集和校验规则时,是可以只指定字符集的,校验规则可以省略,这是因为给MySQL设置字符集后,MySQL会自动根据下图的这个表找到该字符集对应的Default collation默认校验规则,然后自动设置校验规则。当然我们也可以既指定字符集,又指定校验规则。
如下图所示,使用show collation即可查看数据库支持的校验规则。下图中的Collation这一列就表示校验规则;Charset表示该校验规则是匹配的哪个字符集;至于Default,在上文中说过一个字符集是可以匹配多个校验规则的,如下图红框处所示, 相同的字符集latin1可以匹配左侧蓝框处的多个校验规则就再次佐证了这一点,而黄框处的Yes则表示字符集latin1匹配的默认的校验规则是latin1_swedish_ci(如果忘了默认校验规则是什么意思,请回顾上一段的内容)。
说一下,通过下图这个表我们还可以得到一个结论A,即【一个校验规则只能唯一匹配一个字符集】,既然校验规则是一对一匹配的,所以我们又能再得到一个结论B,即【我们在给MySQL设置字符集和校验规则时,是可以只指定校验规则的,字符集可以省略,这是因为给MySQL设置校验规则后,MySQL会自动根据下图的这个表找到该校验规则唯一匹配的Charset字符集,然后自动设置字符集】。
最后结论A加上在上文中我们得到的结论【一个字符集可以匹配多个校验规则】,我们就得到了一个完整的结论:一个字符集可以匹配多个校验规则,但一个校验规则只能唯一匹配一个字符集。
查看系统默认字符集以及默认校验规则
如下图1所示,通过查看MySQL系统变量variables中的character_set_database,可以得知系统默认的字符集,说一下,如下图2所示,系统默认的字符集就是MySQL配置文件(即MySQL客户端进程mysql和MySQL服务端进程mysqld共同的配置文件my.cnf)中提前配置的字符集。
注意:?如果是use进入某个数据库DB后再使用show variables语句,则查看的是该数据库DB默认使用的字符集,而不是系统默认的字符集。
如下图1所示,通过查看MySQL系统变量variables中的collation_database,可以得知系统默认的校验规则。
说一下,有人此时可能会疑惑,说【在表示MySQL系统配置文件/etc/my.cnf的下图2中只配置了系统默认的字符集,并没有配置系统默认的校验规则,为什么查看MySQL系统变量variables中的collation_database可以得知系统默认的校验规则呢?】,这里笔者要说的是,在上文中说过,我们在给MySQL设置字符集和校验规则时,是可以只指定字符集的,校验规则可以省略,这是因为给MySQL设置字符集后,MySQL会自动根据下图3的这个表找到该字符集对应的Default collation默认校验规则,然后自动设置校验规则。
create database [if not exists] 数据库名称 [charset=字符集名称] [ collate=校验集名称];
该SQL语句就用于创建数据库,说明一下:
如果创建数据库时未指明数据库的编码格式或校验规则,则默认使用下图这个MySQL配置文件(即MySQL客户端进程mysql和MySQL服务端进程mysqld共同的配置文件my.cnf)中提前配置的字符集或校验规则。
说一下,在使用create语句创建一个数据库后(本质是在Linux的var/lib/mysql路径上创建一个目录文件),在该数据库(或者说目录中)中会自动创建一个db.opt文件,在这个文件中就记录了当前数据库的默认字符集和默认校验规则(如何证明呢?在上文我们说过如果use进入某个数据库DB后再使用show variables语句,则查看的是该数据库DB默认使用的字符集,而不是系统默认的字符集。然后如下图蓝框处所示,在使用create语句创建数据库helloworld和hiworld时分别指定数据库的字符集是big5和gbk后,使用use进入对应数据库再使用show variables语句查看数据库DB默认使用的字符集,能够发现的确是big5和gbk,这就证明了数据库helloworld的默认字符集是big5,数据库hiworld的默认字符集是gbk,然后如下图黄框处所示,分别cat打印两个数据库中的db.opt文件,能够发现其记录的字符集的确是自己所在的数据库的默认字符集,这就证明了在db.opt文件中记录了当前数据库的默认字符集和默认校验规则),往后在当前数据库中建表时如果在建表的SQL语句中不指定字符集和校验规则,则就会默认使用db.opt文件中的字符集和校验规则(即使用当前数据库DB的默认字符集和默认校验规则)。
将上一段的内容和上上段的内容结合,我们就能得到一个完整的结论:对MySQL客户端进程mysql和MySQL服务端进程mysqld共同的配置文件my.cnf中的默认字符集和默认校验规则进行设置后(或者说对MySQL系统中的字符集和校验规则进行设置后),如果创建数据库时在SQL语句中不指定字符集和校验规则,则该数据库就会默认使用MySQL系统配置文件my.cnf中的字符集和校验规则(即会让db.opt文件中的字符集和校验规则等于MySQL系统配置文件my.cnf中的字符集和校验规则);对某个数据库DB的配置文件db.opt中的默认字符集和默认校验规则进行设置后,如果在该数据库DB中创建表时在SQL语句中不指定字符集和校验规则,则该表就会默认使用当前数据库DB的配置文件db.opt中的字符集和校验规则。
额外说一下,因为在<<MySQL数据库的基础概念>>一文中我们说过,本质上MySQL中的一个数据库DB就是Linux系统下/var/lib/mysql路径上的一个目录文件,?所以在MySQL中所谓的创建数据库就是在Linux系统下创建了一个目录文件,所以SQL语句create database就等同于Linux命令mkdir(注意也不是完全等同,因为如果在数据库存储所有数据的路径/var/lib/mysql上手动mkdir创建一个目录也就是数据库时,在该数据库中不会有db.opt文件)。
举个例子说明校验规则对数据库的影响,如下。
情况一:当操作数据库时采用utf8_general_ci校验规则时情况如下。
如下图所示,当在创建数据库时指定数据库的校验规则为utf8_general_ci时,数据库的编码格式默认匹配为utf8。
如下图所示,在该数据库中创建一个简单的person表,由于创建表时在SQL语句中未指定表的字符集和校验规则,因此person表将继承当前数据库的字符集和校验规则(即继承当前数据库中的配置文件db.opt中的字符集和校验规则)。
这时向表中插入一些数据。如下:?
通过select语句可以查看插入表中的数据。如下:
如下图1所示,这时指定查看表中name = 'a'的记录时会将A和a一并筛选出来,其根本原因就是校验规则utf8_general_ci在进行数据比对时是不区分大小写的;如下图2所示,这时将表中的所有数据进行排序时(默认从上到下是升序,同时因为A的阿斯克码小于a,同时也小于B,所以正常排是A<B<a<b,即A在最上面,然后是B,然后是a,b在最下面)a能排在B的上面和a能排在A的上面,其根本原因也是校验规则utf8_general_ci在进行数据比对时是不区分大小写的。
情况二:当操作数据库时采用utf8_bin校验规则时情况如下。
如下图所示,当在创建数据库时指定数据库的校验规则为utf8_bin时,数据库的编码格式默认匹配也为utf8。?
如下图所示,在该数据库中同样创建一个简单的person表,由于创建表时在SQL语句中未指定表的字符集和校验规则,因此person表将继承当前数据库的字符集和校验规则(即继承当前数据库中的配置文件db.opt中的字符集和校验规则)。
这时向表中插入刚才相同的数据。如下:
通过select语句可以看到表中的数据与之前相同。如下:?
如下图1所示,但这时指定查看表中name = 'a'的记录时只会将a筛选出来而不会将A筛选出来,其根本原因就是utf8_bin校验规则在进行数据比对时是区分大小写的;如下图2所示,这时将表中的所有数据进行排序时(默认从上到下是升序,同时因为A的阿斯克码小于a,同时也小于B,所以正常排是A<B<a<b,即A在最上面,然后是B,然后是a,b在最下面)能正常排序,其根本原因也是utf8_bin校验规则在进行数据比对时是区分大小写的。
?对以上内容的总结:
综合上文可以发现,以上两种情况中所有的因素都相等,唯一的区别就是情况1采用utf8_general_ci校验规则,情况2采用utf8_bin校验规则,但最后在查询或者排序时呈现的结果却截然不同,这就是校验规则对数据库的影响的一角。
如下图所示,使用SQL语句show database即可查看系统中所有的数据库。
额外说一下,因为在<<MySQL数据库的基础概念>>一文中我们说过,本质上MySQL中的一个数据库DB就是Linux系统下的一个目录文件,并且MySQL中所有的数据都存储在路径/var/lib/mysql上(即所有的数据库DB都存储在该路径上),所以在MySQL中所谓的查看系统中的所有数据库就是在Linux系统下调用了一下ls?/var/lib/mysql -l命令,所以SQL语句show database就等同于Linux命令ls?/var/lib/mysql -l(但不完全等同,因为Linux命令ls?/var/lib/mysql -l会把该路径上的非目录普通文件也显示出来,但show databases只显示/var/lib/mysql路径上的数据库也就是目录文件,不显示表也就是非目录普通文件)。
如下图所示,使用SQL语句【 show create database 数据库名称?】即可查看对应数据库的创建语句。说一下,该条语句并不是用于创建新的数据库的,而是用于查看一个已经存在的数据库的创建语句、用于查看曾经在创建该数据库时写的SQL语句是怎样的。
注意事项:
alter database 数据库名称 [charset=字符集名称] [collate=校验规则名称];
该SQL语句就用于修改数据库,说明一下:
说一下,MySQL是不支持修改某个数据库DB的名称的,但在<<MySQL数据库的基础概念>>一文中我们说过,本质上MySQL中的一个数据库DB就是Linux系统下/var/lib/mysql路径上的一个目录文件,所以如果我们非要改某个数据库DB的名称,先cd?/var/lib/mysql进入该数据库所在的路径,然后通过Linux命令【mv 名称1 名称2】?即可修改名称了,但注意,我们不要这么做,因为如果强制改名后,后序使用MySQL时一定会出现某种未知的错误。
drop database?[if?exists] 数据库名称;
该SQL语句就用于删除数据库,说明一下:
在<<MySQL数据库的基础概念>>一文中我们说过,本质上MySQL中的一个数据库DB就是Linux系统下/var/lib/mysql路径上的一个目录文件,所以如果想备份某个数据库DB,最简单的方式就是先cd?/var/lib/mysql进入该数据库所在的路径,然后通过Linux命令【cp -r 数据库名称 指定路径】即可成功将某个数据库DB拷贝到指定路径上。说一下,如果MySQL客户端和服务端卡住了,但MySQL用于存储所有数据的路径/var/lib/mysql上的数据又很重要,此时如果实在没有办法,可以直接【cp -r /var/lib/mysql 指定路径】将该目录中的所有文件全拷贝到指定路径上。但注意,本段这样的方法虽然可行,但它是违规的,我们平时不要这么做。
数据库的备份
在备份数据库前,我们首先要确保MySQL服务端进程mysqld是启动的,否则无法备份,这是因为接下来要讲解的用于备份数据库和表的Linux命令mysqldump本质也是一个客户端(这也是为什么使用mysqldump时需要在命令行中输入目的端口号),mysqldump之所以能够备份数据库和表,也是因为mysqldump作为客户端向MySQL服务端进程mysqld发起了请求,然后mysqld为mysqldump提供了服务。
在备份数据库前,我们还要确保自己具有备份该数据库的权限,比如张三一般只能备份属于张三的数据库,不能备份属于李四的数据库,但如果是root用户,则都可以进行备份。
mysqldump -P 端口号 -u 用户名 -p 密码 -B 数据库名1 数据库名2 ... > 数据库备份存储的文件路径
使用上面的Linux命令即可对指定数据库进行备份。为了演示数据库备份,下面我们创建一个数据库,并在该数据库中创建两个表。如下:
在student和teacher表中分别插入两条记录。如下:?
如下图所示,这时在命令行中执行如下命令即可将该数据库进行备份,并指定将备份后产生的文件存放在当前目录下(即用户在哪个路径下调用mysqldump命令,该备份文件就会被放在哪个路径下)。
说一下,下图中的Enter passworld后面是要输入登录MySQL客户端进程mysql以连接MySQL服务端进程mysqld的密码,由于我们在MySQL系统配置文件/etc/my.cnf中配置过可以免密码登录,所以这里直接按回车跳过登录密码的步骤即可。
如下图所示,vim打开base.sql文件即可看到,文件中的内容实际就是我们在该数据库中执行的各种SQL命令,包括创建数据库、创建表、插入数据等SQL语句。
数据库的恢复?
source 数据库备份存储的文件路径
使用上面的Linux命令即可对指定数据库进行备份。为了演示数据库恢复,我们先将刚才创建的数据库删除。如下:
这时让MySQL服务器执行如下命令即可对数据库进行恢复。如下:
实际恢复数据库的时候就是按顺序执行数据库备份文件中的SQL语句,如下图所示,执行完毕后数据库也就恢复出来了,同时该数据库下的两张表,以及表当中的数据也都恢复出来了。
表的备份
mysqldump -P 端口号 -u 用户名 -p 密码 数据库名 表名1 表名2 ... > 表备份存储的文件路径
使用上面的Linux命令即可对指定数据库进行备份。如下图1所示,如果在数据库test1中除了student和teacher表之外,还有其他的表,但我们又只想备份数据库test1中的student表和teacher表,这时就可以如下图2所示,在命令行中执行如下命令,并指定将备份后产生的文件存放在当前目录下(即用户在哪个路径下调用mysqldump命令,该备份文件就会被放在哪个路径下)。
如下图所示,这时历史上与student和teacher表相关的SQL语句,就会被保存到备份文件当中。
表的恢复?
表恢复之前需要先选中一个数据库,表明需要将表恢复到哪一个数据库中,为了防止恢复出来的表与该数据库中已有的表的表名重复,一般在恢复表时会选择创建一个空的数据库,然后在该数据库中进行表的恢复。
在数据库中使用如下命令即可对指定表进行恢复:
source 表备份存储的文件路径
为了演示表恢复,我们先将刚才的数据库删除。如下:
如下图所示,这时创建一个空的数据库并在该数据库中执行如下命令即可对表进行恢复。
如下图所示,当备份文件中的SQL语句执行完毕后,该数据库下就恢复出了student和teacher表,并且表当中的数据也都恢复出来了。
如下图所示,使用SQL语句show processlist即可查看当前连接MySQL的用户,说明一下:
SQL语句show processlist可以告诉我们当前有哪些用户连接到我们的MySQL,如果查出某个用户不是正常登录的,那么很有可能你的数据库被人入侵了,以后如果发现自己的数据库比较慢时,可以用这个SQL语句来查看数据库的连接情况。