DBA MySQL基础学习
MySQL简介
MySQL
是由瑞典MySQL AB
公司开发,目前属于 Oracle
(甲骨文)公司旗下,是当下最流行的关系型数据库管理系统软件,并且由于SQL
语句具有通用的特性,在学习完MySQL
后学习其他RDBMS
过程中也同样能使用相同的语法进行操作。
MySQL
是一个C/S
架构的软件,可以在本地通过socket
文件进行登录,也可在远端使用TCP/IP
协议进行登录。
MySQL版本
MySQL
版本丰富,目前主流版本是5.6或5.7,以下是MySQL
各个版本的发行日期,我将使用Linux
平台与MySQL5.7.28
进行演示:
GA代表稳定版
Feature | MySQL Series |
---|---|
First release | 3.11.1(1996) MySQL AB |
Query Cache, Unions, Full-text, InnoDB | 4.0 (2003-03) |
Subqueries, R-trees | 4.1 (2004-10) |
Stored Routies, Views, Cursors, Triggers, XA Transactions, I_S | 5.0 (2005-10) |
Event scheduler, Patitioning, Plugin API, RBR, InnoDB Plugin, MySQL Cluster | 5.1 (2008-11) SUN |
Dtrace support, Semisync-replication, P_S, Supplementary Unicode characters | 5.5 GA版本5.5.8 (2010-12-03) Oracle |
Online-DDL, GTID, Parallel Replication, ICP, MRR ...etc... | 5.6 GA版本5.6.10(2013-02-05) |
XX | 5.7 (2013-02) GA版本5.7.10 (2015-12-07) |
XX | 8.0.0 (2016-09-12) |
XX | 8.0.11(2018-04-19 )GA版本 |
安装启动
软件下载
打开Chorme
浏览器,进入官网找到需要下载的版本,在这里将演示直接安装tar.gz
格式Binary
版本免编译的包。
点我跳转
复制出链接,使用wget
命令对其进行下载。
T > cd ~
T > wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz
配置目录
我们需要三个目录来存放mysqld.service
服务的不同的数据。
T > mkdir -p /usr/local/application/mysql57/ # 存放MySQL软件服务,即安装包路径
T > mkdir -p /usr/local/application/mysql57/data # 存放MySQL服务产生的数据,库、表等信息
T > mkdir -p /usr/local/application/mysql57/logs # 存放MySQL服务产生的日志等信息
tar.gz安装
下载完成之后,执行以下命令进行解压操作:
T > tar zxvf ./mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz -C /usr/local/application/mysql57
T > mv /usr/local/application/mysql57/mysql-5.7.28-linux-glibc2.12-x86_64 /usr/local/application/mysql57/mysql
环境变量
接下来是MySQL
环境变量的配置,打开下面文件:
T > vim /etc/profile
写入以下内容:
export PATH=/usr/local/application/mysql57/mysql/bin:$PATH
记得刷新配置:
T > source /etc/profile
输入以下命令,显示版本信息则代表配置成功:
T > mysql -V
mysql Ver 14.14 Distrib 5.7.28, for linux-glibc2.12 (x86_64) using EditLine wrapper
用户与授权
MySQL
应当由独立的用户进行管理,所以我们需要创建一个名为mysql
的用户组与用户。
在创建之前,先查看是否默认创建了该用户,如果没有创建再进行手动创建也不迟。
T > id mysql
# 没有该用户,手动创建
T > groupadd mysql
T > useradd -g mysql mysql
我们需要对该用户进行目录进行授权操作,命令如下:
T > chown -R mysql:mysql /usr/local/application/mysql57
配置文件
使用配置文件可以对mysql.server
服务启动后的初始化参数进行配置,首先我们需要输入以下命令打开配置文件:
T > vim /etc/my.cnf
写入的内容如下:
[mysqld]
user=mysql # mysql用户配置
server_id=3306 # 当前mysql服务的ID号,适用于多实例mysql服务
port=3306 # 当前mysql服务的端口号
basedir=/usr/local/application/mysql57/mysql # 当前mysql服务软件目录
datadir=/usr/local/application/mysql57/data # 当前mysql服务的数据存放目录
log_error=/usr/local/application/mysql57/logs/mysqld.log # 当前mysql服务中运行日志存放目录及日志名称
socket=/tmp/mysql.sock # socket连接时的文件,本地登录使用
[mysql]
default-character-set=utf8mb4 # 设置mysql客户端链接当前mysql服务时所使用的字符集为utf8mb4
socket=/tmp/mysql.sock # socket连接时的文件,本地登录使用
[client]
port=3306 # 设置mysql客户端连接当前mysql服务时默认使用的端口
初始化
初始化的命令有两条:
—-initialize # 常规初始化
--initialize-insecure # 免密初始化
如果你使用常规初始化,它会生成一个随机密码,可以在配置的日志目录中进行查看,文件名为:mysqld.log
。
推荐使用免密初始化:
T > mysqld --initialize-insecure
所有的初始化工作完成后都在内部生成自带库与表,并且,常规初始化还会其他额外的功能:
- 为root@localhost用户设置临时密码
- 对密码复杂度进行定制,规定其root的登录密码必须为12位,必须具有4种格式(必须拥有大写字符,小写字符,数字,特殊字符)
- 临时密码过期时间为180s
sys服务
现在只是初始化完成,但是还没有将mysqld
加入systemctl
系统服务管控中,也就无法开启服务。
所以现在我们需要对mysqld
制作成系统服务,输入以下命令
T > cat >/etc/systemd/system/mysqld.service <<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/usr/local/application/mysql57/mysql/bin/mysqld --defaults-file=/etc/my.cnf
LimitNOFILE = 5000
EOF
然后就可以开启mysqld.service
服务:
T > systemctl start mysqld.service
尝试登陆:
T > mysql -uroot
将mysqld.service
服务进行开机启动:
systemctl enable mysqld.service
常见错误
例举一些常见的错误:
错误1:
.. ERROR! The server quit without updating PID file (...).
这个错误可能是因为你的系统上已经有mysqld.service
服务启动了,导致了端口占用,你需要kill
掉旧的mysqld.service
服务:
T > ps aux | grep 3306
# 找到相关的的服务PID号
T > kill PID号
错误2:
Can 't connect to local MySQL server through socket /tmp/mysql.sock
这个错误可能是因为你的系统上用于root
用户本地登录的sock
文件被删除,一般来说重启mysql.server
服务即可。
操作步骤:
T > pkill mysql*
T > systemctl start mysqld.service
除此之外,你也可以使用TCP/IP协议进行登录:
T > mysql -uroot -p密码 --protocol tcp -hlocalhost
其他的错误可能是由配置文件导致的,检查配置文件是否是/etc/my.cnf
,不要把路径配置错了。
登录与密码
设置密码
如果你使用免密初始化后想为root
用户生成一个密码,可在终端中输入如下命令:
T > mysqladmin -uroot password "密码"
登录参数
MySQL
支持两种形式的链接,即TCP/IP
协议登录和本地mysql.sock
文件登录:
# mysql.sock文件登录
T > mysql -u用户名 -p密码 -S /tmp/mysql.sock
# TCP/IP协议登录
T > mysql -u用户名 -p密码 -h地址 -P端口号
在本地登录时,都是采用mysql.sock
文件进行登录,如果是单一的MySQL
服务实例,则后面-S
的参数可以省略。
在远端登录时,都是采用TCP/IP
协议进行登录。
以下例举一些常用的登录参数项:
-h:IP地址
-P:端口号,MySQL端口号默认为3306
-u:用户名
-p:密码
-e:一段执行命令
<:导入SQL语句文件
使用参数e
的案例,导出某些查询内容:
T > mysql -uroot -e"SHOW DATABASES;" > /tmp/data
T > cat /tmp/data
# 打印内容:
Database
information_schema
mysql
performance_schema
sys
使用参数<
的案例,导入并执行SQL
语句:
T > mysql -uroot < /tmp/other.sql
用户查看
登录MySQL
后,使用以下命令可查看到自己登录的用户:
M > SELECT USER();
使用以下命令可查看到当前链接该MySQL
服务的所有用户与链接线程:
M > SHOW PROCESSLIST;
忘记密码
MySQL
数据目录下默认会生成一些自带的数据库,其中user
表就是做授权验证的。
这使得MySQL
客户端必须先经过授权登录后才能对服务端进行一系列的操作,但是我们也可以通过一些技术手段绕过这个授权。
T > ls /usr/local/application/mysql57/data/mysql | grep user
user.MYD
user.MYI
user.frm
如何在忘记当前登录密码的情况下修改密码呢?以Linux
平台为例:
# 1.关闭需要授权登录的MySQL服务端
T > systemctl stop mysqld.service
# 2.开启mysql_safe免授权登录的服务端,并且暂时的禁止远端登录
T > mysqld_safe --skip-grant-tables --skip-networking
# 3.开启新终端,使用root用户进行登录,并且修改密码
T > mysql -uroot -S /tmp/mysql.sock
M > UPDATE MYSQL.USER SET authentication_string=password('123') WHERE user = 'root' AND host="localhost";
# 4.将内存中的数据刷写到磁盘并退出
T > FLUSH PRIVILEGES;
M > exit;
# 5.关闭免授权、关闭禁止远端访问的mysqld_safe服务进程
T > ps -ef | grep mysql
T > kill -9 mysql_safe进程PID
# 6.开启正常服务,尝试登录
T > systemctl start mysqld.service
T > mysql -uroot -p123 -S /tmp/mysql.sock
用户与权限
基础概念
在MySQL
中,我们可以使用root
用户创建出一些新的用户并为他们分配一些权限,如可编辑那些数据库,可使用那些SQL
语句等等。
打个比方,一个开发部门可能公用一个数据库,而各个开发小组的组长包括成员只能查看或编辑自身业务范围之内的记录,这种需求下就需要使用到用户管理与权限管理。
系统库表
用户与权限相关的信息存储在内置库mysql
中,共有四张表,如下所示:
表名 | 描述 |
---|---|
user | 针对所有数据库,所有库下所有表,以及表下的所有字段 |
db | 针对某一数据库,该数据库下的所有表,以及表下的所有字段 |
tables_priv | 针对某一张表,以及该表下的所有字段 |
columns_priv | 针对某一个字段 |
用户管理
用户管理需要使用root
账户,且总体来说都是对mysql.user
做操作,除了查看用户的命令外,其他的操作都需要将数据刷写到磁盘。
以下是一些创建用户的示例演示:
# 创建用户名为Yunya的用户,允许该用户从本地进行登录
M > CREATE USER "Yunya"@"localhost" IDENTIFIED BY "123";
# 创建用户名为Yunya的用户,允许该用户从192.168.31.10进行登录
M > CREATE USER "Yunya"@"192.168.31.10" IDENTIFIED BY "123";
# 创建用户名为Yunya的用户,允许该用户从192.168.31.xxx的网段进行登录
M > CREATE USER "Yunya"@"192.168.31.%" IDENTIFIED BY "123";
# 创建用户名为Yunya的用户,允许该用户从任意ip地址的网络进行登录
M > CREATE USER "Yunya"@"%" IDENTIFIED BY "123";
# 将内存中的数据刷写到磁盘
M > FLUSH PRIVILEGES;
# 在MySQL8版本以前,允许创建用户的同时进行授权操作
M > GRANT ALL ON *.* TO Yunya@"%" IDENTIFIED BY "123";
# %代表通配符,与RegExp中的.类似
查询所有用户,则可以使用以下的命令:
M > SELECT user,host FROM mysql.user;
修改用户密码的方式有两种:
# 方式一,非root用户:
M > ALERT USER Yunya@"localhost" IDENTIFIED BY "123";
# 方式二,修改root用户的密码:
M > UPDATE MYSQL.USER SET authentication_string=password('123') WHERE user = 'Yunya' AND host = "localhost";
# 将内存中的数据刷写到磁盘
M > FLUSH PRIVILEGES;
删除用户的方式有两种:
# 方式一,非root用户:
M > DROP USER Yunya@"localhost";
# 方式二:
M > DELETE FROM mysql.user WHERE user = "Yunya" AND host = "localhost";
# 将内存中的数据刷写到磁盘
M > FLUSH PRIVILEGES;
权限管理
权限相关操作必须由root
进行,除了查看命令外,其他的操作都需要将数据刷写到磁盘。
分配权限的相关操作:
# 为Yunya分配所有权限
M > GRANT all ON *.* TO "Yunya"@"%";
# 为Yunya分配db1数据库下的所有数据表的查看权限
M > GRANT select ON db1.* TO "Yunya"@"%";
# 为Yunya分配db1数据库下的t1数据表的查看id,name字段与更新age字段的权限
M > GRANT select(id,name),update(age) ON db1.t1 TO "Yunya"@"%";
# 将内存中的数据刷写到磁盘
M > FLUSH PRIVILEGES;
查看用户权限的命令:
M > SHOW GRANTS FOR root@'localhost';
释放用户权限的命令:
# 释放掉Yunya的所有权限
M > REVOKE all ON *.* FROM "Yunya"@"%";
# 将内存中的数据刷写到磁盘
M > FLUSH PRIVILEGES;
三层架构
基础概念
我们知道MySQL
是通过SQL
语句进行操作的,其实当一个Client
端链接到Server
端后并提交命令这一过程可分为三个环节。
链接层
链接层的主要作用有以下三点:
- 提供链接协议,socket与TCP/IP
- 验证用户名即密码的合法性,会对登录用户匹配专门的授权表
- 派生出一个专用的链接线程,用于接收SQL命令并返回结果
SQL层
SQL
层主要作用于调优方面的工作,也是DBA
及其需要关注的一层,主要作用如下所示:
- 验证SQL语法与sql_mode
- 验证语义
- 验证权限
- 进入解析器进行语句解析,生成多个执行计划(解析树)
- 进入优化器(各种算法,基于执行代价),根据算法,找到代价最低的执行计划(代价:CPU IO MEM)
- 执行器按照优化器选择的执行计划,执行SQL语句,得出获取数据的方法
- 提供查询缓存(默认关闭)
- 记录操作日志binlog(默认关闭)
存储层
存储层依靠存储引擎与磁盘打交道,与Linux
上文件系统的概念相似,其功能是对磁盘上的数据进行存取。
根据SQL
层所提供的取数据的方法,拿到数据,返回给SQL
层将其结构化成表,再由链接层线程返回给用户。
在后续章节存储引擎中,将会详细介绍这一过程。
存储结构
逻辑存储结构
MySQL
逻辑存储结构是按照库表进行存储,并且每个表中还具有字段(列),字段属性,数据行(记录),表属性(元数据,如字符编码校对规则等)等信息。
物理存储结构
对于MySQL
中的一个库来说,实际上就是一个文件夹。
如下所示,我创建一个db1
的库:
M > CREATE DATABASE db1;
在数据根目录中就能看到这样的一个以库名命名的目录:
T > ll /usr/local/application/mysql57/data/ | grep db1
drwxr-x--- 3 _mysql _mysql 102 2 13 21:57 db1
对于MySQL
中的一个表来说,就需要涉及到存储引擎,因为不同的存储引擎对表的物理存储结构也有所不同。
在MyISAM
存储引擎中,表的物理结构如下:
使用tableName.frm文件存储表结构,如字段,字段属性等
使用tableName.MYD存储表的记录
使用tableName.MYI存储表的索引
在InnoDB
存储引擎中,表的物理结构如下:
使用tableName.frm文件存储单张表的表结构,如字段,字段属性等
使用tableName.ibd存储单张表的表的记录以及索引信息等
使用ibdata1文件存储每一张表的元信息等属性,如字符编码、校对规则、统计信息等