Mysql成神之路----初识Mysql

740 阅读9分钟

Mysql成神之路----初识Mysql

万物皆c-s,mysql也是如此分为客户端和服务端两部分,一般客户端命令mysql,服务点命令mysqld。

  1. 客户端连接常用命令:mysql -ulocalhost(主机名) -uusername(用户名) -ppassword(密码)
  2. 服务端常用命令:mysqld --skip-networking 关闭TCP/IP远程连接
  3. 服务端常用命令:mysqld --default-storage-engine=MyISAM 修改mysql默认存储引擎
  4. 服务端常用命令:mysqld --bind-address 绑定可以访问的IP,前提--skip-networking 关闭
  5. 更多命令我们可以使用mysql --help 自己查询

常用的系统变量

mysql系统变量有一个global(全局所有用户客户端)和session(当前会话也就是当前用户也可以叫local)的概念

  • SHOW VARIABLES LIKE 'default_storage_engine'; 查询当前存储引擎 (默认当前会话)
  • SHOW VARIABLES like 'max_connections'; 查询最大连接数
  • LIKE表达式后边可以跟通配符来进行模糊查询 SHOW VARIABLES LIKE 'default%';
  • SET GLOBAL default_storage_engine = MyISAM; SET SESSION default_storage_engine = MyISAM;SET default_storage_engine = MyISAM;(没有作用范围,默认是当前会话级别命令)
  • 还有一些状态变量如Threads_connected查询当前客户端与服务器建立了多少连接,Handler_update表示已经更新了多少行记录 SHOW [GLOBAL|SESSION] STATUS [LIKE 匹配的模式]; SHOW SESSION STATUS LIKE 'Threads_connected';

字符集比较规则简介

字符集和比较规则息息相关(修改一个另一个自动修改成对应的规则)

  • 字符集的比较规则有一个编码和解码的过程,字符集映射成二进制叫做编码,二进制映射成字符集叫做解码,一般比较都是用二进制数据进行比较。
  • utf8mb3(utf8)和utf8mb4的区别,utf8mb3需要1-3字节,utf8mb4需要1-4字节,有些特殊字符需要4个字节如果我们设置成utf8mb3会出现问题,所以一般我们设置为utf8mb4

我们通常都把 character_set_client 、character_set_connection、character_set_results 这三个系统变量设置成和客户端使用的字符集一致的情况,这样减少了很多无谓的字符集转换

总结

  1. 字符集指的是某个字符范围的编码规则。
  2. 比较规则是针对某个字符集中的字符比较大小的一种规则。
  3. 在MySQL中,一个字符集可以有若干种比较规则,其中有一个默认的比较规则,一个比较规则必须对应一个字符集。
  4. 查看MySQL中查看支持的字符集和比较规则的语句如下:SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式];SHOW COLLATION [LIKE 匹配的模式];
  5. MySQL有四个级别的字符集和比较规则:服务器级别,数据库级别,表级别,列级别
  6. 从发送请求到接收结果过程中发生的字符集转换
    • 客户端使用操作系统的字符集编码请求字符串,向服务器发送的是经过编码的一个字节串。
    • 服务器将客户端发送来的字节串采用character_set_client代表的字符集进行解码,将解码后的字符串再按照character_set_connection代表的字符集进行编码。
    • 如果character_set_connection代表的字符集和具体操作的列使用的字符集一致,则直接进行相应操作,否则的话需要将请求中的字符串从character_set_connection代表的字符集转换为具体操作的列使用的字符集之后再进行操作。
    • 将从某个列获取到的字节串从该列使用的字符集转换为character_set_results代表的字符集后发送到客户端。
    • 客户端使用操作系统的字符集解析收到的结果集字节串。
系统变量描述
character_set_client服务器解码请求时使用的字符集
character_set_connection服务器处理请求时会把请求字符串从character_set_client转为character_set_connection
character_set_results服务器向客户端返回数据时使用的字符集

一般情况下要使用保持这三个变量的值和客户端使用的字符集相同。

  1. 比较规则的作用通常体现比较字符串大小的表达式以及对某个字符串列进行排序中

InnoDB记录存储结构

  1. InnoDB的数据读取写入方式:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB,读写都是16KB的数据磁盘和内存交互 (这一点和OS工作原理类似也是4K的内存页工作)

  2. Compact行格式

  3. 一个页一般是16KB,当记录中的数据太多,当前页放不下的时候,会把多余的数据存储到其他页中,这种现象称为行溢出。(某个列的值如果太大会变成溢出列)

  4. 有四种行格式:COMPACT行格式,Redundant行格式,Dynamic和Compressed行格式,我现在使用的MySQL版本是5.7,它的默认行格式就是Dynamic

InnoDB数据结构

  • delete_mask:标记数据是否会被删除 0-否 1-是,删除的数据不会立即刷盘到磁盘这样影响性能,删除的数据会重新组成一个垃圾链表(可重用空间),新进入的数据会把垃圾数据覆盖
  • min_rec_mask:B+树的每层非叶子节点中的最小记录都会添加该标记
  • heap_no:这个属性表示当前记录在本页中的位置,mysql默认自带infimum(最小记录),supremum(最大记录)单独保存
  • record_type:这个属性表示当前记录的类型,一共有4种类型的记录,0表示普通记录,1表示B+树非叶节点记录,2表示最小记录,3表示最大记录。
  • next_record:它表示从当前记录的真实数据到下一条记录的真实数据的地址偏移量。比方说第一条记录的next_record值为32,意味着从第一条记录的真实数据的地址处向后找32个字节便是下一条记录的真实数据。如果你熟悉数据结构的话,就立即明白了,这其实是个链表,可以通过一条记录找到它的下一条记录。但是需要注意注意再注意的一点是,下一条记录指得并不是按照我们插入顺序的下一条记录,而是按照主键值由小到大的顺序的下一条记录。而且规定 Infimum记录(也就是最小记录) 的下一条记录就是本页中主键值最小的用户记录,而本页中主键值最大的用户记录的下一条记录就是 Supremum记录(也就是最大记录) 从图中可以看出来,我们的记录按照主键从小到大的顺序形成了一个单链表。最大记录的next_record的值为0,这也就是说最大记录是没有下一条记录了,它是这个单链表中的最后一个节点。如果从中删除掉一条记录,这个链表也是会跟着变化的,比如我们把第2条记录删掉:

从图中可以看出来,删除第2条记录前后主要发生了这些变化:

  • 第2条记录并没有从存储空间中移除,而是把该条记录的delete_mask值设置为1。
  • 第2条记录的next_record值变为了0,意味着该记录没有下一条记录了。
  • 第1条记录的next_record指向了第3条记录。
  • 还有一点你可能忽略了,就是最大记录的n_owned值从5变成了4,关于这一点的变化我们稍后会详细说明的。 所以,不论我们怎么对页中的记录做增删改操作,InnoDB始终会维护一条记录的单链表,链表中的各个节点是按照主键值由小到大的顺序连接起来的。 再来看一个有意思的事情,因为主键值为2的记录被我们删掉了,但是存储空间却没有回收,如果我们再次把这条记录插入到表中,会发生什么事呢?

从图中可以看到,InnoDB并没有因为新记录的插入而为它申请新的存储空间,而是直接复用了原来被删除记录的存储空间。(垃圾链表,重用功能)

总结:

  1. InnoDB为了不同的目的而设计了不同类型的页,我们把用于存放记录的页叫做数据页。

  2. 一个数据页可以被大致划分为7个部分,分别是

    • File Header,表示页的一些通用信息,占固定的38字节。
    • Page Header,表示数据页专有的一些信息,占固定的56个字节。
    • Infimum + Supremum,两个虚拟的伪记录,分别表示页中的最小和最大记录,占固定的26个字节。
    • User Records:真实存储我们插入的记录的部分,大小不固定。
    • Free Space:页中尚未使用的部分,大小不确定。
    • Page Directory:页中的某些记录相对位置,也就是各个槽在页面中的地址偏移量,大小不固定,插入的记录越多,这个部分占用的空间越多。
    • File Trailer:用于检验页是否完整的部分,占用固定的8个字节。
  3. 每个记录的头信息中都有一个next_record属性,从而使页中的所有记录串联成一个单链表。

  4. InnoDB会把页中的记录划分为若干个组,每个组的最后一个记录的地址偏移量作为一个槽,存放在Page Directory中,所以在一个页中根据主键查找记录是非常快的,分为两步:

    • 通过二分法确定该记录所在的槽。

    • 通过记录的next_record属性遍历该槽所在的组中的各个记录。

  5. 每个数据页的File Header部分都有上一个和下一个页的编号,所以所有的数据页会组成一个双链表。

  6. 为保证从内存中同步到磁盘的页的完整性,在页的首部和尾部都会存储页中数据的校验和和页面最后修改时对应的LSN值,如果首部和尾部的校验和和LSN值校验不成功的话,就说明同步过程出现了问题。