show variables like '%log_bin%';
flush logs
(1)、关闭MYSQL服务systemctl stop mysqld.service
(2)、查看当前 mysql 安装状况
rpm -qa | grep -i mysql # 或 yum list installed | grep mysql
# 方式一 yum remove mysql-xxx mysql-xxx mysql-xxx mysqk-xxxx # 方式二 rpm -e --nodeps my mysql-xxx mysql-xxx mysqk-xxxx
find / -name mysql # 查找相关文件 rm -rf xxx # 删除上述命令查找出的相关文件 rm -rf /etc/my.cnf # 删除 my.cnf
到MYSQL官网中下载如下安装包下载地址
注意:MYSQL5.7和MYSQL8所需要的安装包是不一样的,区别如下(版本号不必在意):
# MYSQL8 需要如下安装包 mysql-communiity-client-8.0.25-1.el7.x86_64.rpm mysql-communiity-client-plugins-8.0.25-1.el7.x86_64.rpm mysql-communiity-common-8.0.25-1.el7.x86_64.rpm mysql-communiity-libs-8.0.25-1.el7.x86_64.rpm mysql-communiity-server-8.0.25-1.el7.x86_64.rpm # MYSQL5.7 需要如下安装包 # mysql-community-common-5.7.26-1.el7.x86_64.rpm # mysql-community-libs-5.7.26-1.el7.x86_64.rpm # mysql-community-client-5.7.26-1.el7.x86_64.rpm # mysql-community-server-5.7.26-1.el7.x86_64.rpm
由于mysql安装过程中,会通过mysql用户在/tmp目录下新建tmp_db文件,所以请给/tmp较大的权限。执行该指令:chmod -R 777 /tmp
rpm -qa|grep libaio # 检查依赖 rpm -qa|grep net-tools # 检查依赖 # 查询是否有相关的依赖,有则删除 rpm -qa|grep mari rpm -e --nodeps mariadb-libs # 例如这样一个个卸载 yum remove mysql-libs # 也可以这样卸载
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 登录用户,如果你是以 root 身份运行 mysql 服务,需要执行下面的命令初始化。
初始化:mysqld --initialize --user=mysql
启动:systemctl start mysqld.service
cat /var/log/mysqld.log
mysql -uroot -p输入默认密码 # 登录到MYSQL ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password'; # 修改ROOT的密码
use mysql; # 使用mysql这个数据库 update mysql set host = '%' where user='root' and host='localhost'; # % 代表任意ip都可以访问 ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'abc123'; # MYSQL5不用做该步骤。这里的密码自己定义。 flush privilege; # 刷新权限
firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-port=3306/tcp
# 在[mysqld]后面加上 character_set_server=utf8
服务器级别
数据库级别
表级别
列级别
提示:当创建数据库时未指定字符集和比较规则时,会默认与服务器级别的字符集、比较规则一致。表级别与数据库级别,列级别再与表级别,以此类推。
show variables like 'character%'; show variables like 'collation%';
character_set_client
服务器解码请求时使用的字符集(需要与客户端一致)
character_set_connection
服务器处理请求时会把请求字符串从character_set_client 转为 character_set_connection
character_set_results
服务器向客户端返回数据时使用的字符集(需要与客户端一致)
find / -name mysql
/var/lib/mysql/
/usr/bin(mysqladmin、mysqlbinlog、mysqldump等命令)和/usr/sbin。
/usr/share/mysql-8.0(命令及配置文件) /etc/mysql(如my.cnf)
(1)mysql
MySQL 系统自带的核心数据库,它存储了MySQL的用户账户和权限信息,一些存储过程、事件的定义信息,一些运行过程中产生的日志信息,一些帮助信息以及时区信息等。
(2)information_schema
MySQL 系统自带的数据库,这个数据库保存着MySQL服务器 维护的所有其他数据库的信息 ,比如有哪些表、哪些视图、哪些触发器、哪些列、哪些索引。这些信息并不是真实的用户数据,而是一些描述性信息,有时候也称之为 元数据 。在系统数据库 information_schema 中提供了一些以innodb_sys 开头的表,用于表示内部系统表。
(3)performance_schema
MySQL 系统自带的数据库,这个数据库里主要保存MySQL服务器运行过程中的一些状态信息,可以用来 监控 MySQL 服务的各类性能指标 。包括统计最近执行了哪些语句,在执行过程的每个阶段都花费了多长时间,内存的使用情况等信息。
(4)sys
MySQL 系统自带的数据库,这个数据库主要是通过 视图 的形式把 information_schema 和performance_schema 结合起来,帮助系统管理员和开发人员监控 MySQL 的技术性能。
举例: 数据库a , 表b 。
MYSQL5.7:b.frm、b.idb、db.opt 三个文件
MYSQL8.0:b.idb一个文件
MySQL5.7 中: b.frm :描述表结构文件,字段长度等。
MySQL8.0 中 b.xxx.sdi :描述表结构文件,字段长度等
b.MYD (MYData):数据信息文件,存储数据信息(如果采用独立表存储模式)
b.MYI (MYIndex):存放索引信息文件
MYSQL5.7:b.frm、b.MYD、b.MYI 三个文件
MYSQL8.0:b.sdi、b.MYD、b.MYI 三个文件
mysql –h hostname|hostIP –P port –u username –p DatabaseName –e "SQL语句"
h参数 后面接主机名或者主机IP,hostname为主机,hostIP为主机IP。
P参数 后面接MySQL服务的端口,通过该参数连接到指定的端口。MySQL服务的默认端口是3306,不使用该参数时自动连接到3306端口,port为连接的端口号。
u参数 后面接用户名,username为用户名。
p参数 会提示输入密码。DatabaseName参数 指明登录到哪一个数据库中。如果没有该参数,就会直接登录到MySQL数据库中,然后可以使用USE命令来选择数据库。
e参数 后面可以直接加SQL语句。登录MySQL服务器以后即可执行这个SQL语句,然后退出MySQL服务器。
# 查询用户 SELECT HOST,USER FROM mysql.user; # 创建用户,这里的意思是只有192.168.22开头的ip可以连接上,密码为123 CREATE USER 'zhangsan'@'192.168.22.*' IDENTIFIED BY '123'; # 创建一个用户,名字为zhagnsan,任意ip都可以登录,密码123 CREATE USER 'zhangsan'@'%' IDENTIFIED BY '123'; # 设置密码(修改密码) ALTER USER 'zhangsan'@'192.168.22.*' IDENTIFIED BY '321'; # 删除用户 DROP USER 'zhangsan'@'192.168.22.*';
# 查询角色 SELECT HOST,USER FROM mysql.user; # 注意角色跟用户都在该表当中 # 创建角色 CREATE role 'manager'@'%'; # 创建一个经理角色 CREATE role 'boos'@'%'; # 创建一个boos角色 # 删除角色 DROP role 'manager'@'%';
# 格式为:GRANT 权限... ON 数据库.数据表 TO 角色; # 为角色授予权限 GRANT ALL PRIVILEGES ON *.* TO 'boos'@'%'; # 为用户授予权限 GRANT SELECT,UPDATE ON mydb.* TO 'zhangsan'@'%'; # 给予mydb数据库下的所有表的查询和更新权限 # 回收用户的角色。(回收角色时,与其操作一致) REVOKE SELECT,UPDATE ON mydb.* FROM 'zhangsan'@'%';
# 将角色授予给用户 GRANT 'boos'@'%' TO 'zhangsan'@'%'; # 激活角色的2种方式 SET DEFAULT ROLE ALL TO 'zhangsan'@'%'; # 为'zhangsan'@'%'用户激活角色 SET GLOBAL activate_all_roles_on_login=ON; # 设置全局激活 # 将角色收回 REVOKE 'boos'@'%' FROM 'zhangsan'@'%';
mysql.user表(第一层)
mysql.db表(第二层)
mysql.tables_priv表(第三层)
mysql.columns_priv表(第四层)
用户登录认证成功时候,若有角色时,将会被赋予角色
会根据用户在mysql.user表中查询权限,若拥有该表中增删改查的任一权限,则可以使用该权限访问如下三层。
接下来会在第二层查询权限,以此类推。
连接MYSQL服务的一些客户端程序
客户端对MYSQL服务器发送请求时,TCP连接池会分出一个连接与客户端进行TCP连接
TCP连接收到请求后,将会从线程池当中分配一个线程来进行该请求的处理。
接下来连接层会进行用户信息的校验
用户名或密码不对,会收到一个Access denied for user错误,客户端程序结束执行
用户名密码认证通过,会从权限表查出账号拥有的权限与连接关联,之后的权限判断逻辑,都将依赖于此时读到的权限。
接收客户端发送的SQL命令
返回SQL处理的结果给客户端
解析器用于对SQL进行解析
检查语法、语义,如果检查出错误,直接让SQL Interface返回报错结果
检查语法、语义,如果检查没有错误,则生成SQL的语法树,交给Optimizer优化器
对SQL语法树进行逻辑优化(比如说同一个功能换个写法)
对SQL语法树进行物理优化(更换代码位置等)
查询缓存的存储规则为:key:value,其中的key是SQL语句,value是查询的结果。
在服务层的SQL Interface接收到了客户端的SQL时,就会进入缓存中查一查,查到就直接返回结果了
如果对表中数据进行了删除,但是查询时又命中了缓存,可能导致读取到脏数据
命中率低
均为可插拔式引擎,真正的负责了MySQL中数据的存储和提取,对物理服务器级别维护的底层数据执行操作。服务器通过API与存储引擎进行通信。不同的存储引擎具有的功能不同。
所有的数据,数据库、表的定义,表的每一行的内容,索引,都是存在 文件系统 上,以 文件 的方式存在的,并完成与存储引擎的交互。
在 InnoDB 存储引擎中有一部分数据会放到内存中,缓冲池则占了这部分内存的大部分,它用来存储各种数据的缓存
如果你使用的是 InnoDB 存储引擎,可以通过查看 innodb_buffer_pool_size
变量来查看缓冲池的大
小
修改缓冲池大小的方法
# 设置全局变量 set global innodb_buffer_pool_size = 268435456; # 修改配置文件 [server] innodb_buffer_pool_size = 268435456 innodb_buffer_pool_instances = 2 # 缓冲池数量
如果缓冲池的大小不超过1G,那么没必要拆分多个示例
缓冲池按照一定的规则,定期将数据写入磁盘文件当中
select @@profiling; show variables like 'profiling';
set profiling=1; set global profiling=1;
show profiles;
show profile; show profile for query 1~n; show profile cpu,block io for query 1~n;
存储引擎在以前被称之为表处理器,实质上就是存储表的类型。
查看MYSQL提供什么存储引擎
show engines;
查看默认的存储引擎
show variables like '%storage_engine%';
select @@default_storage_engine;
修改默认的存储引擎
SET DEFAULT_STORAGE_ENGINE=MyISAM; 也可以修改默认文件 default-storage-engine=MyISAM # 重启服务 systemctl restart mysqld.service
show engines;
命令的结果Engine:引擎名称
Support:是否支持使用该存储引擎
Transcations:是否支持事物
XA:是否支持分布式事物
Savepoints:是否支持保存点
MySQL从3.23.34a开始就包含InnoDB存储引擎。 大于等于5.5之后,默认采用InnoDB引擎 。
InnoDB是MySQL的 默认事务型引擎 ,它被设计用来处理大量的短期(short-lived)事务。可以确保事务的完整提交(Commit)和回滚(Rollback)。
除了增加和查询外,还需要更新、删除操作,那么,应优先选择InnoDB存储引擎。增删改查。
除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎。
InnoDB是 为处理巨大数据量的最大性能设计 。
MyISAM提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM 不支持事务、行级锁、外键 ,有一个毫无疑问的缺陷就是 崩溃后无法安全恢复 。(不适合高并发的操作)
** 5.5之前默认的存储引擎**。
优势是访问的 速度快 ,对事务完整性没有要求或者以SELECT、INSERT为主的应用
针对数据统计有额外的常数存储。故而** count(*) 的查询效率很高**
应用场景:只读应用或者以读为主的业务
对比MyISAM的存储引擎, InnoDB写的处理效率差一些 ,并且会占用更多的磁盘空间以保存数据和索引。
MyISAM只缓存索引,不缓存真实数据;InnoDB不仅缓存索引还要缓存真实数据, 对内存要求较高 ,而且内存大小对性能有决定性的影响。
索引(Index)是帮助MySQL高效获取数据的数据结构。
索引的本质:索引是数据结构。你可以简单理解为 “排好序的快速查找数据结构”,满足特定查找算法。这些数据结构以某种方式指向数据, 这样就可以在这些数据结构的基础上实现 高级查找算法 。
(1)数据库的IO成本
(2)通过创建唯一索引,可以保证数据库表中每一行** 数据的唯一性**
(3)在实现数据的参考完整性方面,可以 加速表和表之间的连接。换句话说,对于有依赖关系的子表和父表联合查询时,可以提高查询速度。
(4)在使用分组和排序子句进行数据查询时,可以显著 减少查询中分组和排序的时间 ,降低了CPU的消耗。
(1)创建索引和维护索引要 耗费时间 ,并且随着数据量的增加,所耗费的时间也会增加。
(2)索引需要占 磁盘空间 ,除了数据表占数据空间之外,每一个索引还要占一定的物理空间, 存储在磁盘上 ,如果有大量的索引,索引文件就可能比数据文件更快达到最大文件尺寸。
(3)虽然索引大大提高了查询速度,同时却会 降低更新表的速度 。当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。
(1)使用记录主键值的大小进行记录页和数据页的排序,这包括三个方面的含义:
页内 的记录是按照主键的大小顺序排成一个 单向链表 。
各个存放 用户记录的页 也是根据页中用户记录的主键大小顺序排成一个 双向链表 。
存放 目录项记录的页 分为不同的层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成一个 双向链表 。
(2)B+树的叶子节点存储的是完整的用户记录
(1)数据访问更快 ,因为聚簇索引将索引和数据保存在同一个B+树中(不用进行回表操作),因此从聚簇索引中获取数据比非聚簇索引更快
(2)聚簇索引对于主键的 排序查找 和 范围查找 速度非常快
(3)按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以 节省了大量的io操作 。
(1)插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
(2)更新主键的代价很高 ,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新。
(3)二级索引访问需要两次索引查找 ,第一次找到主键值,第二次根据主键值找到行数据。
首先,如上三个称呼,表明的意思都是一样的。
由多个非主键列同时组成。数据页存储联合索引列的数据和主键的值。
(1)二级索引的插入速度比聚簇索引快
(2)二级索引各个数据页当中会存储索引列数据和主键的值
MyISAM的索引方式都是“非聚簇”的,与InnoDB包含1个聚簇索引是不同的。小结两种引擎中索引的区别:
(1)在InnoDB存储引擎中,我们只需要根据主键值对 聚簇索引 进行一次查找就能找到对应的记录,而在MyISAM 中却需要进行一次 回表 操作,意味着MyISAM中建立的索引相当于全部都是 二级索引 。
(2) InnoDB的数据文件本身就是索引文件,而MyISAM索引文件和数据文件是 分离的 ,索引文件仅保存数据记录的地址。
(3)InnoDB的非聚簇索引data域存储相应记录 主键的值 ,而MyISAM索引记录的是 地址 。换句话说,InnoDB的所有非聚簇索引都引用主键作为data域。
(4) MyISAM的回表操作是十分 快速 的,因为是拿着地址偏移量直接到文件中取数据的,反观InnoDB是通过获取主键之后再去聚簇索引里找记录,虽然说也不慢,但还是比不上直接用地址去访问。
(5) InnoDB要求表 必须有主键 ( MyISAM可以没有 )。如果没有显式指定,则MySQL系统会自动选择一个可以非空且唯一标识数据记录的列作为主键。如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整型。
(1)有 k 个孩子的节点就有 k 个关键字。也就是孩子数量 = 关键字数,而 B 树中,孩子数量 = 关键字数+1。
(2)非叶子节点的关键字也会同时存在在子节点中,并且是在子节点中所有关键字的最大(或最小)。
(3)非叶子节点仅用于索引,不保存数据记录,跟记录有关的信息都放在叶子节点中。而 B 树中, **非叶子节点既保存索引,也保存数据记录 **。
(4)所有关键字都在叶子节点出现,叶子节点构成一个有序链表,而且叶子节点本身按照关键字的大小从小到大顺序链接。
聚簇索引
非聚簇索引(二级索引、辅助索引)
需要回表的索引一般称之为二级索引
二级索引中的各个节点当中存储的都为 二级索引字段的值以及主键的值。所以需要回表。(因为没有存储完整用户记录)
单列索引
联合索引
# 创建普通索引 CREATE TABLE t_1( id INT, sname VARCHAR(32), sno INT, age INT, intor VARCHAR(64), INDEX t_1_sno(sno) ) # 创建唯一索引 CREATE TABLE t_2( id INT, sname VARCHAR(32), sno INT, age INT, intor VARCHAR(64), UNIQUE INDEX t_1_sname(sname) ) # 创建主键索引(其实就是指定一个主键) CREATE TABLE t_3( id INT, sname VARCHAR(32), sno INT, age INT, intor VARCHAR(64), PRIMARY KEY(id) )
# 第一种方式 ALTER TABLE t_1 ADD INDEX t_1_sname(sname); # 第二种方式 CREATE INDEX t_1_age ON t_1(age);
# 第一种方式 ALTER TABLE t_1 DROP INDEX t_1_age; # 第二种方式 DROP INDEX t_1_sno ON t_1;
SHOW INDEX FROM 表名;
# 例如: CREATE INDEX idx_t_1_age_desc ON t_1(age DESC);
使用场景:想要废弃掉一个索引,但是又无法确认该索引会造成的后果时,可以将该索引设置为隐藏,这样如果该索引没了会导致效率降低或不符合预期,就可以再将索引设置为可见。
隐藏后的特点:当更新表中的数据时,仍然会更新索引
不会使用到该索引(查询优化器不可见所以就无法使用)
使用方法(在创建或修改索引时添加invisable)
# 创建一个索引并设置为隐藏 CREATE INDEX idx_t_1_sname ON t_1(sname) invisible; # 将一个已有的索引设置为隐藏 ALTER TABLE t_1 ALTER INDEX idx_t_1_sname visible;
select @@optimizer_switch; set session optimizer_switch="use_invisible_indexes=on";
use_invisible_indexes=off
(1)字段的数值有唯一性约束(业务上具有唯一特性的字段,即使是组合字段,也必须建立为唯一索引),虽然影响了Insert的速度,但是这个速度是可以忽略不计,对查询速度点提升是明显的。
(2)频繁作为WHERE查询条件的字段
(3)经常GROUP BY 和 ORDER BY的字段
(4)UPDATE、INSERT时的WHERE条件列
(5)DISTINCT字段需要建立索引
(6)多表JOIN操作时,创建索引的注意事项
连接表尽量不要超过3张
对WHERE条件创建索引
最后, 对用于连接的字段创建索引 ,并且该字段在多张表中的 类型必须一致 。
(7)使用列类型小的字段创建索引
(8)字符串创建索引时,需要创建前缀索引alter table t_1 add index(intor(12));
(9)区分度高(散列性高)的列适合作为索引
(10) 使用最频繁的列放到联合索引的左侧
(11)在多个字段都要创建索引的情况下,联合索引优于单值索引
(12)一般一个表中,索引不能超过6个
(1)在where中使用不到的字段,不要设置索引
(2)数据量小的表最好不要使用索引,一般低于1000条数据,就没必要建立索引
(3)有大量重复数据的列上不要建立索引
(4)避免对经常更新的表创建过多的索引
(5)不建议用无序的值作为索引
(6)删除不再使用或者很少使用的索引
(7)不要定义冗余或重复的索引
冗余索引(例如联合索引中已经创建了某个字段的索引,还单独创建了一个该字段的单列索引或联合索引)
重复索引(一个索引又是唯一性索引、又是主键索引,也重复了)
整体思路: 先观察、再行动
SHOW [GLOBAL|SESSION] STATUS LIKE '参数';
一些常用的性能参数如下:
• Connections:连接MySQL服务器的次数。
• Uptime:MySQL服务器的上线时间。
• Slow_queries:慢查询的次数。
• Innodb_rows_read:Select查询返回的行数
• Innodb_rows_inserted:执行INSERT操作插入的行数
• Innodb_rows_updated:执行UPDATE操作更新的行数
• Innodb_rows_deleted:执行DELETE操作删除的行数
• Com_select:查询操作的次数。
• Com_insert:插入操作的次数。对于批量插入的 INSERT 操作,只累加一次。
• Com_update:更新操作的次数。
• Com_delete:删除操作的次数。
当执行了一条SQL语句后,可以通过如下命令获取到执行该条SQL所获取的数据页
SHOW STATUS LIKE '%last_query_cost%';
在进行查询时,采用顺序读取的方式将页面一次性加载到缓冲池中,然后再进行查找。虽然 页数量(last_query_cost)增加了不少 ,但是通过缓冲池的机制,并 不会增加多少查询时间 。
查询慢日志是否开启SHOW VARIABLES LIKE '%slow_query_log%';
开启慢日志SET GLOBAL slow_query_log = 1
再次查看慢日志可以发现多了一个日志文件SHOW VARIABLES LIKE '%slow_query_log%';
这个名字是以主机名-show.log命名的
SHOW STATUS LIKE '%Slow_queries%'
查看慢查询阈值SHOW VARIABLES LIKE '%long_query_time%';
,可以看到默认是10秒
修改慢查询阈值SET [global|session] long_query_time = 1
,
-a: 不将数字抽象成N,字符串抽象成S
-s: 是表示按照何种方式排序:
-t: 即为返回前面多少条的数据
-g: 后边搭配一个正则匹配模式,大小写不敏感的
#得到返回记录集最多的10个SQL mysqldumpslow -s r -t 10 慢查询日志文件路径 #得到访问次数最多的10个SQL mysqldumpslow -s c -t 10 慢查询日志文件路径 #得到按照时间排序的前10条里面含有左连接的查询语句 mysqldumpslow -s t -t 10 -g "left join" 慢查询日志文件路径 #另外建议在使用这些命令时结合 | 和more 使用 ,否则有可能出现爆屏情况 mysqldumpslow -s r -t 10 慢查询日志文件路径 | more
[mysqld] slow_query_log=OFF 或者 [mysqld] #slow_query_log =OFF
SET GLOBAL slow_query_log=off;
删除
重建
mysqladmin -uroot -p flush-logs slow
提示:相当于重建了慢查询日志,如果要使用之前的,记得先备份。
介绍:该功能开启后,可以监控每一条SQL指令,查看SQL的执行成本。
# 查看功能是否开启 SHOW VARIABLES LIKE '%profiling%'; # 开启该功能(这里仅开启session当前会话) SET profiling = 1;
# 查询监控到的SQL,该命令可以看到一个字段叫做Query_ID SHOW PROFILES; # 通过Query_ID查询指定SQL的执行成本,例如Query_ID = 37 SHOW PROFILE FOR QUERY 37;
(1) ALL:显示所有的开销信息。
(2) BLOCK IO:显示块IO开销。
(3) CONTEXT SWITCHES:上下文切换开销。
(4) CPU:显示CPU开销信息。
(5) IPC:显示发送和接收开销信息。
(6)MEMORY:显示内存开销信
息。
(7) PAGE FAULTS:显示页面错误开销信息。
(8) SOURCE:显示和Source_function,Source_file,Source_line相关的开销信息。
(9) SWAPS:显示交换次数开销信息。
版本情况(了解)
MySQL 5.6.3以前只能 EXPLAIN SELECT ;MYSQL 5.6.3以后就可以 EXPLAIN SELECT,UPDATE,DELETE
在5.7以前的版本中,想要显示 partitions 需要使用 explain partitions 命令;想要显示filtered 需要使用 explain extended 命令。在5.7版本后,默认explain直接显示partitions和filtered中的信息。
EXPLAIN 后接SQL语句即可
不论我们的查询语句有多复杂,里边儿 包含了多少个表 ,到最后也是需要对每个表进行 单表访问 的,所以MySQL规定EXPLAIN语句输出的每条记录都对应着某个单表的访问方法,该条记录的table列代表着该表的表名(有时不是真实的表名字,可能是简称)。
(1)一个SELECT对应一个唯一id,被优化器进行SQL优化后可能会有变化.
(2)id如果相同,可以认为是一组,从上往下顺序执行
(3)在所有组中,id值越大,优先级越高,越先执行
(4)关注点:id号每个号码,表示一趟独立的查询, 一个sql的查询趟数越少越好
查询类型。
完整的访问方法如下:按照常理来说越往后效率越低。
(1)system 属于const类型的特例,表只有一条记录行,几乎不会出现
(2)const 常数级别,根据主键或者唯一性二级索引列与常数进行匹配时,对单表的访问类型为const,查询时表中只有一条记录与之对应。
(3)eq_ref 在连接查询时,如果被驱动表是通过主键或者唯一性二级索引列等值匹配的方式进行访问的。(如果是联合索引的话,所有索引列都必须进行等值比较)则对该被驱动表的访问办法就是'rq_ref'。
(4)ref** 根据二级索引列与常数进行匹配时,对单表的访问类型为ref,查询时表中只有一条记录与之对应,在多表连接时,如果被驱动表与驱动表的等值匹配字段为二级索引时,访问类型也为ref。
(5)fulltext
(6)ref_or_null ,在第四点的基础上,再添加一个 and 二级索引 is null.
(7)index_merge ,当多个单列索引共同出现在查询条件中时,优化器可能会使用该种访问方式
(8)unique_subquery
(9)index_subquery
(10)range 使用索引列进行范围查询时
(11)index 覆盖索引时出现
(12)AL L全表扫描
possibale_key : 可能会使用到的索引
key:实际使用到的索引
一般主要对于联合索引比较有参考价值
可以看到联合索引中使用到的索引长度
注意:行格式中null值的标志位为1个字节,可变长度记录列为2个字节
这2个属性通常一起使用
rows表示可能查询出的记录数
filtered表示可能会用上行数的百分比
例如rows为100,而filtered为10,那么可能实际需要的数据量为100 * 10%= 10行
Impossible WHERE(不可能的查询条件,例如1=2)
Using where(没有使用上索引时)
No matching min/max row 没有聚合查询的匹配结果
Using index 使用上了索引
Using index condition 索引下推时
Using join buffer (Block Nested Loop) 连接时使用上了块缓冲池
Not exists 不存在
Using filesort 使用了文件排序
Zero limit
Using temporary 使用上了临时表,例如DISTINCT时
# 传统格式 EXPLAIN # JSON格式 EXPLAIN FORMAT=JSON # Tree格式 EXPLAIN FORMAT=tree # 可视化格式 可以通过MySQL Workbench可视化查看MySQL的执行计划
EXPLAIN不考虑各种Cache
EXPLAIN不能显示MySQL在执行查询时所作的优化工作
EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
部分统计信息是估算的,并非精确值
SHOW WARNINGS;
命令查看优化器优化后的SQL语句# 设置trace开启,并指定格式为JSON SET optimizer_trace="enabled=on",end_markers_in_json=on; # 设置trace最大能够使用的内存大小,避免因内存过小不能够完整展示 set optimizer_trace_max_mem_size=1000000;
select * from information_schema.optimizer_trace;
主机相关:以host_summary开头,主要汇总了IO延迟的信息。
Innodb相关:以innodb开头,汇总了innodb buffer信息和事务等待innodb锁的信息。
I/o相关:以io开头,汇总了等待I/O、I/O使用量情况。
内存使用情况:以memory开头,从主机、线程、事件等角度展示内存的使用情况
连接与会话信息:processlist和session相关视图,总结了会话相关信息。
表相关:以schema_table开头的视图,展示了表的统计信息。
索引信息:统计了索引的使用情况,包含冗余索引和未使用的索引情况。
语句相关:以statement开头,包含执行全表扫描、使用临时表、排序等的语句信息。
用户相关:以user开头的视图,统计了用户使用的文件I/O、执行语句统计信息。
等待事件相关信息:以wait开头,展示等待事件的延迟情况。
#1. 查询冗余索引 select * from sys.schema_redundant_indexes; #2. 查询未使用过的索引 select * from sys.schema_unused_indexes; #3. 查询索引的使用情况 select index_name,rows_selected,rows_inserted,rows_updated,rows_deleted from sys.schema_index_statistics where table_schema='dbname' ;
# 1. 查询表的访问量 select table_schema,table_name,sum(io_read_requests+io_write_requests) as io from sys.schema_table_statistics group by table_schema,table_name order by io desc; # 2. 查询占用bufferpool较多的表 select object_schema,object_name,allocated,data from sys.innodb_buffer_stats_by_table order by allocated limit 10; # 3. 查看表的全表扫描情况 select * from sys.statements_with_full_table_scans where db='dbname';
#1. 监控SQL执行的频率 select db,exec_count,query from sys.statement_analysis order by exec_count desc; #2. 监控使用了排序的SQL select db,exec_count,first_seen,last_seen,query from sys.statements_with_sorting limit 1; #3. 监控使用了临时表或者磁盘临时表的SQL select db,exec_count,tmp_tables,tmp_disk_tables,query from sys.statement_analysis where tmp_tables>0 or tmp_disk_tables >0 order by (tmp_tables+tmp_disk_tables) desc;
#1. 查看消耗磁盘IO的文件 select file,avg_read,avg_write,avg_read+avg_write as avg_io from sys.io_global_by_file_by_bytes order by avg_read limit 10;
#1. 行锁阻塞情况 select * from sys.innodb_lock_waits;
(1)最佳左前缀法则会出现的情况:若是跳过左边的索引,直接想要使用右边的,那不行
(2)当索引列出现函数、计算、类型转换(自动或手动)时会导致该索引失效
(3)范围条件右边的列索引失效
(5)不等于、is not null、等会使索引失效
(6)like以通配符%开头
(7)or前后存在非索引列,索引失效
(8)MYSQL8数据库、表的字符集统一使用utf8mb4,字符集的转换也会导致索引失效。
为被驱动表的等值比较列添加索引
为where条件中的字段添加索引
Index Nested-Loop Join 索引嵌套循环连接
Hash Nested-Loop Join 哈希嵌套循环连接
Block Nested-Loop Join 块嵌套循环连接
Simple Nested-Loop Join 简单嵌套循环连接
简单嵌套循环连接
块嵌套循环连接
由优化器进行确认。
一般如果驱动表与被驱动表进行连接的字段均没有索引、或者均有索引的情况下。 优化器会按照小表驱动大表的原则分配驱动表与被驱动表。(注意大小指的是结果集的行数 * 每行的大小得出)
而一般如果其中任意一张表的连接字段有索引,那么很可能会被优化器当成被驱动表使用
# 查看block_nested_loop是否开启 show variables like '%optimizer_switch%' # 驱动表能不能被一次性加载完,要看join buffer能不能存储下所有驱动表的数据。默认大小为256k,Windows以及32位的操作系统最多申请4G,64位的Linux可以申请4G以上 show variables like '%join_buffer%;'
注意:子查询结果集作为一张表出现时,无法使用到索引
建议:能不用子查询就尽量不用,可以换成多表连接的方式。多表连接起码还有个join缓存池。
SQL 中,可以在 WHERE 子句和 ORDER BY 子句中使用索引,目的是在 WHERE 子句中 避免全表扫描 ,在 ORDER BY 子句 避免使用 FileSort 排序 。当然,某些情况下全表扫描,或者 FileSort 排序不一定比索引慢。但总的来说,我们还是要避免,以提高查询效率。
尽量使用 Index 完成 ORDER BY 排序。如果 WHERE 和 ORDER BY 后面是相同的列就使用单索引列;如果不同就使用联合索引。
无法使用 Index 时,需要对 FileSort 方式进行调优。
当【范围条件】和【group by 或者 order by】的字段出现二选一时,优先观察条件字段的过滤数量,如果过滤的数据足够多,而需要排序的数据并不多时,优先把索引放在范围字段上。反之,亦然。
双路排序(慢)
需要进行2次磁盘扫描,最终得到数据。先从磁盘中取出所有需要排序的字段,在buffer进行排序后再次扫描磁盘获取到其他的字段。
单路排序
一次就将需要排序与不需要排序的字段加载进buffer中进行排序,避免了二次访问磁盘。
sort缓存的大小设置
sort_buffer_size
sort如果Query的字段大小总和小于该值,则会使用单路排序,否则使用双路排序。默认1024字节,可以在1027-8192字节之间调整
show variables like '%max_length_for_sort_data%';
GROUP BY使用索引的原则几乎与ORDER BY一致,即便没有过滤条件使用了索引,GROUP BY 也可以直接使用索引
遵循最佳左前缀法则
当无法使用索引列,也可以通过增大sort中的2个参数进行优化
减少使用order by,像distinct、order by、group by这些语句比较耗费cpu
如果包含了order by、group by、distinct这些查询语句,那么where条件过滤出来的结果集应该保持在1000条以内,否则SQL会很慢
当select字段中仅包含当前使用上的索引时,将不会进行回表操作,这种情况下称之为覆盖索引,表访问类型为index
可能会打破一些上述中描述的可能无法使用索引的情况
结论:不用回表
索引下推 index condition pushdown,当有多个筛选条件时,优先在B+Tree中将条件都筛选完,再进行回表操作。
可能会打破一些上述中描述的可能无法使用索引的情况
结论:减少回表次数,仅支持二级索引
前提: A表大于B表
Exists相当于是一个相关子查询,一般右边为被驱动表(大表)会比较合适
而In相当于是先内层查询再到外层查询,所以外层(左边)为驱动表比较合适
首先COUNT(*)与COUNT(1)的效率是一致的
在都保证查询出的数据无误的情况下,介绍如下情况
(1)保证全局且唯一
(2)保证有序,避免影响B+树索引的创建
(3)UUID其实在经过更新迭代后,将高位的时间与低位进行替换,再使用16进制显示,占用16个字节的同时也可以保证单调递增
(4)雪花算法挺牛的
(1)会释放回滚段上用于恢复数据的信息
(2)会释放被程序语句获得的锁
(3)会释放redo/undo/buffer中的空间
释放资源以提高服务器的性能。
事务是一组逻辑操作单元,使数据从一种状态变换到另一种状态。
原子性(atomicity):表示事务是不可分割的工作单位,要么一起执行成功,要么都不执行。
一致性(consistency):将数据从一个合法性状态转换到另一个合法性状态,这个合法性状态指的不是语法上的,而是语义上的,满足预定的约束就称为满足了一致性。
隔离性(isolation):一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对 并发 的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability):是指事物一旦被提交,那么对数据库中数据的改变就是永久性的。
活动的:事务正在执行的状态
部分提交的:事务已经在内存中完成了操作,但是还没有COMMIT
提交的:执行了COMMIT,数据刷新到磁盘后
失败的:事务执行过程中出现了错误导致程序执行失败。
中止的:将失败的事务进行回滚之后。
# 格式1 begin commit/rollback # 格式2,中括号中3个选项分别为只读,读写、启动一致性读 start transaction [READ ONLY | READ WRITE | WITH CONSISTENT SNAPSHOT] commit/rollback
# 将自动提交关闭 SET autocommit = OFF; commit/rollback;
# 设置保存点,任意取个名 SAVEPOINT aaa; # 回滚到保存点处,注意:这个时候事务并没有关闭。 ROLLBACK TO aaa;
READ UNCOMMITTED :读未提交:会出现脏读、可重复读、幻读的现象
READ COMMITTED:读已提交:会出现 不可重复读、幻读的现象
REPEATABLE READ :可重复读:会出现幻读
SERIALIZABLE:都能解决,但效率非常低
查看当前隔离级别
transaction_isolation
设置当前隔离级别
# 例如设置为读已提交,注意,该变量也可以设置为global全局 set transaction_isolation = 'READ-COMMITTED'; # 如果需要永久生效,需要修改配置文件 [mysqld] transaction-isolation = READ-COMMITTED
Redo日志在事务执行的过程中就会不断的将数据存储在Redo日志当中(保证数据的持久性)。binlog日志只有在COMMIT时才会将内存中的数据写入到binlog日志中
如果内存中的数据还没有刷到磁盘上,那么MYSQL在重启时,会读取Redo日志来恢复日志保证持久性。
redo日志的好处
redo日志的特点
一个事物可以包含若干个语句,而一个语句可以包含若干个mtr,底层的原子操作
redo log buffer当中有着一个个的redo日志块,每个日志块有512字节,刚好有一个扇区的大小,避免因为扇区损坏出现无法保证原子性和一致性问题。
write pos指针记录着已经写到了磁盘文件的哪个位置
checkpoint指针记录这已经清理了的磁盘位置。
当wirte pos 追上了 checkpoint,表示日志文件组满了,这时候不能再写入新的 redo log记录,MySQL 得停下来,清空一些记录,把 checkpoint 推进一下。
innodb_flush_log_at_trx_commit:刷新策略
innodb_log_buffer_size:日志redo log buffer缓存的默认大小为16M
innodb_log_files_in_group:redo日志在磁盘中有几个文件,默认为2
innodb_log_file_size:日志文件大小,注意:是单个日志文件的大小总和,默认为48M,注意所有redo 日志文件的大小不能超过512G
innodb_flush_log_at_timeout:每隔多少秒,将redo log buffer中的数据刷盘到磁盘文件当中
重点提示:Redo日志在事务执行的过程中就会不断的将数据存储在Redo日志当中
undo log是逻辑日志,对事务回滚时,只是将数据库逻辑地恢复到原来的样子。已经开辟的updo 页并不会删除,仅仅是从逻辑上删除了而已。
未提交的回滚数据(uncommitted undo information)
已经提交但未过期的回滚数据(committed undo information)
事务已经提交并过期的数据(expired undo information)
读锁/共享锁/S锁
写锁/排他锁/X锁
表级锁
行级锁
页级锁
小提示:当行锁的压力过大时,MYSQL会自动升级为表锁。
悲观锁
乐观锁:由程序实现,不依赖于MYSQL的锁
隐式锁
显示锁
全局锁:全库逻辑备份时使用
Flush tables with read lock
死锁
show status like 'innodb_row_lock%';
(1)Innodb_row_lock_current_waits:当前正在等待锁定的数量;
(2)Innodb_row_lock_time :从系统启动到现在锁定总时间长度;(等待总时长)
(3)Innodb_row_lock_time_avg :每次等待所花平均时间;(等待平均时长)
(4)Innodb_row_lock_time_max:从系统启动到现在等待最常的一次所花的时间;
(5)Innodb_row_lock_waits :系统启动后到现在总共等待的次数;(等待总次数)
SELECT * FROM information_schema.INNODB_TRX\G;
SELECT * FROM data_lock_waits\G;
SELECT * from performance_schema.data_locks\G;
MVCC (Multiversion Concurrency Control),多版本并发控制。顾名思义,MVCC 是通过数据行的多个版
本管理来实现数据库的 并发控制 。这项技术使得在InnoDB的事务隔离级别下执行 一致性读 操作有了保
证。换言之,就是为了查询一些正在被另一个事务更新的行,并且可以看到它们被更新之前的值,这样
在做查询的时候就不用等待另一个事务释放锁。
MV = undo log
CC = ReadView
仅在读已提交和可重复读这两个隔离级别上有效。
快照读: 读历史记录undo log
当前读: 读最新的记录
row_id ,当表中没有主键和唯一键时又InnoDB设置
trx_id ,对该数据进行操作的事务ID
roll_pointer:回滚指针,指向undo日志中上一个与主键一致的记录
读可提交:每个SELECT都会创建一个新的ReadView
可重复读:一个SELECT只会创建一个ReadView
注意行格式中的删除标记,可以被ReadView利用
作用:记录所有连接的起始时间和终止时间,以及连接发送给数据库服务器的所有指令,对我们复原操作的实际场景、发现问题,甚至是对数据库操作的审计都有很大的帮助。
查看通用查询日志是否开启以及文件地址show variables like '%general_log%';
(默认关闭)
开启该日志set global general_log = 1;
随便执行几条SQL,查看一下日志文件
关闭该日志set global general_log = 0;
作用:记录MySQL服务的启动、运行或停止MySQL服务时出现的问题,方便我们了解服务器的状态,从而对服务器进行维护。(默认开启且无法被关闭)
查看错误日志的配置信息show variables like 'log_error%';
查看一下错误日志vim /var/log/mysqld.log;
show variables like '%log_bin%';
flush logs
# 启用二进制日志,指名路径。比如:自己本地的路径/log/mysql-bin log-bin=/log/mysql-bin # 设置日志文件保留的时长,单位是秒 binlog_expire_logs_seconds=6000 # 控制单个二进制日志大小。此参数的最大和默认值是1GB max_binlog_size=200M # 设置不要复制的数据库 binlog-ignore-db=test # 设置需要复制的数据库,默认全部记录。多个数据库的话,该配置可以写多次比如:binlog-do-db=codestarts_master_slave binlog-do-db=需要复制的主数据库名字 # 设置binlog格式 binlog_format=STATEMENT
Statement
不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能,如果记录的行出现了函数,可能会导致主从机数据不一致,例如主机插入数据时使用了NOW()函数。binlog记录时只是记录了NOW()函数,并不是插入的行记录。
Row
row level 的日志内容会非常清楚的记录下每一行数据修改的细节。而且不会出现某些特定情况下
的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题。
Mixed(如上2种的结合)
0:当执行提交时,只会将binlog cache中的数据写入到操作系统的Page Cache当中(如果操作系统宕机可能出现数据的丢失)
1:每当进行提交时,都会将数据写入Page Cache并进行刷盘操作(与redo 日志的刷新规则参数有些相似)
n:这个n指的是1 + n,当第n次提交时候,才会主动执行刷盘操作,其他时候都只会将数据写入Page Cache
binlog是逻辑日志,记录内容是语句的原始逻辑。
redo log是物理日志,记录的是一条条的执行结果,属于InnoDB存储层产生的。
思考:执行commit时,redo日志是在事物的过程中就不断写入,binlog是在commit时才会写入。(注意这里说的都是写入缓存),redo日志完成了刷盘操作,而此时binlog 还没有完成刷盘操作,此时服务器宕机了,就会导致binlog中的数据不完整,那么在进行主从复制时,从机的数据就与主机不一致了。怎么解决这个问题?
二阶段提交
# -v 以伪sql的方式展示出来 mysqlbinlog -v binlog日志文件路径
show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]; # IN 'log_name' :指定要查询的binlog文件名(不指定就是第一个binlog文件) # FROM pos :指定从哪个pos起始点开始查起(不指定就是从整个文件首个pos点开始算) # LIMIT [offset] :偏移量(不指定就是0) # row_count :查询总条数(不指定就是所有行) 例如:show binlog events in 'codestarts-bin.000003';
(1)使用show binlog events in '日志文件';
来定位需要恢复的数据位置
(2)使用如下命令完成数据恢复
# 注意开始的定位、结束的定位、数据库名、binlog文件名、用户名密码、以及-v后面的数据库名 /usr/bin/mysqlbinlog --start-position=? --stop-position=? --database=? /var/lib/mysql/binlog/codestarts-bin.000003 | /usr/bin/mysql -uroot -p? -v 数据库名 /usr/bin/mysqlbinlog --start-position= --stop-position=? --database=? /var/lib/mysql/binlog/codestarts-bin.000003 | /usr/bin/mysql -uroot -p? -v 数据库名
insert into table1 values(10,'lisi'); insert into table1 values(11,'lisi'); insert into table1 values(12,'lisi'); delete from table1 where id > 9;
查看binlog日志文件
show binlog events in 'codestarts-bin.000003';
恢复数据(非常好用)
/usr/bin/mysqlbinlog --start-position=219 --stop-position=1014 --database=mydb /var/lib/mysql/codestarts-bin.000003 | /usr/bin/mysql -uroot -pabc123 -v mydb
删除某个binlog日志文件之前的(不包括当前)
purge master logs to 'codestarts-bin.000003';
全部删除(注意后果)
purge master;
提示:恢复文件时,如果需要恢复文件1和文件2,而文件2是在文件1之后生成的,那么则需要先恢复文件1
作用:用于主从服务器架构中,从服务器用来存放主服务器二进制日志内容的一个中间文件。从服务器通过读取中继日志的内容,来同步主服务器上的操作。
中继日志只在主从服务器架构的从服务器上存在。
搭建好主从服务器之后,中继日志默认会保存在从服务器的数据目录下。文件名的格式是: 从服务器名 -relay-bin.序号 。中继日志还有一个索引文件: 从服务器名 -relaybin.index ,用来定位当前正在使用的中继日志。
主机负责写入数据,同时写入binlog日志文件,再调用io线程将数据传递给从机
从机负责读取数据,当主机写入binlog日志后通过io线程获取主机传送过来的binlog日志文件,将其写入中继日志,再将中继日志中的数据写入到从机的数据库。
采用克隆的方式完成新一台虚拟机的配置
新的一台虚拟机需要修改:MAC地址、IP地址、UUID、主机名[可选]、MYSQL的服务的UUID
vim /etc/hostname
vim /var/lib/mysql/auto.cnf
reboot重启一下
# 1.关闭防火墙 systemctl stop firewalld.service; # 2. 开放端口 firewall-cmd --permanent --add-port=3306/tcp; firewall-cmd --reload;
[mysqld] #启用二进制日志 # 为每个mysql服务器配置的id server-id=1 # binlog日志的前缀 log-bin=codestarts-bin #[可选] 0(默认)表示读写(主机),1表示只读(从机) read-only=0 # 设置日志文件保留的时长,单位是秒,注意:MYSQL8才支持的 # binlog_expire_logs_seconds=6000 ##控制单个二进制日志大小。此参数的最大和默认值是1GB max_binlog_size=200M ##[可选]设置不要复制的数据库 binlog-ignore-db=test ##[可选]设置需要复制的数据库,默认全部记录。比如:binlog-do-db=atguigu_master_slave binlog-do-db=codestarts_db ##[可选]设置binlog格式 binlog_format=STATEMENT
[mysqld] #[必须]从服务器唯一ID server-id=2 #[可选]启用中继日志 relay-log=mysql-relay #[可选] 0(默认)表示读写(主机),1表示只读(从机) read-only=1
#在主机MySQL里执行授权主从复制的命令 GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'从机器数据库IP' IDENTIFIED BY 'abc123'; # 例如 GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'%' IDENTIFIED BY '123123';
CREATE USER 'slave1'@'%' IDENTIFIED BY '123123'; GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'%'; #此语句必须执行。否则见下面。 ALTER USER 'slave1'@'%' IDENTIFIED WITH mysql_native_password BY '123123'; flush privileges;
show master status;
CHANGE MASTER TO MASTER_HOST='主机的IP地址', MASTER_USER='主机用户名', MASTER_PASSWORD='主机用户名的密码', MASTER_LOG_FILE='mysql-bin.具体数字', MASTER_LOG_POS=具体值; CHANGE MASTER TO MASTER_HOST='192.168.22.22',MASTER_USER='slave1',MASTER_PASSWORD='123123',MASTER_LOG_FILE='codestarts-bin.000005',MASTER_LOG_POS=154;
从机:启动SLAVE同步slave start;
主/从机:查看SLAVE状态show slave status;
从机:删除中继文件reset slave;
reset slave; #删除SLAVE数据库的relaylog日志文件,并重新启用新的relaylog文件,这时候需要重新复制主机
主机:查看当前主机binlog信息show master slave;
mysqldump -uroot -pabc123 db_dump_test>db_dump_test.sql
# 使用--all-databases或者-A参数 mysqldump -uroot -pabc123 --all-databases >all_databases.sql
mysqldump –u user –h host –p --databases [数据库的名称1 [数据库的名称2...]] > 备份文件名 称.sql
mysqldump –u user –h host –p 数据库的名称 [表名1 [表名2...]] > 备份文件名称.sql # 例如备份多张表 mysqldump -uroot -p db_dump_test book studetn > multi_tables.sql
# 备份student表中id小于10的数据 mysqldump -uroot -p db_dump_test student --where="id < 10 " > student_part_id_low10.sql
mysqldump -uroot -p db_dump_test --ignore-table=db_dump_test.student > no_stu_bak.sql
# 只备份结构:没有数据 mysqldump -uroot -p db_dump_test --no-data > db_no_data_bak.sql # 只备份数据:没有结构 mysqldump -uroot -p db_dump_test --no-create-info > db_no_create_info_bak.sql
# 可以使用 --routines 或 -R 选项来备份存储过程及函数,使用 --events 或 -E 参数来备份事件。 mysqldump -uroot -p -R -E --databases db_dump_test > fun_db_bak.sql
--add-drop-database:在每个CREATE DATABASE语句前添加DROP DATABASE语句。 --add-drop-tables:在每个CREATE TABLE语句前添加DROP TABLE语句。 --add-locking:用LOCK TABLES和UNLOCK TABLES语句引用每个表转储。重载转储文件时插入得更快。 --all-database, -A:转储所有数据库中的所有表。与使用--database选项相同,在命令行中命名所有数据库。 --comment[=0|1]:如果设置为0,禁止转储文件中的其他信息,例如程序版本、服务器版本和主机。--skipcomments与--comments=0的结果相同。默认值为1,即包括额外信息。 --compact:产生少量输出。该选项禁用注释并启用--skip-add-drop-tables、--no-set-names、--skipdisable-keys和--skip-add-locking选项。 --compatible=name:产生与其他数据库系统或旧的MySQL服务器更兼容的输出,值可以为ansi、MySQL323、 MySQL40、postgresql、oracle、mssql、db2、maxdb、no_key_options、no_table_options或者 no_field_options。 --complete_insert, -c:使用包括列名的完整的INSERT语句。 --debug[=debug_options], -#[debug_options]:写调试日志。 运行帮助命令 mysqldump --help ,可以获得特定版本的完整选项列表。 提示 如果运行mysqldump没有--quick或--opt选项,mysqldump在转储结果前将整个结果集装入内 存。如果转储大数据库可能会出现问题,该选项默认启用,但可以用--skip-opt禁用。如果使用最 新版本的mysqldump程序备份数据,并用于恢复到比较旧版本的MySQL服务器中,则不要使用--opt 或-e选项。 --delete,-D:导入文本文件前清空表。 --default-character-set=charset:使用charsets默认字符集。如果没有指定,就使用utf8。 --delete--master-logs:在主复制服务器上,完成转储操作后删除二进制日志。该选项自动启用-masterdata。 --extended-insert,-e:使用包括几个VALUES列表的多行INSERT语法。这样使得转储文件更小,重载文件时可 以加速插入。 --flush-logs,-F:开始转储前刷新MySQL服务器日志文件。该选项要求RELOAD权限。 --force,-f:在表转储过程中,即使出现SQL错误也继续。 --lock-all-tables,-x:对所有数据库中的所有表加锁。在整体转储过程中通过全局锁定来实现。该选项自动关 闭--single-transaction和--lock-tables。 --lock-tables,-l:开始转储前锁定所有表。用READ LOCAL锁定表以允许并行插入MyISAM表。对于事务表(例 如InnoDB和BDB),--single-transaction是一个更好的选项,因为它根本不需要锁定表。 --no-create-db,-n:该选项禁用CREATE DATABASE /*!32312 IF NOT EXIST*/db_name语句,如果给出- -database或--all-database选项,就包含到输出中。 --no-create-info,-t:只导出数据,而不添加CREATE TABLE语句。 --no-data,-d:不写表的任何行信息,只转储表的结构。 --opt:该选项是速记,它可以快速进行转储操作并产生一个能很快装入MySQL服务器的转储文件。该选项默认开启, 但可以用--skip-opt禁用。 --password[=password],-p[password]:当连接服务器时使用的密码。 -port=port_num,-P port_num:用于连接的TCP/IP端口号。 --protocol={TCP|SOCKET|PIPE|MEMORY}:使用的连接协议。 --replace,-r –replace和--ignore:控制替换或复制唯一键值已有记录的输入记录的处理。如果指定-- replace,新行替换有相同的唯一键值的已有行;如果指定--ignore,复制已有的唯一键值的输入行被跳过。如果不 指定这两个选项,当发现一个复制键值时会出现一个错误,并且忽视文本文件的剩余部分。 --silent,-s:沉默模式。只有出现错误时才输出。 --socket=path,-S path:当连接localhost时使用的套接字文件(为默认主机)。 --user=user_name,-u user_name:当连接服务器时MySQL使用的用户名。 --verbose,-v:冗长模式,打印出程序操作的详细信息。 --xml,-X:产生XML输出。
# 如果备份文件中包含了创建数据库的语句,则恢复的时候不需要指定数据库名称 mysql -uroot -p < mydb.sql # 如果不包含,则需要自己创建数据库后 mysql -uroot -p mydb< mydb.sql
mysql –u root –p < all.sql
# 从全量备份中将单个数据库的信息抽取出来 sed -n '/^-- Current Database: `db_dump_test`/,/^-- Current Database: `/p' all_database.sql> db_dump_test.sql # 这个时候就只需要执行恢复单库命令即可 mysql -uroot -p < db_dump_test.sql
# 获取单表的结构,例如这里是从db_dump_test.sql这个数据库备份中获取student表的结构 cat db_dump_test.sql | sed -e '/./{H;$!d;}' -e 'x;/CREATE TABLE `student`/!d;q' >student_structure.sql # 获取单表的数据 cat db_dump_test.sql | grep --ignore-case 'insert into `student`' > student_data.sql # 接下来只需要把如上2个生成的SQL都在MYSQL命令行执行(注意路径问题) source student_structure.sql; source student_data.sql;
mysql默认对导出的目录有权限限制,也就是说使用命令行进行导出的时候,需要指定目录进行操作。
查询secure_file_priv值:
上面结果中显示,secure_file_priv变量的值为/var/lib/mysql-files/,导出目录设置为该目录,SQL语句如下。
SELECT * FROM account INTO OUTFILE "/var/lib/mysql-files/account.txt";
导出的结果如下:
mysqldump -uroot -p -T "/var/lib/mysql-files/" db_dump account
mysqldump -uroot -p -T "/var/lib/mysql-files/" db_dump account --fields-terminatedby=',' --fields-optionally-enclosed-by='\"'
- 使用mysql语句导出db_dump数据中account表中的记录到文本文件 mysql -uroot -p --execute="SELECT * FROM account;" db_dump>"/var/lib/mysqlfiles/account.txt" - 将db_dump数据库account表中的记录导出到文本文件,使用--veritcal参数将该条件记录分为多行显示 mysql -uroot -p --vertical --execute="SELECT * FROM account;" db_dump >"/var/lib/mysql-files/account_1.txt" - 将db_dump数据库account表中的记录导出到xml文件,使用--xml参数 mysql -uroot -p --xml --execute="SELECT * FROM account;" db_dump>"/var/lib/mysqlfiles/account_3.xml" - 如果要将表数据导出到html文件中,可以使用 --html 选项。然后可以使用浏览器打开。
# 先导出点数据 SELECT * FROM db_dump.account INTO OUTFILE '/var/lib/mysql-files/account_0.txt'; # 删除account表中的数据 DELETE FROM db_dump.account; # 导入数据 LOAD DATA INFILE '/var/lib/mysql-files/account_0.txt' INTO TABLE db_dump.account;
# 使用SELECT…INTO OUTFILE将db_dump数据库account表中的记录导出到文本文件,使用FIELDS选项和LINES选项,要求字段之间使用逗号","间隔,所有字段值用双引号括起来 SELECT * FROM db_dump.account INTO OUTFILE '/var/lib/mysql-files/account_1.txt' FIELDS TERMINATED BY ',' ENCLOSED BY '\"'; # 删除account表中的数据 DELETE FROM db_dump.account; # 从/var/lib/mysql-files/account.txt中导入数据到account表中 LOAD DATA INFILE '/var/lib/mysql-files/account_1.txt' INTO TABLE atguigu.account FIELDS TERMINATED BY ',' ENCLOSED BY '\"';
# 导出文件account.txt,字段之间使用逗号","间隔,字段值用双引号括起来 SELECT * FROM db_dump.account INTO OUTFILE '/var/lib/mysql-files/account.txt' FIELDS TERMINATED BY ',' ENCLOSED BY '\"'; # 删除表中数据 DELETE FROM db_dump.account; # 使用mysqlimport命令将account.txt文件内容导入到数据库db_dump的account表 mysqlimport -uroot -p db_dump '/var/lib/mysql-files/account.txt' --fields-terminated by=',' --fields-optionally-enclosed-by='\"