Mysql逻辑架构:
1.连接层 2.服务层(sql优化)3.引擎层(存储和提取)4.存储层(数据存储再文件系统,完成与存储引擎的交互)
适用于读操作多于写操作,写锁后其他线程不能做任何操作,会造成阻塞。不支持事务。适合小并发,小数据。
支持Btree索引
MyISAM 使用表锁:执行select语句前,会自动给涉及的表加读锁,执行增删改前给涉及的表自动加写锁。
Mysql 默认InnoDB 存储引擎,支持事务,适合插入和更新操作较多的场景,支持Btree和自适应Hash索引,使用行锁。适合高并发,大数据。
行锁变表锁:varchar 类型字段没写引号,发生类型转换,索引失效导致行锁变表锁。
间隙锁:当我们用范围条件检索数据,并请求共享或排他锁时,InnoDB会给已有的数据记录的索引项加锁;
对于键值在范围内但不存在的记录,就叫间隙。
间隙锁的危害:InnoDB会对这个间隙加锁。导致这个间隙无法进行操作,产生阻塞。
锁定一行的方式:
begin;
select * from A where a=8 for update; 锁定一行后对该行的其他操作将被阻塞,直到锁定行commit。
commit;
InnoDB 行锁分析:
通过检查InnoDB_row_lock_xxx 分析行锁的争夺情况
show status like 'innodb_row_lock%';
InnoDB_row_lock_time_avg 等待平均时长
InnoDB_row_lock_waits 等待总次数
InnoDB_row_lock_time 等待总时长
读锁(read)共享锁
当前线程只能读当前被锁的表,不能修改任何表。 其他线程对被锁表只能读,写操作阻塞。其他表可以读写。
写锁 (write)排他锁
当前线程只能对当前表读写。其他线程对当前表读写阻塞。
总结来说:读锁会阻塞写,不会阻塞读,而写锁则把读和写都阻塞。
查询语句写的不好(子查询,关联查询太多)。
没建索引,或建了索引但索引失效。
服务器调优以及各个参数设置不合理(缓冲,线程数)。
rpm -ivh MySQL-client-5.6.22-1.el6.i686.rpm
rpm -ivh MySQL-server-5.6.22-1.el6.i686.rpm
cat /etc/passwd|grep mysql 查看mysql安装是否成功
cat /etc/group|grep mysql 查看有没有mysql组
rpm -qa|grep -i mysql 查询已安装
ps -ef|grep mysql单值索引:create index idx_user_name on user(name)
复合索引:create index idx_user_nameEmail on user(name,email)
创建索引:alter table `book` add index z(`card`);
删除索引:drop index idx_class_card on book;
3.1 是什么?
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高校获取数据的数据结构。可以得到索引的本质:索引是数据结构
索引是排好序的快速查找数据结构,可以提高MySQL查询效率,索引通常以索引文件的形式存储在磁盘上。
索引分类:单值索引 唯一索引(索引列的值必须唯一) 复合索引
3.2 优劣势
优势:提高数据检索效率,降低数据库的IO成本;索引列对数据进行排序,降低数据排序的成本,降低cpu的消耗。
劣势:占用空间,表的更新速度减慢,每次更新都要保存新添数据的索引列字段,需要进行索引信息调整。需要不停优化。
3.3 mysql 索引结构
BTree索引
真实数据存储在叶子节点(磁盘中),非叶子节点存储的是搜索方向(范围区间)。
Hash索引
全文索引
R-Tree索引
3.4 哪些情况需要建立索引
1.主键自动创建唯一索引
2.频繁查询的字段
3.查询中与其他表关联的字段,外键关系建立索引
4. 频繁更新不适合建索引。
5.where条件用不到的字段不建索引
6.高并发组合索引
7.查询中统计或者分组字段
使用EXPLAIN关键字可以模拟优化器执行SQL语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是结构的性能瓶颈。
4.1 关键字介绍
1. id select查询的序列号,表示查询中执行select子句或者表的执行顺序
1)id相同,按顺序执行
2)id不同,递增,数字大优先级高
3)id相同也不同 数字大优先级高,相同按顺序执行
2.select_type :查询类型(普通,联合,子查询)
simple 简单查询 primary 最外层查询 subquery 子查询 derived 衍生(from列表中的子查询) union select出现在UNION之后
3.table 表
4.type 访问类型,以何种方式去访问数据
好-->差 尽可能达到rang级别,最好达到ref
system > const > eq_ref > ref > range > index > All
1)all 全表扫描,数据量较大时需要优化
2)index 全索引扫描
3)rang 范围扫描
4)ref 使用了非唯一索引进行数据查找 例如部门号
5)eq_ref 使用唯一性索引进行数据查找 例如员工号
6)const 至多一个匹配行
7)system 系统只有一行记录
5.possible_keys 可能用到的索引
6.key 实际用到的索引
7.key_len 索引中使用的字节数,保证结果前提下,越短越好
8.ref 显示索引的那一列被使用了
9.rows 查找结果读取的行数
10.Extra 包含不适合在其他列中显示但十分重要的信息
1)Using filesort 无法利用索引完成的排序操作称为文件排序
2)Using temporary 建立临时表来保存中间结果,查询完成之后把临时表删除,常见order by group by
3)Using index 表示当前查询是覆盖索引的
4)Using where 使用了where 过滤
4.2 覆盖索引和最左前缀
覆盖索引:select的数据列只用从索引中就能取得,不必读取数据行,查询列要被所建的索引覆盖。
最左前缀法则:多列索引要遵循最左前缀法则,查询从索引的最左列开始并且不跳过索引中的列。
5.1 索引失效
1)不要在索引上做操作(计算,函数,自动或手动类型转换)
2)存储引擎不能使用索引中范围条件右边的列。
3)尽量使用覆盖索引(索引列和查询列一致),减少select *
4)使用 != 或<>无法使用索引会导致全表扫描。
5)is null is not null无法使用索引
6)like以通配符开头(%abc)索引失效会变成全表扫描的操作。 想使用 %abc% 就建立覆盖索引,like KK%相当于=常量 %KK和%KK% 相当于范围。
7)尽量少用or,使用or连接索引会失效
8)字符串不加单引号索引失效
5.2 优化口诀
【优化口诀】
全值匹配我最爱,最左前缀要遵循;
带头大哥不能死,中间兄弟不能断;
索引列上少计算,范围之后全失效;
like百分写最右,覆盖索引不写 * ;
不等空值还有or,索引失效要少用;
VARCHAR引号不可丢,SQL高级so easy;
让系统跑一段时间,查看生产的慢sql情况。
开启慢查询日志,设置阙值,将慢sql语句抓取出来。 show variables like '%slow_query_log%';
使用explain 进行分析。
show profile 查询sql在服务器里的执行细节和生命周期情况。
sql 数据库服务器参数调优。
select * from A where id in (select id from B)
当B表数据集小于A表,使用 in
select * from A where exists (select 1 from B where B.id = A.id)
当A的数据集小于B表,使用 exists
exists 将主查询的数据,放到子查询中做条件验证,根据验证结果决定主查询结果是否保留。
3.1 Mysql 两种排序方式
文件排序 FileSort效率低,扫描有序索引排序 Index效率高
index 方式排序:OrderBy语句使用索引最左前列,使用Where子句与OrderBy子句条件列组合满足索引最左前列
尽可能在索引上完成排序操作,遵循最左前缀,如果不在索引列上mysql 就会启动单路排序。
3.2 单路排序
从磁盘读取查询需要的所有列,按照orderby列在buffer对它们进行排序,将排序好的列表进行输出。避免了二次读取数据,把随机IO变成顺序IO,但是会使用很大空间。
单路排序的问题:数据列超过buffer容量,导致大量IO操作。
单路排序优化:
1. 忌select *
2. 尝试提高sort_buffer_size
3.max_length_for_sort_data
① 数据库的优化,包括合理的事务隔离级别、SQL语句优化、索引的优化
② 使用缓存,尽量减少数据库 IO
③ 分布式数据库、分布式缓存
④ 服务器的负载均衡
① 读写分离
② 分段加锁
③ 减少锁持有的时间
④ 多个线程尽量以相同的顺序去获取资源
①sql语句及索引的优化
②数据库表结构的优化
③系统配置的优化
④硬件的优化
①选取最适用的字段属性,尽可能减少定义字段宽度,尽量把字段设置NOTNULL,例如’省份’、’性别’最好适用ENUM
②使用连接(JOIN)来代替子查询
③适用联合(UNION)来代替手动创建的临时表
④事务处理
⑤锁定表、优化事务处理
⑥适用外键,优化锁定表
⑦建立索引
⑧优化查询语句
SQL注入产生的原因:程序开发过程中不注意规范书写sql语句和对特殊字符进行过滤,导致客户端可以通过全局变量POST和GET提交一些sql语句正常执行。
防止SQL注入的方式:
开启配置文件中的magic_quotes_gpc 和 magic_quotes_runtime设置
执行sql语句时使用addslashes进行sql语句转换
Sql语句书写尽量不要省略双引号和单引号。
过滤掉sql语句中的一些关键词:update、insert、delete、select、 * 。
提高数据库表和字段的命名技巧,对一些重要的字段根据程序的特点命名,取不易被猜到的。
Php配置文件中设置register_globals为off,关闭全局变量注册
控制错误信息,不要在浏览器上输出错误信息,将错误信息写到日志文件中。
char是一种固定长度的类型,varchar则是一种可变长度的类型,它们的区别是:
char(M)类型的数据列里,每个值都占用M个字节,如果某个长度小于M,MySQL就会在它的右边用空格字符补足.(在检索操作中那些填补出来的空格字符将被去掉)在varchar(M)类型的数据列里,每个值只占用刚好够用的字节再加上一个用来记录其长度的字节(即总长度为L+1字节).
varchar使用场景:
1.字符串列得最大长度比平均长度大很多
2.字符串很少被更新,容易产生存储碎片
3.使用多字节字符集存储字符串
Char使用场景:
1.存储固定长度(身份证,手机号)
2.长度比较短小得字符串
3.适合经常更新的字符串,更新时不会出现页分裂得情况,避免出现存储碎片,获得更好的io性能