关系型数据库

DML: Data Manapulate Lanauage 数据操作语言

      INSERT, REPALCE, UPDATE, DELETE


DDL:  Data Definition Lanauage 数据定义语言

      CREATE, ALTER, DROP


DCL: Data Control Lanauage  数据控制语言

      GRANT,REVOKE



DBMS:

    数据管理的独立性

    有效的完成数据的存取

    数据完整性和安全性

    数据集中管理

    并发存储与故障恢复

    减少应用程序的开发时间


RDBS拥有的组件:

    缓存器

    故障恢复器

    磁盘空间管理器

    事务管理器

    锁管理器

    SQL分析器

    SQL优化器

    SQL计划执行器


mysql

    -u USERNAME

    -p PASSWD

    -h DOMAIN


mysql客户端:

    交互式模式

    批处理模式(执行mysql脚本)


交互式模式中的命令类别:

    客户端命令

    服务器端命令



关系数据库对象

    表

    索引

    视图

    约束

    存储过程

    存储函数

    触发器(主动数据库)

    游标

    用户

    权限

    事务


    行,列

    表:实体

    列:field,column

    行:raw


字段名称

    字符

        CHAR(n)

        VARCHAR(n) 

        BINARY(n):区分大小写 

        VARBINARY(n)

        TEXT(n)

        BLOB(n)

    数值

        精确数值型

            整型

                  TINYINT

                  SMALLINT

                  MEDIUMINT

                  INT

                  BIGINT


                  修饰符: UNSIGNED

                           NOT NULL

            十进制

                  DECIMAL

        近似数值型

            浮点型

                  FLOAT

                  DOUBLE

    日期时间

        DATA

        TIME

        DATETIME    

        STAMP

    布尔

    内置:ENUM, SET




DDL

    CREATE

    ALTER

    DROP

DML

    INSERT

    UPDATE

    DELETE

DCL

    GRANT

    REVOKE


创建数据库

    CREATE DATABASE db_name; 

    CREATE DATABASE [IF NOT EXISTS] db_name;


    DROP DATABASE [IF EXISTS] db_name;


创建表

    CREATE TABLE tb_name(col1,col2,...);


    create:

        create table TABLE_NAME (

        Id   int NOT NULL,

        Name char(10),

        Age  int,

        Sex  char(5)

        );



    查看库中的表:SHOW TABLES FROM db_name;

    查看表的结构:DESC tb_name;


    删除表:DROP TABLE tb_name;


修改表:

    ALTER TABLE tb_name 

        MODIFY   mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;

        CHANGE   mysql> ALTER TABLE t1 CHANGE a b INTEGER;

        ADD

        DROP


DML:

    INSERT INTO tb_name (col1,col2,...) VALUES|VALUE ('STRING', NUM,...);

    INSERT INTO tb_name (col1,col2,...) VALUES|VALUE ('STRING', NUM,...),('STRING',NUM,...);    


    UPDATE tb_name SET column=value WHERE  


    DELETE FROM tb_name WHERE CONDITION;


选择:

    SELECT 字段 FROM tb_name WHERE CONDITION


    *: 所有字段

    WHERE:没有条件表示显示所有行;


创建用户:

    CREATE USER 'USERNAME'@'HOST' [IDENTIFIED BY 'PASSWORD'];

    DROP USER 'USERNAME'@'HOST';


    HOST:

        IP:

        HOSTNAME:

        NETWORK:

        通配符

            _:匹配任意单个字符, 172.16.0._

            %:匹配任意字符;


    jerry@'%'

DCL:

    GRANT pri1,pri2,... ON DB_NAME.TB_NAME TO 'USERNAME'@'HOST' [IDENTIFIED BY 'PASSWORD'];

    REVOKE pri1,pri2,... ON DB_NAME.TB_NAME FROM 'USERNAME'@'HOST';


    查看用户的授权:SHOW GRANTS FOR 'USERNAME'@'HOST';


    ALL PRIVILEGES


关系型数据

表示层:表

逻辑层:存储引擎

物理层:数据文件


数据查询和存储

存储管理器:

            权限及完整性管理器

            事物管理器

            文件管理器

            缓冲区管理器

查询管理器:

            DML解释器  

            DCL解释器          

            DDL解释器

            查询执行引擎

smp:对称多处理器      


MySQL插件式存储引擎

5.5.8之前:MyISAM(不支持事务,适用于查询多,增删少)

5.5.8之后:InnoDB(支持事物,适用于增删比较多)


文件中记录组织:

堆文件组织:一条记录可以放在任何地方

顺序文件组织:根据“搜索码”值顺序存放

散列文件组织:分成N个片



表结构定义文件,表数据文件


表空间:实现一个表放多个表的数据(table space)


数据字典:

    关系的元数据:

        关系的名字、字段的名字、字段的类型和长度、视图、约束


缓冲区管理器:

    缓存置换策略

    被钉住的块:不允许置换出去



Root user password assignment

1,#mysqladmin -u USERNAME -h HOSTNAME password 'NEW_TION;PASS' -p(输入旧密码)

2,mysql> SET PASSWORD FOR 'USERNAME'@'HOST'=PASSWORD('new_passwd');

3,mysql> UPDATE mysql.user SET PASSWORD=PASSWORD('new_passwd') WHERE CONDITION;


mysql客户端工具

    mysql

    mysqladmin

    mysqldump

    mysqlcheck

    mysqlimport


可以在用户家目录建立my.cnf

[client]

user = 'root'

password = 'redhat'

host = localhost



mysql非客户端工具

    myisamchk

    myisampack


存储引擎:

MyISAM:不支持事务,只支持表锁,不支持外键,并发写不好,支持B树索引、FULLTEXT索引、空间索引,支持表压缩

    每表三个文件:

    .frm:表结构

    .MYD:表数据

    .MYI:表索引


InnoDB:支持事务,行级别的锁,支持B树索引、聚簇索引、自适应hash索引,表空间,支持raw(裸设备)磁盘

    默认所有表数据共享一个表空间,可以编辑/etc/my.cnf永久话化

    SHOW VARIABLES LIKE '%innodb'中找到innodb_file_per_table

    .frm:表结构

    .ibd:表空间

    .opt:默认字符集和排序规则选项


MRG_MYISAM:支持两个表逻辑上的合并


CSV:两个数据库移植的时候使用


ARCHIVE:用于实现归档,用于做数据挖掘,不再修改


MEMORY:用于创建临时表,存储在内存中

mysql 

    --user, -u

    --host, -h

    --password, -p

    --port

    --protocol

    --database DATABASE, -D



mysql>

    交互模式

    批处理模式(执行mysql脚本)    

    mysql -uroot -p'redhat' < test.sql

    或

    mysql> source test.sql


客户端命令:

    \c:提前终止语句的执行

    \g:无论语句结束符是什么,直接执行

    \d:自定义结束符是什么

    \G:竖排显示

    \W:显示警告信息

    \#: 新建对象field自动补全






AUTO_INCREMENT

    整型

    非空

    无符号

    主键或唯一


Mysql服务器变量

    全局变量:对当前会话无效,只对新会话生效

    mysql> SHOW GLOBAL VARIABLES

    会话变量:及时生效,只对当前会话有效

    mysql> SHOW [SESSION] VARIABLES


生效时间:

    动态--临时修改

    静态--写在配置文件,通过参数传递给mysqld


mysql> SHOW TABLE STATUS LIKE 'students'\G;

mysql> SHOW CHARACTER SET;(查看字符集)

mysql> SHOW INDEXES FROM 'students';(查看表上的索引)

mysql> SHOW COLLATION;(查看字符集)

mysql> SHOW GLOBAL VARIABLES LIKE '%char%';(查看变量)

mysql> SELECT LAST_INSERT_ID();

mysql> SELECT DATABASE();


查看服务器变量 :@@变量名

mysql> SELECT @@global.sql_mode; 或 mysql> SHOW GLOBAL VARIABLES LIKE 'sql_mode';

mysql> SELECT @@session.sql_mode; 或 mysql> SHOW SESSION LIKE 'sql_mode';


设定服务器变量:SET GLOBAL|SESSION 变量名='value'


SQL语句:

mysql> SHOW COLLATION LIKE '%gbk%';

mysql> CREATE SCHEMA IF NOT EXISTS students CHARACTER SET 'gbk' COLLATION 'gbk_chinese_ci'



选择:SELECT * FROM tb_name WHERE 

    布尔表达式

        算术运算:

        比较操作符:

        其它运算符:IN, BETWEEN ... AND ..., LIKE, RLIKE(REGEXP), IS NULL, IS NOT NULL

        逻辑运算:AND, OR, NOT, XOR


    DISTINCT


投影:SELECT field1, ... FROM tb_name;


ORDER BY field,... {ASC|DESC}


聚合计算:COUNT()、SUM()、MAX()、MIN()和AVG();


GROUP BY field1,... 

    HAVING 


LIMIT [offset],num


多表查询:

    交叉连接

    自然连接

        WHERE tb1.field=tb2.field

    外连接

        左外

            FROM tb1 LEFT JOIN tb2 ON condition

        右外

            FROM tb1 RIGHT JOIN tb2 ON condtion

    自连接


子查询:

    FROM

    WHERE

        比较操作符:子查询只能返回一个字段的单值;

        IN:列表(某字段的多个值)



广义查询:

DML: 

    DELETE

    INSERT INTO

    UPDATE


INSERT INTO tb_name (col1, col2, ...) VALUES (val1, val2, ...)[,(val1, val2, ...),...]

    字符型:单引号

    数值型:不需要引号

    日期时间型:

    空值:NULL, ''


INSERT三种:

INSERT INTO tutors (Tname,Gender,Age) VALUES ('Joe','M',28);

INSERT INTO tutors SET Tname='Tom',Gender='F',Age=30;

INSERT INTO tutors (Tname,Gender,Age) SELECT Name,Gender,Age FROM students WHERE Age>20;


REPLACE INTO

REPLACE INTO tutors (Tname,Gender,Age) VALUES ('Joe','M',28);

REPLACE INTO tutors SET Tname='Tom',Gender='F',Age=30;

REPLACE INTO tutors (Tname,Gender,Age) SELECT Name,Gender,Age FROM students WHERE Age>20;


DELETE: 

    DELETE FROM tb_name WHERE condition;


TRUNCATE tb_name: 清空表,并重置AUTOINCREMENT计数器;



UPDATE tb_name SET col1=..., col2=... WHERE 


锁:

    读锁:共享锁

    写锁:独占锁

      LOCK TABLES tb_name {READ|WRITE}

      UNLOCK TABLES


锁粒度:从大到小,Mysql服务器仅支持表级锁,行锁需要由存储引擎支持

    表锁:整张表

    页锁:锁定一个数据块,划分的DATA BLOCK

    行锁:一个实体,元组



Mysql的事务(ACID测试):

原子性(Atomicity)  :事务引起的操作,要么都完成,要么都不执行。

一致性(Consistency):写入的事务和处理后的数据在完成之前和完成之后应当一致

隔离性(Isolation)  :如果两个事物同时执行,不能互相影响。MVCC:多版本并发控制

持久性(Durability) :出现崩溃,要可以恢复,保持在磁盘的数据应持久


日志中存储的操作过程,而非数据本身


隔离级别(隔离级别越高,并发越差):

READ-UNCOMMITTED:读未提交。只要第一个事务操作,即使未提交,第二个也可以立刻就可以看到。

READ-COMMITTED  :读提交。同上,会产生"幻读"

REPEATABLE-READ :可重读。无论提交与否,截止事务提交之前都不变。

SERIABLIZABLE   :可串行。一个事务一个事务排队来。


查看隔离级别:mysql> SHOW GLOBAL VARIABLES LIKE '%iso%';

修改隔离级别:mysql> SET SESSION tx_isolation='READ-UNCOMMITTED';

再查看隔离级别:mysql> SELECT @@tx_isolation;


事务:CPU, I/O

    RDBMS, 

        ACID:

            Automicity:原子性,事务所引起的数据库操作,要么都完成,要么都不执行;

            Consistency:一致性,A(3000)-->B(2000)

                1:A:3000-->2500, 

                2: A+B: 4500, 

            Isolation: 隔离性

                事务调度:事务之间影响最小

                MVCC:多版本并发控制

            Durability:一旦事务成功完成,系统必须保证任何故障都不会引起事务表示出不一致性;

                1、事务提交之前就已经写出数据至持久性存储;

                2、结合事务日志完成;

                    事务日志:顺序IO

                    数据文件:随机IO


    事务的状态:

        活动的:active

        部分提交的:最后一条语句执行后

        失败的:提交后未能完成

        中止的:没提交,走了一半就提前停止

        提交的:


事务:并发执行

    1、提高吞吐量和资源利用率

    2、减少等待时间


事务调度:

    可恢复调度;

    无级联高度:


mysql> START TRANSACTION;(启动事务)

mysql> DELETE FROM tutors WHERE Tname LIKE 'stu%'

mysql> ROLLBACK;(回滚delete操作)

mysql> COMMIT;(事务提交之后不可以撤销)


查看是否自动提交(建议关闭自动提交,减少I/O操作):

mysql> SELECT @@autocommit


记录/回滚事务保存点

mysql> SAVEPOINT pointA;

mysql> ROLLBACK TO pointA;


=============================================================================================

Mysql用户权限管


user: Contains user accounts, global privileges, and other non-privilege columns.

user: 用户帐号、全局权限


db: Contains database-level privileges.

db: 库级别权限


host: Obsolete.

host: 废弃


tables_priv: Contains table-level privileges.

表级别权限


columns_priv: Contains column-level privileges.

列级别权限


procs_priv: Contains stored procedure and function privileges.

存储过程和存储函数相关的权限


proxies_priv: Contains proxy-user privileges.

代理用户权限



权限级别:

    全局级别: SUPER、

    库

    表: DELETE, ALTER, TRIGGER

    列: SELECT, INSERT, UPDATE

    存储过程和存储函数

=============================================================================================

Mysql日志类型



错误日志:服务器启动和关闭、服务器运行过程中的错误信息、事物调度器运行一个事件时产生的信息、在从服务器上启动从服务的日志

    log_error

    log_warnings

一般查询日志:DML、DDL

    general_log

    general_log_file

    log

    log_output

慢查询日志

    long_query_time

    log_slow_queries={YES|NO}

    slow_query_log                       

    slow_query_log_file                       


二进制日志:任何引起或可能引起数据库变化的操作;

    复制、即时点恢复;

    mysqlbinlog


    二进制日志的格式(binlog_format):

        基于语句: statement

        基于行: row

        混合方式: mixed


    二进制日志事件:

        产生的时间

        相对位置


    二进制日志文件:

        索引文件

        二进制日志文件




查找关于log的参数

mysql> SHOW GLOBAL VARIABLES LIKE '%log%'

查看二进制日志的信息

mysql> SHOW BINLOG EVENTS IN '二进制日志文件名' [FROM pos];

mysql> SHOW BINLOG EVENTS IN 'mysql-bin.000005' [FROM 107];


查看当前正在使用的二进制日志文件

mysql> SHOW MASTER STATUS;

查看当前拥有的二进制文件

mysql> SHOW BINARY LOGS; 

删除二进制日志 

mysql> PURGE BINARY LOGS TO '某二进制日志文件'

滚动二进制日志

mysql>FLUSH LOGS;



利用mysqlbinlog查看日志和导出

root# mysqlbinlog  --start-position=177  --stop-position=358 mysql-bin.000005

root# mysqlbinlog  --start-datetime='2017-04-09 15:14:39'  [--stop-datetime] mysql-bin.000005

root# mysqlbinlog  --start-datetime='2017-04-09 15:14:39'  [--stop-datetime] mysql-bin.000005 > /root/back.sql





中继日志:

    从主服务器的二进制日志文件中复制而来的时间,并保存为的日志文件


事务日志:ACID,将随机IO转换为顺序IO;

    事务性存储引擎用于保证保证原子性、一致性、隔离性和持久性

    innodb_flush_log_at_trx_commit:

        0:每秒同步,并执行磁盘flush操作

        1:每事务同步,并执行磁盘flush操作(推荐)

        2:每事务同步,但不执行磁盘flush操作,有操作系统决定flush



expire_logs_days={0..99}

设定二进制日志的过期天数,超出此天数的二进制日志文件将被自动删除。默认为0,表示不启用过期自动删除功能。如果启用此功能,自动删除工作通常发生在MySQL启动时或FLUSH日志时。作用范围为全局,可用于配置文件,属动态变量。


general_log={ON|OFF}

设定是否启用查询日志,默认值为取决于在启动mysqld时是否使用了--general_log选项。如若启用此项,其输出位置则由--log_output选项进行定义,如果log_output的值设定为NONE,即使用启用查询日志,其也不会记录任何日志信息。作用范围为全局,可用于配置文件,属动态变量。


general_log_file=FILE_NAME

查询日志的日志文件名称,默认为“hostname.log"。作用范围为全局,可用于配置文件,属动态变量。



binlog-format={ROW|STATEMENT|MIXED}

指定二进制日志的类型,默认为STATEMENT。如果设定了二进制日志的格式,却没有启用二进制日志,则MySQL启动时会产生警告日志信息并记录于错误日志中。作用范围为全局或会话,可用于配置文件,且属于动态变量。


log={YES|NO}

是否启用记录所有语句的日志信息于一般查询日志(general query log)中,默认通常为OFF。MySQL 5.6已经弃用此选项。


log-bin={YES|NO}

是否启用二进制日志,如果为mysqld设定了--log-bin选项,则其值为ON,否则则为OFF。其仅用于显示是否启用了二进制日志,并不反应log-bin的设定值。作用范围为全局级别,属非动态变量。


log_bin_trust_function_creators={TRUE|FALSE}

此参数仅在启用二进制日志时有效,用于控制创建存储函数时如果会导致不安全的事件记录二进制日志条件下是否禁止创建存储函数。默认值为0,表示除非用户除了CREATE ROUTING或ALTER ROUTINE权限外还有SUPER权限,否则将禁止创建或修改存储函数,同时,还要求在创建函数时必需为之使用DETERMINISTIC属性,再不然就是附带READS SQL DATA或NO SQL属性。设置其值为1时则不启用这些限制。作用范围为全局级别,可用于配置文件,属动态变量。


log_error=/PATH/TO/ERROR_LOG_FILENAME

定义错误日志文件。作用范围为全局或会话级别,可用于配置文件,属非动态变量。


log_output={TABLE|FILE|NONE}

定义一般查询日志和慢查询日志的保存方式,可以是TABLE、FILE、NONE,也可以是TABLE及FILE的组合(用逗号隔开),默认为TABLE。如果组合中出现了NONE,那么其它设定都将失效,同时,无论是否启用日志功能,也不会记录任何相关的日志信息。作用范围为全局级别,可用于配置文件,属动态变量。


log_query_not_using_indexes={ON|OFF}

设定是否将没有使用索引的查询操作记录到慢查询日志。作用范围为全局级别,可用于配置文件,属动态变量。


log_slave_updates

用于设定复制场景中的从服务器是否将从主服务器收到的更新操作记录进本机的二进制日志中。本参数设定的生效需要在从服务器上启用二进制日志功能。


log_slow_queries={YES|NO}

是否记录慢查询日志。慢查询是指查询的执行时间超出long_query_time参数所设定时长的事件。MySQL 5.6将此参数修改为了slow_query_log。作用范围为全局级别,可用于配置文件,属动态变量。


log_warnings=#

设定是否将警告信息记录进错误日志。默认设定为1,表示启用;可以将其设置为0以禁用;而其值为大于1的数值时表示将新发起连接时产生的“失败的连接”和“拒绝访问”类的错误信息也记录进错误日志。


long_query_time=#

设定区别慢查询与一般查询的语句执行时间长度。这里的语句执行时长为实际的执行时间,而非在CPU上的执行时长,因此,负载较重的服务器上更容易产生慢查询。其最小值为0,默认值为10,单位是秒钟。它也支持毫秒级的解析度。作用范围为全局或会话级别,可用于配置文件,属动态变量。


max_binlog_cache_size{4096 .. 18446744073709547520}

二进定日志缓存空间大小,5.5.9及以后的版本仅应用于事务缓存,其上限由max_binlog_stmt_cache_size决定。作用范围为全局级别,可用于配置文件,属动态变量。


max_binlog_size={4096 .. 1073741824}

设定二进制日志文件上限,单位为字节,最小值为4K,最大值为1G,默认为1G。某事务所产生的日志信息只能写入一个二进制日志文件,因此,实际上的二进制日志文件可能大于这个指定的上限。作用范围为全局级别,可用于配置文件,属动态变量。


max_relay_log_size={4096..1073741824}

设定从服务器上中继日志的体积上限,到达此限度时其会自动进行中继日志滚动。此参数值为0时,mysqld将使用max_binlog_size参数同时为二进制日志和中继日志设定日志文件体积上限。作用范围为全局级别,可用于配置文件,属动态变量。


innodb_log_buffer_size={262144 .. 4294967295}

设定InnoDB用于辅助完成日志文件写操作的日志缓冲区大小,单位是字节,默认为8MB。较大的事务可以借助于更大的日志缓冲区来避免在事务完成之前将日志缓冲区的数据写入日志文件,以减少I/O操作进而提升系统性能。因此,在有着较大事务的应用场景中,建议为此变量设定一个更大的值。作用范围为全局级别,可用于选项文件,属非动态变量。


innodb_log_file_size={108576 .. 4294967295}

设定日志组中每个日志文件的大小,单位是字节,默认值是5MB。较为明智的取值范围是从1MB到缓存池体积的1/n,其中n表示日志组中日志文件的个数。日志文件越大,在缓存池中需要执行的检查点刷写操作就越少,这意味着所需的I/O操作也就越少,然而这也会导致较慢的故障恢复速度。作用范围为全局级别,可用于选项文件,属非动态变量。


innodb_log_files_in_group={2 .. 100}

设定日志组中日志文件的个数。InnoDB以循环的方式使用这些日志文件。默认值为2。作用范围为全局级别,可用于选项文件,属非动态变量。


innodb_log_group_home_dir=/PATH/TO/DIR

设定InnoDB重做日志文件的存储目录。在缺省使用InnoDB日志相关的所有变量时,其默认会在数据目录中创建两个大小为5MB的名为ib_logfile0和ib_logfile1的日志文件。作用范围为全局级别,可用于选项文件,属非动态变量。



relay_log=file_name

设定中继日志的文件名称,默认为host_name-relay-bin。也可以使用绝对路径,以指定非数据目录来存储中继日志。作用范围为全局级别,可用于选项文件,属非动态变量。


relay_log_index=file_name

设定中继日志的索引文件名,默认为为数据目录中的host_name-relay-bin.index。作用范围为全局级别,可用于选项文件,属非动态变量。


relay-log-info-file=file_name

设定中继服务用于记录中继信息的文件,默认为数据目录中的relay-log.info。作用范围为全局级别,可用于选项文件,属非动态变量。



relay_log_purge={ON|OFF}

设定对不再需要的中继日志是否自动进行清理。默认值为ON。作用范围为全局级别,可用于选项文件,属动态变量。


relay_log_space_limit=#

设定用于存储所有中继日志文件的可用空间大小。默认为0,表示不限定。最大值取决于系统平台位数。作用范围为全局级别,可用于选项文件,属非动态变量。



slow_query_log={ON|OFF}

设定是否启用慢查询日志。0或OFF表示禁用,1或ON表示启用。日志信息的输出位置取决于log_output变量的定义,如果其值为NONE,则即便slow_query_log为ON,也不会记录任何慢查询信息。作用范围为全局级别,可用于选项文件,属动态变量。


slow_query_log_file=/PATH/TO/SOMEFILE

设定慢查询日志文件的名称。默认为hostname-slow.log,但可以通过--slow_query_log_file选项修改。作用范围为全局级别,可用于选项文件,属动态变量。



sql_log_bin={ON|OFF}

用于控制二进制日志信息是否记录进日志文件。默认为ON,表示启用记录功能。用户可以在会话级别修改此变量的值,但其必须具有SUPER权限。作用范围为全局和会话级别,属动态变量。


sql_log_off={ON|OFF}

用于控制是否禁止将一般查询日志类信息记录进查询日志文件。默认为OFF,表示不禁止记录功能。用户可以在会话级别修改此变量的值,但其必须具有SUPER权限。作用范围为全局和会话级别,属动态变量。


sync_binlog=#

设定多久同步一次二进制日志至磁盘文件中,0表示不同步,任何正数值都表示对二进制每多少次写操作之后同步一次。当autocommit的值为1时,每条语句的执行都会引起二进制日志同步,否则,每个事务的提交会引起二进制日志同步。









=============================================================================================

MySQL优化框架


1. SQL语句优化

2. 索引优化

3. 数据库结构优化

4. InnoDB表优化

5. MyISAM表优化

6. Memory表优化

7. 理解查询执行计划

8. 缓冲和缓存

9. 锁优化

10. MySQL服务器优化

11. 性能评估

12. MySQL优化内幕


MySQL优化需要在三个不同层次上协调进行:MySQL级别、OS级别和硬件级别。MySQL级别的优化包括表优化、查询优化和MySQL服务器配置优化等,而MySQL的各种数据结构又最终作用于OS直至硬件设备,因此还需要了解每种结构对OS级别的资源的需要并最终导致的CPU和I/O操作等,并在此基础上将CPU及I/O操作需要尽量降低以提升其效率。


数据库层面的优化着眼点:

1、是否正确设定了表结构的相关属性,尤其是每个字段的字段类型是否为最佳。同时,是否为特定类型的工作组织使用了合适的表及表字段也将影响系统性能,比如,数据频繁更新的场景应该使用较多的表而每张表有着较少字段的结构,而复杂数据查询或分析的场景应该使用较少的表而每张表较多字段的结构等。

2、是否为高效进行查询创建了合适的索引。

3、是否为每张表选用了合适的存储引擎,并有效利用了选用的存储引擎本身的优势和特性。

4、是否基于存储引擎为表选用了合适的行格式(row format)。例如,压缩表在读写操作中会降低I/O操作需求并占用较少的磁盘空间,InnoDB支持读写应用场景中使用压缩表,但MyISAM仅能在读环境中使用压缩表。

5、是否使用了合适的锁策略,如在并发操作场景中使用共享锁,而对较高优先级的需求使用独占锁等。同时,还应该考虑存储引擎所支持的锁类型。

6、是否为InnoDB的缓冲池、MyISAM的键缓存以及MySQL查询缓存设定了合适大小的内存空间,以便能够存储频繁访问的数据且又不会引起页面换出。


操作系统和硬件级别的优化着眼点:

1、是否为实际的工作负载选定了合适的CPU,如对于CPU密集型的应用场景要使用更快速度的CPU甚至更多数量的CPU,为有着更多查询的场景使用更多的CPU等。基于多核以及超线程(hyperthreading)技术,现代的CPU架构越来越复杂、性能也越来越强了,但MySQL对多CPU架构的并行计算能力的利用仍然是有着不太尽如人意之处,尤其是较老的版本如MySQL 5.1之前的版本甚至无法发挥多CPU的优势。不过,通常需要实现的CPU性能提升目标有两类:低迟延和高吞吐量。低延迟需要更快速度的CPU,因为单个查询只能使用一颗;而需要同时运行许多查询的场景,多CPU更能提供更好的吞吐能力,然而其能否奏效还依赖于实际工作场景,因为MySQL尚不能高效的运行于多CPU,并且其对CPU数量的支持也有着限制。一般来说,较新的版本可以支持16至24颗CPU甚至更多。

2、是否有着合适大小的物理内存,并通过合理的配置平衡内存和磁盘资源,降低甚至避免磁盘I/O。现代的程序设计为提高性能通常都会基于局部性原理使用到缓存技术,这对于频繁操作数据的数据库系统来说尤其如此——有着良好设计的数据库缓存通常比针对通用任务的操作系统的缓存效率更高。缓存可以有效地延迟写入、优化写入,但并能消除写入,并综合考虑存储空间的可扩展性等,为业务选择合理的外部存储设备也是非常重要的工作。

3、是否选择了合适的网络设备并正确地配置了网络对整体系统系统也有着重大影响。延迟和带宽是网络连接的限制性因素,而常见的网络问题如丢包等,即是很小的丢包率也会赞成性能的显著下降。而更重要的还有按需调整系统中关网络方面的设置,以高效处理大量的连接和小查询。

4、是否基于操作系统选择了适用的文件系统。实际测试表明大部分文件系统的性能都非常接近,因此,为了性能而苦选文件系统并不划算。但考虑到文件系统的修复能力,应该使用日志文件系统如ext3、ext4、XFS等。同时,关闭文件系统的某些特性如访问时间和预读行为,并选择合理的磁盘调度器通常都会给性能提升带来帮助。

5、MySQL为响应每个用户连接使用一个单独的线程,再加内部使用的线程、特殊目的线程以及其它任何由存储引擎创建的线程等,MySQL需要对这些大量线程进行有效管理。Linux系统上的NPTL线程库更为轻量级也更有效率。MySQL 5.5引入了线程池插件,但其效用尚不明朗。







使用InnoDB存储引擎最佳实践:

1、基于MySQL查询语句中最常用的字段或字段组合创建主键,如果没有合适的主键也最好使用AUTO_INCRMENT类型的某字段为主键。

2、根据需要考虑使用多表查询,将这些表通过外键建立约束关系。

3、关闭autocommit。

4、使用事务(START TRANSACTION和COMMIT语句)组合相关的修改操作或一个整体的工作单元,当然也不应该创建过大的执行单元。

5、停止使用LOCK TABLES语句,InnoDB可以高效地处理来自多个会话的并发读写请求。如果需要在一系列的行上获取独占访问权限,可以使用SELECT ... FOR UPDATE锁定仅需要更新的行。

6、启用innodb_file_per_table选项,将各表的数据和索引分别进行存放。

7、评估数据和访问模式是否能从InnoDB的表压缩功能中受益(在创建表时使用ROW_FORMAT=COMPRESSED选项),如果可以,则应该启用压缩功能。






EXPLAIN语句解析:

id:SELECT语句的标识符,一般为数字,表示对应的SELECT语句在原始语句中的位置。没有子查询或联合的整个查询只有一个SELECT语句,因此其id通常为1。在联合或子查询语句中,内层的SELECT语句通常按它们在原始语句中的次序进行编号。但UNION操作通常最后会有一个id为NULL的行,因为UNION的结果通常保存至临时表中,而MySQL需要到此临时表中取得结果。


select_type:

即SELECT类型,有如下值列表:

SIMPLE:简单查询,即没有使用联合或子查询;

PRIMARY:UNION的最外围的查询或者最先进行的查询;

UNION:相对于PRIMARY,为联合查询的第二个及以后的查询;

DEPENDENT UNION:与UNION相同,但其位于联合子查询中(即UNION查询本身是子查询);

UNION RESULT:UNION的执行结果;

SUBQUERY:非从属子查询,优化器通常认为其只需要运行一次;

DEPENDENT SUBQUERY:从属子查询,优化器认为需要为外围的查询的每一行运行一次,如用于IN操作符中的子查询;

DERIVED:用于FROM子句的子查询,即派生表查询;



table:

输出信息所关系到的表的表名,也有可能会显示为如下格式:

<unionM,N>:id为M和N的查询执行联合查询后的结果;

<derivedN>:id为N的查询执行的结果集;



type:

MySQL官方手册中解释type的作用为“type of join(联结的类型)”,但其更确切的意思应该是“记录(record)访问类型”,因为其主要目的在于展示MySQL在表中找到所需行的方式。通常有如下所示的记录访问类型:

system: 表中仅有一行,是const类型的一种特殊情况;

const:表中至多有一个匹配的行,该行仅在查询开始时读取一次,因此,该行此字段中的值可以被优化器看作是个常量(constant);当基于PRIMARY KEY或UNIQUE NOT NULL字段查询,且与某常量进行等值比较时其类型就为const,其执行速度非常快;

eq_ref:类似于const,表中至多有一个匹配的行,但比较的数值不是某常量,而是来自于其它表;ed_ref出现在PRIMARY KEY或UNIQUE NOT NULL类型的索引完全用于联结操作中进行等值(=)比较时;这是除了system和const之外最好的访问类型;

ref:查询时的索引类型不是PRIMARY KEY或UNIQUE NOT NULL导致匹配到的行可能不惟一,或者仅能用到索引的左前缀而非全部时的访问类型;ref可被用于基于索引的字段进行=或<=>操作;

fulltext:用于FULLTEXT索引中用纯文本匹配的方法来检索记录。

ref_or_null:类似于ref,但可以额外搜索NULL值;

index_merge:使用“索引合并优化”的记录访问类型,相应地,其key字段(EXPLAIN的输出结果)中会出现用到的多个索引,key_len字段中会出现被使用索引的最长长度列表;将多个“范围扫描(range scan)”获取到的行进行合并成一个结果集的操作即索引合并(index merge)。

unique_subquery:用于IN比较操作符中的子查询中进行的“键值惟一”的访问类型场景中,如 value IN (SELECT primary_key FROM single_table WHERE some_expr);

index_subquery:类似于unique_subquery,但子查询中键值不惟一;

range:带有范围限制的索引扫描,而非全索引扫描,它开始于索引里的某一点,返回匹配那个值的范围的行;相应地,其key字段(EXPLAIN的输出结果)中会输出所用到的索引,key_len字段中会包含用到的索引的最长部分的长度;range通常用于将索引与常量进行=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或IN()类的比较操作中;

index:同全表扫描(ALL),只不过是按照索引的次序进行而不行的次序;其优点是避免了排序,但是要承担按索引次序读取整个表的开销,这意味着若是按随机次序访问行,代价将非常大;

ALL:“全表扫描”的方式查找所需要的行,如果第一张表的查询类型(EXPLAIN的输出结果)为const,其性能可能不算太坏,而第一张表的查询类型为其它结果时,其性能通常会非常差;



Extra:

Using where:MySQL服务器将在存储引擎收到数据后进行“后过滤(post-filter)”以限定发送给下张表或客户端的行;如果WHERE条件中使用了索引列,其读取索引时就由存储引擎检查,因此,并非所有带有WHERE子句的查询都会显示“Using where”;

Using index:表示所需要的数据从索引就能够全部获取到,从而不再需要从表中查询获取所需要数据,这意味着MySQL将使用覆盖索引;但如果同时还出现了Using where,则表示索引将被用于查找特定的键值;

Using index for group-by:类似于Using index,它表示MySQL可仅通过索引中的数据完成GROUP BY或DISTINCT类的查询;

Using filesort:表示MySQL会对结果使用一个外部索引排序,而不是从表里按索引次序来读取行;


====================================================================================

Mysql备份类型

热备份:读写均不受影响

温备份:仅可以执行读操作

冷备份:离线备份,读写均停止


物理备份和逻辑备份

物理备份:复制数据文件,速度快,

逻辑备份:将数据导出至文本文件中,速度慢,容易丢失浮点精度,可移植能力强


完全备份、增量备份、差异备份

完全备份:备份所有数据

增量备份:仅备份上次完全备份后增加的数据

差异备份:以完全备份为准,备份差异数据,可能出现包含


备份什么?数据,配置文件,二进制日志,事务日志



MyISAM:温备份

InnoDB:热备份xtrabackup,mysqldump


Mysql备份工具:

mysqldump:逻辑备份工具(对于MyISAM-温备份,对于Innodb-热备份)

mysqlhotcopy:物理备份工具、温备份


文件系统工具:

cp:冷备用

lv:逻辑卷快照,几乎热备

    mysql>FLUSH TABLES;

    mysql>LOCK TABLES;

    创建快照,释放锁,而后复制数据


第三方工具:

ibbackup:商业工具

xtrabackup:开源工具



mysqldump使用


mysql> FLUSH TABLES WITH READ LOCK;

root#mysqldump -uroot -p jiaowu > /root/jiaowu.sql

mysql> UNLOCK TABLES;

mysql> FLUSH LOGS;

mysql> SHOW BINARY LOGS;



--master-data={0|1|2}

    0: 不记录二进制日志文件及路位置;

    1:以CHNAGE MASTER TO的方式记录位置,可用于恢复后直接启动从服务器;

    2:以CHANGE MASTER TO的方式记录位置,但默认为被注释;



将二进制日志的保存点记录在日志中,下次接着备份就可以

root#mysqldump -uroot -p --master-data=2 studb > /root/studb-`data +%F-%H-%M-%S`.sql


--lock-all-tables:锁定所有表

--flush-logs:执行日志flush滚动


如果指定库中的表类型均为InnoDB,可使用--single-transaction启动热备份


备份多个库:

    --all-databases:备份所有库

    --databases DB_NAME,DB_NAME :备份指定库


备份所有库(完全备份)

root# mysqldump -uroot -p --lock-all-tables --flush-logs --all-databases --master-data=2 > /root/all.sql

mysql>PURGE BINARY LOGS TO 'mysql-bin.000011' (复制完二进制文件后,删除11之前的日志)

root# mysqlbinlog mysql-bin.0000111 > /root/mon-incremental.sql


 备份策略:每周完全+每日增量

    完全备份:mysqldump

    增量备份:备份二进制日志文件(flush logs)


模拟:

root# mysql_install_db --user=mysql --datadir=/mydata/data

root# service mysqld start

root# mysql -uroot -p < alldatabases.sql(导入完整) 因为初始化,root暂时为空密码

root# mysql -uroot -p < mon-incremental.sql(导入增量)