一、破解密码以及无密码登录
1.1 破解密码
vim /etc/my.cnf
[mysqld]
skip-grant-tables //增加这一行,然后重启服务
mysql
mysql> use mysql;
mysql> UPDATE user SET password=password("123456") WHERE user='root';
mysql> flush privileges;
mysql> exit;
1.2 无密码登录
1.mycnf增加[client]标签
vim /etc/my.cnf
[client]
user="root"
password="123456"
1.3 定义不同的客户端
[mysql] //给/usr/local/mysql/bin/mysql使用
user="root"
password="123456"
[mysqladmin] //给/usr/local/mysql/bin/mysqladmin使用
user="root"
password="123456"
1.4 家目录下
vim ~/.my.cnf
[client]
user="root"
password="123456"
重启服务就可以输入mysql登录
1.5修改密码的方式
mysql5.7初始化密码报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement before
#必须这样修改密码
mysql -uroot -p
mysql> alter user 'root'@'localhost' identified by '123456';
mysql> flush privileges
方法1:
运行MySQL 5.7 Command Line Client,输入老的密码;
use mysql;
update user set authentication_string=password('test1234') where user='root';
方法2:
运行MySQL 5.7 Command Line Client,输入老的密码;
set password=password('newpassword');
方法3:
alter user root@'localhost' identified by 'test1234';
假如已经修改mysql下的user表root账号下的host为%时,需要用下面的语句
alter user root@'%' identified by 'test1234';
方法4:进入mysql的bin目录:
mysqladmin -uroot -poldpassword pasword "newpassword"
修改完密码后,退出mysql,重启mysql服务,密码才能生效。
二、视图
视图:VIEW,虚表,保存有实表的查询结果
创建方法:
CREATE VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]
查看视图定义:SHOW CREATE VIEW view_name
删除视图:
DROP VIEW [IF EXISTS] view_name [, view_name] ... [RESTRICT | CASCADE]
视图中的数据事实上存储于“基表”中,因此,其修改操作也会针对基表实现;其修改操作受基表限制
三、函数
3.1 系统函数
系统函数 :https://dev.mysql.com/doc/refman/5.7/en/func-op-summary-ref.html
自定义函数 (user-defined function UDF)
保存在mysql.proc表中
创建UDF:
CREATE [AGGREGATE] FUNCTION function_name(parameter_name type,[parameter_name type,...]) RETURNS {STRING|INTEGER|REAL} runtime_body
说明:
参数可以有多个,也可以没有参数
必须有且只有一个返回值
3.2 自定义函数
查看函数列表:
SHOW FUNCTIOIN STATUS;
查看函数定义
SHOW CREATE FUNCTION function_name
删除UDF:
DROP FUNCTION function_name
调用自定义函数语法:
SELECT function_name(parameter_value,...)
示例:无参UDF
CREATE FUNCTION simpleFun() RETURNS VARCHAR(20) RETURN "Hello World!“;
示例:有参数UDF
DELIMITER //
CREATE FUNCTION deleteById(uid SMALLINT
UNSIGNED) RETURNS VARCHAR(20)
BEGIN
DELETE FROM students WHERE stuid = uid; RETURN (SELECT COUNT(uid) FROM students);
END//
DELIMITER ;
3.3 自定义函数中定义局部变量语法:
DECLARE 变量1[,变量2,... ]变量类型 [DEFAULT 默认值]
说明:局部变量的作用范围是在BEGIN...END程序中,而且定义局
部变量语句必须在BEGIN...END的第一行定义
示例:
DELIMITER //
CREATE FUNCTION addTwoNumber(x SMALLINT
UNSIGNED, Y SMALLINT UNSIGNED)
RETURNS SMALLINT
BEGIN
DECLARE a, b SMALLINT UNSIGNED DEFAULT 10;
SET a = x, b = y;
RETURN a+b;
END//
为变量赋值语法
SET parameter_name = value[,parameter_name = value...] SELECT INTO parameter_name
示例:
...
DECLARE x int;
SELECT COUNT(id) FROM tdb_name INTO x;
RETURN x;
END//
四、存储过程procedure
4.1 存储过程:存储过程保存在mysql.proc表中
创建存储过程
CREATE PROCEDURE sp_name ([ proc_parameter、 [,proc_parameter ...]]) routime_body
其中:proc_parameter : [IN|OUT|INOUT] parameter_name type
其中IN表示输入参数,OUT表示输出参数,INOUT表示既可以输入也可以输出;param_name表示参数名称;type表示参数的类型
查看存储过程列表
SHOW PROCEDURE STATUS
存储过程
查看存储过程定义
SHOW CREATE PROCEDURE sp_name
调用存储过程:
CALL sp_name ([ proc_parameter [,proc_parameter...]])
CALL sp_name
说明:当无参时,可以省略"()",当有参数时,不可省略"()”
存储过程修改:
ALTER语句修改存储过程只能修改存储过程的注释等无关紧要的东西,不能修改存储过程体,所以要修改存储过程,方法就是删除重建
删除存储过程:
DROP PROCEDURE [IF EXISTS] sp_name
存储过程示例
创建无参存储过程:
delimiter //
CREATE PROCEDURE showTime()
BEGIN
SELECT now();
END//
delimiter ;
CALL showTime;
存储过程示例
创建含参存储过程:只有一个IN参数
delimiter //
CREATE PROCEDURE seleById(IN id SMALLINT
UNSIGNED)
BEGIN
SELECT * FROM students WHERE stuid = uid;
END//
delimiter ;
call seleById(2);
存储过程示例
示例
delimiter //
CREATE PROCEDURE dorepeat(p1 INT)
BEGIN
SET @x = 0;
REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
END
//
delimiter ;
CALL dorepeat(1000);
SELECT @x;
存储过程示例
创建含参存储过程:包含IN参数和OUT参数
delimiter //
CREATE PROCEDURE deleteById(IN id SMALLINT
UNSIGNED, OUT num SMALLINT UNSIGNED)
BEGIN
DELETE FROM students WHERE stuid = id;
SELETE row_count() into num;
END//
delimiter ;
call seleById(2,@Line);
SELETE @Line;
说明:创建存储过程deleteById,包含一个IN参数和一个OUT参数.调用时,传入删除的ID和保存被修改的行数值的用户变量@Line,select @Line;输出被影响行数.
4.2 存储过程优势
存储过程优势:
存储过程把经常使用的SQL语句或业务逻辑封装起来,预编译保存在数据库中,当需要时从数据库中直接调用,省去了编译的过程
提高了运行速度
同时降低网络数据传输量
存储过程与自定义函数的区别:
存储过程实现的过程要复杂一些,而函数的针对性较强
存储过程可以有多个返回值,而自定义函数只有一个返回值
存储过程一般独立的来执行,而函数往往是作为其他SQL语句的一部分来使用
4.3 流程控制
流程控制
存储过程和函数中可以使用流程控制来控制语句的执行
流程控制:
IF:用来进行条件判断。根据是否满足条件,执行不同语句
CASE:用来进行条件判断,可实现比IF语句更复杂的条件判断
LOOP:重复执行特定的语句,实现一个简单的循环
LEAVE:用于跳出循环控制
ITERATE:跳出本次循环,然后直接进入下一次循环
REPEAT:有条件控制的循环语句。当满足特定条件时,就会跳出循环语句
WHILE:有条件控制的循环语句
五、触发器
触发器的执行不是由程序调用,也不是由手工启动,而是由事件来触发、激活从而实现执行
5.1 创建触发器
CREATE [DEFINER = { user | CURRENT_USER }] TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW trigger_body
说明:
trigger_name:触发器的名称
trigger_time:{ BEFORE | AFTER },表示在事件之前或之后触发
trigger_event::{ INSERT |UPDATE | DELETE },触发的具体事件
tbl_name:该触发器作用在表名
触发器示例
CREATE TABLE student_info (stu_no INT(11) NOT NULL AUTO_INCREMENT,stu_name VARCHAR(255) DEFAULT NULL,PRIMARY KEY (stu_no));
CREATE TABLE student_count ( student_count INT(11) DEFAULT 0 );
INSERT INTO student_count VALUES(0);
触发器示例
示例:创建触发器,在向学生表INSERT数据时,学生数增加,DELETE学生时,学生数减少
CREATE TRIGGER trigger_student_count_insert AFTER INSERTON student_info FOR EACH ROW UPDATE student_count SET student_count=student_count+1;
CREATE TRIGGER trigger_student_count_delete AFTER DELETE ON student_info FOR EACH ROW UPDATE student_count SET student_count=student_count-1;
5.2 查看触发器
SHOW TRIGGERS
查询系统表information_schema.triggers的方式指定查询条件,查看指定的触发器信息。
mysql> USE information_schema;
Database changed
mysql> SELECT * FROM triggers WHERE
trigger_name='trigger_student_count_insert';
删除触发器
DROP TRIGGER trigger_name;
五、服务器配置(变量)
mysqld选项,服务器系统变量和服务器状态变量
https://dev.mysql.com/doc/refman/5.7/en/mysqld-option-tables.html
https://mariadb.com/kb/en/library/full-list-of-mariadb-options-system-and-status-variables/
获取运行中的mysql进程使用各服务器参数及其值
mysql> SHOW GLOBAL VARIABLES;
mysql> SHOW [SESSION] VARIABLES;
注意:其中有些参数支持运行时修改,会立即生效;有些参数不支持,且只能通过修改配置文件,并重启服务器程序生效;有些参数作用域是全局的,且不可改变;有些可以为每个用户提供单独(会话)的设置
5.1 服务器配置
设置服务器系统变量三种方法:
在命令行中设置:
shell> ./mysqld_safe --aria_group_commit="hard“
在配置文件my.cnf中设置:
aria_group_commit = "hard"
在mysql客户端使用SET命令:
SET GLOBAL aria_group_commit="hard";
5.2 服务器端设置
修改服务器变量的值:
mysql> help SET
修改全局变量:仅对修改后新创建的会话有效;对已经建立的会话无效
mysql> SET GLOBAL system_var_name=value;
mysql> SET @@global.system_var_name=value;
修改会话变量:
mysql> SET [SESSION] system_var_name=value;
mysql> SET @@[session.]system_var_name=value;
状态变量(只读):用于保存mysqld运行中的统计数据的变量,不可更改
mysql> SHOW GLOBAL STATUS;
mysql> SHOW [SESSION] STATUS;
5.3 SQL_MODE
服务器变量SQL_MODE:对其设置可以完成一些约束检查的工作,可分别进行全局的设置或当前会话的设置
常见MODE:
NO_AUTO_CREATE_USER 禁止GRANT创建密码为空的用户
NO_AUTO_VALUE_ON_ZERO 在自增长的列中插入0或NULL将不会是下一个自增长值
NO_BACKSLASH_ESCAPES 反斜杠“\”作为普通字符而非转义字符
PAD_CHAR_TO_FULL_LENGTH 启用后,对于CHAR类型将不会截断空洞数据
PAD_CHAR_TO_FULL_LENGTH 启用后,对于CHAR类型将不会截断空洞数据
PIPES_AS_CONCAT 将"||"视为连接操作符而非“或运算符 ”
六、查询缓存
6.1 查询缓存( Query Cache )原理:
缓存SELECT操作或预处理查询的结果集和SQL语句,当有新的SELECT语句或预处理查询语句请求,先去查询缓存,判断是否存在可用的记录集,判断标准:与缓存的SQL语句,是否完全一样,区分大小写
6.2 优缺点
不需要对SQL语句做任何解析和执行,当然语法解析必须通
过在先,直接从Query Cache中获得查询结果,提高查询性能
查询缓存的判断规则,不够智能,也即提高了查询缓存的使
用门槛,降低其效率;
查询缓存的使用,会增加检查和清理Query Cache中记录集的开销
6.3 查询缓存
哪些查询可能不会被缓存
查询语句中加了SQL_NO_CACHE参数
查询语句中含有获得值的函数,包含自定义函数,如:NOW() CURDATE()、GET_LOCK()、RAND()、CONVERT_TZ()等
对系统数据库的查询:mysql、information_schema 查询语句中使用SESSION级别变量或存储过程中的局部变量
查询语句中使用了LOCK IN SHARE MODE、FOR UPDATE的语句 查询语句中类似SELECT …INTO 导出数据的语句
对临时表的查询操作;存在警告信息的查询语句;不涉及任何表或视图的查询语句;某用户只有列级别权限的查询语句
事务隔离级别为Serializable时,所有查询语句都不能缓存
6.4 查询缓存相关的服务器变量
query_cache_min_res_unit: 查询缓存中内存块的最小分配单位,默认4k,较小值会减少浪费,但会导致更频繁的内存分配操作,较大值会带来浪费,会导致碎片过多,内存不足
query_cache_limit:单个查询结果能缓存的最大值,默认为1M,对于查询结果过大而无法缓存的语句,建议使用 SQL_NO_CACHE
query_cache_size:查询缓存总共可用的内存空间;单位字节,必须是1024的整数倍,最小值40KB,低于此值有警报
query_cache_wlock_invalidate:如果某表被其它的会话锁定,是否仍然可以从查询缓存中返回结果, 默认值为OFF,表示可以在表被其它会话锁定的场景中继续从缓存返回数据;ON则表示不允许
query_cache_type: 取值为ON, OFF, DEMAND
参看: https://dev.mysql.com/doc/refman/5.7/en/query-cache-configuration.html
6.5 SELECT语句的缓存控制
SQL_CACHE: 显式指定存储查询结果于缓存之中
SQL_NO_CACHE: 显式查询结果不予缓存
query_cache_type参数变量:
query_cache_type的值为OFF或0时,查询缓存功能关闭
query_cache_type的值为ON或1时,查询缓存功能打开,SELECT的结果符合缓存条件即会缓存,否则,不予缓存,显式指定SQL_NO_CACHE,不予缓存,此为默认值
query_cache_type的值为DEMAND或2时,查询缓存功能按需进行,显式指定SQL_CACHE的SELECT语句才会缓存;其它均不予缓存
6.6 查询缓存相关的状态变量
SHOW GLOBAL STATUS LIKE ‘Qcache%';
Qcache_free_blocks:处于空闲状态 Query Cache中内存 Block 数
Qcache_free_memory:处于空闲状态的 Query Cache 内存总量
Qcache_hits:Query Cache 命中次数
Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次数,即没有命中的次数
Qcache_lowmem_prunes:当 Query Cache 内存容量不够,需要删除老的 Query Cache 以给新的 Cache 对象使用的次数
Qcache_not_cached:没有被 Cache 的 SQL 数,包括无法被Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache的 SQL语句
Qcache_queries_in_cache:在 Query Cache 中的 SQL 数量
Qcache_total_blocks:Query Cache 中总的 Block
6.7 命中率
命中率和内存使用率估算
query_cache_min_res_unit ≈(query_cache_size -Qcache_free_memory) / Qcache_queries_in_cache
查询缓存命中率 ≈ (Qcache_hits – Qcache_inserts) /Qcache_hits * 100%
查询缓存内存使用率 ≈ (query_cache_size –qcache_free_memory) / query_cache_size * 100%
6.8 InnoDB存储引擎
InnoDB存储引擎的缓冲池:通常InnoDB存储引擎缓冲池的命中不应该小于99%
查看相关状态变量:
show global status like 'innodb%read%'\G
Innodb_buffer_pool_reads: 表示从物理磁盘读取页的次数
Innodb_buffer_pool_read_ahead: 预读的次数
Innodb_buffer_pool_read_ahead_evicted: 预读页,但是没有读取就从缓冲池中被替换的页数量,一般用来判断预读的效率
Innodb_buffer_pool_read_requests: 从缓冲池中读取页次数
Innodb_data_read: 总共读入的字节数
Innodb_data_reads: 发起读取请求的次数,每次读取可能需要读取多个页
七、索引
7.1 索引简介
索引是特殊数据结构:定义在查找时作为查找条件的字段
优点:提高查询速度,缺点:占用额外空间,影响插入速度
索引实现在存储引擎
7.2 索引类型:
- 索引类型
聚簇(集)索引、非聚簇索引:数据是否与索引存储在一起
主键索引、辅助索引
稠密索引、稀疏索引:是否索引了每一个数据项
B+ TREE、HASH、R TREE
简单索引、组合索引
左前缀索引:取前面的字符做索引
覆盖索引:从索引中即可取出要查询的数据,性能高
7.3 B+ Tree索引
B+ Tree索引:顺序存储,每一个叶子节点到根结点的距离是相同的;左前缀索引,适合查询范围类的数据
可以使用B-Tree索引的查询类型:
全值匹配:精确所有索引列,如:姓wang,名xiaochun,年龄30
匹配最左前缀:即只使用索引的第一列,如:姓wang
匹配列前缀:只匹配一列值开头部分,如:姓以w开头的
匹配范围值:如:姓ma和姓wang之间
精确匹配某一列并范围匹配另一列:如:姓wang,名以x开头的
只访问索引的查询
7.4 B-Tree索引的限制:
如果不从最左列开始,则无法使用索引:如:查找名为xiaochun,或姓为g结尾
不能跳过索引中的列:如:查找姓wang,年龄30的,只能使用索引第一列
如果查询中某个列是为范围查询,那么其右侧的列都无法再使用索引:如:姓wang,名x%,年龄30,只能利用姓和名上面的索引
特别提示:
索引列的顺序和查询语句的写法应相匹配,才能更好的利用索引
为优化性能,可能需要针对相同的列但顺序不同创建不同的索引来满足不同类型的查询需求
7.5 Hash索引
Hash索引:基于哈希表实现,只有精确匹配索引中的所有列的查询才有效,索引自身只存储索引列对应的哈希值和数据指针,索引结构紧凑,查询性能好
只有Memory存储引擎支持显式hash索引
适用场景:
只支持等值比较查询,包括=, IN(), <=>
不适合使用hash索引的场景:
不适用于顺序查询:索引存储顺序的不是值的顺序
不支持模糊匹配
不支持范围查询
不支持部分索引列匹配查找:如A,B列索引,只查询A列索引无效
7.6 空间索引(R-Tree):
MyISAM支持空间索引,可以使用任意维度组合查询,使用特有的函数访问,常用于做地理数据存储,使用不多
全文索引(FULLTEXT):
在文本中查找关键词,而不是直接比较索引中的值,类似搜索引擎
索引优点:
索引可以降低服务需要扫描的数据量,减少了IO次数
索引可以帮助服务器避免排序和使用临时表
索引可以帮助将随机I/O转为顺序I/O
7.7 高性能索引策略:
独立地使用列:尽量避免其参与运算,独立的列指索引列不能是表达式的一部分,也不能是函数的参数,在where条件中,始终将索引列单独放在比较符号的一侧
左前缀索引:构建指定索引字段的左侧的字符数,要通过索引选择性来评估
索引选择性:不重复的索引值和数据表的记录总数的比值多列索引:AND操作时更适合使用多列索引,而非为每个列创建单独的索引
选择合适的索引列顺序:无排序和分组时,将选择性最高放左侧
冗余和重复索引:(A),(A,B)即为冗余索引
不好的索引使用策略,建议扩展索引,而非冗余
7.8 索引优化建议
只要列中含有NULL值,就最好不要在此例设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引
- 尽量使用短索引,如果可以,应该制定一个前缀长度
- 对于经常在where子句使用的列,最好设置索引
- 对于有多个列where或者order by子句,应该建立复合索引
- 对于like语句,以%或者‘-’开头的不会使用索引,以%结尾会使用索引
- 尽量不要在列上进行运算(函数操作和表达式操作)
- 尽量不要使用not in和<>操作
7.9 EXPLAIN
通过EXPLAIN来分析索引的有效性:
EXPLAIN SELECT clause 获取查询执行计划信息,用来查看查询优化器如何执行查询
- 输出信息说明:参考
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
id: 当前查询语句中,每个SELECT语句的编号
复杂类型的查询有三种:
简单子查询
用于FROM中的子查询
联合查询:UNION
注意:UNION查询的分析结果会出现一个额外匿名临时表
select_type:
- 简单查询为SIMPLE
- 复杂查询:
SUBQUERY: 简单子查询
PRIMARY:最外面的SELECT
DERIVED: 用于FROM中的子查询
UNION:UNION语句的第一个之后的SELECT语句
UNION RESULT: 匿名临时表
table:SELECT语句关联到的表
type:关联类型或访问类型,即MySQL决定的如何去查询表中的行的方式,以下顺序,性能从低到高
- ALL: 全表扫描
- index:根据索引的次序进行全表扫描;如果在Extra列出现“Using index”表示了使用覆盖索引,而非全表扫描
- range:有范围限制的根据索引实现范围扫描;扫描位置始于索引中的某一点,结束于另一点
- ref: 根据索引返回表中匹配某单个值的所有行
- eq_ref:仅返回一个行,但与需要额外与某个参考值做比较
- const, system: 直接返回单个行
- possible_keys:查询可能会用到的索引
- key: 查询中使用到的索引
- key_len: 在索引使用的字节数
- ref: 在利用key字段所表示的索引完成查询时所用的列或某常量值
- rows:MySQL估计为找所有的目标行而需要读取的行数
Extra:额外信息
Using index:MySQL将会使用覆盖索引,以避免访问表
Using where:MySQL服务器将在存储引擎检索后,再进行一次过滤
Using temporary:MySQL对结果排序时会使用临时表
Using filesort:对结果使用一个外部索引排序
7.10 管理索引
创建索引:
CREATE INDEX index_name ON tbl_name (index_col_name,...); help CREATE INDEX
删除索引:
DROP INDEX index_name ON tbl_name;
查看索引:
SHOW INDEXES FROM [db_name.]tbl_name;
优化表空间:
OPTIMIZE TABLE tb_name
7.11 SQL语句性能优化
查询时,能不要*就不用*,尽量写全字段名
大部分情况连接效率远大于子查询
多表连接时,尽量小表驱动大表,即小表 join 大表
在千万级分页时使用limit
对于经常使用的查询,可以开启缓存
多使用explain和profile分析查询语句
查看慢查询日志,找出执行时间长的sql语句优化
八、并发控制
并发控制通过三种方式实现:
- 锁粒度:
- 表级锁
- 行级锁
8.1 锁:
读锁:共享锁,只读不可写,多个读互不阻塞,
写锁:独占锁,排它锁,一个写锁会阻塞其它读和它锁
实现
存储引擎:自行实现其锁策略和锁粒度
服务器级:实现了锁,表级锁;用户可显式请求
分类:
隐式锁:由存储引擎自动施加锁
显式锁:用户手动请求
锁策略:在锁粒度及数据安全性寻求的平衡机制
显示使用锁
LOCK TABLES tbl_name [[AS] alias] lock_type [, tbl_name [[AS] alias] lock_type] ...lock_type: READ , WRITE
UNLOCK TABLES 解锁
FLUSH TABLES tb_name[,...] [WITH READ LOCK]
关闭正在打开的表(清除查询缓存),通常在备份前加全局读锁
SELECT clause [FOR UPDATE | LOCK IN SHARE MODE]
查询时加写或读锁
8.2 事务
事务Transactions:一组原子性的SQL语句,或一个独立工作单元
事务日志:记录事务信息,实现undo,redo等故障恢复功能
ACID特性:
A:atomicity原子性;整个事务中的所有操作要么全部成功执行,要么全部失败后回滚
C:consistency一致性;数据库总是从一个一致性状态转换为另一个一致性状态
I:Isolation隔离性;一个事务所做出的操作在提交之前,是不能为其它事务所见;隔离有多种隔离级别,实现并发
D:durability持久性;一旦事务提交,其所做的修改会永久保存于数据库中启动事务:START TRANSACTION
结束事务:
(1) COMMIT:提交
(2) ROLLBACK: 回滚
注意:只有事务型存储引擎方能支持此类操作
建议:显式请求和提交事务,而不要使用“自动提交”功能
set autocommit={1|0}
事务支持保存点:savepoint SAVEPOINT identifier ROLLBACK [WORK] TO [SAVEPOINT] identifier RELEASE SAVEPOINT identifier
8.3 事务隔离级别
事务隔离级别:从上至下更加严格
READ UNCOMMITTED 可读取到未提交数据,产生脏读
READ COMMITTED 可读提交数据,但未提交数据不可读,产生不可重复读,即可读取到多个提交数据,导致每次读取数据不一致
REPEATABLE READ 可重复读,多次读取数据都一致,产生幻读,即读取过程中,即使有其它提交的事务修改数据,仍只能读取到未修改前的旧数据。此为MySQL默认设置
SERIALIZABILE 可串行化,未提交的读事务阻塞修改事务,或者未提交的修改事务阻塞读事务。导致并发性能差
MVCC: 多版本并发控制,和事务级别相关
指定事务隔离级别:
服务器变量tx_isolation指定,默认为REPEATABLE-READ,可在GLOBAL和SESSION级进行设置
SET tx_isolation=''
READ-UNCOMMITTED
READ-COMMITTED
REPEATABLE-READ
SERIALIZABLE
服务器选项中指定
vim /etc/my.cnf
[mysqld]
transaction-isolation=SERIALIZABLE
死锁:
两个或多个事务在同一资源相互占用,并请求锁定对方占
用的资源的状态
事务日志:
事务日志的写入类型为“追加”,因此其操作为“顺序
IO”;通常也被称为:预写式日志 write ahead logging
日志文件: ib_logfile0, ib_logfile1
九、日志
9.1 日志分类
事务日志:transaction log
错误日志:error log
查询日志:query log
慢查询日志:slow query log
二进制日志:binary log
中继日志:reley log
9.2 事务日志:transaction log
事务型存储引擎自行管理和使用
redo log
undo log
Innodb事务日志相关配置:
show variables like '%innodb_log%';
innodb_log_file_size 5242880 每个日志文件大小
innodb_log_files_in_group 2 日志组成员个数
innodb_log_group_home_dir ./ 事务文件路径
9.3 中继日志:relay log
主从复制架构中,从服务器用于保存从主服务器的二进制日志中读取到的事件
9.4 错误日志
mysqld启动和关闭过程中输出的事件信息
mysqld运行中产生的错误信息
event scheduler运行一个event时产生的日志信息
在主从复制架构中的从服务器上启动从服务器线程时产生的信息
错误日志相关配置
SHOW GLOBAL VARIABLES LIKE 'log_error'
错误文件路径:
log_error=/PATH/TO/LOG_ERROR_FILE
是否记录警告信息至错误日志文件
log_warnings=1|0 默认值1
9.5 查询日志:记录查询操作
文件:file,默认值
表:table
查询日志相关设置
general_log=ON|OFF
general_log_file=HOSTNAME.log
log_output=TABLE|FILE|NONE
9.6 慢查询日志
慢查询日志:记录执行查询时长超出指定时长的操作
slow_query_log=ON|OFF 开启或关闭慢查询
long_query_time=N 慢查询的阀值,单位秒
slow_query_log_file=HOSTNAME-slow.log 慢查询日志文件
log_slow_filter = admin,filesort,filesort_on_disk,full_join,
full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk
log_queries_not_using_indexes=ON 不使用索引也没有达到慢查询阀值的语句是否记录日志,默认OFF,即不记录
log_slow_rate_limit = 1 多少次查询才记录,mariadb特有
log_slow_verbosity= Query_plan,explain 记录内容
log_slow_queries = OFF 同slow_query_log 新版已废弃
9.7 二进制日志
记录导致数据改变或潜在导致数据改变的SQL语句
功能:通过“重放”日志文件中的事件来生成数据副本
注意:建议二进制日志和数据文件分开存放
- 二进制日志相关配置
查看mariadb自行管理使用中的二进制日志文件列表
SHOW {BINARY | MASTER} LOGS
查看使用中的二进制日志文件
SHOW MASTER STATUS
查看二进制文件中的指定内容
SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos]
[LIMIT [offset,] row_count]
show binlog events in 'mariadb-bin.000001' from 6516 limit 2,3
9.8二进制日志记录格式
二进制日志记录三种格式
基于“语句”记录:statement,记录语句,默认模式
基于“行”记录:row,记录数据,日志量较大
混合模式:mixed, 让系统自行判定该基于哪种方式进行
- 格式配置
show variables like '%binlog_format%';
二进制日志文件的构成
有两类文件
日志文件:mysql|mariadb-bin.文件名后缀,二进制格式
如: mysql-bin.000001
索引文件:mysql|mariadb-bin.index,文本格式
9.9 二进制日志相关的服务器变量:
sql_log_bin=ON|OFF:是否记录二进制日志,默认ON
log_bin=/PATH/BIN_LOG_FILE:指定文件位置;默认OFF,表示不启用二进制日志功能,上述两项都开启才可
binlog_format=STATEMENT|ROW|MIXED:二进制日志记录的格式,默认STATEMENT
max_binlog_size=1073741824:单个二进制日志文件的最大体积,到达最大值会自动滚动,默认为1G
说明:文件达到上限时的大小未必为指定的精确值
sync_binlog=1|0:设定是否启动二进制日志即时同步磁盘功能,默认0,由操作系统负责同步日志到磁盘
expire_logs_days=N:二进制日志可以自动删除的天数。默认为0,即不自动删除
9.10 mysqlbinlog:二进制日志的客户端命令工具
命令格式:
mysqlbinlog [OPTIONS] log_file…
--start-position=# 指定开始位置
--stop-position=#
--start-datetime=
--stop-datetime=
时间格式:YYYY-MM-DD hh:mm:ss--base64-output[=name]
示例: mysqlbinlog --start-position=6787 --stop-position=7527 /var/lib/mysql/mariadb-bin.000003
mysqlbinlog --start-datetime="2018-01-30 20:30:10" --stop-datetime="2018-01-30 20:35:22" mariadb-bin.000003;
9.11 二进制日志事件的格式:
# at 328
#151105 16:31:40 server id 1 end_log_pos 431 Query
thread_id=1 exec_time=0 error_code=0
use `mydb`/*!*/;
SET TIMESTAMP=1446712300/*!*/;
CREATE TABLE tb1 (id int, name char(30))
/*!*/;
事件发生的日期和时间:151105 16:31:40
事件发生的服务器标识:server id 1
事件的结束位置:end_log_pos 431
事件的类型:Query
事件发生时所在服务器执行此事件的线程的ID:thread_id=1
语句的时间戳与将其写入二进制文件中的时间差:exec_time=0
错误代码:error_code=0
事件内容:
GTID:Global Transaction ID,mysql5.6以mariadb10以上版本专属属性:GTID
9.12 清除指定二进制日志:
PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr }
示例:
PURGE BINARY LOGS TO ‘mariadb-bin.000003’;删除3前日志
PURGE BINARY LOGS BEFORE '2017-01-23';
PURGE BINARY LOGS BEFORE '2017-03-22 09:25:30';
9.103 删除所有二进制日志,index文件重新记数
RESET MASTER [TO #]; 日志文件从#开始记数,默认
从1开始,一般是master第一次启动时执行,MariaDB10.1.6开始支持TO #
切换日志文件:
FLUSH LOGS;
十、备份和恢复
为什么要备份
灾难恢复:硬件故障、软件故障、自然灾害、黑客攻击、误操作测试等数据丢失场景
备份注意要点
能容忍最多丢失多少数据
恢复数据需要在多长时间内完成
需要恢复哪些数据
还原要点
做还原测试,用于测试备份的可用性
还原演练
10.1备份类型
备份类型:
- 完全备份,部分备份
完全备份:整个数据集
部分备份:只备份数据子集,如部分库或表 - 完全备份、增量备份、差异备份
- 增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)以来变化的数据,备份较快,还原复杂
- 差异备份:仅备份最近一次完全备份以来变化的数据,备份较慢,还原简单
//注意:二进制日志文件不应该与数据文件放在同一磁盘
10.2 备份种类
冷、温、热备份
- 冷备:读写操作均不可进行
- 温备:读操作可执行;但写操作不可执行
- 热备:读写操作均可执行
MyISAM:温备,不支持热备
InnoDB: 都支持 - 物理和逻辑备份
- 物理备份:直接复制数据文件进行备份,与存储引擎有关,占用较多的空间,速度快
- 逻辑备份:从数据库中“导出”数据另存而进行的备份,与存储引擎无关,占用空间少,速度慢,可能丢失精度
10.3 备份时需要考虑的因素
温备的持锁多久
备份产生的负载
备份过程的时长
恢复过程的时长
- 备份什么
数据
二进制日志、InnoDB的事务日志
程序代码(存储过程、存储函数、触发器、事件调度器)
服务器的配置文件
10.4 设计备份方案
数据集:完全+增量
备份手段:物理,逻辑
备份工具
mysqldump:逻辑备份工具,适用所有存储引擎,温备;支持完全或部分备份;对InnoDB存储引擎支持热备
cp, tar等复制归档工具:物理备份工具,适用所有存储引擎;只支持冷备;完全和部分备份
LVM的快照:先加锁,做快照后解锁,几乎热备;借助文件系统管理工具进行备份
mysqlhotcopy:几乎冷备;仅适用于MyISAM存储引擎
10.5 备份工具的选择:
mysqldump+复制binlog:
mysqldump:完全备份复制binlog中指定时间范围的event:增量备份
LVM快照+复制binlog:
LVM快照:使用cp或tar等做物理备份;完全备份复制binlog中指定时间范围的event:增量备份
xtrabackup:由Percona提供支持对InnoDB做热备(物理备份)的工具,支持完全备份、增量备份
MariaDB Backup: 从MariaDB 10.1.26开始集成,基于
Percona XtraBackup 2.3.8实现
mysqlbackup:热备份, MySQL Enterprise Edition组件
10.6 mysqldump备份命令
逻辑备份工具:mysqldump, mydumper, phpMyAdmin
Schema和数据存储在一起、巨大的SQL语句、单个巨大的备份文件
mysqldump工具:客户端命令,通过mysql协议连接至mysqld服务器进行备份
mysqldump [OPTIONS] database [tables]
mysqldump [OPTIONS] –B DB1 [DB2 DB3...]
mysqldump [OPTIONS] –A [OPTIONS]
mysqldump参考:
https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html
10.61 mysqldump常见选项:
-A, --all-databases 备份所有数据库,含create database
-B , --databases db_name… 指定备份的数据库,包括
create database语句
-E, --events:备份相关的所有event scheduler
-R, --routines:备份所有存储过程和存储函数
--triggers:备份表相关的触发器,默认启用,用--skip-triggers,不备份触发器
--master-data[=#]: 此选项须启用二进制日志
1:所备份的数据之前加一条记录为CHANGE MASTER TO语句,非注释,不指定#,默认为1
2:记录为注释的CHANGE MASTER TO语句
此选项会自动关闭--lock-tables功能,自动打开--lock-all-tables功能(除非开启--single-transaction)
-F, --flush-logs :备份前滚动日志,锁定表完成后,执行flush logs命令,生成新的二进制日志文件,配合-A时,会导致刷新多次数据
库,在同一时刻执行转储和日志刷新,则应同时使用--flush-logs和-x,--master-data或-single-transaction,此时只刷新一次
建议:和-x,--master-data或 --single-transaction一起使用
--compact 去掉注释,适合调试,生产不使用
-d, --no-data 只备份表结构
-t, --no-create-info 只备份数据,不备份create table
-n,--no-create-db 不备份create database,可被-A或-B覆盖
--flush-privileges 备份mysql或相关时需要使用
-f, --force 忽略SQL错误,继续执行
--hex-blob 使用十六进制符号转储二进制列(例如,“abc”变为0x616263),受影响的数据类型包括BINARY, VARBINARY,BLOB,BIT
-q, --quick 不缓存查询,直接输出,加快备份速度
10.62 MyISAM备份选项:
支持温备;不支持热备,所以必须先锁定要备份的库,而后启动备份操作
锁定方法如下:
-x,--lock-all-tables:加全局读锁,锁定所有库的所有表,同时加--single-transaction或--lock-tables选项会关闭此选项功能
注意:数据量大时,可能会导致长时间无法并发访问数据库
-l,--lock-tables:对于需要备份的每个数据库,在启动备份之前分别锁定其所有表,默认为on,--skip-lock-tables选项可禁用,对备份MyISAM的多个库,可能会造成数据不一致
注:以上选项对InnoDB表一样生效,实现温备,但不推荐使用
10.63 InnoDB备份选项:
支持热备,可用温备但不建议用
--single-transaction
此选项Innodb中推荐使用,不适用MyISAM,此选项会开始备份前,先执行START TRANSACTION指令,并且在备份期间,不允许对数据进行修改操作
此选项和--lock-tables(此选项隐含提交挂起的事务)选项是相互排斥
备份大型表时,建议将--single-transaction选项和--quick结合一起使用
10.64InnoDB建议备份策略
mysqldump –uroot –A –F –E –R --single-transaction --master-data=1 --flush-privileges --triggers --hex-blob >$BACKUP_DIR/fullbak_$BACKUP_TIME.sql
MyISAM建议备份策略
mysqldump –uroot –A –F –E –R –x --master-data=1 --flush-privileges --triggers --hex-blob >$BACKUP_DIR/fullbak_$BACKUP_TIME.sql
10.7 基于LVM的备份
(1) 请求锁定所有表
mysql> FLUSH TABLES WITH READ LOCK;
(2) 记录二进制日志文件及事件位置
mysql> FLUSH LOGS;
mysql> SHOW MASTER STATUS;
mysql -e 'SHOW MASTER STATUS' > /PATH/TO/SOMEFILE
(3) 创建快照
lvcreate -L # -s -p r -n NAME /DEV/VG_NAME/LV_NAME
(4) 释放锁
mysql> UNLOCK TABLES;
(5) 挂载快照卷,执行数据备份
(6) 备份完成后,删除快照卷
(7) 制定好策略,通过原卷备份二进制日志
10.8 xtrabackup备份命令
Xtrabackup
percona提供的mysql数据库备份工具,惟一开源的能够对innodb和xtradb数据库进行热备的工具
特点:
(1)备份还原过程快速、可靠
(2)备份过程不会打断正在执行的事务
(3)能够基于压缩等功能节约磁盘空间和流量
(4)自动实现备份检验
(5)开源,免费
Xtrabackup2.2版之前包括4个可执行文件:
Innobackupex: perl 脚本
Xtrabackup: C/C++ 编译的二进制
Xbcrypt:加解密
Xbstream:支持并发写的流文件格式
xtrabackup 是用来备份 InnoDB 表的,不能备份非 InnoDB 表,和 mysqld server 没有交互;innobackupex 脚本用来备份非InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 mysqld server 发送命令进行交互,如加读锁(FTWRL)、获取位点(SHOW SLAVESTATUS)等。即innobackupex是在xtrabackup 之上做了一层封装实现的。
虽然目前一般不用 MyISAM 表,只是mysql 库下的系统表是MyISAM 的,因此备份基本都通过 innobackupex 命令进行
10.81 Xtrabackup的备份过程
10.82 xtrabackup的特性
使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命名的目录中,在备份时,innobackupex还会在备份目录中创建如下文件:
(1)xtrabackup_checkpoints:备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息,每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的
(2)xtrabackup_binlog_info:mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置
(3)xtrabackup_binlog_pos_innodb:二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当position
(4)xtrabackup_binary:备份中用到的xtrabackup的可执行文件
(5)backup-my.cnf:备份命令用到的配置选项信息在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据
10.83 xtrabackup用法
备份:innobackupex [option] BACKUP-ROOT-DIR
选项说明:
--user:该选项表示备份账号
--password:该选项表示备份的密码
--host:该选项表示备份数据库的地址
--databases:该选项接受的参数为数据名,如果要指定多个数据库,彼此间需要以空格隔开;如:"xtra_test dba_test",同时,在指定某数据库时,也可以只指定其中的某张表。如:"mydatabase.mytable"。该选项对innodb引擎表无效,还是会备份所有innodb表
--defaults-file:该选项指定了从哪个文件读取MySQL配置,必须放在命令行第一个选项的位置
--incremental:该选项表示创建一个增量备份,需要指定--incremental-
basedir
--incremental-basedir:该选项表示接受了一个字符串参数指定含有full backup的目录为增量备份的base目录,与--incremental同时使用
--incremental-dir:该选项表示增量备份的目录
--include=name:指定表名,格式:databasename.tablename
Prepare:innobackupex --apply-log [option] BACKUP-DIR
选项说明:
--apply-log:一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。此选项作用是通过回滚未提交的事务及同步已经提交的事务至数据文件使数据文件处于一致性状态
--use-memory:该选项表示和--apply-log选项一起使用,prepare 备份的时候,xtrabackup做crash recovery分配的内存大小,单位字节。也可(1MB,1M,1G,1GB),推荐1G
--defaults-file:该选项指定了从哪个文件读取MySQL配置,必须放在命令行第一个选项的位置
-export:表示开启可导出单独的表之后再导入其他Mysql中
--redo-only:这个选项在prepare base full backup,往其中merge增量备份时候使用
还原:innobackupex --copy-back [选项] BACKUP-DIR
innobackupex --move-back [选项] [--defaults-group=GROUP-NAME] BACKUP-DIR
选项说明:
--copy-back:做数据恢复时将备份数据文件拷贝到MySQL服务器的datadir
--move-back:这个选项与--copy-back相似,唯一的区别是它不拷贝文件,而是移动文件到目的地。这个选项移除backup文件,用时候必须小心。使用场景:没有足够的磁盘空间同事保留数据文件和Backup副本
xtrabackup示例
1普通全量备份、还原(库:dba_test、xtra_test)
#备份所有数据库:备份目录里生成日期命名的文件夹
innobackupex --defaults-file=/etc/mysql/my.cnf --user=root --password=123 /home/zhoujy/xtrabackup/
#还原
1.先prepare,利用--apply-log的作用是通过回滚未提交的事务及同步已经提交的事务至数据文件使数据文件处于一致性状态
innobackupex --apply-log /home/zhoujy/xtrabackup/2016-09-23_10-53-51/
2.copy:需要数据目录为空
innobackupex --defaults-file=/etc/mysql/my.cnf --copy-back /home/zhoujy/xtrabackup/2016-09-23_10-53-51/
3.改权限
++++++++++++++++++
#备份所有数据库:指定备份目录
innobackupex --defaults-file=/etc/mysql/my.cnf --user=root --password=123 --no-timestamp /home/zhoujy/xtrabackup/
#还原同上
++++++++++++++++++
#备份指定数据库名,多个数据库用空格分开
innobackupex --defaults-file=/etc/mysql/my.cnf --user=root --password=123 --no-timestamp --databases="dba_test xtra_test" /home/zhoujy/xtrabackup/
#还原
1.先prepare,利用--apply-log的作用是通过回滚未提交的事务及同步已经提交的事务至数据文件使数据文件处于一致性状态
innobackupex --apply-log /home/zhoujy/xtrabackup/
2.copy,因为是部分备份,不能直接用--copy-back,只能手动来复制需要的库,也要复制ibdata(数据字典)
cp -r dba_test/ /var/lib/mysql/
cp -r xtrabackup/dba_test/ /var/lib/mysql
3.改权限
++++++++++++++++++
#备份指定表
备份不同库下的不同表
1:innobackupex --defaults-file=/etc/mysql/my.cnf --user=root --password=123 --no-timestamp --databases="dba_test.tb1 xtra_test.M" /home/zhoujy/xtrabackup/
备份一个库下面的表,支持正则,如:--include='^mydatabase[.]mytable'
2:innobackupex --defaults-file=/etc/mysql/my.cnf --user=root --password=123 --no-timestamp --include='xtra_test.I' /home/zhoujy/xtrabackup/
备份指定文件里的表,文件里每行的格式是:dbname.tbname
3:innobackupex --defaults-file=/etc/mysql/my.cnf --user=root --password=123 --no-timestamp --tables-file=/tmp/tbname.txt /home/zhoujy/xtrabackup/
#还原
同指定数据库还原一样,需要还原ibdata。注意,还原的时候可以这样还原:
innobackupex --apply-log --export xtrabackup/
生成如下几个文件:
-rw-r--r-- 1 root root 425 9月 23 17:16 I.cfg
-rw-r----- 1 root root 16K 9月 23 17:16 I.exp
-rw-r----- 1 root root 8.4K 9月 23 17:15 I.frm
-rw-r----- 1 root root 96K 9月 23 17:15 I.ibd
然后:
alter table I discard tablespace;
将I.exp和I文件传到目标机目标目录中执行:
alter table I import tablespace;
2.普通增量备份、还原
全量备份,这里举例单个表,也可以是指定几个库,甚至所有库
innobackupex --defaults-file=/etc/mysql/my.cnf --user=root --password=123 --no-timestamp --databases="xtra_test.I" /home/wangchao/xtrabackup/
#增量备份1
innobackupex --defaults-file=/etc/mysql/my.cnf --user=root --password=123 --no-timestamp --databases="xtra_test.I" --incremental-basedir=/home/wangchao/xtrabackup/ --incremental/home/zhoujy/increment_data/
#增量备份2
innobackupex --defaults-file=/etc/mysql/my.cnf --user=root --password=123 --no-timestamp --databases="xtra_test.I" --incremental-basedir=/home/wangchao/increment_data/ --incremental/home/zhoujy/increment_data1/
信息
通过上面三个目录里的xtrabackup_checkpoints文件,可以看出是哪种备份类型,全量(full-backuped)还是增量(incremental)。并且全量到增量的from_lsn和last_lsn是一一对应的。
在第2次做增量备份的时候 --incremental-basedir 指向全量备份,则第一次增量备份中的数据会被第2次包含,只需要还原一次就可以恢复,现在则需要还原2次增量备份。
还原
1.先prepare全备
innobackupex --incremental --apply-log --redo-only /home/zhoujy/xtrabackup
2.再prepare第一个增量
innobackupex --incremental --apply-log --redo-only /home/zhoujy/xtrabackup/ --user-memory=1G --incremental-dir=/home/zhoujy/increment_data/
3.然后prepare最后一个增量
innobackupex --incremental --apply-log --redo-only /home/zhoujy/xtrabackup/ --user-memory=1G --incremental-dir=/home/zhoujy/increment_data1/
通过上面额可以看到全量备份里xtrabackup_checkpoints文件的to_lsn是最新的lsn。
4.最后再prepare全量备份
innobackupex --apply-log /home/zhoujy/xtrabackup/
5.copy
因为是部分备份,不是所有库备份,所以和上面介绍的一样,先手动复制需要的文件再修改权限即可恢复数据。
10.84 还原注意事项:
1.datadir目录必须为空。除非指定innobackupex --force-non-empty-directorires选项指定,否则--copy-backup选项不会覆盖
2.在restore之前,必须shutdown MySQL实例,你不能将一个运行中的实例restore到datadir目录中
3.由于文件属性会被保留,大部分情况下你需要在启动实例之前将文件的属主改为mysql,这些文件将属于创建备份的用户chown -R mysql:mysql /data/mysql以上需要在用户调用innobackupex之前完成--force-non-empty-directories:指定该参数时候,使得innobackupex --copy-back或--move-back选项转移文件到非空目录,已存在的文件不会被覆盖。如果--copy-back和--move-back文件需要从备份目录拷贝一个在datadir已经存在的文件,会报错失败!