zoukankan      html  css  js  c++  java
  • Mysql快速入门(三)

    MySQL性能优化之查看执行计划explain

    介绍:

    (1).MySQL 提供了一个 EXPLAIN 命令, 它可以 SELECT 语句进行分析, 并输出 SELECT 执行的详细信息, 以供开发人员针对性优化.

    (2).使用explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有没有使用上了索引,有没有做全表扫描,这都可以通过explain命令来查看。

    (3).可以通过explain命令深入了解MySQL的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行SQL语句时哪种策略预计会被优化器采用。

    (4).EXPLAIN 命令用法十分简单, 在 SELECT 语句前加上 explain 就可以了, 例如:

    参数说明:

    expain出来的信息有10列,分别是idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra,下面对这些字段进行解释:

    (1).id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符.

    (2).select_type: SELECT 查询的类型.

    (3).table: 查询的是哪个表

    (4).partitions: 匹配的分区

    (5).type: join 类型

    (6).possible_keys: 此次查询中可能选用的索引

    (7).key: 此次查询中确切使用到的索引.

    (8).ref: 哪个字段或常数与 key 一起被使用

    (9).rows: 显示此查询一共扫描了多少行. 这个是一个估计值.

    (10).filtered: 表示此查询条件所过滤的数据的百分比

    (11).extra: 额外的信息

    select_type列说明:

    (1).SIMPLE, 表示此查询不包含 UNION 查询或子查询

    (2).PRIMARY, 表示此查询是最外层的查询

    (3).UNION, 表示此查询是 UNION 的第二或随后的查询

    (4).DEPENDENT UNION, UNION 中的第二个或后面的查询语句, 取决于外面的查询

    (5).UNION RESULT, UNION 的结果

    (6).SUBQUERY, 子查询中的第一个 SELECT

    (7).DEPENDENT SUBQUERY: 子查询中的第一个 SELECT, 取决于外面的查询. 即子查询依赖于外层查询的结果.

    type列说明:

    通常来说, 不同的 type 类型的性能关系如下:
    ALL < index < range ~ index_merge < ref < eq_ref < const < system

    类型

    含义

    system

    表只有一行

    const

    表最多只有一行匹配,通用用于主键或者唯一索引比较时

    eq_ref

    每次与之前的表合并行都只在该表读取一行,这是除了system,const之外最好的一种,特点是使用=,而且索引的所有部分都参与join且索引是主键或非空唯一键的索引

    ref

    如果每次只匹配少数行,那就是比较好的一种,使用=或<=>,可以是左覆盖索引或非主键或非唯一键

    fulltext

    全文搜索

    ref_or_null

    与ref类似,但包括NULL

    index_merge

    表示出现了索引合并优化(包括交集,并集以及交集之间的并集),但不包括跨表和全文索引。

    这个比较复杂,目前的理解是合并单表的范围索引扫描(如果成本估算比普通的range要更优的话

    unique_subquery

    在in子查询中,就是value in (select...)把形如“select unique_key_column”的子查询替换。

    PS:所以不一定in子句中使用子查询就是低效的!

    index_subquery

    同上,但把形如”select non_unique_key_column“的子查询替换

    range 

    常数值的范围

    index

    a.当查询是索引覆盖的,即所有数据均可从索引树获取的时候(Extra中有Using Index);

    b.以索引顺序从索引中查找数据行的全表扫描(无 Using Index);

    c.如果Extra中Using Index与Using Where同时出现的话,则是利用索引查找键值的意思;

    d.如单独出现,则是用读索引来代替读行,但不用于查找

    all

    全表扫描

     

    参考网站:

    https://segmentfault.com/a/1190000008131735

    https://blog.csdn.net/rewiner120/article/details/70598797

    MySQL性能优化之慢查询

    介绍:

    (1).数据库查询快慢是影响项目性能的一大因素,对于数据库,我们除了要优化 SQL,更重要的是得先找到需要优化的 SQL

    (2).MySQL 数据库有一个“慢查询日志”功能,用来记录查询时间超过某个设定值的SQL,这将极大程度帮助我们快速定位到症结所在,以便对症下药。

    * 至于查询时间的多少才算慢,每个项目、业务都有不同的要求。

    传统企业的软件允许查询时间高于某个值,但是把这个标准放在互联网项目或者访问量大的网站上,估计就是一个bug,甚至可能升级为一个功能性缺陷。

    (3).MySQL的慢查询日志功能,默认是关闭的,需要手动开启

    开启慢查询功能:

    (1).查看是否开启慢查询功能:

    参数说明

    slow_query_log    :是否开启慢查询日志,ON 为开启,OFF 为关闭,如果为关闭可以开启。

    * log-slow-queries  :旧版(5.6以下版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺省的文件host_name-slow.log

    slow-query-log-file:新版(5.6及以上版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺省的文件host_name-slow.log

    long_query_time :慢查询阈值,当查询时间多于设定的阈值时,记录日志,单位为秒。

    临时开启慢查询功能:

    MySQL 执行 SQL 语句设置,但是如果重启 MySQL 的话将失效

    set global slow_query_log = ON;

    set global long_query_time = 1;

    永久开启慢查询功能:

    修改/etc/my.cnf配置文件,重启 MySQL, 这种永久生效.

    [mysqld]

    slow_query_log = ON

    slow_query_log_file = /var/log/mysql/slow.log

    long_query_time = 1

    慢日志格式:

     

    格式说明:

    第一行,SQL查询执行的时间

    第二行,执行SQL查询的连接信息,用户和连接IP

    第三行,记录了一些我们比较有用的信息,如下解析

        Query_time,这条SQL执行的时间,越长则越慢

        Lock_time,在MySQL服务器阶段(不是在存储引擎阶段)等待表锁时间

        Rows_sent,查询返回的行数

        Rows_examined,查询检查的行数,越长就当然越费时间

    第四行,设置时间戳,没有实际意义,只是和第一行对应执行时间。

    第五行及后面所有行(第二个# Time:之前),执行的sql语句记录信息,因为sql可能会很长。

    分析慢查询日志:

    MySQL自带的mysqldumpslow

    [root@localhost mysql]# mysqldumpslow /var/lib/mysql/localhost-slow.log

    常用参数说明:

    (1).-s:是表示按照何种方式排序

    (2).-t:top n的意思,即为返回前面多少条的数据

    (3).-g:后边可以写一个正则匹配模式,大小写不敏感的

    MySQL性能分析语句show profile:

    介绍:

    (1).Query Profiler是MYSQL自带的一种query诊断分析工具,通过它可以分析出一条SQL语句的性能瓶颈在什么地方。

    (2).通常我们是使用的explain,以及slow query log都无法做到精确分析,但是Query Profiler却可以定位出一条SQL语句执行的各种资源消耗情况,比如CPU,IO等,以及该SQL执行所耗费的时间等。不过该工具只有在MYSQL 5.0.37以及以上版本中才有实现。

    (3.)默认的情况下,MYSQL的该功能没有打开,需要自己手动启动

    语句使用:

    (1).show profile  show profiles 语句可以展示当前会话(退出session后,profiling重置为0) 中执行语句的资源使用情况.

    (2).show profiles :以列表形式显示最近发送到服务器上执行的语句的资源使用情况.显示的记录数由变量:profiling_history_size 控制,默认15条

    (3).show profile: 展示最近一条语句执行的详细资源占用信息,默认显示 Status和Duration两列

    (4).show profile 还可根据 show profiles 列表中的 Query_ID ,选择显示某条记录的性能分析信息

    开启Profile功能:

    (1).Profile 功能由MySQL会话变量 : profiling控制,默认是OFF关闭状态。

    (2).查看是否开启了Profile功能:

    * select @@profiling;

    * show variables like ‘%profil%’;

    开启profile功能:

    * set profiling=1; --1是开启0是关闭

    MySQL事务处理

    事务概述:

    (1). MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务

    (2).事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。

    (3).事务用来管理DDL、DML、DCL操作,比如 insert,update,delete 语句

    一般来说,事务是必须满足4个条件(ACID):

    (1).Atomicity(原子性)

    (2).Consistency(稳定性、一致性)

    (3).Isolation(隔离性)

    (4.)Durability(可靠性、持久性)

    对于ACID的解释如下:

    (1).原子性:构成事务的的所有操作必须是一个逻辑单元,要么全部执行,要么全部不执行。

    (2).稳定性(一致性)数据库在事务执行前后状态都必须是稳定的。

    (3).隔离性:事务之间不会相互影响。

    (4).可靠性(持久性)事务执行成功后必须全部写入磁盘。

    MySQL事务支持:

    常见的操作有一下三个:

    (1).BEGIN或START TRANSACTION;显式地开启一个事务;

    (2).COMMIT;也可以使用COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改称为永久性的;

    (3).ROLLBACK;有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;

    MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。

    创建表

    插入数据

    提交测试

    回滚测试

    事务并发问题:

    在事务的并发操作中可能会出现一些问题:

    (1).脏读:一个事务读取到另一个事务未提交的数据。

    (2).不可重复读:一个事务因读取到另一个事务已提交的数据。导致对同一条记录读取两次以上的结果不一致。update操作

    (3).幻读:一个事务因读取到另一个事务已提交的数据。导致对同一张表读取两次以上的结果不一致。insert、delete操作

    事务隔离级别:

    为了避免上面出现的几种情况,在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同

    四种隔离级别:

    现在来看看MySQL数据库为我们提供的四种隔离级别(由低到高):

    ① Read uncommitted (读未提交):最低级别,任何情况都无法保证。

    ② Read committed (读已提交):可避免脏读的发生。

    ③ Repeatable read (可重复读):可避免脏读、不可重复读的发生。

    ④ Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

    默认隔离级别:

    大多数数据库的默认隔离级别是Read committed,比如Oracle、DB2等。

    MySQL数据库的默认隔离级别是Repeatable read。

    如何查看和设置隔离级别

    MySQL数据库中查看当前事务的隔离级别:

      select @@tx_isolation;

    MySQL数据库中设置事务的隔离 级别:

    set  [glogal | session]  transaction isolation level 隔离级别名称;
        set tx_isolation=’隔离级别名称;’

    MySQL锁

    锁介绍:

    * 数据库锁定机制简单来说就是数据库为了保证数据的一致性而使各种共享资源在被并发访问访问变得有序所设计的一种规则。

    * 对于任何一种数据库来说都需要有相应的锁定机制,所以MySQL自然也不能例外。

    *  MySQL数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储引擎所针对的应用场景特点都不太一样,为了满足各自特定应用场景的需求,

        每种存储引擎的锁定机制都是为各自所面对的特定场景而优化设计,所以各存储引擎的锁定机制也有较大区别。

    总的来说,MySQL各存储引擎使用了三种类型(级别)的锁定机制:行级锁定,页级锁定和表级锁定。下面我们先分析一下MySQL这三种锁定的特点和各自的优劣所在。

    行级锁定(row-level):

    行级锁定最大的特点就是锁定对象的颗粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的。由于锁定颗粒度很小,

    所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。

     

    虽然能够在并发处理能力上面有较大的优势,但是行级锁定也因此带来了不少弊端。由于锁定资源的颗粒度很小,

    所以每次获取锁和释放锁需要做的事情也更多,带来的消耗自然也就更大了。此外,行级锁定也最容易发生死锁。

    表级锁定(table-level):

    和行级锁定相反,表级别的锁定是MySQL各存储引擎中最大颗粒度的锁定机制。该锁定机制最大的特点是实现逻辑非常简单,

    带来的系统负面影响最小。所以获取锁和释放锁的速度很快。由于表级锁一次会将整个表锁定,所以可以很好的避免困扰我们的死锁问题。

    当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并大度大打折扣。

    页级锁定(page-level):

    页级锁定是MySQL中比较独特的一种锁定级别,在其他数据库管理软件中也并不是太常见。页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之间,

    所以获取锁定所需要的资源开销,以及所能提供的并发处理能力也同样是介于上面二者之间。另外,页级锁定和行级锁定一样,会发生死锁。

    总的来说,MySQL这3种锁的特性可大致归纳如下:

    * 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;

    * 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;

    * 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

    表级锁:

    MySQL的表级锁定有两种模式:表共享读锁Table Read Lock)和表独占写锁Table Write Lock)。

    MySQL 实现的表级锁定的争用状态变量:show status like 'table%';

    `

    * table_locks_immediate:产生表级锁定的次数;

    * table_locks_waited:出现表级锁定争用而发生等待的次数;

    手动增加表锁

    lock table 表名称 read(write),表名称2 read(write),其他;

    查看表锁情况

    show open tables;

    删除表锁

    unlock tables;

    表锁演示

    建表演示:

    CREATE TABLE `mylock` (  
         `id` int(11) NOT NULL AUTO_INCREMENT,   
        `NAME` varchar(20) DEFAULT NULL,   
        PRIMARY KEY (`id`) );

    添加记录:

    INSERT INTO mylock (id,NAME) VALUES (1, 'a');
    INSERT INTO mylock (id,NAME) VALUES (2, 'b');
    INSERT INTO mylock (id,NAME) VALUES (3, 'c');
    INSERT INTO mylock (id,NAME) VALUES (4, 'd');

     

     

    集群搭建之主从复制

    主服务器配置:

    第一步:修改my.conf文件:

    [mysqld]段下添加:

    #启用二进制日志
    log-bin=mysql-bin
    #服务器唯一ID,一般取IP最后一段
    server-id=133

    第二步:重启mysql服务

    service mysqld restart

    第三步:建立帐户并授权slave

    mysql>GRANT FILE ON *.* TO 'backup'@'%' IDENTIFIED BY '123456';
    mysql>GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* to 'backup'@'%' identified by '123456'; 

    #一般不用root帐号,“%”表示所有客户端都可能连,只要帐号,密码正确,此处可用具体客户端IP代替,如192.168.145.226,加强安全。

    刷新权限

    mysql> FLUSH PRIVILEGES;

    查看mysql现在有哪些用户

    mysql>select user,host from mysql.user;

    第四步:查询master的状态

    mysql> show master status;

    +------------------+----------+--------------+------------------+-------------------+

    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |

    +------------------+----------+--------------+------------------+-------------------+

    | mysql-bin.000001 |      120 | db1          | mysql            |                   |

    +------------------+----------+--------------+------------------+-------------------+

    1 row in set

    从服务器配置:

    第一步:修改my.conf文件

    [mysqld]

    server-id=134

     第二步删除UUID文件

    错误处理:

    如果出现此错误:

    Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.

    因为是mysql是克隆的系统所以mysql的uuid是一样的,所以需要修改。

    解决方法:

    删除/var/lib/mysql/auto.cnf文件,重新启动服务。

    第三步:配置从服务器

    mysql>change master to master_host='192.168.25.134',master_port=3306,master_user='backup',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=120

    注意语句中间不要断开,master_port为mysql服务器端口号(无引号),master_user为执行同步操作的数据库账户,“120”无单引号(此处的120就是show master status 中看到的position的值,这里的mysql-bin.000001就是file对应的值)。

    第四步:启动从服务器复制功能

    mysql>start slave;

    第五步:检查从服务器复制功能状态:

    mysql> show slave status

    ……………………(省略部分)

    Slave_IO_Running: Yes //此状态必须YES

    Slave_SQL_Running: Yes //此状态必须YES

    ……………………(省略部分)

    注:Slave_IO及Slave_SQL进程必须正常运行,即YES状态,否则都是错误的状态(如:其中一个NO均属错误)。

    注释:----这是接着上一章的,咱们的Mysql未完待续,有需要的可以关注一下,咱们后面还有待更新!!!

  • 相关阅读:
    js代码与html代码分离示例
    day24_Nginx学习笔记
    bookStore商城开发文档
    API Management Architecture Notes
    Taking A Fresh Look At What Open Source API Management Architecture Is Available
    使用API Gateway
    Qcon2017实录|Service Mesh:下一代微服务
    聊聊 API Gateway 和 Netflix Zuul
    项目长期运维中产生的一些问题
    忆情天书的由来
  • 原文地址:https://www.cnblogs.com/Myoyc/p/12113027.html
Copyright © 2011-2022 走看看