深入浅出MySQL -- 读书笔记
第一部分 基础篇. - 2 -
第1章 MySQL的安装与配置. - 2 -
第2章 SQL 基础. - 2 -
第3章 MySQL支持的数据类型. - 3 -
第4章 MySQL中的运算符. - 6 -
第5章 常用函数. - 7 -
第6章 图形化工具的使用. - 9 -
第二部分 开发篇. - 9 -
第7章 存储引擎(表类型)的选择. - 9 -
第8章 选择合适的数据类型. - 11 -
第9章 字符集. - 12 -
第10章 索引的设计和使用. - 13 -
第11章 视图. - 13 -
第12章 存储过程和函数. - 14 -
第13章 触发器. - 17 -
第14章 事务控制和锁定语句. - 17 -
第15章 SQL中的安全问题. - 18 -
第16章 SQLMode 及相关问题. - 18 -
第17章 SQL 分区. - 19 -
第三部分 优化篇. - 22 -
第18章 SQL优化. - 22 -
第四部分. - 24 -
第19章. - 24 -
第一部分 基础篇
1. MySQL 由于性能好,在开源数据库中独占鳌头,ANSI/ISO标准符合性不是太好
第1章 MySQL的安装与配置
2. Linux中启动、重启、关闭MySql
service mysql start /servicemysql restart /service mysql stop
第2章 SQL 基础
3. SQL分为DDL数据定义语言(create、drop)、DML数据操作语言(select、insert等)、DCL数据控制语言(权限、安全,grant,revoke)
4. 进入mysql控制台: mysql -uroot -p
5. sql常用DDL语句
show databases; |
查看所有数据库 |
create database db1; |
|
use db1; |
|
show tables; |
|
drop database dbname; drop table tablename; |
|
CREATE TABLE `users` ( `id` char(9) NOT NULL, `age` varchar(45), PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
|
desc tablename; |
查看表定义 |
show create table tablename; |
查看表定义语句 |
alter table tablename modify [column]column_definition [first|after col_name] |
修改列类型,可排序列 |
alter table tablename add [column]column_definition [first|after col_name] |
|
alter table tablename drop [column]columnname |
删除字段 |
alter table tablename change[column]oldcolNamecolumn_definition [first|after col_name] |
字段改名 |
alter table tablename rename [to] new_tablename |
表改名 |
like通配符:%匹配多个字符,下划线_匹配单个字符 |
|
6. DML语句
insert into tablename[(field1,…,fieldn)] values (value1,…,valuen),(value1,…,valuen),... |
|
update tablename set field1=value1,... [Where Condition] |
|
delete from tablename[where...] |
|
select [distinct] col1,col2,... from tablename [where..][order by colname asc|desc][limit start,count ] |
start 从0开始,可省略。limit 1,3表示从第2条记录开始取3条记录 |
select name,count(1) count1 from users group by name having count1 >1 |
having是设置聚合后的选择条件的。聚合函数(sum,count,max,min,avg) |
内连接 inner join 或者 from table1,table2 |
|
外链接分为左(外)连接和右(外)连接 left (outer) join/right (outer)join |
左连接,结果包含左表全部行 |
子查询 in / not in / exists /not exists |
有时候可用表连接优化 |
union/union all |
union all 直接合并 union 去重(distinct) |
group by 的with rollup子句 select staff_id,sum(amount) from payment group by staff_id with rollup |
Ø 可查询总的统计数据 Ø 或者 group by 有两列时,还可以只根据第一列分组的本组统计信息。p305 |
bit_and(col_name) / bit_or(colname) 与 group by 结合使用 |
对每一个小组的col_name列的各值做 按位与,按位或 操作,类似与 sum()分组统计 |
7. DCL语句
grant select,insert on dbname.* to 'z1'@'localhost' identified by '123' |
对z1用户授予 dbname数据库所有表的select和insert权限 |
revoke insert on dbname.* from 'z1'@'localhost' |
收回insert权限 |
8. MySQL 查看帮助
? contents; 或者 helpcontents;查看帮助列表
?/help
9. 查询元数据( information_schema数据库)
该数据库是虚拟数据库(视图),Schemata表存储所有数据库信息,tables表存储所有表信息,columns存储列信息,statistics表存储索引信息。
第3章 MySQL支持的数据类型
10. MySQL 支持数值类型、字符串类型(包含枚举、Set类型)、日期时间
11. 数值类型
类型 |
大小 |
用途 |
|
TINYINT |
1 字节 |
小整数值 |
|
SMALLINT |
2 字节 |
大整数值 |
|
MEDIUMINT |
3 字节 |
大整数值 |
|
INT或INTEGER |
4 字节 |
大整数值 |
|
BIGINT |
8 字节 |
极大整数值 |
|
FLOAT(M,D) |
4 字节 |
单精度浮点数值 |
|
DOUBLE(M,D)【等同于real】 |
8 字节 |
双精度浮点数值 |
|
DECIMAL(M,D) |
M+2 |
小数值 M是表示有效数字数的精度。M范围为1〜65。 D是表示小数点后的位数。 D的范围是0~30。MySQL要求D小于或等于(<=)M。 |
|
BIT(M) |
1-8 |
位类型。最小值BIT(1),最大值BIT(64) 不指定宽度时,默认为1位 select 时不显示,需要用bin(),hex()函数转换成二进制或十六进制 select bin(col2),hex(col2) from t2 |
12. 指定int(5)类型,表示当宽度小于5时,在前面补0,配合zerofill使用.不指定宽度时,默认补齐11位。
create table t1(id1 int zerofill,id2int(5) zerofill);
13. 整形都有 unsigned 可选属性,最小值从0开始
14. 小数表示有浮点数(float、double)和定点数decimal。decimal在数据库中以字符串形式存放,比浮点数更精确,用于货币等精度高的数据。
15. 日期时间类型
类型 |
大小(字节) |
范围 |
格式 |
用途 |
DATE |
3 |
1000-01-01/9999-12-31 |
YYYY-MM-DD |
日期值 |
TIME |
3 |
'-838:59:59'/'838:59:59' |
HH:MM:SS |
时间值或持续时间 |
DATETIME |
8 |
1000-01-01 00:00:00/9999-12-31 23:59:59 |
YYYY-MM-DD HH:MM:SS |
混合日期和时间值 |
YEAR |
1 |
1901/2155 |
YYYY |
年份值 |
TIMESTAMP |
4 |
1970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07 |
YYYYMMDD HHMMSS |
混合日期和时间值,时间戳 |
16. now()函数获取当前日期时间,或者 CURRENT_DATE
17. DATETIME与TIMESTAMP区别:
Ø DATETIME范围更广
Ø TIMESTAMP显示值与时区有关
Ø 表中的第一个TIMESTAMP列自动设置为系统时间(CURRENT_TIMESTAMP)
18. 字符串类型
类型 |
大小 |
用途 |
CHAR |
0-255字节 |
定长字符串 |
VARCHAR |
0-65535 字节 |
变长字符串 |
TINYBLOB |
0-255字节 |
不超过 255 个字符的二进制字符串 |
TINYTEXT |
0-255字节 |
短文本字符串 |
BLOB |
0-65 535字节 |
二进制形式的长文本数据 |
TEXT |
0-65 535字节 |
长文本数据 |
MEDIUMBLOB |
0-16 777 215字节 |
二进制形式的中等长度文本数据 |
MEDIUMTEXT |
0-16 777 215字节 |
中等长度文本数据 |
LONGBLOB |
0-4 294 967 295字节 |
二进制形式的极大文本数据 |
LONGTEXT |
0-4 294 967 295字节 |
极大文本数据 |
enum |
enum('M','F') |
枚举类型(数据取单个值) |
set |
|
集合类型,(有多个值) |
19. CHAR 和 VARCHAR 区别
Ø CHAR 长度固定,存储时尾部空格补齐。VarChar长度可变。
Ø Char不存储数据的尾部空格,Varchar存储
Ø char最大长度255,varchar 最大长度65535(5.0.3以后版本)
20. BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR
Ø 不同的是它们包含二进制字符串而不包含非二进制字符串。它们没有字符集,并且排序和比较基于列值字节的数值。
Ø Binary末尾补0,而Char末尾补空格。
第4章 MySQL中的运算符
21. 算术运算符
+ - * /【DIV】 %【MOD】 取模可用函数 MOD(a,b)
22. 比较运算符
Ø select 时,比较结果为true,返回1,为false返回0,不确定返回NULL
Ø 默认数字作为浮点数比较,字符串不区分大小写进行比较
运算符 |
作用 |
= |
等于 |
<=> |
安全的等于(可以用于比较NULL值,2个NULL相等) |
<>(!=) |
不等于 |
< <= |
小于 小于等于 |
> >= |
大于 大于等于 |
IS NULL、ISNULL |
判断一个值是否为NULL |
IS NOT NULL |
判断一个值是否不为NULL |
LEAST |
在有两个或多个参数时,返回最小值 |
GREATEST |
当有2或多个参数时,返回最大值 |
BETWEEN AND |
判断一个值是否落在两个值之间(含边界) |
IN 、NOT IN |
判断一个值是否落在IN列表中的任意一个值 |
LIKE |
通配符匹配 |
REGEXP、RLIKE |
正则表达式匹配 |
23. 逻辑运算符
NOT或者! AND或者&& OR或者|| XOR异或
24. 位运算符
~位取反 &位与 |位或 ^位异或 <<位左移 >>位右移
第5章 常用函数
25. 常用函数包括字符串函数,日期函数,数值函数、流程函数
26. 字符串函数
27. 数值函数
经测试,ceil(1) , floor(1) 结果都为 1.
所以CEIL(x)返回大于等于x的最小整数值,FLOOR(x)返回小于等于x的最大整数值
28. 日期时间函数
29. 流程函数
30. 其他函数
第6章 图形化工具的使用
31. 客户端MySQL workbench 和 web客户端phpMyAdmin
workbench功能有SQL开发,数据建模,Server管理、MySQL Utilities功能
32. 编写存储过程时,经常用 delimiter // 将 默认分隔符分号(;)变成双斜杠(//),存储过程编写完成后,delimiter ; 变回默认值。【存储过程中有分号】
33. MySQL Utilities工具集
第二部分 开发篇
第7章 存储引擎(表类型)的选择
34. 常用MySQL引擎:InnoDB(默认)、MyISAM(5.5之前默认)、Memory、Merge、CSV、PERFORMANCE_SCHEMA。第三方引擎TokuDB高写性能高压缩支持事务。
BLACKHOLE存储引擎不在磁盘存数据,只将DML操作记录在Bin LOG中,适合多级复制里的二级主库,见31章
35. 查看当前数据库支持的引擎:show engines \G;
36. 创建表时,设置引擎:create table t23( id int,primarykey (id))engine=MyISAM defaultcharset=gbk;
alter table t23 engine=InnoDB;
37. MyISAM存储引擎
MyISAM不支持事务、不支持外键,支持表锁。其优势是访问速度快。对事务完整性没有要求或者以select、Insert为主的应用可以采用。MyISAM类型的表可能会损坏。
MyISAM表在磁盘上对应三个文件.frm存储表定义; .MYD(MYData,存储数据);
.MYI(MYIndex,存储索引)。
MyISAM支持3中存储格式:
Ø 静态表(固定长度)【默认】: 表中的字段都是非变长字段,用空格补齐。优点:访问速度快,容易缓存,出现故障容易恢复。缺点:占用空间大
Ø 动态表:包含变长字段,记录长度不是固定的。频繁更新和删除记录会产生碎片。需要定期执行OPTIMIZE TABLE 语句或者 myisamchk-r 命令来改善性能。
Ø 压缩表:myisampack工具创建
38. InnoDB存储引擎
提供了外键、事务安全,但是比MyISAM写的效率差一些,且会占用更多存储空间和内存使用。支持行锁,分布式事务。
存储方式:
Ø 共享表空间存储:表结构存储在.frm文件中,数据和索引保存在innodb_data_home_dir和innodb_data_file_path定义的表空间中
Ø 多表空间存储:表结构存储在.frm文件中。每个表的数据和索引单独保存在.ibd文件中
39. MEMORY存储引擎
MEMORY存储引擎使用存在于内存中的内容来创建表。多用于内容变化不频繁的代码表和临时(中间)表。优点:访问速度非常地快,因它的数据存放在内存,并且默认使用Hash索引。缺点一旦服务关闭,数据丢失。
40. MERGE存储引擎
Merge存储引擎是一组MyISAM表的组合,这些表必须结构完全相同。Merge表本身没有数据,对merge表的增删改查实际是对内部MyISAM表进行的。
Merge表通常用来透明地对多个表进行查询和更新,而对按照时间记录的日志操作则可以进行透明的插入操作。
对于Merge表的插入,通过INSERT_METHOD子句定义
Ø FIRST:插入到第一个内部表
Ø LAST: 插入到最后一个内部表
Ø NO或者不定义INSERT_METHOD 子句: 不能对该MERGE表进行插入
新建MERGE表语句:
create table ta(id int,name char(10))engine=merge union=(tb2,tb3) insert_method=LAST ;
其中tb2与tb3结构与ta一样,只是engine=myisam
41. 如何选择合适的存储引擎
42. 创建Hash/Btree索引
create index name_index using hash[或btree] on tablename(colname);
查看表中的索引
show index from tablename [\G];
43. 使用 select LAST_INSERT_ID();返回当前线程最后插入记录的自增长列的值
44. 外键级联操作
临时关闭外键检查:set FOREIGN_KEY_CHECKS=0; 开启时设为1
Ø RESTRICT / NO ACTION 限制在子表有关联记录的情况下,父表不能更新或删除
Ø CASCADE 父表做更新相关列或删除记录时,更新或删除子表
Ø SET NULL ……子表对应字段被设置为NULL
第8章 选择合适的数据类型
45. char 与 varchar用来存储少量字符串
Ø char 固定长度,使用空格补齐,检索时去除尾部空格(即使插入实际数据时尾部有空格)。处理速度快,但是浪费存储空间,程序需要对数据尾部空格进行处理。对于长度变化不大,而对查询速度有要求的可选用。
Ø varchar可变长度。varchar 性能逐渐提高
Ø MyISAM存储引擎 推荐使用固定长度的char
Ø InnoDB建议使用varchar。所有数据行都使用指向数据列值的头指针,因此主要看存储性能。
Ø MEMORY 无论使用char还是varchar都是作为固定长度处理(作为char)
46. Text与BLOB用来存储大文本
Ø BLOB可存储二进制,Text只能保存字符串
Ø 进行大量删除操作后,使用OPTIMIZE TABLE tablename;来进行碎片整理
Ø 可使用前缀索引,为字段的前n字符创建索引。context为text类型。查询时%不能放在最前面,否则将无法使用索引。
create index idx_text on tb2(context(100));
Ø 【优化】不必要的时候不检索Text列,select col1,col2 而不是select *
Ø 【优化】把BLOB或者Text放到单独的表。把原表中的数据列转为固定长度,可以减少主表碎片。
47. 浮点数与定点数
Ø 浮点数float double超出精度时,四舍五入。
Ø 定点数decimal实际以字符串存储,可以更精确的表示精度(可用于货币)。
Ø 编程中应避免浮点数==比较,应使用范围比较
48. 日期类型选择:
Ø 尽量选择最小日期类型,YEAR DATE TIME
Ø 如果记录日期时间比较久远,选择DATETIME因其范围广
Ø 如果记录日期需要让不同时区的用户使用,使用TIMESTAMP
49. Linux du命令用于显示目录或文件的大小。du会显示指定的目录或文件所占用的磁盘空间
du -sh t.* -s只显示总大小不显示子目录;-h以K M G 友好显示
第9章 字符集
50. 查看所有字符集:
Ø show character set;
Ø select * from information_schema.character_sets;
51. MySQL 的字符集包括字符集和校对规则(用于比较)
Ø _ci 不区分大小写
Ø _cs 区分大小写
Ø _bin 比较是基于字符编码的值(区分大小写)
52. MySQL字符集和校对规则的4个级别的默认设置:
Ø 服务器级
在my.cnf中设置
[mysqld]
character_set_server=gbk
Ø 数据库级
Ø 表级
Ø 字段级
53. mysqldump 备份数据库结构,和数据 -d只导出表结构
第10章 索引的设计和使用
54. myISAM和InnoDB默认创建的是BTREE索引
55. 目前只有MyISAM引擎支持全文索引(innoDB从MySQL5.6支持),仅支持char varchar text
56. Memory引擎使用Hash索引,也支持Btree索引
57. 索引分类(第18章中还有索引详细讲解)
Ø 按底层结构:Hash索引和Btree索引。BTree索引适用于范围匹配【> < between<>】Hash单值匹配【= in】
Ø 普通索引、主键索引、唯一索引、全文索引
Ø 多列索引(组合索引)、前缀索引(部分索引):只是列的前面N个字符建索引
58. B树索引,不是二叉树,而是平衡树,B代表平衡(balanced)
59. 索引设计原则
Ø 搜索列设索引,即Where后面的列
Ø 列值没有大量相同值时,索引效率高
Ø 使用段索引(前缀索引)
Ø 使用最左索引(多列索引时)
Ø 不要过度使用索引,索引占空间,写操作性能降低
第11章 视图
60. 视图是虚拟表,对用户透明,数据来自实际表,且仅在使用视图时动态生成
Ø 简单:不用关心后台关联和筛选条件
Ø 安全:使用视图的用户仅能看到允许查询的结果
Ø 数据独立:可屏蔽表结构的修改对用户的影响,原表修改可通过修改视图解决
61. 创建视图:
不指定时,默认CASCADED。CASCADED需要满足定义本视图时使用到的所有视图的条件(Where)
62. show tables;可显示表和视图
show create view viewname ;可查看视图定义
information_schema.views表中可以查看视图相关信息
第12章 存储过程和函数
63. 存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合。
Ø 减少应用开发人员的工作(处理数据的逻辑在数据库,如需修改,不用改程序)
Ø 减少数据在数据库和应用服务器之间的传输
Ø 提高数据处理效率(预编译)
64. 存储过程Procedure与函数Function区别
Ø 函数必须有返回值,存储过程没有
Ø 函数的参数只能是IN类型的,存储过程的参数可以是IN,OUT,INOUT
65. 定义
66. 调用存储过程或者函数 call sp_name(parameter[,…])
67. 创建存储过程时,常用delimiter $$ 命令将语句结束符由;改为$$
68. 删除存储过程或者函数:
drop {procedure | function} [if exists]sp_name;
69. 授权执行存储过程的权限:
70. 使用局部变量(仅在Begin 和 end 中有效,且必须在begin语句后面第一句)
Ø 定义: declare var_name[,…] type [defaut value]
Ø 赋值:1.直接赋值(常量、或表达式) Set;2.查询赋值 selectcolname into varname
71. 定义 条件 和 处理。(在处理过程中遇到问题时相应的处理步骤)
实例:
72. 光标:对结果集进行循环处理。
73. 流程控制
Ø if then elseif then else end if
Ø case when 两种用法
Ø loop leave(退出) itreate(继续下一轮循环)
Ø repeat … until … end repeat
Ø while … do … end while
74. 事件调度器(时间触发器),定期创建表,定期清理历史数据
set GLOBAL event_scheduler=1; 打开事件调度器
或者 on schedule every 5second ……
第13章 触发器
75. 创建触发器
trigger_time 可以是 before 或者 after
trigger_event 可以是 insert update delete
Ø 同一个表相同时间的相同触发事件只能定义一个触发器。
Ø 使用别名 new和 old 来引用触发器中变化的记录
76. 删除触发器
drop trigger [schema_name.]trigger_name;
删除表中所有触发器:drop trigger tblname;
77. 查看触发器
show triggers;显示所有触发器
查询information_schema.triggers表
78. 添加过多或过复杂触发器影响插入、更新、删除效率
第14章 事务控制和锁定语句
79. MySQL支持的锁
Ø InnoDB支持 行级锁定
Ø MyISAM 和MEMORY 支持 表级锁定
Ø BDB存储引擎的表支持 页级锁定
80. 表锁
Ø LOCK TABLES tbl_name[[AS] alias] lock_type [, tbl_name [[AS] alias]lock_type] ...
Ø lock_type:READ[LOCAL]|[LOW_PRIORITY] WRITE
Ø UNLOCK TABLES
Ø UNLOCK TABLES显示的释放当前session锁保持的锁。
Ø 另外通过LOCK TABLEs语句为当前session获取新锁前会隐式的释放当前session之前的所有锁
81. 事务定义语法
chain :启动一个新事物 release:断开和客户端的连接。
82. 默认情况下MySQL是自动提交事务的。手动提交或回滚set autocommit=0;,设置之后所有的事务都需要通过明确的命令进行提交或者回滚
83. 事务提交前,修改并没有实际提交到数据库。
84. 所有DDL语句不能回滚。可以通过SAVEPOINT指定回滚事务的一个部分。
savepoint spname;…… rollback to savepoint spname;
85. 分布式事务 XA事务
Ø 只支持InnoDB存储引擎
Ø 存在问题,当前不推荐使用分布式事务P213
第15章 SQL中的安全问题
86. SQL注入:利用数据库的外部接口将用户数据插入到实际的数据库操作语言SQL中,入侵数据库
87. 注入方式
Ø or 1=1
Ø username=czf'/*
88. 应对措施
Ø PreparedStatement
Ø 使用应用程序提供的转换函数
Ø 自定义函数进行校验
第16章 SQL Mode 及相关问题
89. MySQL 可以运行在不同的SQL Mode(SQL模式)下,(支持的SQL语法和数据校验不同)
Ø ANSI模式,保证大多数SQL符合标准的SQL语法,迁移时方便
Ø STRICT_TRANS_TABLES(严格模式) ,插入记录列长度超出定义时,产生ERROR而不是WARNING
Ø TARDITIONAL(也是严格模式)模式时,插入错误格式的日期插入会报错,MOD(X,0)报错,而ANSI模式下错误格式的日期插入会变成“0000-00-0000:00:00”,MOD(X,0)结果为NULL
Ø 设置NO_BACKSLASH_ESCAPES模式,使数据中的反斜线\称为普通字符。
Ø PIPES_AS_CONCAT模式(ANSI模式包含此模式):使||视为字符串连接操作符(为了兼容ORACLE)。
90. SET [SESSION|GLOBAL] sql_mode= 'ANSI';修改SQL MODE
91. 常用SQL MODE
“严格模式”为MYSQL 提供了很好的数据校验功能。
92. SQL MODE 在数据库迁移时(迁入或迁出其他类型数据库)有一定作用。为兼容其他数据库设置不同组合的SQL MODE。P224
第17章 SQL 分区
93. 分区:把数据表分成多个更小更容易管理的部分。分区对应用透明,不影响业务逻辑。逻辑上只有一个表,实际上对应数个物理分区对象。分区优点如下:
Ø 跨多磁盘存储,可以存储更多数据,获得更大的查询吞吐量。
Ø 优化查询。当where子句包含分区条件时,可以只扫描必要的分区提高效率
Ø 对于过期数据,可以通过删除分区来快速删除数据
94. 分区类型:
95. HASH分区示例:(分散热点读,使数据在各分区尽可能平均分布)
Ø 常规HASH分区:对分区数使用取模算法确定数据存储的分区。当增加或减少分区时,所有数据需要重新计算。数据分布均衡
Ø 线性HASH分区(BY LINER HASH(……)):使用 线性的2的幂运算法则(找到一个大于等于当前分区数(num)的2的幂(N),对这个值取模,如果结果大于分区数,则对N/2取模)。P238.分区维护时,MySQL能够处理的更加迅速,缺点是各分区数据分布不太均衡。
96. KEY分区:
KEY分区类似于HASH分区,也可以指定LINER,不同在于:
Ø HASH允许自定义表达式,KEY不允许
Ø HASH只支持整数分区,KEY支持出BLOB和TEXT以外的其他类型
Ø 创建KEY分区表时,可以不指定分区键,默认选择主键作为分区键(没有主键时,选择非空唯一键做分区键,如果没主键也没非空唯一键,就必须指定分区列)
97. Range分区示例:适用于需要删除过期数据和包含分区键的查询
此时如果插入 store_id 大于30 会出错。增加分区如下:
98. 分区表上要么没有 主键/唯一键时 ,要么分区字段必须是在 主键/唯一键 中。
99. explain partitions select …… 可以看到 查询用到了哪些分区
100. List分区示例
101. Columns分区(分为RANGE COLUMNS和LIST COLUMNS)支持所有整形,日期类型和字符类型。支持多列分区(相当于按多列依次排序分区:a<10 或者 a=10,b<10两种情况会分到P02分区):
102. 子分区:又称复合分区,对RANGE/LIST分区了的表再进行HASH/KEY分区,适用于数据量非常大的数据记录:
103. 分区对NULL值的处理
Ø RANGE分区当最小值处理
Ø HASH/KEY当0处理
Ø LIST分区中NULL必须出现在枚举值中,否则无法插入
104. RANGE/LIST分区管理
Ø alter table tbname drop partition p2; 删除分区并删除该分区数据
Ø 只能从RANGE分区列表的最大端增加分区,否则出错
alter tabletabname add partition(partition p4 values less than (20));
Ø 合并/拆分分区:alter table tbname reorganize partition p2[,p3,……] into (partition p4 values less than(2005)[,……]);重新定义分区时,只能够重新定义相邻的分区
105. HASH/KEY
Ø 合并(减少)分区:alter table tbname coalesce partition 2;减少到2个分区。不能用来增加分区
Ø 增加分区:alter table tbname add partition 8;增加8个分区,而不是增加到8个
第三部分 优化篇
第18章 SQL优化
106. 用 mysql 命令获得一些服务优化信息(看是查询多还是增删改多):
(1)show [session|global] status like'com_%'; 默认是Session。 #主要看 com_select,com_insert,com_update,com_delete统计结果,查到都是本次会话结果|本次服务启动后的所有结果
(2)就想查看 innodb 存储引擎的这些信息:show status like 'innodb_rows_%'; 主 要 查 看innodb_rows_read,innodb_rows_inesrted,innodb_rows_updated,innodb_rows_deleted 这四个参数
(3)show status like 'connections'; #查看连接 mysql 服务器的次数
(4)show status like 'uptime'; #mysql 服务器的工作时间
(5)show status like 'slow_queries'; #慢查询的次数
107. 定位效率较低的SQL语句
Ø 使用--log-slow-queries[=file_name] 选项启动mysql时,会记录所有执行时间超过long_query_time秒的sql语句到日志文件。
Ø 使用show processlist;命令实时查看mysql当前线程状态,是否锁表等
108. 通过explain[extended]或者desc分析低效率SQL的执行计划(分析后可用 show warnings;得到优化后的sql语句):
explain partitions select …… 可查看分区使用情况
mysql>explain select * from t1 \G 或:
mysql>desc select * from t1 \G 主要查看以下属性:
(1)type (访问类型)是否用到索引
ALL index range ref eq_refconst,system NULL 性能左至右,由最差到最好
(2)key 索引名称
(3)rows 查询影响的行数(越少说明优化的越好)
109. 通过show profile分析sql
Ø 开启profile: set profiling=1;
Ø show profiles;得到query_id;
Ø show profile for query query_id;展示语句执行过程中每个状态消耗的时间
110. 通过trace 分析优化器如何选择执行计划。p266
111. 索引优化问题:
Ø 一般的要加索引的字段为:where | order by后面字段
Ø 查看索引使用情况: mysql>show status like'handler_read%'; #如果其中handler_read_rnd_next 的值高则索引低效,需要去优化索引,而如果低则说明索引 高效.
112. 存在索引但是优化器没有使用(索引失效)的情况:
Ø 以%开头的Like查询无法使用B-Tree索引(应使用全文索引解决)
Ø 数据类型出现隐式转换时不会使用索引(列类型是字符串,where中要用'123',而不是123)
Ø 复合索引不满足最左索引时(最左匹配是B-Tree索引的首要原则)
Ø MySQL估计使用索引比全表扫描更慢(表数据量很小时)或(筛选性越高越容易使用的到索引,比如like 'w%'使用全表扫描,而like'sw%' 使用索引)
Ø or 前后列都有索引时才会用到索引
113. 实用的(表管理)优化方法
Ø 定期分析表和检查表:analyze|check table tbname;刷新系统的统计信息使其能够做出正确的执行计划|检查表(视图)是否有错
Ø 定期优化表:optimize table tablename;对含有变长类型varchar等的表进行大量删除后,留下的碎片进行整理。
114. 常用SQL的优化
Ø Select col1,col2,…… 而不是 select * from 只选择必要字段
Ø insert优化:
(1)大批量数据的导入优化: 前后执行以下操作
alter table t1 disable keys | alter table t1 enable keys;
mysql>set unique_checks=0; | msyql>set unique_checks=1;
mysql>autocommit=0; | mysql>autocommit=1;
(2)当一个文件装载一个表时,用 load data infile 要比很多 insert 语句快 20 倍,而 mysqlimport 这种导入也很快,因为它用的本来就是 load data infile 这种函数接口.
(3)优化 insert 语句,最好用一行多值的这种形式:
insert into t1(name) values(1),(2),(3)
Ø order by 优化p289:尽量减少额外的排序,通过索引直接返回有序数据。Where条件和order by 使用相同的索引,并且orderby 的顺序和索引的顺序相同(组合索引时),并且order by 的字段都是升序或者都是降序。否则需要额外的排序
Ø 查询包括 groupby 但如何避免排序结果的消耗:
mysql>desc select id from t1 group by idorder by null \G
Ø 优化嵌套查询:
(1)mysql>desc select * from t1 wheres_id not in (select id from comany2) \G
(2)mysql>desc select * form t1 left joincompany2 on t1.s_id=comany2.id where t1.s_id is null \G #以上 leftjoin 这种形式明显快于 not in ()这种子查询,因为 join 不需要在内存中建立临时表来 完成这个逻辑上需要两个步骤的查询工作.
Ø 分页查询优化思路:
(1):在索引上完成排序分页操作,最后根据主键关联回原表查询所需要的其他列。
(2):记录上一页最大/小值,将limit m,n 转为where id
Ø sql 索引提示:
(1)use index
mysql>desc select * from t1 use index (ind_id) where id=3 \G
(2)ignore index
mysql>desc select * from t1 ignore index (ind_id) where id=3\G
(3)force index
mysql>desc select * from t1 force index (ind_id) where id>0 \G #注意这种 where 后这种带范围判断的字段的索引是不起作用的,但可以人为的强制去用 index,虽然使用索引效率不是最高,这是 mysql 留给用户的一个自行选择计划的权力而已.
Ø 与删除表有关的优化: 用truncate和delete两种方法都可以把表中数据清空,但是用truncate明显比delete速度要快,而且节省内存
115. 什么叫做覆盖索引?
索引是高效找到行的一个方法,当能通过检索索引就可以读取想要的数据,那就不需要再到数据表中读取行了。如果一个索引包含了(或覆盖了)满足查询语句中字段与条件的数据就叫做覆盖索引。
是非聚集组合索引的一种形式,它包括在查询里的Select、Join和Where子句用到的所有列(即建立索引的字段正好是覆盖查询语句[select子句]与查询条件[Where子句]中所涉及的字段,也即,索引包含了查询正在查找的所有数据)。
MySQL只能使用B-Tree索引做覆盖索引
当发起一个被索引覆盖的查询(也叫作索引覆盖查询)时,在EXPLAIN的Extra列可以看到“Using index”的信息
116. SQL中使用正则表达式 REGEXP
select 'abcdefg' REGEXP '^a';结果为1
select * from where colname REGEXP '@163[,.]com$';
117. 使用RAND()提取随机行
select * from tbname order by rand()[ limit count_num ];
118. MySQL数据库对应操作系统下的目录,表对应一个或多个文件。操作系统的大小写敏感决定了数据库名和表名的大小写敏感性。(window不敏感,Unix敏感)。列、索引、存储程序和触发器名在任何平台都对大小写不敏感。
第19章 优化数据库对象
119. 优化表的数据类型
select * from tablename procedure analyse();让mysql给出优化建议
120. 垂直拆分和水平拆分
Ø 垂直拆分:某些列常用,某些列不常用。查询时减少io次数。缺点是需要管理冗余列,查询所有数据时需要联合join操作
Ø 水平拆分:表数据量很大、表中分别记录不同时期或不同地区数据,有的数据常用,有的不常用。缺点给应用增加复杂度,需要union操作
121. 使用逆规范化加快查询(增加冗余列等)
122. 使用中间表提高统计速度(统计时不会影响线上应用,可以对中间表增加索引或者新列提高效率和辅助查询)
第20章 锁问题
123. MyISAM和MEMORY采用表级锁,InnoDB采用行级锁(默认),也支持表级锁
Ø 表级锁(应用最广泛):开销小,加锁快,不会出现死锁(总是一次获得sql语句所需要的全部锁),锁定粒度最大,发生冲突概率最高,并发度最低。适用于以查询为主,少量更新的应用。
Ø 行级锁:开销大,加锁慢,会出现死锁,锁定粒度最小,发送锁冲突概率最低,并发度最高。
Ø 页面锁(BDB存储引擎【已被innoDB取代】支持):会死锁,开销和粒度位于表级和行级之间
124. 查询表级锁争用情况:showstatus like 'table%';
如果Table_locks_waitd值比较高,说明存在较严重的表级锁争用情况
125. 表级锁模式locktable tbname read|write;…… unlock tables;
Ø 表共享读锁:读与读可以共享
Ø 表独占写锁:写与读,写与写之间必须串行(其他线程阻塞)
126. MyISAM执行查询(select)前会自动给涉及的所有表加读锁,在执行更新操作(insert/update/delete)前会自动给涉及到的表加写锁。显式加锁可以实现某一时间点对多个表读取的一致性。
127. 同一个表一个语句中出现多次时,要通过与SQL语句中相同的别名锁定多次,否则会出错:
lock table tb2 as a read,tb2 as b read;
128. 并发插入(解决对同一个表查询和插入的锁争用):
Ø Session1:lock tabletbname read local; 当前Session无法访问其他Session并发插入的数据行。
Ø Session2:其他线程虽然不能对tbname表进行更新和删除操作,但是可以在尾部进行并发的插入操作。
129. MyISAM锁调度:
Ø 写进程优先获得锁,即使其比读进程后来到锁等待队列。(因此,MyISAM不太适合有大量更新操作和查询操作的应用)
Ø 为防止大量更新操作导致查询操作很难得到读锁,有以下方式:
130. 事务的acid属性
Ø 原子性:一个事务包含多个操作,这些操作要么全部执行,要么全都不执行
Ø 一致性:一致性是指事务使得系统从一个一致的状态转换到另一个一致状态。(如果你做个银行数据库的话,无论怎么转账,钱的总数都不变)
Ø 隔离性:并发事务之间互相影响的程度,比如一个事务会不会读取到另一个未提交的事务修改的数据
Ø 持久性(Durability): 事务提交后,对系统的影响是永久的
131. 并发事务问题:
Ø 更新丢失:俩事务同时修改同一份数据,后保存的覆盖了先保存的
Ø 脏读:事务A修改了一个数据,但未提交,事务B读到了事务A未提交的更新结果,如果事务A提交失败,事务B读到的就是脏数据。
Ø 不可重复读:在同一个事务中,对于同一份数据读取到的结果不一致。比如,事务B在事务A提交前读到的结果,和提交后读到的结果可能不同。不可重复读出现的原因就是事务并发修改记录,要避免这种情况,最简单的方法就是对要修改的记录加锁,这回导致锁竞争加剧,影响性能。另一种方法是通过MVCC可以在无锁的情况下,避免不可重复读。
Ø 幻读:在同一个事务中,同一个查询多次返回的结果不一致。事务A新增了一条记录,事务B在事务A提交前后各执行了一次查询操作,发现后一次比前一次多了一条记录。幻读是由于并发事务增加记录导致的,这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。
132. 数据库实现事务隔离的方式
Ø 加锁
Ø MVCC(MultiVersion Concurrency Control)多版本并发控制(乐观锁???)
133. 隔离级别(下面4种MySQL都支持)
Ø 未提交读Read Uncommitted:最低的隔离级别,什么都不需要做,一个事务可以读到另一个事务未提交的结果。所有的并发事务问题都会发生。
Ø 已提交读Read Committed:只有在事务提交后,其更新结果才会被其他事务看见。可以解决脏读问题。
Ø 可重复读Repeated Read:在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读。
Ø 可串行化Serializable:事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题。
134. 隔离级别的选用:
Ø 尽量使用较低的隔离级别,以减少锁争用的机率
Ø 通过优化逻辑,大部分应用使用Read Committed隔离级别就够了
Ø 修改隔离级别:set session transaction isolation level repeatable read|serializable;
135. 获取InnoDB行锁争用情况
Ø show status like 'innodb_row_lock%';结果中的InnoDB_row_lock_waits和InnoDB_row_lock_time_avg的值高的话,说明锁争用严重
Ø 查看 information_schema.innodb_locks表
Ø 设置InnoDB Monitors观察锁冲突p327
136. InnoDB行锁模式
Ø 共享锁(S):允许事务去读某些行,阻止其他事务获得相同数据集的排他锁
Ø 排他锁(X):允许更新相关行,阻止其他事务获得S或者X锁
意向锁(表锁)是InnoDB自动加的,不需要用户干预
Ø 意向共享锁(IS):加共享锁时必须取得该表的IS锁
Ø 意向排他锁(IX):加排他锁时必须取得该表的IX锁
137. 加锁语句
对于update、delete、insert语句InnoDB会自动给涉及数据集加排他锁(X);
对于普通select语句InnoDB不会自动加锁,显示加锁如下:
Ø 共享锁(S): select * from tbname where …… lock in share mode;
Ø 排他锁(X):select * from tbname where …… for update;
Ø commit;释放锁(获得锁之前设置setautocommit=0;)
138. 死锁示例:P329
两个Session都对同一记录获取S锁,再都对这条记录进行update,结果都等待获取X锁而产生死锁,发生死锁时,会导致某Session自动退出释放锁。
139. InnoDB 行锁实现方式:
Ø 通过给索引上的索引项加锁来实现,如果没有索引,将通过隐藏的聚簇索引来对记录加锁。
Ø 如果不通过索引条件检索数据,InnoDB将对表中的所有记录加锁,等同于表锁
Ø Next-Key锁(防止“幻读”):对于键值在条件范围内但实际并不存在的记录,叫做“间隙”。当加锁时用的是范围条件而不是相等条件检索数据时,InnoDB会给符合条件的数据记录的索引项加锁,也会对间隙加锁,这就是Next-Key锁。
140. MySQL通过BINLOG记录执行成功的insert update delete等更新数据的sql语句,并由此实现MySQL数据库的恢复和从主复制。
141. InnoDB使用表锁的情况(默认应使用行级锁,事务和行级锁往往是选择InnoDB的理由)
Ø 事务需要更新大部分或者所有的数据
Ø 事务涉及多个表,比较复杂,很可能引起死锁。
142. InnoDB死锁处理方法
Ø InnoDB 一般能自动检测到,并使一个事务释放锁并回退,另一个事务获得锁,继续完成事务
Ø 设置锁等待超时参数innodb_lock_wait_timeout来解决
143. InnoDB死锁避免方法:
Ø 不同程序并发访问多个表时,约定相同的顺序访问,降低死锁概率
Ø 批处理数据时,实现排好序,保证每个线程按固定的顺序处理记录,……
Ø 如果需要更新记录,应直接申请足够级别的锁(排他锁),而不是先申请共享锁,更新时再请排他锁。
Ø 尽量使用小事务,锁冲突概率小
Ø 尽量使用相等条件访问数据,避免Next-Key锁对并发插入的影响。
Ø 对于复杂事务采用表锁来提高处理速度和减少发生死锁概率。
144. 查看隔离级别:select @@tx_isolation;
145. 查看最后一个死锁产生的原因:showinnodb status \G;
第21章 优化MySQL Server
146. MySQL 内存优化原则
Ø 将尽量多的内存分配给MySQL做缓存(前提给OS和其他程序留够足够内存)
Ø MyISAM的数据文件读取依赖于操作系统自身的IO缓存,需要预留更多内存给系统IO缓存
Ø 排序区、连接区等缓存是给每个数据库会话专用的,其默认值要根据最大连接数合理分配,如果太大,不但浪费内存资源,并发高时会导致物理内存耗尽。
147. MyISAM内存优化
Ø 建议至少将1/4的可用内存分配给key_buffer_size: key_buffer_size=4G
Ø 使用多个索引缓存,利用配置文件在MySQL启动时自动创建并预加载索引缓存
hot_cache.key_buffer_size=2G
cache index tablename in hot_cache;
load index into cache tablename;
Ø 调整“中点插入策略”:set globalkey_cache_division_limit=70; p355
Ø 调整read_buffer_size(经常顺序扫描时)和read_rnd_buffer_zize(经常做排序时);
148. InnoDB内存优化
Ø 专用数据库服务器可将80%的物理内存分配给InnoDB buffer pool: 设置 innodb_buffer_pool_size
Ø ……p357
149. redo log 是innodb保证事务ACID属性的重要机制
150. 调整MySQL并发参数
Ø 调整max_connections提高并发连接
Ø 调整thread_cache_size控制MySQL缓存客户线程的数量
Ø 调整innodb_lock_wait_timeout,而控制innodb事务等待行锁的时间,需要快速反馈交互时调小,后台批处理操作时跳大以避免回滚
第22章 磁盘IO问题
151. io优化思路
Ø 使用磁盘阵列RAID
Ø 使用虚拟文件卷或者软RAID
Ø 采用符号链接(Symbolic Links)分布I/O
Ø 禁止Linux操作系统更新文件的atime属性
Ø 使用裸设备(raw device)存放InnoDB的共享表空间
Ø 调整I/O调度算法(建议MySQL环境设置为deadline调度算法)
Ø RAID卡充放电时,会禁用write back功能,性能下降(业务量低时,手动触发充放电;或设置Forced writeBack 写策略)
152. Linux系统,ln命令用来为文件创件连接,连接类型分为硬连接和符号连接(软连接)两种,默认的连接类型是硬连接。如果要创建符号连接必须使用"-s"选项。
Ø 硬链接:建立硬链接时,在另外的目录或本目录中增加目标文件的一个目录项,这样,一个文件就登记在多个目录中。ln命令会增加链接数,rm命令会减少链接数。一个文件除非链接数为0,否则不会从文件系统中被物理地删除。
Ø 符号链接:符号链接也称为软链接,是将一个路径名链接到一个文件。符号链接事实上只是一个文本文件,其中包含它提供链接的另一个文件的路径名。另一个文件是实际包含所有数据的文件。所有读、写文件内容的命令被用于符号链接时,将沿着链接方向前进来访问实际的文件。
153. 裸设备:也叫裸分区(原始分区),是一种没有经过格式化,不被Unix/Linux通过文件系统来读取的特殊字符设备。它由应用程序负责对它进行读写操作。不经过文件系统的缓冲。裸设备可以绑定一个分区,也可以绑定一个磁盘。
因为使用裸设备避免了在经过unix操作系统这一层,数据直接从disk到mysql之间进行无缝传输,所以使用裸设备对于读写频繁的数据库应用来说,可以极大的提高数据库系统的性能
第23章 应用优化
154. 优化思路
Ø 使用连接池(建立数据库连接代价较昂贵)
Ø 减少对MySQL访问(避免重复检索数据、使用MySQL查询缓存、Web加Cache层(redis、EhCache等))
Ø 数据库负载均衡(利用MySql主从复制分流查询;采用分布式数据库架构MySQL CLUSTER)
第四部分 管理维护篇
第24章 MySQL高级安装和升级
155. 安装方式(启动MySQL:bin/mysqld_safe –user=mysql &)p388:
Ø 安装RPM包:无法设置路径安装最简单
Ø 安装编译后的二进制包:折中方案
Ø 安装源码包:配置灵活,性能最优
156. 安装相关linux命令
Ø 安装rpm包:rpm -ivh ****.rpm
Ø 添加用户组 groupaddmysql
Ø 添加用户 useradd -g mysql mysql
Ø 常用解压命令 tar -xzvf ***.tar.gz
Ø 符号链接: ln-s mysql-**-os mysql
Ø 改变文件主 chown -r root var # -r递归
Ø 改变用户组 chgrp -r root .
在linux中,&和&&,|和||介绍如下:
Ø & 表示任务在后台执行,如要在后台运行redis,则有 redis-server &
Ø && 表示前一条命令执行成功时才执行后一条命令 ,如 echo '1‘ && echo '2'
Ø | 表示管道,上一条命令的输出作为下一条命令参数,如 echo 'yes' | wc -l
Ø || 表示上一条命令执行失败后才执行下一条,如cat nofile || echo "fail"
157. MySql配置文件加载顺序,后面的会覆盖前面的
--defaults-extra-file是MySQL启动参数
修改参数的三种方式:
Ø mysql> set para_name=value; 仅本Session有效
Ø mysql> set global para_name=value; 本Session无效,新连接有效,MySQL重启后失效
Ø 修改my.cnf或者my.ini 永久有效
158. MySQL备份数据
mysqldump –-tab=DUMPDIR db_name #导出数据 -tab表示分别生成.sql 和.txt 分别表示创建语句和纯数据文本
mysqlimport db_name DUMPDIR/*.txt ; #加载数据
159. MySQL升级时,数据库迁移(MyISAM引擎可直接复制文件.frm/.MYD/.MYI)P392
第25章 MySQL中的常用工具
160. mysql客户端连接工具
Ø 大写P端口,小写p密码
Ø --default-character-set=utf8 设置默认字符集
Ø -e "sqlquerytext"或者 --execute="sqlquerytext" 连接后直接执行
Ø
Ø -f多语句时,遇错误继续执行下句
Ø mysql -uroot test
Ø my.cnf里面[client]组内可以配置用户名密码
[client]
user=z1
password=z222
161. mysqladmin(MySQL管理工具,功能与mysql类似,侧重于管理,例如关闭数据库),可执行命令有flush-privileges/processlist/killid/等p404
mysqladmin -uroot -p shutdown 关闭数据库
162. myisampack(MyISAM表压缩工具,压缩率高,单压缩后,表只能读取)
163. mysqlhotcopy(MysISAM表热备份工具,是Perl脚本,速度快但需要Unix或Linux环境且只用于MyISAM引擎)
它使用lock tables/flushtables/cp或scp 快速备份数据库,用法如下:
mysqlhotcopy db_name[dbname2……] [/path]
164. mysqlcheck(MyISAM表检查修复维护工具)
165. mysqlbinlog(日志管理工具)
166. mysqldump(数据导出工具)
Ø mysqldump [options] db_name [tables]
Ø mysqldump [options] –-database DB1 [DB2,……]
Ø mysqldump [options] –-all-database #备份所有数据库
Ø -T 参数创建 tab分割的文本文件,--fields-terminated-by=name设置字段分隔符
167. mysqlimport(数据导入工具)
LOAD DATA INFILE也可导入文本数据
mysqlimport [options] db_name textfile1[textfile2……]
168. mysqlshow(数据库对象查看工具)
mysqlshow [options][db_name[tablename[colname]]]
Ø 不加选项显示所有数据库 mysqlshow -uroot -p
Ø --count显示数据库和表的统计信息
Ø -k或者--keys显示指定表所有索引
169. perror(错误查看工具)
170. replace(文本替换工具)
Ø replace from to[from to]…… --filename[filename2]……
Ø replace from to[from to]…… < filename
将文件filename中的from字符串全部替换为to字符串。区别是第二种 < 只是把文件作为输入,文件内容不会改变
171. Linux 的more命令查看文本文件,sed利用script来处理文本文件,nl 命令可以输出文本文件并加上编号
第26章 MySQL日志
172. 4种主要日志(还有undo log/redo log保持事务持久性用的):
Ø 错误日志--error_log=filename;记录mysql启动和停止及运行时的严重错误
Ø 二进制日志 --log-bin[=filename]:记录所有的DDL和DML语句但不包括查询,对于灾难时的数据恢复起着及其重要的作用。
三种格式,可通过--binlog_format参数设置
1) STATEMENT(记录SQL语句,缺点当客户端采用了不确定函数如current_user()时会导致主从数据库不一致)、
2) ROW(记录变化的数据行,缺点日志量大)
3) MIXED(混合前两种模式,目前默认采用)
日志删除:
1) 【优选】参数--expire_logs_days=3;设置日志文件保留日期,3天后自动删除
2) RESET MASTER;命令删除所有binlog
3) PURGE MASTER LOGS TO 'mysql-bin.000006';将000006编号之前的日志删除
4) PURGE MASTER LOGS BEFORE'yyyy-mm-dd hh24:mi:ss';删除此日期前的日志
Ø 查询日志 --general_log=1;--general_log_file=filename;
Ø 慢查询日志 --slow_query_log=1;slow_query_log_file[=file_name];所有执行时间超过long_query_time(单位秒,默认10秒)并且扫描记录数大于min_examined_row_limit的所有SQL语句日志。使用mysqldumpslow工具可对慢查询日志进行分类汇总,便于查看(只是变量不一样的SQL视为同一个SQL)
173. 第三方MySQL日志分析工具mysqlsla(sla,Statement Log Analyzer)可查看各种日志,较方便P433
第27章 备份与恢复
174. MySQL备份主要分为逻辑备份(对不同存储引擎用相同的方法备份)和物理备份(基于文件复制,不同存储引擎备份方法不同)
175. 备份策略:
Ø 区分表的存储引擎是事务型或非事务型
Ø 全备份(只需要保持最新备份,恢复时间短)还是增量备份(需要全备份加日志,恢复时间长)
Ø 定期备份,在系统负载小时备份
Ø 确保打开MySQL的log-bin选项,产生BINLOG才能恢复
Ø 复制不能代替备份,无法处理误操作
176. 逻辑备份:mysqldump见25章,MyISAM引擎时需要-l来用读锁锁定所有表,保证数据一致性
Ø 完全恢复时,需要恢复某一个备份,还要将备份后执行的日志进行重做:
Ø 基于时间点的恢复:利用mysqlbinlog的--stop-date和--start-date参数
Ø 基于位置的恢复:利用mysqlbinlog的--stop-position和--start-position
177. 物理备份比逻辑备份快(基于文件复制)分为冷备份和热备份
Ø 冷备份适合(MyISAM和InnoDB):停服务,备份数据文件和日志。恢复时,先停服务恢复文件,再启用MySQL服务,使用mysqlbinlog恢复自备份以来的binlog
Ø 热备份(对要备份的表加读锁,再复制文件,无需停MySQL服务):
1) MyISAM热备份:使用mysqlhotcopy工具或者给所有表加读锁(flush tables for read;)后复制数据文件到备份目录。
2) InnoDB热备份:第三方工具(ibbackup[收费]或Xtrabackup【免费开源,支持MyISAM和InnoDB】)P443
178. 导出数据为文本文件(CSV都好分割)而不是sql,优点(excel显示,节省空间,导入数据库速度快【LOAD DATA比普通SQL快20倍】),方法如下:
Ø 方法一:SELECT……INTO OUTFILE 命令
Ø 方法二:mysqldump
mysqldump除了生成tbname.txt还会生额外成表的创建SQL文件tbname.sql
179. 纯文本数据导入:P457
Ø LOAD DATA [LOCAL] INFILEfilename INTO TABLE tablename命令
Ø mysqlimport工具
mysqlimport -uroot -p*** [--LOCAL] dbname filename.txt[options]
LOCAL参数表示,文件在客户端,上传到服务器端读取,如果不指定LOCAL参数,则表明文件在服务器端,直接由服务器读取。
第28章 MySQL权限与安全
180. MySQL权限系统
Ø 登录认证【通过“mysql”数据库user表对ip地址和用户名联合认证】
Ø 用户权限管理【"mysql"数据库中有3个权限表(user/db/host[不常用])】,按照user->db->tables_priv->columns_priv表的顺序读取用户权限,权限范围逐渐缩小,全局权限覆盖局部权限
grant select on *.* to z1@localhost;
revoke select on *.* to z1@localhost;
181. 账号管理
创建账号:
Ø 【优选】grant语句直接创建[用户不存在时,创建用户;存在时增加权限]
grant allprivileges on *.* to 'z2'@'%' identified by '123' ……授予所有权限,%代表所有ip,用户名z2,密码123
Ø 直接操作mysql.user表 插入用户名,密码(password(***)),然后使用flushprivileges;刷新权限
182. MySql的权限如下表所示:
Ø ALL 除GRANT OPTION外的所有权限
Ø ALTER 使用ALTER TABLE
Ø ALTER ROUTING 使用ALTER PROCEDURE和DROPPROCEDURE
Ø CREATE 使用CREATE TABLE
Ø CREATE ROUTING 使用CREATE PROCEDURE
Ø CREATE TEMPORARY TABLES 使用CREATE TEMPORARY TABLE
Ø CREATE USER 使用CREATE USER、DROP USER、RENAME USER和REVOKE ALL PRIVILLEAGES
Ø CREATE VIEW 使用CREATE VIEW
Ø DELETE 使用DELETE
Ø DROP 使用DROP TABLE
Ø EXECUTE 使用CALL和存储过程
Ø FILE 使用SELECT INTO OUTFILE和LOAD DATA INFILE
Ø GRANT OPTION 使用GRANT和REVOKE
Ø INDEX 使用CREATE INDEX和DROP INDEX
Ø INSERT 使用INSERT
Ø LOCK TABLES 使用LOCK TABLES
Ø PROCESS 使用SHOW FULL PROCESSLIST
Ø RELOAD 使用FFLUSH
Ø REPLICATION CLIENT 服务器位置的访问
Ø REPLICATION SLAVE 由复制从属使用
Ø SELECT 使用SELECT
Ø SHOW DATABASES 使用SHOW DATABASES
Ø SHOW VIEW 使用SHOW CREATE VIEW
Ø SHUTDOWN 使用mysqladmin shutdown(用来关闭MySQL)
Ø SUPER 使用CHANGE MASTER、KILL、LOGS、PURGE、MASTER和SET GLOBAL。还允许mysqladmin调试登录
Ø UPDATE 使用UPDATE
Ø USAGE 无访问权限,只可以登录
183. 查看权限:
Ø show grants for user@host;
Ø 直接查看information_schema.SCHEMA_PRIVILEGES表
184. 收回权限:revoke语句 ,用法类似 grant
185. 修改密码:
Ø mysqladmin -u user_name -h host_name password"new_pwd"
Ø set password for 'jeff'@'%' = password('newpwd');
Ø set password = password('newpwd');改自己密码
Ø grant usage on *.* to 'jeff'@'%' identified by [password] 'pwd';加password关键字时,pwd要用md5计算过的字符串,这样不用明文更安全
Ø 直接修改mysql.user表,然后flushprivileges;刷新权限
186. 删除账号:
Ø drop user;
Ø 直接操作mysql.user表,删除用户
187. 账号资源限制:
188. MySQL安全问题
Ø 操作系统安全:
1) mysql除了数据文件目录,其他文件和目录属主都改为root
2) 尽量避免以root权限运行MySQL
3) 创建用户时,如果用域名指定host列,可能受到DNS攻击
Ø 数据库安全
1) 删除匿名账户(安装时,默认有个空账户可以操作test数据库)
2) 给root账户设置口令
3) 设置安全密码(6位以上含字符数字下划线特殊字符)
4) 只授予必需的权限(而不是 all privileges)
5) 除root外,任何用户不应有mysql数据库user表的存取权限
6) 不要将FILE、PROCESS或SUPER权限授予管理员以外的账号
7) Load Data Local安全问题P488
8) MERGE存储引擎权限漏洞(B有表T的权限,创建一个包含T的MERGE表,当B对T的权限被收回时,B仍能通过MERGE表访问T的数据)
9) Drop Table 命令并不回收权限,需手动回收(删表后,建同名表,以前有权限的还是有权限)
10) 使用SSL连接
11) 尽量给用户加上IP限制
12) Revoke命令漏洞(在同一个数据库上多次赋予权限,权限会自动合并,但是在不同数据库上多次赋予权限,不会自动合并。回收时必须分别回收)P494
第29章 MySQL监控
189. 监控目标:完成服务器中各种监控信息(CPU,内存,网络,数据库状态等)的采集、分析、存储,且支持快速的报警和信息发送
190. 常用网络监控工具:Cacti、Nagios、Zabbix+Fromdual插件P506【优选,开源、支持中文、配置简单、Email通知】等
191. LAMP环境(Linux、Apache、MySQL、PHP)
第30章 MySQL常见问题和应用技巧
192. 忘记root 密码时,用--skip-grant-tables选项重启MySQL服务,跳过认证,用root登录无需密码,然后通过setpassword=password('123');flush privileges
193. MyISAM表损坏时(1.使用myisamchk工具;2.SQL命令:CHECK/REPAIR TABLE)
194. MyISAM表超过4G无法访问:alter table tbl_name MAX_ROWS=10000000 AVG_ROW_LENGTH=15000,修改表的最大记录数和平均记录长度,因此改变最大size
195. 数据目录磁盘空间不足:
Ø MyISAM引擎:创建表时,使用DATA DIRECTORY和INDEX DIRECTORY分别指定数据目录和索引目录的存储目录。如果表已创建,可以将表的数据文件和索引文件mv到磁盘空间充足的分区上,然后在原文件处创建符号链接即可。
Ø InnoDB引擎:在MySQL配置文件中用innodb_data_file_path中增加文件:innodb_data_file_path=/home/ibdata1:2000M;/home1/ibdata2:200M:autoextend重启数据库生效
196. Linux export命令用于设置或显示环境变量。在shell中执行程序时,shell会提供一组环境变量。export可新增,修改或删除环境变量,供后续执行的程序使用。export的效力仅及于该次登陆操作。
197. 客户端通过中继服务器访问某内网的MySQL数据库(使用SecureCRT或MySQL Proxy工具)
第五部分 架构篇
第31章 MySQL复制
198. 主从复制原理:将主数据库的DDL和DML操作通过二进制日志传到复制服务器(从库),然后在从库上对这些日志进行重做,保存主从同步。MySQL使用3个线程完成主从复制,Binlog Dump线程跑在主库上,I/O线程和SQL线程跑在从库上。
199. MySQL复制优点:
Ø 【冗余】如果主库出问题,可快速切换至从库提供服务
Ø 【负载均衡】在从库执行查询操作,降低主库的访问压力
Ø 【便于备份】在从库上备份,避免备份对主库影响
200. 复制中的两种文件(二进制日志binlog,中继日志relay log)。中继日志格式与二进制日志一样,从库上的SQL线程执行完当前中继日志文件中的事件后,会自动删除中继日志。从库创建两个日志文件master.info和relay_log.info来保存复制进度,分别记录从库IO线程当前读取二进制日志binlog的进度和SQL线程应用中继日志的进度。
201. 二进制日志的三种格式(格式对应MySQL参数binlog_format)对应三种复制方式(Statement、Row、Mixed)
mysqlbinlog检查Row格式的binlog,会显示乱码,需要通过Base64解码后查看(参数: --v --base64-output=DECODE-ROWS)
202. 常见复制的3中架构:
Ø 一主多从:用在读请求压力非常大时。实现读写分离,把实时性要求不高的的读请求通过负载均衡分布到多个从库上,降低主库读取压力。当主库异常时,可把一个从库切换为主库。
Ø 多级复制:随着从库的增加,主库的IO压力和网络压力会增长(每个从库在主库上有一个独立的Binlog Dump线程来发送事件)。多级复制解决了这个问题。【缺点】:经历两次复才到从节点,延时大。可用BLACKHOLE存储引擎,降低延时。(BLACKHOLE存储引擎不在磁盘存数据,只将DML操作记录在Bin LOG中,适合多级复制里的二级主库)
Ø 双主复制:适用于DBA做维护等需要主从切换的场景,在维护时,不影响服务。维护过程见P546.
203. 复制方式:
Ø 异步复制:
1) 保证主从数据库版本一致,在主库建用户,授予REPLICATION SLAVE权限,grant replicationslave on *.* TO 'repl'@'192.168.7.200' identified by '1234test'
2) 修改主库配置文件my.cnf,开启binlog,设置server-id。
[mysqld]
binlog = /home/mysql/log/mysql-bin-log.log
server-id = 1
3) 锁定所有表只可以读,保证得到一致性快照,flush tables with readlock;然后用show master status;命令得到二进制文件名和偏移量;备份数据库;unlock tables;
4) 恢复数据到从库,在从库中设置server-id=2;使用--skip-slave-start选项启动数据库;配置主库信息:
启动slave线程:startslave;
Ø 半同步复制:半同步复制是通过插件(semisync_master.so和semisync_slave.so)实现的(更好的保证二进制日志的完整性和安全性P552。异步复制时,主库执行完Commit提交操作后,在主库写入binlog日志后可成功返回客户端,无需等待binlog日志传送给从库。而半同步复制时,必须等待其中一个从库也收到Binlog事务并成功写入中继日志后,主库才返回Commit操作成功给客户端)
1) 一般插件在$MYSQL_HOME/lib/plugin目录下,在主库上安装:install pluginrepl_semi_sync_master SONAME 'semisync_master.so';在从库上安装:install plugin repl_semi_sync_slave SONAME 'semisync_slave.so';
2) 在主库上打开半同步参数:
set global rpl_semi_sync_master_enabled=1;
set global rpl_semi_sync_master_timeout=30000;等30秒超时后自动转异步复制,如果网络状况恢复,会自动切换为半同步模式
3) 从库:set global rpl_semi_sync_slave_enabled=1;
4) 如果是异步复制改为半同步复制则需要重启主库IO线程:(新配置不需要重启)
STOP SLAVE IO_THREAD;START SLAVE IO_THREAD;
204. iptables命令是Linux上常用的防火墙软件
205. 复制时的启动选项:
Ø log-slave-updates:从库上的更新操作是否写进二进制日志,默认不打开,如果从库也要作为其他库的主库,则需要打开
Ø master-connect-retry:主库和从库连接丢失时重试的时间间隔,默认60秒。
Ø read-only:设置从库只能接受超级用户的更新操作,限制应用程序错误的对从库进行了更新操作。
Ø replicate-do-db/replicate-do-table /replicate-ignore-db/replicate-ignore-table等:指定哪些库或表需要复制到从库。
Ø slave-skip-errors:从库执行SQL出错时,逃过继续执行(默认会停止复制)
206. 维护:
Ø 查看从库状态:show slave status;可查看Slave_IO_Running和Slave_SQL_Running值是不是都为YES,如果有一个为NO则复制停止了
Ø 切换主从库
1) 在每个从库上,执行STOP SLAVE IO_THREAD;然后检查SHOW PROCESSLIST输出,直到状态是Has read all relay log.表示执行了所有的Relay Log
2) 在从库S1上执行stop slave;停止从服务,执行reset master;设置成主数据库。删除master.info和relay_log.info文件,否则下次还会启动为从库。
3) 在其他各从库上执行:
stop slave;
change master to master_host='此处是S1的ip';
start slave;
4) 通知客户端将数据库地址切换到s1,如果之前的主库可修复,则配置为S1的从库
第32章 MySQL Cluster
207. 集群架构:
三种节点都是逻辑节点,可以在不同服务器,也可以在同一台服务器。
Ø 管理节点:只能有一个,对其他节点进行管理。通过config.ini配置文件配置数据节点位置,每个数据节点上保存数据的磁盘位置等信息。
Ø SQL节点,存放表结构。可以有多个。应用不能直接访问数据节点,只能通过SQL节点去访问。
Ø 数据节点,必须使用NDB 存储引擎存放数据,否则不会同步到其他节点。可以有多个
208. MySQL Cluster访问过程:
209. MySQL Cluster目前只支持Linux(不支持Windows),配置过程示例(详见P580):
Ø 安装Cluster软件包:SQL节点和数据节点必须下载Server包和Cluster storage engine包。管理节点必须下载Client包和Cluster storage engine management/basic tools/extra tools三个包。
Ø 管理节点配置:创建目录mysql_cluster,并创建文件config.ini,[NDB_MGMD]表示管理节点配置,只能有一个。[NDBD]:表示数据节点。[MYSQLD]表示SQL节点
Ø SQL节点和数据节点配置。在my.cnf[MYSQLD]中加入ndbcluster,和ndb-connectstring=192.168.7.187等配置
210. Cluster使用
Ø 节点启动顺序为:管理节点-> 数据节点-> SQL节点
Ø shell下启动管理节点:ndb_mgmd -f ./config.ini
Ø 启动数据节点:ndbd --initial--ndb-connectstring=192.168.7.187:1186
Ø SQL节点的启动,启动MySQL服务即可:./bin/mysqld_safe &
Ø ndb_mgm命令进入控制台,ndb_mgm>show命令可查看集群状态
211. Cluster关闭:ndb_mgm -e shutdown
212. Cluster备份:
Ø 可以使用mysqldump在SQL节点备份。
Ø 也可以在管理服务器使用ndb_mgm工具下start_backup命令备份 ndb_mgm>start backup;备份的数据在各个数据节点
Ø 恢复时需在各个数据节点使用工具ndb_restore工具。详见P590
213. Cluster日志管理:集群日志在配置文件config.ini所在的目录。在ndb_mgm命令行中,cluster_info命令查看当前日志状态,clusterlogon/off命令打开或者关闭日志。
第33章 高可用架构
214. 数据库高可用框架MMM和MHA
215. MMM(Master-Master replication manager for MySQL)
Ø 是一套支持双主故障切换和双主日常管理的脚本程序。
Ø 使用Perl语言开发。
Ø 双主复制业务上同一时刻值允许对一个主库进行写入(也可读),另一台备选主上提供部分读服务。
Ø MMM一方面实现了故障切换的功能,也可以实现多个从库SLAVES的READ的负载均衡。
Ø MMM无法完全地保证数据一致性,适用于对数据一致性要求不是很高的场景
216. MHA【优选】(MasterHigh Availability)
Ø 是目前在MySQL高可用方面相对成熟的解决方案,是一套高可用环境下故障切换和主从提升的高可用软件。
Ø MHA能在30秒内自动完成故障切换,并可最大程度保证数据的一致性(与MySQL半同步复制配合)。
Ø MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。
Ø MHA主要支持一主多从架构,一个复制集群中最少有三台服务器,一主二从。
Ø Manager节点定期探测集群中的master节点,当master节点故障时,可以自动将最新数据的SLAVE提升为新的master,其他SLAVE指向新的master。(整个过程对应用透明)
217. scp命令用于Linux之间复制文件和目录。scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令。