一、安装前的说明
1.1 Linux系统及工具的准备
- 安装并启动好两台虚拟机: CentOS 7
- 掌握克隆虚拟机的操作
- mac地址
- 主机名
- ip地址
- UUID
- 掌握克隆虚拟机的操作
- 安装有 Xshell 和 Xftp 等访问CentOS系统的工具
- CentOS6和CentOS7在MySQL的使用中的区别
- 防火墙:6是iptables,7是firewall
- 启动服务的命令:6是service,7是systemctl
1.2 查看是否安装过MySQL
- 如果你是用rpm安装, 检查一下RPM PACKAGE:
rpm -qa | grep -i mysql # -i 忽略大小写
- 检查mysql service:
systemctl status mysqld.service
- 如果存在mysql-libs的旧版本包,显示如下:
- 如果不存在mysql-lib的版本,显示如下:
1.3 MySQL的卸载
- 关闭 mysql 服务
systemctl stop mysqld.service
- 查看当前 mysql 安装状况
rpm -qa | grep -i mysql
# 或
yum list installed | grep mysql
- 卸载上述命令查询出的已安装程序
yum remove mysql-xxx mysql-xxx mysql-xxx mysqk-xxxx
务必卸载干净,反复执pm -qa | grep -i mysql
确认是否有卸载残留
4. 删除 mysql 相关文件
- 查找相关文件
find / -name mysql
- 删除上述命令查找出的相关文件
rm -rf xxx
- 删除 my.cnf
rm -rf /etc/my.cnf
二、MySQL的Linux版安装
2.1 MySQL的4大版本
- MySQL Community Server 社区版本,开源免费,自由下载,但不提供官方技术支持,适用于 大多数普通用户。
- MySQL Enterprise Edition 企业版本,需付费,不能在线下载,可以试用30天。提供了更多的 功能和更完备的技术支持,更适合于对数据库的功能和可靠性要求较高的企业客户。
- MySQL Cluster 集群版,开源免费。用于架设集群服务器,可将几个MySQL Server封装成一个 Server。需要在社区版或企业版的基础上使用。
- MySQL Cluster CGE 高级集群版,需付费。
- 截止目前,官方最新版本为 8.0.37 。此前,8.0.0 在 2016.9.12日就发布了。
- 本课程中主要使用 8.0.25版本 。同时为了更好的说明MySQL8.0新特性,还会安装 本,作为对比。
此外,官方还提供了 MySQL5.7 版MySQL Workbench (GUITOOL)
一款专为MySQL设计的ER/数据库建模工具
。它是著名的数据库设计工具DBDesigner4的继任者。MySQLWorkbench又分为两个版本,分别是社区版 (MySQL Workbench OSS)
、商用版(MySQL WorkbenchSE)
。
下载MySQL指定版本
- 下载地址 官网
- 打开官网,点击
DOWNLOAD
然后,点击MySQL Community(GPL) Downloads
- 点击
MySQL Community Server
- 在
General Availability(GA) Releases
中选择适合的版本
- 如果安装Windows 系统下MySQL ,推荐下载
MSI安装程序
;点击Go to Download Page
即可 - Windows下的MySQL安装有两种安装程序
mysql-installer-web-community-8.0.25.0.msi
下载程序大小:2.4M;安装时需要联网安装组件。mysql-installer-community-8.0.25.0.msi
下载程序大小:435.7M;安装时离线安装即可。推荐。
- Linux系统下安装MySQL的几种方式
- Linux系统下安装软件的常用三种方式
- 方式1:rpm命令
使用rpm命令安装扩展名为".rpm"的软件包。 .rpm包的一般格式:
- 方式2:yum命令
需联网,从 互联网获取的yum源,直接使用yum命令安装。 - 方式3:编译安装源码包
针对t ar.gz 这样的压缩格式,要用tar命令来解压;如果是其它压缩格式,就使用其它命令。
- 方式1:rpm命令
- Linux系统下安装MySQL,官方给出多种安装方式
- Linux系统下安装软件的常用三种方式
安装方式 | 特点 |
---|---|
rpm | 安装简单,灵活性差,无法灵活选择版本、升级 |
rpm repository | 安装包极小,版本安装简单灵活,升级方便,需要联网安装 |
通用二进制包 | 安装比较复杂,灵活性高,平台通用性好 |
源码包 | 安装最复杂,时间长,参数设置灵活,性能好 |
- 这里不能直接选择CentOS 7系统的版本,所以选择与之对应的
Red Hat Enterprise Linux
- https://downloads.mysql.com/archives/community/ 直接点Download下载RPM Bundle全量包。包括了所有下面的组件。不需要一个一个下载了。
- 下载的tar包,用压缩工具打开
- 解压后rpm安装包 (红框为抽取出来的安装包)
- 解压后rpm安装包 (红框为抽取出来的安装包)
2.3 CentOS7下检查MySQL依赖
- 检查/tmp临时目录权限(必不可少)
由于mysql安装过程中,会通过mysql用户在/tmp目录下新建tmp_db文件,所以请给/tmp较大的权限。执行 :
chmod -R 777 /tmp
- 安装前,检查依赖
rpm -qa|grep libaio
- 如果存在libaio包如下:
rpm -qa|grep net-tools
- 如果存在net-tools包如下:
rpm -qa|grep net-tools
- 如果不存在需要到centos安装盘里进行rpm安装。安装linux如果带图形化界面,这些都是安装好的。
2.4 CentOS7下MySQL安装过程
1. 将安装程序拷贝到/opt目录下
在mysql的安装文件目录下执行:(必须按照顺序执行)
rpm -ivh mysql-community-common-8.0.25-1.el7.x86_64.rpm
rpm -ivh mysql-community-client-plugins-8.0.25-1.el7.x86_64.rpm
rpm -ivh mysql-community-libs-8.0.25-1.el7.x86_64.rpm
rpm -ivh mysql-community-client-8.0.25-1.el7.x86_64.rpm
rpm -ivh mysql-community-server-8.0.25-1.el7.x86_64.rpm
- 注意: 如在检查工作时,没有检查mysql依赖环境在安装mysql-community-server会报错
- rpm 是Redhat Package Manage缩写,通过RPM的管理,用户可以把源代码包装成以rpm为扩展名的 文件形式,易于安装。
-i
, --install 安装软件包-v
, --verbose 提供更多的详细信息输出-h
, --hash 软件包安装的时候列出哈希标记 (和 -v 一起使用效果更好),展示进度条
2. 安装过程截图
安装过程中可能的报错信息:
一个命令:yum remove mysql-libs 解决,清除之前安装过的依赖即可
3.查看MySQL版本
执行如下命令,如果成功表示安装mysql成功。类似java -version如果打出版本等信息
mysql --version
#或
mysqladmin --version
执行如下命令,查看是否安装成功。需要增加 -i 不用去区分大小写,否则搜索不到。
rpm -qa|grep -i mysql
4.服务的初始化
为了保证数据库目录与文件的所有者为 mysql 登录用户,如果你是以 root 身份运行 mysql 服务,需要执行下面的命令初始化:
mysqld --initialize --user=mysql
说明: --initialize
选项默认以“安全”模式来初始化,则会为 root 用户生成一个密码并将过期,登录后你需要设置一个新的密码。生成的·会往日志中记录一份。
查看密码:
cat /var/log/mysqld.log
root@localhost: 后面就是初始化的密码
5. 启动MySQL,查看状态
#加不加.service后缀都可以
启动:systemctl start mysqld.service
关闭:systemctl stop mysqld.service
重启:systemctl restart mysqld.service
查看状态:systemctl status mysqld.service
mysqld
这个可执行文件就代表着 MySQL 服务器程序,运行这个可执行文件就可以直接启动一个服务器进程。
查看进程:
ps -ef | grep -i mysql
6.查看MySQL服务是否自启动
systemctl list-unit-files|grep mysqld.service
默认是enabled。
- 如不是enabled可以运行如下命令设置自启动
systemctl enable mysqld.service
- 如果希望不进行自启动,运行如下命令设置
systemctl disable mysqld.service
三、MySQL登录
3.1 首次登录
通过mysql -hlocalhost -P3306 -uroot -p
进行登录,在Enter password:录入初始化密码
3.2 修改密码
- 因为初始化密码默认是过期的,所以查看数据库会报错 修改密码:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';
-
5.7版本之后(不含5.7),mysql加入了全新的密码安全机制。设置新密码太简单会报错。
-
改为更复杂的密码规则之后,设置成功,可以正常使用数据库了
3.3 设置远程登录
-
当前问题
在用SQLyog或Navicat中配置远程连接Mysql数据库时遇到如下报错信息,这是由于Mysql配置了不支持远 程连接引起的。
-
确认网络
1.在远程机器上使用ping ip地址保证网络畅通
2.在远程机器上使用telnet命令保证端口号开放
访问
telnet ip地址 端口号
拓展: telnet命令开启 :
3. 关闭防火墙或开放端口
方式一:关闭防火墙
CentOS6 :
service iptables stop
CentOS7:
systemctl start firewalld.service
systemctl status firewalld.service
systemctl stop firewalld.service
#设置开机启用防火墙
systemctl enable firewalld.service
#设置开机禁用防火墙
systemctl disable firewalld.service
方式二:开放端口
- 查看开放的端口号
firewall-cmd --list-all
- 设置开放的端口号
firewall-cmd --add-service=http --permanent firewall-cmd --add-port=3306/tcp --permanent
- 重启防火墙
firewall-cmd --reload
- Linux下修改配置
在Linux系统MySQL下测试:
use mysql;
select Host,User from user;
可以看到root用户的当前主机配置信息为localhost。
- 修改Host为通配符%
Host列指定了允许用户登录所使用的IP,比如user=root Host=192.168.1.1。这里的意思就是说root用户只 能通过192.168.1.1的客户端去访问。 user=root Host=localhost,表示只能通过本机客户端去访问。而% 是个通配符
,如果Host=192.168.1.%,那么就表示只要是IP地址前缀为“192.168.1.”的客户端都可以连接。如果 Host=% ,表示所有IP都有连接权限。
注意:在生产环境下不能为了省事将host设置为%,这样做会存在安全问题,具体的设置可以根据生产 环境的IP进行设置。
update user set host = '%' where user ='root';
Host设置了“%”后便可以允许远程访问。
Host修改完成后记得执行flush privileges使配置立即生效:
flush privileges;
- 测试
- 如果是 MySQL5.7 版本,接下来就可以使用SQLyog或者Navicat成功连接至MySQL了。
- 如果是 MySQL8 版本,连接时还会出现如下问题:
配置新连接报错:错误号码 2058,分析是 mysql 密码加密方法变了。
解决方法:Linux下mysql -u root -p
登录你的 mysql 数据库,然后执行这条SQL:
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'abc123';
然后在重新配置SQLyog的连接,则可连接成功了,OK。
四、字符集的相关操作
4.1 修改MySQL5.7字符集
1. 修改步骤
在MySQL 8.0版本之前,默认字符集为latin1
,utf8字符集指向的是utf8mb3
。网站开发人员在数据库设计的时候往往会将编码修改为utf8
字符集。如果遗忘修改默认的编码,就会出现乱码的问题。从MySQL8.0开始,数据库的默认编码将改为utf8mb4
,从而避免上述乱码的问题。
操作1:查看默认使用的字符集
show variables like 'character%';
# 或者
show variables like '%char%';
- MySQL8.0中执行:
- MySQL5.7中执行:
MySQL 5.7 默认的客户端和服务器都用了latin1 ,不支持中文,保存中文会报错。MySQL5.7截图如下:
在MySQL5.7中添加中文数据时,报错:
因为默认情况下,创建表使用的是latin1
。如下:
操作2:修改字符集
vim /etc/my.cnf
在MySQL5.7或之前的版本中,在文件最后加上中文字符集配置:
character_set_server=utf8
操作3:重新启动MySQL服务
systemctl restart mysqld
但是原库、原表的设定不会发生变化,参数修改只对新建的数据库生效。
2. 已有库&表字符集的变更
MySQL5.7版本中,以前创建的库,创建的表字符集还是latin1
。
修改已创建数据库的字符集
alter database dbtest1 character set 'utf8';
修改已创建数据表的字符集
alter table t_emp convert to character set 'utf8';
注意:但是原有的数据如果是用非'utf8'编码的话,数据本身编码不会发生改变。已有数据需要导出或删除,然后重新插入。
4.2 各级别的字符集
MySQL有4个级别的字符集和比较规则,分别是:
- 服务器级别
- 数据库级别
- 表级别
- 列级别
执行如下SQL语句:
show variables like 'character%';
- character_set_server:服务器级别的字符集
- character_set_database:当前数据库的字符集
- character_set_client:服务器解码请求时使用的字符集
- character_set_connection:服务器处理请求时会把请求字符串从character_set_client转为
- character_set_connection
- character_set_results:服务器向客户端返回数据时使用的字符集
1. 服务器级别
character_set_server
:服务器级别的字符集。
我们可以在启动服务器程序时通过启动选项或者在服务器程序运行过程中使用SET
语句修改这两个变量的值。比如我们可以在配置文件中这样写:
CREATE DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];
ALTER DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];
当服务器启动的时候读取这个配置文件后这两个系统变量的值便修改了。
2. 数据库级别
character_set_database
:当前数据库的字符集
我们在创建和修改数据库的时候可以指定该数据库的字符集和比较规则,具体语法如下:
CREATE DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];
ALTER DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];
3. 表级别
我们也可以在创建和修改表的时候指定表的字符集和比较规则,语法如下:
CREATE TABLE 表名 (列的信息)
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]]
ALTER TABLE 表名
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]
- 如果创建和修改表的语句中没有指明字符集和比较规则,将使用该表所在数据库的字符集和比较规则作为该表的字符集和比较规则。
4. 列级别
对于存储字符串的列,同一个表中的不同的列也可以有不同的字符集和比较规则。我们在创建和修改列定义的时候可以指定该列的字符集和比较规则,语法如下:
CREATE TABLE 表名(
列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],
其他列...
);
ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];
对于某个列来说,如果在创建和修改的语句中没有指明字符集和比较规则,将使用该列所在表的字符集和比较规则作为该列的字符集和比较规则。
提示:
在转换列的字符集时需要注意,如果转换前列中存储的数据不能用转换后的字符集进行表示会发生错误。比方说原先列使用的字符集是utf8,列中存储了一些汉字,现在把列的字符集转换为ascii的话就会出错,因为ascii字符集并不能表示汉字字符。
5. 小结
我们介绍的这4个级别字符集和比较规则的联系如下:
- 如果
创建或修改列
时没有显式的指定字符集和比较规则,则该列默认用表的字符集和比较规则 - 如果
创建表
时没有显式的指定字符集和比较规则,则该表默认用数据库的字符集和比较规则 - 如果
创建数据库
时没有显式的指定字符集和比较规则,则该数据库默认用服务器的字符集和比较规则
知道了这些规则之后,对于给定的表,我们应该知道它的各个列的字符集和比较规则是什么,从而根据这个列的类型来确定存储数据时每个列的实际数据占用的存储空间大小了。比方说我们向表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个字节
4.3 字符集与比较规则(了解)
1.utf8 与 utf8mb4
utf8
字符集表示一个字符需要使用1~4个字节,但是我们常用的一些字符使用1~3个字节就可以表示
了。而字符集表示一个字符所用的最大字节长度,在某些方面会影响系统的存储和性能,所以设计
MySQL的设计者偷偷的定义了两个概念:
utf8mb3
:阉割过的utf8 字符集,只使用1~3个字节表示字符。utf8mb4
:正宗的utf8 字符集,使用1~4个字节表示字符。
2.比较规则
上表中,MySQL版本一共支持41种字符集,其中的Default collation
列表示这种字符集中一种默认
的比较规则,里面包含着该比较规则主要作用于哪种语言,比如utf8_polish_ci
表示以波兰语的规则
比较,utf8_spanish_ci
是以西班牙语的规则比较, utf8_general_ci
是一种通用的比较规则。
后缀表示该比较规则是否区分语言中的重音、大小写。具体如下:
最后一列Maxlen
,它代表该种字符集表示一个字符最多需要几个字节。
常用操作1:
#查看GBK字符集的比较规则
SHOW COLLATION LIKE 'gbk%';
#查看UTF-8字符集的比较规则
SHOW COLLATION LIKE 'utf8%';
常用操作2:
#查看服务器的字符集和比较规则
SHOW VARIABLES LIKE '%_server';
#查看数据库的字符集和比较规则
SHOW VARIABLES LIKE '%_database';
#查看具体数据库的字符集
SHOW CREATE DATABASE dbtest1;
#修改具体数据库的字符集
ALTER DATABASE dbtest1 DEFAULT CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
常用操作3:
#查看表的字符集
show create table employees;
#查看表的比较规则
show table status from atguigudb like 'employees';
#修改表的字符集和比较规则
ALTER TABLE emp1 DEFAULT CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
4.4 请求到响应过程中字符集的变化
这几个系统变量在我的计算机上的默认值如下(不同操作系统的默认值可能不同):
为了体现出字符集在请求处理过程中的变化,我们这里特意修改一个系统变量的值:
mysql> set character_set_connection = gbk;
Query OK, 0 rows affected (0.00 sec)
现在假设我们客户端发送的请求是下边这个字符串:
SELECT * FROM t WHERE s = '我';
为了方便大家理解这个过程,我们只分析字符'我' 在这个过程中字符集的转换。
现在看一下在请求从发送到结果返回过程中字符集的变化:
- 客户端发送请求所使用的字符集
一般情况下客户端所使用的字符集和当前操作系统一致,不同操作系统使用的字符集可能不一样,如下:- 类Unix 系统使用的是utf8
- Windows 使用的是gbk
当客户端使用的是utf8
字符集,字符'我'
在发送给服务器的请求中的字节形式就是:0xE68891
提示
如果你使用的是可视化工具,比如navicat之类的,这些工具可能会使用自定义的字符集来编码发送到服务器的字符串,而不采用操作系统默认的字符集(所以在学习的时候还是尽量用命令行窗口)。
- 服务器接收到客户端发送来的请求其实是一串二进制的字节,它会认为这串字节采用的字符集是character_set_client ,然后把这串字节转换为character_set_connection 字符集编码的字符。
由于我的计算机上character_set_client 的值是utf8 ,首先会按照utf8 字符集对字节串0xE68891 进行解码,得到的字符串就是'我' ,然后按照character_set_connection 代表的字符集,也就是gbk 进行编码,得到的结果就是字节串0xCED2 。 - 因为表t 的列col 采用的是gbk 字符集,与character_set_connection 一致,所以直接到列中找字节值为0xCED2 的记录,最后找到了一条记录。
提示
如果某个列使用的字符集和character_set_connection代表的字符集不一致的话,还需要进行一次字符集转换。
- 上一步骤找到的记录中的col 列其实是一个字节串0xCED2 , col 列是采用gbk 进行编码的,所以首先会将这个字节串使用gbk 进行解码,得到字符串'我' ,然后再把这个字符串使用character_set_results 代表的字符集,也就是utf8 进行编码,得到了新的字节串:0xE68891 ,然后发送给客户端。
- 由于客户端是用的字符集是utf8 ,所以可以顺利的将0xE68891 解释成字符我,从而显示到我们的显示器上,所以我们人类也读懂了返回的结果。
总结图示如下:
五、 SQL大小写规范
5.1 Windows和Linux平台区别
在 SQL 中,关键字和函数名是不用区分字母大小写的,比如 SELECT、WHERE、ORDER、GROUP BY 等关键字,以及 ABS、MOD、ROUND、MAX 等函数名。
不过在 SQL 中,你还是要确定大小写的规范,因为在 Linux 和 Windows 环境下,你可能会遇到不同的大
小写问题。windows系统默认大小写不敏感
,但是linux系统是大小写敏感的
。
通过如下命令查看:
SHOW VARIABLES LIKE '%lower_case_table_names%'
- Windows系统下:
- Linux系统下:
- lower_case_table_names参数值的设置:
- 默认为0,大小写敏感。
- 设置1,大小写不敏感。创建的表,数据库都是以小写形式存放在磁盘上,对于sql语句都是转换为小写对表和数据库进行查找。
- 设置2,创建的表和数据库依据语句上格式存放,凡是查找都是转换为小写进行。
- 两个平台上SQL大小写的区别具体来说:
MySQL在Linux下数据库名、表名、列名、别名大小写规则是这样的:
1、数据库名、表名、表的别名、变量名是严格区分大小写的;
2、关键字、函数名称在 SQL 中不区分大小写;
3、列名(或字段名)与列的别名(或字段别名)在所有的情况下均是忽略大小写的;
MySQL在Windows的环境下全部不区分大小写
5.2 Linux下大小写规则设置
当想设置为大小写不敏感时,要在my.cnf
这个配置文件 [mysqld]
中加入
lower_case_table_names=1
,然后重启服务器。
- 但是要在重启数据库实例之前就需要将原来的数据库和表转换为小写,否则将找不到数据库名。
- 此参数适用于MySQL5.7。在MySQL 8下禁止在重新启动 MySQL 服务时将lower_case_table_names 设置成不同于初始化 MySQL 服务时设置的lower_case_table_names 值。如果非要将MySQL8设置为大小写不敏感,具体步骤为:
1、停止MySQL服务
2、删除数据目录,即删除 /var/lib/mysql 目录
3、在MySQL配置文件( /etc/my.cnf )中添加 lower_case_table_names=1
4、启动MySQL服务
5.3 SQL编写建议
如果你的变量名命名规范没有统一,就可能产生错误。这里有一个有关命名规范的建议:
关键字
和函数名
称全部大写;- 数据库名、表名、表别名、字段名、字段别名等全部小写;
- SQL 语句必须以分号结尾。
数据库名、表名和字段名在 Linux MySQL 环境下是区分大小写的,因此建议你统一这些字段的命名规则,比如全部采用小写的方式。
虽然关键字和函数名称在 SQL 中不区分大小写,也就是如果小写的话同样可以执行。但是同时将关键词和函数名称全部大写,以便于区分数据库名、表名、字段名。
六、sql_mode的合理设置
6.1 宽松模式 vs 严格模式
宽松模式:
如果设置的是宽松模式,那么我们在插入数据的时候,即便是给了一个错误的数据,也可能会被接受,并且不报错。
举例
:我在创建一个表时,该表中有一个字段为name,给name设置的字段类型时char(10)
,如果我在插入数据的时候,其中name这个字段对应的有一条数据的长度超过了10 ,例如'1234567890abc',超过了设定的字段长度10
,那么不会报错
,并且取前10个字符存上,也就是说你这个数据被存为了'1234567890',而'abc'就没有了。但是,我们给的这条数据是错误的,因为超过了字段长度,但是并没有报错,并且mysql自行处理并接受了,这就是宽松模式
的效果。
应用场景
:通过设置sql mode为宽松模式,来保证大多数sql符合标准的sql语法,这样应用在不同数据库之间进行迁移
时,则不需要对业务sql 进行较大的修改。
严格模式:
出现上面宽松模式的错误,应该报错才对,所以MySQL5.7版本就将sql_mode默认值改为了严格模式。所以在生产等环境
中,我们必须采用的是严格模式,进而开发、测试环境
的数据库也必须要设置,这样在开发测试阶段就可以发现问题。并且我们即便是用的MySQL5.6,也应该自行将其改为严格模式。
开发经验
:MySQL等数据库总想把关于数据的所有操作都自己包揽下来,包括数据的校验,其实开发中,我们应该在自己开发的项目程序级别将这些校验给做了
,虽然写项目的时候麻烦了一些步骤,但是这若设置模式中包含了NO_ZERO_DATE
,那么MySQL数据库不允许插入零日期,插入零日期会抛出错误而
不是警告。例如,表中含字段TIMESTAMP列(如果未声明为NULL或显示DEFAULT子句)将自动分配DEFAULT '0000-00-00 00:00:00'(零时间戳),这显然是不满足sql_mode中的NO_ZERO_DATE而报错。
6.2 宽松模式再举例
宽松模式举例1:
select * from employees group by department_id limit 10;
set sql_mode = ONLY_FULL_GROUP_BY;
select * from employees group by department_id limit 10;
宽松模式举例2:
设置 sql_mode 模式为 STRICT_TRANS_TABLES
,然后插入数据:
6.3 模式查看和设置
- 查看当前的sql_mode
select @@session.sql_mode
select @@global.sql_mode
#或者
show variables like 'sql_mode';
- 临时设置方式:设置当前窗口中设置sql_mode
SET GLOBAL sql_mode = 'modes...'; #全局
SET SESSION sql_mode = 'modes...'; #当前会话
- 举例:
#改为严格模式。此方法只在当前会话中生效,关闭当前会话就不生效了。
set SESSION sql_mode='STRICT_TRANS_TABLES';
#改为严格模式。此方法在当前服务中生效,重启MySQL服务后失效。
set GLOBAL sql_mode='STRICT_TRANS_TABLES';
- 永久设置方式:在/etc/my.cnf中配置sql_mode
在my.cnf文件(windows系统是my.ini文件),新增:
[mysqld]
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
然后重启MySQL。
当然生产环境上是禁止重启MySQL服务的,所以采用临时设置方式 + 永久设置方式
来解决线上的问题,那么即便是有一天真的重启了MySQL服务,也会永久生效了。
七、MySQL8的主要目录结构
[root@atguigu01 ~]# find / -name mysql
安装好MySQL 8之后,我们查看如下的目录结构:
7.1 数据库文件的存放路径
MySQL数据库文件的存放路径:/var/lib/mysql/
mysql> show variables like 'datadir';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| datadir | /var/lib/mysql/ |
+---------------+-----------------+
1 row in set (0.04 sec)
从结果中可以看出,在我的计算机上MySQL的数据目录就是/var/lib/mysql/
。
7.2 相关命令目录
相关命令目录:/usr/bin(mysqladmin、mysqlbinlog、mysqldump等命令)和/usr/sbin。
7.3 配置文件目录
配置文件目录:/usr/share/mysql-8.0(命令及配置文件),/etc/mysql(如my.cnf)
八、数据库和文件系统的关系
8.1 查看默认数据库
查看一下在我的计算机上当前有哪些数据库:
mysql> SHOW DATABASES;
可以看到有4个数据库是属于MySQL自带的系统数据库。
- mysql
MySQL 系统自带的核心数据库,它存储了MySQL的用户账户和权限信息,一些存储过程、事件的定义信息,一些运行过程中产生的日志信息,一些帮助信息以及时区信息等。 - information_schema
MySQL 系统自带的数据库,这个数据库保存着MySQL服务器维护的所有其他数据库的信息,比如有哪些表、哪些视图、哪些触发器、哪些列、哪些索引。这些信息并不是真实的用户数据,而是一些描述性信息,有时候也称之为元数据。在系统数据库information_schema 中提供了一些以
innodb_sys 开头的表,用于表示内部系统表。
mysql> USE information_schema;
Database changed
mysql> SHOW TABLES LIKE 'innodb_sys%';
+--------------------------------------------+
| Tables_in_information_schema (innodb_sys%) |
+--------------------------------------------+
| INNODB_SYS_DATAFILES |
| INNODB_SYS_VIRTUAL |
| INNODB_SYS_INDEXES |
| INNODB_SYS_TABLES |
| INNODB_SYS_FIELDS |
| INNODB_SYS_TABLESPACES |
| INNODB_SYS_FOREIGN_COLS |
| INNODB_SYS_COLUMNS |
| INNODB_SYS_FOREIGN |
| INNODB_SYS_TABLESTATS |
+--------------------------------------------+
10 rows in set (0.00 sec)
performance_schema
- MySQL 系统自带的数据库,这个数据库里主要保存MySQL服务器运行过程中的一些状态信息,可以用来监控 MySQL 服务的各类性能指标。包括统计最近执行了哪些语句,在执行过程的每个阶段都花费了多长时间,内存的使用情况等信息。
sys
- MySQL 系统自带的数据库,这个数据库主要是通过视图的形式把
information_schema
和performance_schema
结合起来,帮助系统管理员和开发人员监控 MySQL 的技术性能。
- MySQL 系统自带的数据库,这个数据库主要是通过视图的形式把
8.2 数据库在文件系统中的表示
看一下我的计算机上的数据目录下的内容:
[root@atguigu01 mysql]# cd /var/lib/mysql
[root@atguigu01 mysql]# ll
总用量 189980
-rw-r-----. 1 mysql mysql 56 7月 28 00:27 auto.cnf
-rw-r-----. 1 mysql mysql 179 7月 28 00:27 binlog.000001
-rw-r-----. 1 mysql mysql 820 7月 28 01:00 binlog.000002
-rw-r-----. 1 mysql mysql 179 7月 29 14:08 binlog.000003
-rw-r-----. 1 mysql mysql 582 7月 29 16:47 binlog.000004
-rw-r-----. 1 mysql mysql 179 7月 29 16:51 binlog.000005
-rw-r-----. 1 mysql mysql 179 7月 29 16:56 binlog.000006
-rw-r-----. 1 mysql mysql 179 7月 29 17:37 binlog.000007
-rw-r-----. 1 mysql mysql 24555 7月 30 00:28 binlog.000008
-rw-r-----. 1 mysql mysql 179 8月 1 11:57 binlog.000009
-rw-r-----. 1 mysql mysql 156 8月 1 23:21 binlog.000010
-rw-r-----. 1 mysql mysql 156 8月 2 09:25 binlog.000011
-rw-r-----. 1 mysql mysql 1469 8月 4 01:40 binlog.000012
-rw-r-----. 1 mysql mysql 156 8月 6 00:24 binlog.000013
-rw-r-----. 1 mysql mysql 179 8月 6 08:43 binlog.000014
-rw-r-----. 1 mysql mysql 156 8月 6 10:56 binlog.000015
-rw-r-----. 1 mysql mysql 240 8月 6 10:56 binlog.index
-rw-------. 1 mysql mysql 1676 7月 28 00:27 ca-key.pem
-rw-r--r--. 1 mysql mysql 1112 7月 28 00:27 ca.pem
-rw-r--r--. 1 mysql mysql 1112 7月 28 00:27 client-cert.pem
-rw-------. 1 mysql mysql 1676 7月 28 00:27 client-key.pem
drwxr-x---. 2 mysql mysql 4096 7月 29 16:34 dbtest
-rw-r-----. 1 mysql mysql 196608 8月 6 10:58 #ib_16384_0.dblwr
-rw-r-----. 1 mysql mysql 8585216 7月 28 00:27 #ib_16384_1.dblwr
-rw-r-----. 1 mysql mysql 3486 8月 6 08:43 ib_buffer_pool
-rw-r-----. 1 mysql mysql 12582912 8月 6 10:56 ibdata1
-rw-r-----. 1 mysql mysql 50331648 8月 6 10:58 ib_logfile0
-rw-r-----. 1 mysql mysql 50331648 7月 28 00:27 ib_logfile1
-rw-r-----. 1 mysql mysql 12582912 8月 6 10:56 ibtmp1
drwxr-x---. 2 mysql mysql 4096 8月 6 10:56 #innodb_temp
drwxr-x---. 2 mysql mysql 4096 7月 28 00:27 mysql
-rw-r-----. 1 mysql mysql 26214400 8月 6 10:56 mysql.ibd
srwxrwxrwx. 1 mysql mysql 0 8月 6 10:56 mysql.sock
-rw-------. 1 mysql mysql 5 8月 6 10:56 mysql.sock.lock
drwxr-x---. 2 mysql mysql 4096 7月 28 00:27 performance_schema
-rw-------. 1 mysql mysql 1680 7月 28 00:27 private_key.pem
-rw-r--r--. 1 mysql mysql 452 7月 28 00:27 public_key.pem
-rw-r--r--. 1 mysql mysql 1112 7月 28 00:27 server-cert.pem
-rw-------. 1 mysql mysql 1680 7月 28 00:27 server-key.pem
drwxr-x---. 2 mysql mysql 4096 7月 28 00:27 sys
drwxr-x---. 2 mysql mysql 4096 7月 29 23:10 temp
-rw-r-----. 1 mysql mysql 16777216 8月 6 10:58 undo_001
-rw-r-----. 1 mysql mysql 16777216 8月 6 10:58 undo_002
这个数据目录下的文件和子目录比较多,除了information_schema
这个系统数据库外,其他的数据库
在数据目录下都有对应的子目录。
以我的temp
数据库为例,在MySQL5.7 中打开:
[root@atguigu02 mysql]# cd ./temp
[root@atguigu02 temp]# ll
总用量 1144
-rw-r-----. 1 mysql mysql 8658 8月 18 11:32 countries.frm
-rw-r-----. 1 mysql mysql 114688 8月 18 11:32 countries.ibd
-rw-r-----. 1 mysql mysql 61 8月 18 11:32 db.opt
-rw-r-----. 1 mysql mysql 8716 8月 18 11:32 departments.frm
-rw-r-----. 1 mysql mysql 147456 8月 18 11:32 departments.ibd
-rw-r-----. 1 mysql mysql 3017 8月 18 11:32 emp_details_view.frm
-rw-r-----. 1 mysql mysql 8982 8月 18 11:32 employees.frm
-rw-r-----. 1 mysql mysql 180224 8月 18 11:32 employees.ibd
-rw-r-----. 1 mysql mysql 8660 8月 18 11:32 job_grades.frm
-rw-r-----. 1 mysql mysql 98304 8月 18 11:32 job_grades.ibd
-rw-r-----. 1 mysql mysql 8736 8月 18 11:32 job_history.frm
-rw-r-----. 1 mysql mysql 147456 8月 18 11:32 job_history.ibd
-rw-r-----. 1 mysql mysql 8688 8月 18 11:32 jobs.frm
-rw-r-----. 1 mysql mysql 114688 8月 18 11:32 jobs.ibd
-rw-r-----. 1 mysql mysql 8790 8月 18 11:32 locations.frm
-rw-r-----. 1 mysql mysql 131072 8月 18 11:32 locations.ibd
-rw-r-----. 1 mysql mysql 8614 8月 18 11:32 regions.frm
-rw-r-----. 1 mysql mysql 114688 8月 18 11:32 regions.ibd
在MySQL8.0中打开:
[root@atguigu01 mysql]# cd ./temp
[root@atguigu01 temp]# ll
总用量 1080
-rw-r-----. 1 mysql mysql 131072 7月 29 23:10 countries.ibd
-rw-r-----. 1 mysql mysql 163840 7月 29 23:10 departments.ibd
-rw-r-----. 1 mysql mysql 196608 7月 29 23:10 employees.ibd
-rw-r-----. 1 mysql mysql 114688 7月 29 23:10 job_grades.ibd
-rw-r-----. 1 mysql mysql 163840 7月 29 23:10 job_history.ibd
-rw-r-----. 1 mysql mysql 131072 7月 29 23:10 jobs.ibd
-rw-r-----. 1 mysql mysql 147456 7月 29 23:10 locations.ibd
-rw-r-----. 1 mysql mysql 131072 7月 29 23:10 regions.ibd
8.3 表在文件系统中的表示
8.3.1 InnoDB存储引擎模式
- 表结构
为了保存表结构, InnoDB 在数据目录下对应的数据库子目录下创建了一个专门用于描述表结构的文件,文件名是这样:
表名.frm
比方说我们在atguigu 数据库下创建一个名为test 的表:
mysql> USE atguigu;
Database changed
mysql> CREATE TABLE test (
-> c1 INT
-> );
Query OK, 0 rows affected (0.03 sec)
那在数据库atguigu 对应的子目录下就会创建一个名为test.frm 的用于描述表结构的文件。.frm文件的格式在不同的平台上都是相同的。这个后缀名为.frm是以二进制格式存储的,我们直接打开是乱码的。
- 表中数据和索引
① 系统表空间(system tablespace)
默认情况下,InnoDB会在数据目录下创建一个名为ibdata1 、大小为12M 的文件,这个文件就是对应的系统表空间在文件系统上的表示。怎么才12M?注意这个文件是自扩展文件,当不够用的时候它会自己增加文件大小。
当然,如果你想让系统表空间对应文件系统上多个实际文件,或者仅仅觉得原来的ibdata1 这个文件名难听,那可以在MySQL启动时配置对应的文件路径以及它们的大小,比如我们这样修改一下my.cnf 配置文件:
[server]
innodb_data_file_path=data1:512M;data2:512M:autoextend
② 独立表空间(file-per-table tablespace)
在MySQL5.6.6以及之后的版本中,InnoDB并不会默认的把各个表的数据存储到系统表空间中,而是为每一个表建立一个独立表空间
,也就是说我们创建了多少个表,就有多少个独立表空间。使用独立表空间来存储表数据的话,会在该表所属数据库对应的子目录下创建一个表示该独立表空间
的文件,文件名和表名相同,只不过添加了一个.ibd
的扩展名而已,所以完整的文件名称长这样:
表名.ibd
比如:我们使用了独立表空间
去存储atguigu
数据库下的test
表的话,那么在该表所在数据库对应的atguigu
目录下会为test
表创建这两个文件:
test.frm
test.ibd
其中test.ibd
文件就用来存储test 表中的数据和索引。
③ 系统表空间与独立表空间的设置
我们可以自己指定使用系统表空间还是独立表空间来存储数据,这个功能由启动参数innodb_file_per_table
控制,比如说我们想刻意将表数据都存储到系统表空间时,可以在启动MySQL服务器的时候这样配置:
[server]
innodb_file_per_table=0
# 0:代表使用系统表空间; 1:代表使用独立表空间
默认情况:
mysql> show variables like 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
1 row in set (0.01 sec)
④ 其他类型的表空间
随着MySQL的发展,除了上述两种老牌表空间之外,现在还新提出了一些不同类型的表空间,比如通用表空间(general tablespace)、临时表空间(temporary tablespace)等。
8.3.2 MyISAM存储引擎模式
- 表结构
在存储表结构方面,MyISAM
和InnoDB
一样,也是在数据目录
下对应的数据库子目录下创建了一个专门用于描述表结构的文件:
表名.frm
- 表中数据和索引
在MyISAM中的索引全部都是二级索引
,该存储引擎的数据和索引是分开存放的。所以在文件系统中也是使用不同的文件来存储数据文件和索引文件,同时表数据都存放在对应的数据库子目录下。假如test
表使用MyISAM
存储引擎的话,那么在它所在数据库对应的atguigu
目录下会为test
表创建这三个文件:
test.frm 存储表结构
test.MYD 存储数据 (MYData)
test.MYI 存储索引 (MYIndex)
举例:创建一个MyISAM
表,使用ENGINE
选项显式指定引擎。因为InnoDB
是默认引擎。
CREATE TABLE `student_myisam` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL,
`age` int DEFAULT NULL,
`sex` varchar(2) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=MYISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb3;
8.4 小结
举例: 数据库a
, 表b
。
1、如果表b采用InnoDB
,data\a
中会产生1个或者2个文件:
b.frm
:描述表结构文件,字段长度等- 如果采用
系统表空间模式
的,数据信息和索引信息都存储在ibdata1
中 - 如果采用
独立表空间
存储模式,data\a中还会产生b.ibd
文件(存储数据信息和索引信息)
此外:
① MySQL5.7 中会在data/a的目录下生成db.opt
文件用于保存数据库的相关配置。比如:字符集、比较规则。而MySQL8.0不再提供db.opt文件。
② MySQL8.0中不再单独提供b.frm
,而是合并在b.ibd文件中。
2、如果表b采用MyISAM
,data\a中会产生3个文件: - MySQL5.7 中:
b.frm
:描述表结构文件,字段长度等。 - MySQL8.0 中
b.xxx.sdi
:描述表结构文件,字段长度等 b.MYD (MYData)
:数据信息文件,存储数据信息(如果采用独立表存储模式)b.MYI (MYIndex)
:存放索引信息文件
评论区