zoukankan      html  css  js  c++  java
  • MySQL

    MySql体系结构

    一,连接层功能:

    1,TCP/IP或者Socket的链接方式

    2,验证用户名密码功能

    3,连接线程(客服):接收SQL语句,返回执行结果

     

    二,SQL层

    1,语法检查模块,检查上层发过来的SQL语句,进行语法检查

    2,权限检查模块,检测当前登录用户是否有权限操作数据库对象

    3,语义检查模块,识别语句种类

    4,解析器,解析出SQL语句所有可能的执行方式,这些方式被称为“执行计划”

    5,优化器,基于执行代价(系统资源的消耗作为维度(cpu、内存、IO),管理员可以通过间接的方法,干扰优化器的选择)

    6,执行器,按照优化器选择的“最优”的执行计划,执行SQL语句。得出结论:某某磁盘的某某位置,发送给存储引擎层。

    7,提供查询缓存:有局限性。一般会用Redis产品来替代

    8,记录查询日志

       

    SQL语句的分类:

    DDL:数据定义语言

    DCL:数据控制语言

    DML:数据操作语言

    DQL:数据查询语言

     

    三,存储引擎层:

    和“磁盘”(文件系统)打交道的层次

    根据SQL层执行的结果,去磁盘上找到对应的数据。结构化成表的模式,返回给用户。

      

    MySql逻辑结构组成:

    一,库(库名字,库属性)

     二,库(库名字,列(列名字,列属性)表属性,表数据)

     

    MySQL索引

      MySQL索引分类

    存储引擎管理

    一,索引管理以及原理

    1,索引的种类

    B树(B+tree  B*tree b-tree)

    B-tree:针对某个明确值的查询

    查找顺序:根节点——>枝节点——>叶子节点

    B+tree:针对明确的范围的查询

    缺点:无法同时包含回表查询以及其它列的查询

     

    辅助索引:(B TREE)

    alter table t1 add index idx_num(telnum);

    怎么生成的:

    根据创建索引时,指定的列的值,进行排序后,存储在叶子节点中

    优点:

    1,优化了查询,减少CPU 内存  IO消耗

    2,减少了文件排序

     

    覆盖索引:(联合索引)

    通过一个索引列把需要查询的列都添加到索引树里面去

    直接在索引树里面直接有,减少或尽量避免回表查询操作

    优点:减少回表查询的操作的几率

    聚集索引

    同一等级情况下效率最高

    大部分情况下辅助索引和聚集索引结合使用

    辅助索引:where 条件   有id列的时候,比如id=28

    随机读​ 顺序读

    建表时,如果有主键列,自动生成聚集索引

    没有主键列,会去找unique列

    优点:

    减少回表查询

    将随机IO转换成顺序IO

    加强了缓存的应用,查询效率提升

     

    2,R树

    3,hash索引

    4,全文索引

    2,B树索引的类型

      1,聚簇索引(cluster index):一般是基于主键的

      2,辅助索引(普通辅助索引:回表查询;覆盖索引;不回表查询;唯一性索引)

      3,唯一索引

    3,索引管理

    索引的作用:在mysql数据库中,索引是用来优化查询的

    除缓存之外,数据的查询有两种方式:

    1,全表扫描

    2,索引扫描

    优化器索引扫描要优于全表扫描

    索引管理:

    索引就是一张表

    创建索引的语句:

    为某张表基于某列建索引:alter table 表名 add index idx_name(列名)

     

      MySQL不走索引的情况(开发规范)

    重点关注:

    1,没有查询条件,或者查询条件没有建立索引

      select * from tab ;全表扫描

      select * from tab where 1=1;

      在业务数据库中,特别是数据库量比较大的表,是没有全表扫描这种需求的,当然我们也应该避免这种情况

        1,对用户查看是非常痛苦的

        2,对服务器来说是毁灭性的

        (1) select * from tab

        SQL改写成以下语句:

        select * from tab order by price limit 10 ;       需要在price列上建立索引

        (2) select * from tab where name=‘zhangsan';   name列没有索引

    2,查询结果集是原表中的大部分数据,应该是25%以上。

      查询的结果集,超过了总数行数25%,优化器就会觉得没有必要走索引了。

      假如:tab表 id,name      id:1-100w,id列有索引

      select * from tab where id>50000;

    3,索引本身失效,统计数据不真实

      大量的操作插入删除操作,对表内容变化比较频繁的情况下,有可能会出现索引失效的情况。

    4,查询条件使用函数在索引上,或者列进行计算,运算包括(+,-,*,/,!等)

      算数运算

      函数运算

      子查询

    例子:

      错误的例子:select * from test where id-1=9;

      正确的例子:select * from test where id=10;

    5,隐式转换导致索引失效,这一点应当引起重视,也是开发中经常遇到会犯的错误!

     6,<>,not in 不走索引

        单独的 >,<,in有可能走,也有可能不走,和结果集有关,尽量结合业务添加limit

        or或 in  尽量改成 union

    7,like "%_"百分号在前面不走索引

        %link%类的搜索需求,可以使用elasticsearch 专门做搜索服务的数据库产品

    8,单独引用联合索引里非第一位置的索引列,作为条件查询时不走索引。

    例子:

      复合索引

      DROP TABLE t1

      CREATE TABLE t1(id INT,NAME VARCHAR(20),age INT , sex ENUM('m','f'),money INT );

       ALTER TABLE t1 ADD INDEX t1_idx(money,age,sex);

      DESC t1

      SHOW INDEX FROM t1

      走索引的情况测试:

        EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30  AND  sex='m'; 

        EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30 ;

        EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND sex='m';   ----->部分走索引

      不走索引的情况;

        EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30;

        EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30  AND  sex='m';  

        EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE sex='m'; 

     

    MySQL存储引擎

    查看存储引擎:

    show engines;

    show create table world.city;

    插件式,即插即用存储引擎,是在表级别设定的。

    mysql5.5以后默认的是InnoDB

    InnoDB与MyISAM存储引擎的区别:

    MVCC: innoDB支持,MyISAM不支持

    锁(行级别): innodb支持,myisam表级别

    外键: innodb支持,myisam不支持

    事务: innodb支持,myisam不支持

    热备份: innodb支持,myisam温备份

    CSR(故障断电自动恢复)innodb支持,myisam不支持

    InnoDB

    MVCC

     锁定粒度

    外键

    MyISAM

    MEMORY(memory)

    ARCHIVE(archive)

     

     

    也可以使用第三方的存储引擎

    TokuDB  ------>zabbix

    myrocks

     

    InnoDB存储引擎的物理存储方式:

    表空间(TBS)的管理模式:

    来自于Oracle

    表存储到磁盘上是以表空间的管理模式来存储

    共享表空间:类似于Oracle管理模式

    独立表空间:每个表单独使用表空间存储

    5.5默认:共享表空间

    5.6以后:默认管理模式独立表空间存储,共享表空间也存在

     

    表空间存储数据的分类:

    共享表空间:ibdata1   

    存了什么?

    系统数据

    undo日志

    磁盘临时表

    独立表空间:

    t1.ibd  ----->t1表的数据和索引

    t1.frm ------>t1表的列相关信息

    表空间操作:

    共享表空间:

    我们建议,在数据库初始化的时候就配置好

    一般建议2-3个,512M

    /etc/my.cnf

    innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend

    mysql_install_db

     

    独立表空间:一个表一个ibd文件,存储表数据和索引

    show variables like 'innodb_file_per_table';

     

    事务

    InnoDB存储引擎核心特性:

    1,事务

      简单来说:

        事务会把业务流程中的多条语句放到一个执行(工作)单元里面,保证这多条语句要么全部成功,要么全部失败。

        保证交易类业务完整性

      官方:

      一组数据操作执行步骤,这些步骤被视为一个工作单元

      用于对多个语句进行分组

      可以在多个客户机并发访问同一个表中的数据时使用

      所有步骤都成功或者都失败

      如果所有步骤正常,则执行

      如果步骤出现错误或不完整,则取消

      

    2,事务是保证数据的ACID特性

      Atomic(原子性)

        所有语句作为一个执行单元全部成功执行或全部取消执行。

        保证了稳定性。

      Consistent(一致性)

        如果数据库在事务开始时处于一致状态,则在执行该VT事务期间将保留一致状态。

      Isolated(隔离性)

        事物之间不相互影响

      Durable(持久性)

        事务成功完成后,所做的所有更改都会准确地记录在VT数据库中,所做的更改不会丢,即使数据库宕机

     

    3,标准的事务控制语句:

      事务常见生命周期:

      周期一:

      begin;    开启事务

      DML

      DML

      commit;   结束事务

     

      周期二:   开启事务

      begin;

      DML

      DML

      rollback;   撤销事务

      常识:MySQL5.5版本以后不需要自己手动来写begin语句,写DML语句时自动生成

      注意:正常的遵循事务的ACID特性的事务,对于autocommit=1,需要手动关闭,默认等于1处于开启状态,自动提交功能

        临时关闭,临时生效

        set  autocommit=0;

        set  global  autocommit=0;

        永久关闭

        在my.cnf设置

        autocommit=0;

    4,隐式提交

      用于隐式提交的SQL语句:
         START TRANSACTION
         SET AUTOCOMMIT = 1
      导致提交的非事务语句:
         DDL语句:  ALTER、CREATE、DROP
         DCL语句:  GRANT、REVOKE、SET PASSWORD
         锁定语句  LOCK TABLES 和 UNLOCK TABLES
      导致隐式提交的语句:
         TRUNCATE TABLES
         LOAD DATA INFILE
         SELECT FOR UPDATE

      隐式提交的几种情况:

        情况一:

          begin

          DML1

          DML2

          begin

        情况二:

          begin

          DDL

          DDL

        情况三:

          begin

          DCL

          DDL

    5,innodb存储引擎物理存储层

      表空间(t1.ibd)----->

      段    一个表就是一个段(除了分区表)

      区    连续的多个页

      页    page(16KB)

      每个数据页作为一个存储单元

    6,存储引擎日志 -----物理层面

    Redo:重做日志

     

      Redo记录的是内存数据页的变化过程

      Rudo:事务日志的一种,在事务ACID过程中,实现的是“D”持久化的作用,AC特性也和它有关

      Rudo:CSR过程中实现前滚

      存储位置:数据路径下存放,默认两个日志,默认标准大小50M,轮询覆盖形式使用文件日志

        通过这两个参数控制,可以按照自己需求设定文件大小

          innodb_log_file_size=50331648

          innodb_log_files_in_group=2

        ib_logfile0

        ib_logfile1

        查看标准大小:

          mysql -uroot  -p

          show varables like '%log%';

       LSN:日志序列号(也就是数据变化的版本号)

        哪些地方会有日志序列版本号:

          data page      磁盘数据页

          logfile

          data buffer

          redo log  buffer  日志的内存区域

          

        数据库要求:启动时,必须保证data page 与logfile 中LSN号一致才能正常打开数据库,否则就会进行数据恢复

     

     

    undo:回滚日志

      undo记录了什么?

        undo:记录数据页变化之前的数据状态以及TXID(数据页的id)

       undo:事务日志的一种,在事务ACID过程中,实现的是“ACI”原子性,一致性的作用

      undo作用:

        1,rollback

        2,CSR过程中实现回滚

      事务没有进行commit提交的情况下:

        先Rudo前滚

        再undo回滚

     

      四种隔离级别:

        READ UNCOMMITTED  脏读

          允许事务查看其他事务所进行的未提交更改

        READ COMMITTED     幻读

          允许事务查看其他事务所进行已提交更改

            有可能出现幻读的现象,企业中坚决避免

        REPEATABLE READ******可重复读,防止幻读现象

          确保每个事务的SELECT 输出一致

          InnoDB默认级别

        SERIALIZABLE

          将一个事务的结果与其他事务完全隔离

            会阻塞其他事务的所有操作,只保证当前事务正常运行

     

      Innodb事务锁机制

      锁:顾名思义就是锁定的意思

      种类:行级锁与表级锁

      作用:在事务ACID过程中,锁和隔离级别一起来实现隔离性的作用

      锁的粒度:

        MyIasm:低并发锁  ——表级锁

        InooDB:高并发锁  ——行级锁

      事务出现冲突,出现锁争用:也名冲突事务

      冲突事务例子:

        例子:

            1,事务1想要把a=1修改成a=2,,而这时事务2想要把a=1修改成a=3,这种情况下

            2,两个事务同时更新一条数据

     

     InnoDB体系结构扩展:

      1,内存结构

      2,线程结构

      3,事务工作更详细流程

      4,InnoDB存储引擎在安全和性能上的体现

      5,Double  Write

      6,Db crash恢复流程

     

     

     

    日志管理

    1,错误日志

      a,作用:

        记录启动关闭日常运行过程中,状态信息,警告,错误

      b,配置:

        默认就是开启状态:/数据路径下/hostname.err

        手动设定:

          vim /etc/my.cnf

          log_error=/var/log/mysql.log

          重启生效:

          show variables like 'log_error';

       c,查看日志内容

          主要关注[error],看上下文

    2,二进制日志:binlog

       1,作用:

          1,备份恢复

          2,主从环境

       2,binlog配置(5.7必须加server_id)

          vim /etc/my.cnf

          server_id=6

          log_bin=/data/mysql/mysql-bin

          binlog_format=row

          重启生效

          注意:=/data/mysql 必须事先创建好,必须对mysql有权限

       3,binlog记录了什么?

          记录mysql数据库所有变更类的SQL语句

          DDL,DCL,记录方式:SQL语句直接记录

          DML记录三种方式:  只记录已经commit的DML

            row       5.7默认

              特点:记录数据行的变化,可读性不高,日志量较大,记录数据精确

            statment    5.6默认

              特点:可读性较高,日志量较少,但是以后恢复数据可能会是错误数据

            mixed

       4, event二进制的最小记录单元

          对于DDL,DCL,一个事务就是一个event

          对于DML,一个事务就被分为了四个event:

              begin;

              DML1

              DML2

              commit;

          event组成:开始位置 + 事件内容 +结束位置

       5,日志文件查看

          log_bin参数设置的路径,可以找到二进制日志

          show binary logs;

          show master status;

       6,日志内容查看

          show master status;

          show master status in 'mysql-bin.000002';

     

          录入数据,看事件信息:

          create database testdb;

          create table t1(id int);

          insert into t1 values(1);

          commit;

          show binlog events in 'mysql-bin.000002;

     

          查看binlog文件详细内容:

          mysqlbinlog /data/mysql/mysql-bin.000002;

          mysqlbinlog --base64-output=decode-rows      -vvvv /data/mysql/mysql-bin.000002;

          mysqlbinlog -d testdb /data/mysql/mysql-bin.000002;

       7,日志截取

          mysqlbinlog --start-position   --stop-position

          恢复:

          set sql_log_bin=0;

          source /tmp/binlog.sql

          set sql_log_bin=1;

       8,二进制日志恢复数据

        数据库的故障(损坏),原因:

          1,软件损坏了

          2,数据损坏了

          3,硬件损坏,数据文件,数据页

          4,逻辑损坏

          5,SQL导致的误删除,误修改

        只要拥有全量的binlog,就可以把数据库恢复到任意的时间点

     

    3,慢日志(slow_log)

      1,作用:

        记录慢SQL语句的日志

      2,开启慢日志,默认没开启

        配置:

        开启慢日志:

          slow_query_log=1

        文件位置以及名字:

          slow_query_log_file=/data/mysql/slow.log

        设定慢查询时间:

          long_query_time=0.01

        没走索引的语句也记录:

          log_queries_not_using_indexes  

        

        服务器端配置,几条语句加进去就可以了

          vim /etc/my.cnf

            slow_query_log=1

            slow_query_log_file=/data/mysql/slow.log

            long_query_time=0.01

            log_queries_not_using_indexes

          /etc/init.d/mysql  restart

       3,分析慢日志

         mysqldumpslow

         mysqldumpslow  -s c -t  10 /data/mysql/slow.log

    备份恢复

    1,备份类型

      热备:在数据库正常业务是,备份数据,并且能够一致性恢复

      冷备:关闭数据库业务,数据库没有任何变更的情况下,进行备份数据

      温备:锁表备份,只能查询不能修改

    2,备份方式,工具

      逻辑备份:基于SQL语句进行备份:mysqldump,mysqlbinlog

      物理备份:基于磁盘文件备份:cp,xtrabackup(XBK)

    3,备份策略

      1,全备:全库备份

      2,增量:备份变化的数据

      备份周期:多久全备,多久增量

      

     

    4,恢复备份

    5,故障恢复

    6,迁移

     

     

    主从复制

    前提:

      1,准备2个以上的mysql实例,有主有从

         2,每台实例server_id不同

      3,主库方面创建专用的复制用户

      4,主库必须开启二进制日志

      5,从库需要初始化数据,保证和主库数据在一个时间点上数据一致

    1,搭建主从复制

      1,准备多个mysql实例(3307(master),3308(slave1),3309(slave2))

        具体环境配置文档(待QAQ续)  

      2,主库必须授权一个专门用作主从复制的用户

        在创建一个复制用户

        mysql  -S /data/3307/mysql.sock

        grant  replication slave on *.* ro repl@'10.0.0.%' indextified  by '123';

      3,全备主库数据,恢复到从库

        mysqldump -S /data/3307/mysql.sock -A  -R  --triggers  --master-data=2 --single-transaction >/tmp/full.sql

        

        mysql  -S /data/3308mysql.sock

        set sql_log_bin=0;

        source  /tmp/full.sql

      4,开启主从复制

        mysql -S /data/3308/mysql.sock

        命令两条:

          忘记了请记得让我们的help小姐姐来帮你QAQ: help change master to

          CHANGE MASTER TO

            MASTER_HOST='10.0.0.51',         填写主库ip

            MASTER_USER='repl',          填写主库复制用户名

            MASTER_PASSEORD='123',          填写主库复制用户密码

            MASTER_[PORT=3307,          填写主库端口号

            MASTER_LOG_FILE='mysql-bin.000001',  填写需要复制二进制日志名

            MASTER_LOG_POS=325,         填写需要复制的二进制日志复制的起点

            MASTER_CONNECT_RETRY=10;      重连重试次数

            

            启动复制线程:

              start slave;

               查看主从状态:

                show slave status G

              当你看到这两条命令为Yes,那么恭喜你成功了!

                Slave_IO_Running:Yes

                Slave_SQL_Running:Yes

     2,主从复制存在原因

        1,辅助备份

           解决物理损坏

        2,演变高可用架构

           在主库发生故障时,自动进行故障转移,对于应用透明

        3,演变高性能架构

          读写分离

          分布式

     

     3,延时从库

     

     4,过滤复制

      控制过滤

        从主库方面控制:复制指定的库到从库,对主库业务数据进行垂直拆分

        从从库方面控制:只接收主库某个库复制过来的内容   

     

      1,从主库方面控制

        show master status;

        Binlog_Do_DB=白名单,在此参数中的库,记录二进制日志

        Binlog_Ignore_DB=黑名单,在此参数中的库,不记录二进制日志

     

      2,从库方面控制

        Replicate_Do_DB:  白名单,在此参数中的库,复制

        Replicate_Ignore_DB:  黑名单,在此参数中的库,不复制

        Replicate_Do_Table:  白名单,在此参数中的表,复制

        Replicate_Ignore_Table:  黑名单,在此参数中的表,不复制

        模糊的表名字    

        Replicate_Wild_Do_Table:  wolrd.t*

        Replicate_Wild_Ignore_Table:

        写法:

        vim /data/3308/my.cnf

        replicate_do_db=world

        replicate_do_db=oldboy

     

    5,主从复制之架构扩展GTID复制

    1,环境准备

      环境准备Centos拿db01克隆两台虚拟机

      干掉原来数据库,并清理/application/mysql/data下所有数据,保证环境一致,干净

        pkill mysqld

        rm -rf  /application/mysql/data*

      1,备份三台机器/etc/my.cnf文件

        mv/etc/my.cnf  /tmp

      2,书写配置文件:

        master:10.0.0.51

        vim/etc/my.cnf  

        

        [mysqld]

        dasedir=/application/mysql

        datadir=/application/mysql/data

        socket=/tmp/mysql.sock

        log-error=/var/log/mysql.log

        log-bin=/data/mysql/mysql-bin

        binlog_format=row

        skip-name-resolve

        server-id=51

        gtid-more=on

        enforce-gtid-consistency=true

        log-slave-updates=1

        [client]

        socket=/tmp/mysql.sock

        

        slave1:10.0.0.52

        vim /etc/my.cnf

        [mysqld]

        dasedir=/application/mysql

        datadir=/application/mysql/data

        socket=/tmp/mysql.sock

        log-error=/var/log/mysql.log

        log-bin=/data/mysql/mysql-bin

        binlog_format=row

        skip-name-resolve

        server-id=52

        gtid-more=on

        enforce-gtid-consistency=true

        log-slave-updates=1

        [client]

        socket=/tmp/mysql.sock

     

        slave2:10.0.0.53

        vim /etc/my.cnf

        [mysqld]

        dasedir=/application/mysql

        datadir=/application/mysql/data

        socket=/tmp/mysql.sock

        log-error=/var/log/mysql.log

        log-bin=/data/mysql/mysql-bin

        binlog_format=row

        skip-name-resolve

        server-id=53

        gtid-more=on

        enforce-gtid-consistency=true

        log-slave-updates=1

        [client]

        socket=/tmp/mysql.sock

     

      3,重新初始化三台机器数据

        /application/mysql/scripts/mysql_install_db  --basedir=/application/mysql/ --datadir=/application/mysql/data  --user=mysql

      4,分别启动三台数据库服务器

        etc/init.d/mysqld start

     

     2,GTID介绍

      GTID是对于一个已提交事务的编号,并且是一个全局唯一的编号

       官方定义:

       GTID=source_id :transaction_id

      7E11FA47-31CA-19E1-9E56-C43AA21293967:29

      

      1,什么是sever_uuid和Server-id区别?

      source_id  也叫uuid   默认是在第一次启动数据库时,自动生成的

      /application/mysql/data/auto.cnf

      手动删除掉此文件,重启数据库,可以生成新的

     

      2,重要参数

      gtid-mode=on            --启动gtid类型,否则就是普通的复制架构

      erforce-gtid-consistency=true     --强制GTID的一致性

      log-slave-updates=1          --slave更新是否记入日志

     

      3,基于GTID的复制构建

        master:51

        slave:52,53

        51:

        grant  replication  slave  on  *.* to  repl@'10.0.0.%' identified by '123';

        5253:

        source bak.sql

        change master to msater_host ='10.0.0.51',master_user='repl',master_password='123',MASTER_AUTO_POSITION=1;

        start  slave;

        change master to msater_host ='10.0.0.51',master_user='repl',master_password='123',MASTER_AUTO_POSITION=1; 

     

     

    高可用以及读写分离

     

     

    分布式系统

     

     

     

    数据库优化

      搜索引擎优化

      SQL语句优化

  • 相关阅读:
    变参宏 __VA_ARGS__
    预处理中的 # 和 ##
    strlen与sizeof异同
    .vimrc
    sudo:有效用户 ID 不是 0,sudo 属于 root 并设置了 setuid 位吗
    远程ssh登陆时报错:/bin/bash: Permission denied
    Excel中VBA进行插入列、格式化、排序
    ORACLE发送带附件邮件的二三事之一
    Windows Server 2008 双网卡同时上内外网 不能正常使用
    VMWARE修改CPUID
  • 原文地址:https://www.cnblogs.com/Rglin/p/11280867.html
Copyright © 2011-2022 走看看