MySQL运维命令速查手册

1,445 阅读25分钟

1. MySQL常用查询语句

1.1. 库操作

1.1.1. 创建数据库

CREATE database dbname;

1.1.2. 删除库

DROP database db1;srment12052

1.1.3. 切换到库

USE dbname; 

1.2. 表操作

1.2.1. 创建数据表

CREATE TABLE <表明>
  (
     列名1, 数据类型[约束][默认值],
     列名2, 数据类型[约束][默认值],
     列名n, 数据类型[约束][默认值],
     )[ENGINE=存储引擎][CHARACTER SET=字符集];

例:

CHARACTER TABLE t1
  (
    id INT PRIMARY KEY,   #设定该列为主键,主键内的值必须唯一,会自动创建主键索引
    id2 INT not null,     #设置id2不允许为空
    name varchar(10),
    sex ENUM('F','M','UN')
  	)ENGINE=MYISAM CHARACTER SET utf8;

# 创建表t1,并设置两个列,一个列叫id类型是整形INT长度10,第二列叫name类型是可变长字符串VARCHAR长度20
#其中的长度代表显示的长度,一般没效果
CREATE TABLE t1( id INT(10), name VARCHAR(20) );

设定主键的第二种方式,先设定好每一列,最后再声明主键,方便一次性给多列设置主键

CREATE TABLE t1
  (
  	uid INT(100),
  	certid INT(20),
  	name VARCHAR(10),
  	sex ENUM('F','M','UN'),
  	PRIMARY KEY(uid,certid)
  	)ENGINE=InnoDB CHARACTER SET uft8;

创建表并沿用另外一张表的数据结构

CREATE TABLE t2 LIKE t1;

1.2.2. 表约束

1.2.2.1. 非空约束

#name列设置为非空列
CREATE TABLE t1
  (
  	uid INT PRIMARY KEY,
  	name VARCHAR(10) NOT NULL,             #非空
  	)ENGINE=MYISAM CHARACTER SET utf8;

1.2.2.2. 唯一性约束

约束列中的值不能重复,可以有但只能有一个空值
CREATE TABLE t13
  (
  	certid VARCHAR(20) UNIQUE
  	)ENGINE=MYISAM CHARACTER SET utf8;

1.2.2.3. 默认默认约束(默认值约束)

约束列中的值的默认值。

除非默认值为空值,否则不允许插入空值

CREATE TABLE t1
  (
      sex ENUM('F', 'M', 'NU') DEFAULT 'UN'
  )ENGINE=MYISAM CHARACTER SET utf8;

1.2.2.4. 自增长约束

用于系统自动生成字段的主键值

用于数据量较大且数据又连续性增长的列

值不能为空

CREATE TABLES t1
(
    uid INT PRIMARY KEY AUTO_INCREMENT
)ENGINE=MYISAM CHARACTER SET utf8;

1.2.3. 创建表,并设定外键

#设定外键的名称为fk_t1,关联到当前表t2的fid列,关联到其他表t1点uid列
CREATE TABLE t2
  (
  	fid INT(100),
  	phone varchar(16),
  	location varchar(50),
  	CONSTRAINT fk_t1 FOREIGN KEY(fid) REFERENCES t1(uid)
  	);

1.2.4. 删除表

DROP TABLE t1;

1.2.5. 删除表,如果表存在就删除,如是不存在也不会报错

DROP TABLE IF EXISTS t1;

1.2.6. 显示库中的所有表

SHOW TABLES;

根据关键词查找表 SHOW TABLES LIKE '%flex%';

1.2.7. 查看表结构

DESC tablename;
DESCRIBE tablename;

1.2.8. 修改表数据

1.2.8.1. 对表插入单行数据,有SET关键字

INSERT INTO table_name SET <字段1>=值1, <字段2>=值2, <字段n>=值n;

INSERT INTO tablename SET id = 1, name = 'tube';

1.2.8.2. 对表插入多行数据,无SET关键字

字符串值必须用单引号引起来

如果要插入所有字段,则字段可省略

INSERT INTO table_name
  [(字段1, 字段2, 字段n)]
VALUES
  (值1, 值2, 值n), (值1n, 值2n, 值3n);

INSERT INTO tablename (id,name) VALUES (2, 'kevin'), (3, 'mark');

1.2.8.3. 对表插入查询结果

将select的查询结果插入到表中

INSERT INTO table_name1
  (字段1, 字段2, 字段n)
SELECT 字段a, 字段b, 字段c FROM table_name2 [WHERE condition];

INSERT INTO t2
  (id, name, location)
SELECT id, name, locaton FROM t3;

1.2.8.4. 更新数据 update

UPDATE table_name SET
  字段1=值1,
  字段2=值2,
  字段n=值n
[WHERE condition];

UPDATE t1 SET
  name='Tom'
WHERE id=1;

1.2.8.5. 删除数据 DELETE

如果不带上where语句的话,delete会直接清空整张表

DELETE FROM table_nam [WHERE <condition>];

例子

DELETE FROM t8 where id> 13;
DELETE FROM t8 where id> 13 AND id< 18;
DELETE FROM t8 where id> 13 OR id< 3;

1.2.8.6. 清空表 TRUNCATE

将表内的所有数据清空,注意表名不要加引号

TRUNCATE TABLE tablename;

1.2.9. 其他操作

1.2.9.1. 显示创建库时使用的sql命令

SHOW CREATE database db3;

1.2.9.2. 显示有关在当前 session 中执行语句所产生的条件(错误,警告和注释)的信息

SHOW WARNINGS;

1.2.9.3. 显示错误总数

SHOW COUNT(*) WARNINGS;

1.2.9.4. 显示创建该表的指令

SHOW CREATE TABLE tablename; 
# \G将输出的结果旋转90度变成纵向
SHOW CREATE TABLE tablename\G;

1.2.9.5. 统计表中的行数

#统计t2表的行数
SELECT COUNT(*) FROM t2;

#通过WHERE指定一个条件来计数;
SELECT COUNT(*FROM t2 WHERE id = 2;

#加上DISTINCT,统计表中的唯一行
SELECT COUNT(DISTINCT id) FROM t2;

#以一列作为基准,统计列中每个值出现的次数
SELECT id, count(*) FROM t2 GROUP BY id;

#以一列为基准,统计列中每个值出现的次数,并只列出出现9次以上的结果
SELECT id, count(*) FROM t2 GROUP BY id HAVING count(*) >= 9;

1.2.9.6. 分析查询语句执行的过程

使用explain命令可以分析查询语句执行的过程

EXPLAIN SELECT * FROM t2 WHERE id>1 AND age<25;

1.2.9.7. 刷新查询缓存

清空查询缓存

reset query cache;

1.2.10. 修改表结构

1.2.10.1. 修改表名

ALTER TABLE <旧表名> RENAME <新表名>;

例:

ALTER TABLE ti RENAME t4;

1.2.10.2. 修改字段的数据类型

当表内已经有数据,一定要谨慎修改

ALTER TABLE <表名> MODIFY <字段名> <数据类型>;

例:

ALTER TABLE t1 MODIFY name VARCHAR(20);

1.2.10.3. 修改字段名

ALTER TABLE <表名> CHANGE <旧字段名> <新字段名> <新数据类型>;

例:

ALTER TABLE t1 CHANGE name username VARCHAR(20);

1.2.10.4. 添加字段(添加列)

当表中数据量很大时,会严重影响性能

ALTER TABLE <表名> ADD <新字段名> <新数据类型> [约束条件] [FIRST|AFTER 已存在当字段名];

例:

ALTER TABLE t1 ADD location VARCHAR(20) AFTER uname;
ALTER TABLE t1 ADD location VARCHAR(20) NOT NULL AFTER uname;
#创建在第一列
ALTER TABLE t1 ADD location VARCHAR(20) FIRST;

1.2.10.5. 删除字段(删除列)

ALTER TABLE <表名> DROP <字段名>;

ALTER TABLES t1 DROP location;

1.2.10.6. 修改字段排列位置

ALTER TABLE <表名> MODIFY <字段名1> <数据类型> FIRST|AFTER <字段2>;

例:

ALTER TABLE t1 MODIFY name VARCHAR(20) AFTER uid;

1.2.10.7. 修改表存储引擎

ALTER TABLE <表名> ENGINE=<新引擎名称>;

ALTER TABLE t1 ENGINE=InnoDB;

1.2.10.8. 删除表的外键约束

在删除所有对应的外键之前,主键对应的表是无法被删掉的

ALTER TABLE <表名> DROP FOREIGN KEY <外键名>;

ALTER TABLE t2 DROP FOREIGN KEY fk_1;

1.2.11. 事务操作

使用InnoDB数据引擎的表支持事务操作

默认情况Mysql开启了自动提交,每提交一条sql语句会自动作为一个事务处理

  • BEGIN开启一个事务
  • ROLLBACK 回滚一个事务
  • COMMIT 提交一个事务

例子:

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t8 VALUES (1, 'simon' ,'10');
Query OK, 1 row affected (0.01 sec)

#此时,数据只插入到了当前事务内(redolog),还未提交到物理存储中(binlog)
#所以该条目目前只能在当前事务内(session内)看到

mysql> select * from t8;
+------+-------+------+
| id   | name  | age  |
+------+-------+------+
|    1 | simon |   10 |
+------+-------+------+
1 row in set (0.00 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.01 sec)
#commit后数据才提交到了物理存储中

如果事务添加时,后悔了,在commit之前可以使用rollback回滚操作

mysql> select * from t8;
Empty set (0.00 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t8 VALUES (2, 'simon2' ,'10');
Query OK, 1 row affected (0.00 sec)

mysql> ROLLBACK;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from t8;
Empty set (0.00 sec)

查看与关闭自动提交

在做大量单行提交时,关闭自动提交能提高效率,减少mysql commit的次数

#查看mysql环境配置
mysql> show variables like '%commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| autocommit                     | ON    |
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
2 rows in set (0.00 sec)

#关闭自动提交
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| autocommit                     | OFF   |
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
2 rows in set (0.01 sec)

1.2.11. 表查询操作

1.2.11.1. 单表查询操作

  • select指定需要查询的列名
  • from 指定需要查询的表
  • where过滤值条件
SELECT * FROM city;
SELECT name, population FROM city WHERE id=1;
  • IN关键字查询

IN相当于where or条件,相当于例子中查询id为100或101的条目

SELECT id, name, population FROM city WHERE id IN (100,101);
  • AND多条件查询,代表必须同时符合多个条件才会显示
SELECT name,district,population FROM city WHERE district LIKE 'Nord' AND id< 5;
  • OR多条件查询,代表只需要满足多个条件中的任意一个即可
SELECT name,district,population FROM city WHERE district LIKE 'Nord' OR id< 5;
  • ANDOR可以一起使用,但是AND优先生效优先级高于OR
SELECT name,district,population FROM city WHERE district LIKE 'Nord' OR district LIKE 'shanghai' AND id< 5;
  • NOT排除条件,一般需要组合使用例如NOT LIKE
SELECT * FROM city WHERE id< 5 AND district NOT LIKE 'N%d';
  • WHERE BETWEEN AND 范围查询

例子查询10~20的数据

SELECT name,population FROM city WHERE id BETWEEN 10 AND 20;
  • WHERE LIKE搜索字符查询
SELECT name,district,population FROM city WHERE district LIKE 'Nord';
  • 模糊查询,模糊匹配,模糊搜索字符

使用百分号%代表任意个任意字符,_代表一个任意字符

SELECT name,district,population FROM city WHERE district LIKE 'N%d';
SELECT name,district,population FROM city WHERE district LIKE 'No_d';
  • LIMIT限制显示行数

显示头20行

SELECT * FROM city LIMIT 20;

从第10行开始显示之后10行,显示特定范围

SELECT * FROM city LIMIT 10,10;
  • DISTINCT查询结果不重复
SELECT DISTINCT * FROM city WHERE district id< 20;
  • ORDER BY查询结果排序

Mysql 默认采用升序(ASC),也可以指定采用降序(DESC)

例子里根据population列排序

如果使用order by排序的时候不起作用,原因是order by的字段是varchar类型的,在字段后加上'+0' 则转化为int类型,例如: select * from ORDER BY 字段+0 即可

SELECT * FROM city WHERE id < 10 ORDER BY population;
SELECT * FROM city WHERE id < 10 ORDER BY population DESC;

多列排序,按照先后进行排序,中间用逗号分开

SELECT * FROM city WHERE id <10 ORDER BY countrycode,name;
  • GROUP BY分组查询,将相应的结果组织到一起回显

count(*)是一个统计函数,统计行数

AS给列起一个别名

例子里先用GROUP BY将结果分组,再使用count(*)统计每一个列的行数

SELECT CountryCode,count(*) AS Total FROM city WHERE ID<10 GROUP BY countrycode;

多字段分组,用逗号分隔列名,会先分组一个,再分组第二个

SELECT * FROM city GROUP BY countrycode,district;
  • HAVING过滤分组

用于数据输出前的最后一次筛选,二次过滤使用

SELECT CountryCode,count(*) AS Total FROM city 
WHERE id <101 
GROUP BY CountryCode
HAVING count(*) >10;
  • WITH ROLLUP 统计求和

需要配合GROUP BY使用,输出结果的末尾会增加一个总和

mysql> select name,count(*) as total from t group by name with rollup;
+-------+-------+
| name  | total |
+-------+-------+
| qq    |     2 |
| simon |     2 |
| NULL  |     4 |
+-------+-------+
3 rows in set (0.00 sec)

mysql> 

1.2.11.2. 多表查询操作

1.2.11.2.1. 内连接查询INNER JOIN

内连接查询使用比较运算符进行表间列数据的比较操作。

并输出符合条件的结果。

FROM后面跟着要查询的多个表,用逗号分隔

SELECT后面查询的列需要声明从哪个表查,例如City.Name查询的是City表的Name列,

如果某一列只存在于其中一个表,这个列可以不需要声明表名,例如ID

如果不加上WHERE会出现显示异常,称为笛卡尔积的现象

#简单写法
SELECT ID, City.Name, Population, LifeExpectancy
FROM City, Coutry
WHERE ID< 10 and City.CountryCode = Country.Code;

#标准写法
SELECT ID, City.Name, Population, LifeExpectancy
FROM City INNER JOIN Coutry
WHERE ID< 10 and City.CountryCode = Country.Code;
1.2.11.2.2. 外连接查询

在内连接的基础上,还包含左表中所有不符合条件的数据行,并在其中的右表列填写NULL

OUTER JOIN,LEFT and RIGHT ON

外连接分为左连接与右连接

左连接代表以左表作为基准LEFT OUTER JOIN ON

右连接代表以右表作为基准RIGHT OUTER JOIN ON

SELECT ID, City.Name, City.Population, LifeExpectancy
FROM City LEFT OUTER JOIN Country
ON ID<10 and City.CountryCode=Country.Code LIMIT 10;

1.2.11.2.3. 子查询

  • ANYSOME子查询

通过创建表达式,对返回对结果进行比较,并输出符合条件的结果

下面例子,查询t2表的name与age列,并过滤出age大于t1表中任何age的结果

SELECT name, age FROM t2
WHERE age > ANY (SELECT age FROM t1);
  • EXISTSNOT EXISTS子查询

这是一种判断子查询

EXISTS判断子查询是否有返回行,如果有则执行外层语句中的查询,如果没有则不执行。

NOT EXISTS相反

例子中,查询state表,过滤出Nginx等于Fail的结果,如果结果存在,则再查询log表过滤出category='Nginx'

SELECT * FROM log
WHERE category='Nginx'
AND EXISTS (SELECT * from state WHERE Nginx='Fail');
  • IN子查询

判断子查询是否有返回行,如果有则执行外层语句中的查询,如果没有则不执行。

且有返回行的情况下,比对查询结果,输出值相同的行

例子查询blacklist表的Name列,如果有数据,则与People比对,输出People中Name存在于Blacklist的行

SELECT * FROM People
WHERE name IN (SELECT Name FROM blacklist);
  • UNION子查询

用于合并查询结果,可以将多条select结果组合成单个结果。

要求被组合的表列数必须相同。数据类型也必须相同。

默认组合会去掉相同的结果,只留下一条

SELECT * FROM t1
UNION SELECT * FROM t2;

而加上ALL语句,则会将重复的行都显示出来

SELECT * FROM t1
UNION ALL SELECT * FROM t2;

1.2.11.3. 使用函数查询

  • COUNT()函数,统计行数

默认用于统计所有数据行的总行数,不包括空行

SELECT COUNT(*) FROM city;

统计特定列的行数

SELECT COUNT(name) FROM city;

  • SUM()函数,数据求和

用于列求和,在数字类型的数据使用可用,在字符类型列使用则会返回0

SELECT SUM(population) from city;

  • AVG()函数,统计平均

SELECT AVG(population) from city;

  • MAX()函数,取出列最大值

SELECT name,MAX(population) from city;

  • MIN()函数,取出最小值

SELECT name,MIN(population) from city;

1.2.11.4. 正则表达式查询REGEXP

  • 以特定字符开头 REGEXP ^

SELECT * FROM city WHERE contrycode like 'CHN' and District REGEXP '^z';

  • 以特定字符结尾 REGEXP $

SELECT * FROM city WHERE contrycode like 'CHN' and District REGEXP 'g$';

  • 匹配任意单个字符REGEXP .

SELECT * FROM city WHERE contrycode like 'CHN' and District REGEXP 'C.N';

  • 匹配前面的字符0个或多个REGEXP *

例子中可匹配开头包含S,或开头包含Sh的结果,等价于{0,}

例如可匹配到Shanghai、S、Hongkong

SELECT * FROM city WHERE district REGEXP '^Sh*';

  • 匹配前面的字符1个或多个REGEXP +

例子中可匹配开头包含Sh的结果,例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}

SELECT * FROM city WHERE district REGEXP '^Sh+';

  • 匹配一个字符串或另外一个或多个字符串|
SELECT * from city
WHERE district REGEXP 'Shan|Guang'
  • 匹配任意一个字符[Sh]

如果写 [^Sh]则是不包含这两个字母的结果

SELECT * from city
WHERE district REGEXP '[Sh]'
  • 匹配指定字符连续出现的次数h{1,2}

h{1,}h{1}相当于匹配h连续出现1次或以上

SELECT * from city
WHERE district REGEXP 'h{1,5}'

1.2.12. 数据库视图

视图是一个虚拟表,是从数据库中一个或多个表导出的表。

视图是一个编译好的sql语句,而表不是

视图保存在内存中,所以速度更快

当建视图的SQL语句中包含以下子句时,无法使用MERGE算法:

  • 聚集函数
  • DISTINCT
  • GROUP BY
  • HAVING
  • 集合操作(UNION,UNION ALL)
  • 子查询

视图的特点:

  • 视图用于提高安全性
  • 简化工作
  • 逻辑独立

1.2.12.1. 创建单表视图

语法

CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED ] MERGE | TEMPTABLE}]
# REPLACE 重新设置视图时使用
# ALGORITHM 定义视图算法,默认 undefined 会自动选择合适的视图
# MERGE 合并视图的语意定义,如果能使用底层表的索引则会自动使用这个算法
# TEMPTABLE 如果底层数据表没有索引,则使用这个算法,该算法会创建一个临时表,效率更低
VIEW view_name 【(column_list)】
# 设置视图的名称,可选性加上列名称
AS SELECT_statement
# 视图的查询语句
[WITH [ CASCADED | LOCAL ] CHECK OPTION]
# CASCADED 默认值,更新时必须满足底层表的条件,例如非空约束等等
# LOCAL 更新时仅满足该视图本身定义的条件即可,忽视底层表的数据结构约束
# 创建名为view_user的视图,其值包含从表user查出的列name, age
CREATE VIEW view_user
AS SELECT name, age FROM user;

1.2.12.2. 查看视图

# 查询视图
SELECT * FROM view_user;

#查看视图结构
DESC view_user;

#查看创建视图的sql语句(不能加引号)
SHOW CREATE VIEW view_user;

#查看表/视图的属性信息
SHOW TABLE STATUS LIKE 'view_userinfo' \G;

#在infomation_schema表view列中查看视图
SELECT * FROM infomation_schema.views \G;

1.2.12.3. 修改视图

因为视图是一个虚拟表,其中显示的数据是视图指向的基本表的数据

修改或删除视图的内容就相当于修改或删除了视图所指向表的内容

# 修改视图的表内容
UPDATE view_user SET age = 20 
WHERE name='simon';

# 修改视图的结构
CREATE OR REPLACE VIEW view_user
AS SELECT id, name FROM user;

# 使用ALTER语句修改视图结构
ALTER [ALGORITHM = {UNDEFINED ] MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS SELECT_statement [WITH [ CASCADED | LOCAL ] CHECK OPTION]

ALTER VIEW view_user
AS SELECT name from user;

1.2.12.4. 创建多表视图

CREATE VIEW view_userinfo(new_name, new_phone)
# 视图名称后括号里设置里视图里列的名称
AS SELECT user.name, userinfo.phone FROM user, userinfo
WHERE id= fid;

1.2.12.5. 删除视图

# 如果被删除的视图原本就不存在,会报错
DROP VIEW view_user;
# 就算视图不存在也不会报错
DROP VIEW IF EXISTS view_user;

1.2.12.6. 设置视图定义人

某些情况下非视图定义者访问视图时,会报错没有权限,所以需要将视图的定义者改为需要访问视图的mysql账户

创建视图时设置视图定义者

/*!50001 CREATE ALGORITHM=UNDEFINED DEFINER=`platform`@`%` SQL SECURITY DEFINER VIEW `v_i18n_resourcekey` AS SELECT 
 1 AS `resourcekey`,
 1 AS `resourcetype`,
 1 AS `appcode`,
 1 AS `createtime`,
 1 AS `createusername`*/;
 
 
 # 主要关注其中的:
 DEFINER=`platform`@`%` SQL SECURITY DEFINER

已存在的视图修改定义者

# 先查询视图的创建语句
mysql> SHOW CREATE VIEW ACT_ID_GROUP \G
*************************** 1. row ***************************
                View: ACT_ID_GROUP
         Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`srment`@`%` SQL SECURITY DEFINER VIEW `ACT_ID_GROUP` AS select `t`.`roleid` AS `id_`,1 AS `rev_`,`t`.`rolename` AS `name_` from `s_role` `t` where (`t`.`stopflag` = 0)
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
1 row in set (0.00 sec)

根据创建视图的语句修改,将create命令改为ALTER
ALTER ALGORITHM=UNDEFINED DEFINER=`srment`@`%` SQL SECURITY DEFINER VIEW `ACT_ID_GROUP` AS select `t`.`roleid` AS `id_`,1 AS `rev_`,`t`.`rolename` AS `name_` from `s_role` `t` where (`t`.`stopflag` = 0)

1.2.13. 数据库锁

1.2.13.1. MyISAM数据库锁

#给表加写锁
LOCK TABLES 'table' write;
#给表解锁
UNLOCK TABES;

2. Shell命令

2.1. 初始化mysql,创建默认库

./mysql_install_db --basedir=/usr/local/mysql/(mysql的安装路径) \
--datadir=/var/lib/mysql(数据库的存放路径) \
--no-defaults --user=mysql

2.2. 在shell环境里执行sql语句

使用-e参数在shell环境里执行sql语句

其中i是外部变量

md5()函数用于生成值的md5值

i=10
mysql db1 -e "insert into test1 value ($i, md5($i));"

3. 关键说明

3.1. 内置库

3.1.1. infomation_schema

这个库并不存在磁盘,而是mysql启动时临时创建出来的

这个数据库中保存了MySQL服务器所有数据库的信息。

如数据库名,数据库的表,表栏的数据类型与访问权限等。

再简单点,这台MySQL服务器上,到底有哪些数据库、各个数据库有哪些表,

每张表的字段类型是什么,各个数据库要什么权限才能访问,等等信息都保存在information_schema里面。

  • information_schema的表schemata中的列schema_name记录了所有数据库的名字
  • information_schema的表tables中的列table_schema记录了所有数据库的名字
  • information_schema的表tables中的列table_name记录了所有数据库的表的名字
  • information_schema的表columns中的列table_schema记录了所有数据库的名字
  • information_schema的表columns中的列table_name记录了所有数据库的表的名字
  • information_schema的表columns中的列column_name记录了所有数据库的表的列的名字

3.1.2. performance_schema

这个库并不存在磁盘,而是mysql启动时临时创建出来的

主要用于保存性能收集信息

3.2. 索引

  • 普通索引和唯一索引
    • 普通索引是MySQL的基本索引类型
    • 唯一索引对应列的值必须唯一,但允许空值。如果是组合索引,则列值但组合必须唯一。
    • 主键索引是一种特殊的唯一索引,不允许空值。给列添加主键约束时,会自动添加主键索引。
  • 单列索引和组合索引
    • 单列索引指只包含一列的索引。一个表可以有多个单列索引。
    • 组合索引指表的多个字段组合上创建的索引。遵循做前缀组合。
  • 全文索引
    • FULLTEXT类型索引。可以在CHAR,VARCHAR或者TEXT类型的列上创建。
    • 仅MyISAM支持
  • 空间索引
    • 对空间数据类型对字段建立的索引。

索引原则

  • 索引并非越多越好。每次插入数据,就会触发重新计算索引,如果索引多将造成很大压力。
  • 数据量不多不需要键索引。
  • 列中的值变化不多也不需要建索引,因为查询时数据会存入缓存,缓存速度很快。
  • 经常排序和分组的数据列要建立索引。
  • 唯一性约束对应使用唯一性索引。

3.2.1. 创建表的时候创建索引

3.2.1.2. 创建普通索引

定义好每个列后使用INDEX语句声明要创建索引的列,例子中针对name列创建索引

CREATE TABLE t1
  (
    id INT PRIMARY KEY,
    name VARCHAR(10),
    sex ENUM('F', 'M', 'UN'),
    INDEX(name) 
  )ENGINE=InnoDB CHARACTER SET utf8;

3.2.1.3. 创建唯一索引

UNIQUE INDEX关键词创建唯一索引,其后必须跟着可自定义的索引名称id_in,最后声明对id列创建索引

CREATE TABLE t1
  (
    id INT NOT NULL,
    name VARCHAR(10),
    sex ENUM('F', 'M', 'UN'),
    UNIQUE INDEX 'id_in' ('id')
  )ENGINE=InnoDB CHARACTER SET utf8;

3.2.1.4. 创建单列索引

INDEX关键词创建单列索引,其后跟上自定义的索引名称'name_in',之后声明对name列创建索引,并且指定索引长度为10个字符

CREATE TABLE t1
  (
    name VARCHAR(10),
    sex ENUM('F', 'M', 'UN'),
    INDEX 'name_in' ('name'(10))
  )ENGINE=InnoDB CHARACTER SET utf8;

3.2.1.5. 创建组合索引

组合索引与单列所以的区别就在于,创建索引事声明的列为多个

使用了组合索引,查询语句的查询条件必须包含了索引声明的第一个列(如id)才会触发索引查询

例如where name like 'Tom' and age <25 无法触发索引查询

例如where name like 'Tom' and id <25 能触发索引查询

CREATE TABLE t1
  (
    id INT NOT NULL,
    name VARCHAR(20),
    age INT NOT NULL,
    INDEX muti_in (id,name) 
  )ENGINE=InnoDB CHARACTER SET utf8;

3.2.1.6. 创建全文索引(FULLTEXT索引支持MyISAM,不支持InnoDB)

使用FULLTEXT INDEX关键词创建全文索引

CREATE TABLE t1
  (
    id INT NOT NULL,
    name VARCHAR(20),
    age INT NOT NULL,
    info TEXT,
    FULLTEXT INDEX 'info_in' (info)
  )ENGINE=InnoDB CHARACTER SET utf8;

3.2.2. 对已有表创建或删除索引

使用ALTER创建索引

ALTER TABLE t1 ADD INDEX nameIdx (name(20));

使用CREATE INDEX创建索引,对t1表的name列创建索引

CREATE INDEX nameIdx ON t1(name);

使用ALTER删除索引

ALTER TABLE t1 DROP INDEX nameIdx;

使用DROP INDEX删除索引

DROP INDEX nameIdx ON t1;

3.2.3. 查看表拥有哪些索引

show create table t1;

4. Mysql的权限管理

Mysql使用逐级下查的方式确认权限,使用以下的顺序查询用户权限,

当匹配到有权限则不再继续下查

  • mysql先查询mysql库的user表,user表是全局生效的,当用户对库有权限则对所有库都有权限
  • 之后再查询db表,db表内描述的是用户对某一个库的权限
  • 之后再查询host表,用户对应用户主机的权限
  • 之后查询tables_priv表的权限,或procs_priv,用户对表级别的权限
  • 之后是columns_priv表,用户对某个列的权限
  • 如果以上的查询结果都是no,则返回用户无权限

4.1. 创建用户

4.1.1. CREATE USER语句创建

# 这样创建的用户没有任何权限
CREATE USER 'username'@'host' [ IDENTIFIED BY 'PASSWORD' ];

# 创建用户允许从任意主机访问过来
CREATE USER 'simon'@'%' IDENTIFIED BY 'PASSWORD' ;

# 创建用户只允许从本地访问
CREATE USER 'simon'@localhost ;

4.1.2. GRANT语句创建用户并授权,如果用户不存在则会自动创建

# 语法
GRANT <ALL|priv1, priv2, ...privn> 
# 设置授予的数据操作权限,all就是所有权限
ON [object]
# object可以是表、函数、存储过程
[WITH GRANT OPTION];

WITH GRANT OPTION]附加设定,附加设定有以下可选:

1、GRANT OPTION代表给这个用户的授权允许下发,允许把自己权限下发给其他人

2、MAX_QUERIES_PER_HOUR设定每小时能发起几次查询

3、MAX_UPDATES_PER_HOUR设定每小时能发起几次数据更新操作

4、MAX_CONNECTIONS_PER_HOUR允许每小时发起多少次连接

5、MAX_USER_CONNECTIONS允许该用户发起总连接多少个

#授权simon用户允许从192.168.1.1发起连接,并允许操作db1库的所有表,允许操作表操作
GRANT ALL ON db1.* to 'simon'@'192.168.1.1' ; 

4.2. FLUSH PRIVILEGES刷新授权表

将内存中的缓存信息写入磁盘

MySQL [wms_im]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

MySQL [wms_im]> 

4.3. 删除用户

删除用户并不是删除一个用户所有的授权

而是删除某一个用户从某个来源地址的授权

DROP USER 'username'@'host';

4.4. 查看用户权限

查询时正常会看到一个用户存在两条GRANT

其中一条GRANT USAGE代表创建用户,这句没有赋予任何权限

SHOW GRANTS FOR 'username'@'host';
SHOW GRANTS FOR 'username'@'host' \G;

mysql> show grants for 'simon';
+-------------------------------------------------+
| Grants for simon@%                              |
+-------------------------------------------------+
| GRANT USAGE ON *.* TO `simon`@`%`               |
| GRANT ALL PRIVILEGES ON `test`.* TO `simon`@`%` |
+-------------------------------------------------+
2 rows in set (0.00 sec)

4.5. 回收权限

语法

REVOKE <ALL|priv1, priv2, ...privn>
[ON table1, table2, ...tableN]
FROM 'username'@'host' [, 'username'@'host'];

REVOKE ALL ON db1.* FROM 'simon'@'192.168.1.1';

4.6. 修改密码

4.6.1. SET PASSWORD修改密码

# 修改自己的密码
SET PASSWORD=PASSWORD('yourpassword');

SET PASSWORD=PASSWORD('1234');

# 修改其他用户密码
SET PASSWORD FOR 'user'@'host' =PASSWORD('newpassword');

4.6.2. 直接修改user表来修改密码

UPDATE mysql.user SET
PASSWORD=PASSWORD('newpassword')
WHERE User='simon' AND Host= 'host';

4.6.3. 使用mysqladmin命令修改密码

mysqladmin -u username -p'oldpassword' password "newpassword"

4.7. 忘记root密码怎么处理

1、关闭数据库

2、使用这个命令启动mysqlmysqld_safe --skip-grant-tables &

3、使用空密码进入数据库(mysql命令后直接回车)

4、使用UPDATE语句修改root密码

update user set password=password('newpass') where user='root';

5、关闭数据库并重新以正常方式启动

5. 参数配置

5.1. 查看参数

mysql的参数,mysql官方叫变量(Varialbes)

MySQL的变量分为以下两种:

  • 系统变量:配置MySQL服务器的运行环境,可以用show variables查看

  • 状态变量:监控MySQL服务器的运行状态,可以用show status查看

5.1.1. 系统变量

系统变量按其作用域的不同可以分为以下两种:

  • 分为全局(GLOBAL)级:对整个MySQL服务器有效

  • 会话(SESSION或LOCAL)级:只影响当前会话

有些变量同时拥有以上两个级别,MySQL将在建立连接时用全局级变量初始化会话级变量,但一旦连接建立之后,全局级变量的改变不会影响到会话级变量。

5.1.1.1. show vairables查看系统变量

mysql> show variables like 'log%';
mysql> show variables where Variable_name like 'log%' and value = 'NO';

show vairables优先显示会话级别变量的值,如果值不存在则显示全局级别变量的值。

查询的时候也可以加上GLOBAL或SESSION关键字区分查询的级别:

show global variables;
show session/local variables;

在存储过程中引用系统变量的值,可以这样引用:

@@GLOBAL.var_name
@@SESSION.var_name
@@LOCAL.var_name

如果变量名前没有级别限定符,将优先显示会话级别的值。

5.1.1.2. 设置和修改系统变量值

mysql启动时修改,有两种方法:

  • mysqld命令行参数,如:mysqld --max_connections
  • 将配置写入my.cnf启动时生效

mysql启动后修改的方法,通过SET语句:

# 全局参数

set global 参数名=参数值;
set @@global.参数名:=参数值;

# 会话参数

set [session] 参数名=参数值;
set @@session.参数名:=参数值;

注意,在运行时设置的值不允许使用后缀字母K、M等。所以需要用表达式来达到效果

例子:

SET GLOBAL read_buffer_size = 2*1024*1024

5.2. 常见参数配置

5.2.1. 最大连接数

max_connections=2000
#默认值:
max_connections=151

指定MySQL可能的连接数量。当MySQL主线程在很短的时间内得到非常多的连接请求,该参数就起作用,之后主线程花些时间(尽管很短)检查连接并且启动一个新线程。

show variables like 'back_log';

back_log=1024
#默认值:
back_log=80

back_log值指出在MySQL暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。

也就是说,如果MySql的连接数达到max_connections时,新来的请求将会被存在堆栈中以等待某一连接释放资源,该堆栈的数量即back_log

如果等待连接的数量超过back_log,将不被授予连接资源。将会报错:

unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待连接进程时.

back_log值不能超过TCP/IP连接的侦听队列的大小。若超过则无效。

查看当前系统的TCP/IP连接的侦听队列的大小命令:

cat /proc/sys/net/ipv4/tcp_max_syn_backlog

对于Linux系统推荐设置为大于512的整数。

修改系统内核参数,可以编辑/etc/sysctl.conf去调整它。

如:net.ipv4.tcp_max_syn_backlog = 2048,改完后执行sysctl -p 让修改立即生效。

5.2.2. 索引块缓冲区大小

key_buffer_size = 32M
#默认值:
key_buffer_size=8M

key_buffer_size指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度。通过检查状态值Key_read_requests和Key_reads,可以知道key_buffer_size设置是否合理。比例key_reads /key_read_requests应该尽可能的低,至少是1:100,1:1000更好(上述状态值可以使用SHOW STATUS LIKE ‘key_read%'获得)。 key_buffer_size只对MyISAM表起作用。即使你不使用MyISAM表,但是内部的临时磁盘表是MyISAM表,也要使用该值。可以使用检查状态值created_tmp_disk_tables得知详情。 对于1G内存的机器,如果不使用MyISAM表,推荐值是16M(8-64M)

6. Mysql数据库备份

6.1. 备份前的规划

  • 需要备份哪些库
  • 数据库的体积
  • 确认存储引擎
  • 选择备份工具以及备份方式
  • 锁和宕机带来的影响
  • 备份保存到什么地方
  • 数据变化的频率
  • 行业规范或者合规性

备份方式大致分为两种:

1、操作系统级别的备份,文件备份

2、逻辑方式备份,SQL语句方式备份

6.2. 操作系统级别备份,文件备份

特点:

  • 操作简单
  • 速度最快
  • 需要停服务操作
  • 需要结合其他手段共同使用

6.2.1. mysqlhotcopy

  • mysqlhotcopy是MySQL软件包自带的备份工具,企业版与社区版都包含
  • mysqlhotcopy是一个Perl脚本,需要安装相关软件包
  • 其本质是使用锁表语句后再使用cpscp命令拷贝数据库文件
  • 备份前后执行FLUSH TABLE WITH READ LOCKUNLOCK TABLES与mysqldump相似
  • 仅支持MyISAM

语法:

mysqlhotcopy -u root -p password mydb /mnt/backup

例:

mysqlhotcopy -u root -p 'password' mydb /backup
mysqlhotcopy -u root -p 'password' mydb1 mydb2 /backup

6.2.2. LVM卷快照备份

  • 几乎是热备,因操作之前需要锁表,操作后需要解锁,无法预计锁表与解锁消耗的时间
  • 支持所有存储引擎
  • 备份速度快
  • 虽然很快,但依然需要锁表,锁表后对磁盘LVM卷做一个快照
  • 数据如果分布在多个卷上,操作复杂度将翻倍

例:

#创建LVM
pvcreate /dev/sdb
vgcreate testvg /dev/sdb
lvcreate -L 200M -n testlv testvg
mkfs -t ext4 /dev/testvg/testlv
mount /dev/testvg/testlv /mnt

#导入数据库,这部分操作省略 。。。

#锁表
mysql> flush tables with read lock;
#记录一下二进制日志数字,留意File与Position字段
mysql> show master status \G;

#创建快照
#使用/dev/testvg/testlv产生一个快照来创建一个大小为50M的名称为snap1的卷
lvcreate -L 50m -s -n snap1 /dev/testvg/testlv 

#解锁表
mysql> unlock tables;

#之后将snap1卷拷贝走即可

6.2.3. mylvmbackup

  • mylvmbackup是一个开源工具,可以自动创建lvm卷或快照
  • 依赖perl

官网:www.lenzg.net/mylvmbackup…

6.3. 逻辑方式备份

特点:

  • 其实是用SQL语句描述数据库,或是输出所有的查询结果
  • 兼容性最好,跨版本、平台、产品
  • 执行效率最慢,影响较大

6.3.1. mysqldump

  • mysqldump是MySQL软件包自带的备份工具
  • 使用SQL语句描述数据库及数据并导出
  • 备份时,在MYISAM引擎锁表,InnoDB引擎锁行
  • 数据量很大时不推荐使用,消耗时间长

语法:

#备份单表
mysqldump [OPTIONS] databases [tables]
#备份多个或1个库
mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3 ...]
#备份所有库
mysqldump [OPTIONS] --all-databases [OPTIONS]

例:

#备份单个表
mysqldump -uroot -p viewdb > backup.sql
#备份多个表
mysqldump -uroot -p viewdb,worlddb >backup.sql

6.3.2. Percona XtraBackup

XtraBackup是一个开源、免费的支持对InnoDB进行热备份对软件。

XtraBackup由Percona发布、支持。

XtraBackup特性:

  • 不暂停服务创建InnoDB热备份。
  • 为Mysql做增量备份。
  • 在Mysql服务器之间做在线表迁移。
  • 简化MySQL Replication创建。
  • 低负担备份数据。
  • Xtrabackup不会备份MyISAM表、.frm文件以及数据库其余部分,需要另外操作备份

安装XtraBackup,通过官网下载:www.percona.com/downloads/P…

使用XtraBackup做完整备份

#如果被备份的mysql版本为5.6,则使用xtrabackup_56命令备份
#备份表空间ibd文件
xtrabackup_56 --backup --target-dir=/var/lib/backup

# 处理事务一致性,将事务日志中已提交的事务补充到库文件内
# --use-memory=500M 用于设置备份时占用多少内存,内存足够多的时候可省略
# 需要执行2次才能达到一致性,数据与事务日志的一致性
xtrabackup_56 --use-memory=500M --prepare --target-dir=/var/lib/backup

使用XtraBackup 增量备份

# 模拟每日增量备份,创建备份目录
mkdir -p {mon.tue,wed}

#创建周一备份
xtrabackup_56 --backup --target-dir=/mon/

#参考周一的备份创建周二的差异备份,使用参数--incremental-basedir
xtrabackup_56 --backup --target-dir=/tue/ --incremental-basedir=/mon/

#参考周二创建周三的备份
xtrabackup_56 --backup --target-dir=/wed/ --incremental-basedir=/tue/

恢复增量备份 所有的备份恢复都应该设置 apply-log-only 参数(only 指的就是只回放 redo log 阶段,跳过 undo 阶段),避免未完成事务的回滚。

# 处理原始备份的一致性,将事务日志补充到备份使其一致
xtrabackup_56 --prepare --apply-log-only --target-dir=/var/lib/backup/

# 根据需要将增量合并至原始备份
# 这里举例将周一的增量备份追加到基础备份
xtrabackup_56 --prepare --apply-log-only --target-dir=/var/lib/backup/ --incremetal-dir=/mon/

# 然后将周二的增量备份追加
xtrabackup_56 --prepare --apply-log-only --target-dir=/var/lib/backup/ --incremetal-dir=/tue/

# 最后处理一次事务一致性,得到最终备份
xtrabackup_56 --prepare --target-dir=/var/lib/backup/

6.3.3. Percona innobackupex

innobackupex是一个对xtrabackup封装的perl脚本, 其提供了用于myisam和innodb引擎,及混合使用引擎备份的能力,主要是为了方便同时备份InnoDB和MyISAM引擎的表。在处理myisam表时需要加一个读锁。

其加入了一些使用的选项。如slave-info可以记录备份恢复后作为slave需要的一些信息,根据这些信息,可以很方便的利用备份来重建slave。

innobackupex比xtarbackup有更强的功能,它整合了xtrabackup和其他的一些功能,它不但可以全量备份/恢复,还可以基于时间的增量备份与恢复。

使用innobackupex做完整备份

# 生成一个完整备份,备份完成后会自动产生一个日期目录
innobackupex --user=root --password=passwd /var/lib/backup/

# 生成InnoDB日志,使备份可用
innobackupex --use-memory=512m --apply-log /var/lib/backup/2019-02-28_02-47-28/ 

使用innobackupex恢复备份

#这条命令根据my.cnf内的datadir设置将备份恢复至数据库
innobackupex --copy-back /var/lib/backup/2019-02-28_02-47-28/

#修改文件权限
chmod -R mysql.mysql /var/lib/mysql

使用innobackupex做增量备份

# 先做一个完整备份,假设当天为周一
innobackupex --user=root --password=passwd /var/lib/backup/mon/

# 创建增量备份,直接运行会报错目录不存在,目录需要手动创建
# 以周一为基准创建周二的增量备份
innobackupex --incremental /var/lib/backup/tue/ --incremental-basedir=/var/lib/backup/mon/ --user=root --password=password

恢复增量备份

#先处理原始备份的一致性
innobackupex --apply-log --redo-only /var/lib/backup/mon/--use-memory=500m --user=root --password=passwd

# 合并增量备份至原始备份,mon是完整备份,tue是增量备份
# 如果有多个增量备份,也一样按顺序合并到基础备份去
innobackupex --apply-log --redo-only /var/lib/backup/mon/日期/ --incremental-dir=/var/lib/backup/tue/日期/ --use-memory=500m --user=root --password=passwd

# 处理完整备份的最终一致性,将redo与undo都合并
innobackupex --apply-log /var/lib/backup/mon/日期/ --use-memory=500m --user=root --password=pass

# 恢复备份到生产库中
innobackupex --copy-back /var/lib/backup/mon/日期/

#修改文件权限
chmod -R mysql.mysql /var/lib/mysql