【读书笔记】《MySQL技术NM InnoDB存储引擎》第一章 MySQL体系结构和存储引擎

第一章 MySQL体系结构和存储引擎

最近在学习MySQL数据库,主要是先学习一些MySQL的一些基本SQL语句。但是呢,我也知道仅仅是掌握这些是远远不够的,因此在学习基础知识的同时我也在看MySQL稍微深入一点的一本书《MySQL技术内幕 InnoDB存储引擎》(第二版) 姜成尧著。因此本系列博客主要内容来自于这本书,以及包括一些我在阅读这本书的过程中的一些实际操作验证和读后感等。本篇博客主要出自第一章 MySQL体系结构和存储引擎。在后期的章节中,根据不同章节所含知识的容量及其难度,会拆分成多篇博客产出。

前言

MySQL被设计为一个可移植的数据库,几乎在当前所有系统上都能运行,如Linux,Solaris,FreeBSD,Mac和Windows。尽管各平台在底层(如线程)实现方面都各有不同,但是MySQL基本上能保证在各平台上的物理体系结构的一致性。因此,用户应该能很好地理解MySQL数据库在所有这些平台上是如何运作的。

1.1 定义数据库和实例

数据库和实例分别是什么?一样吗?作为常见的数据库术语,这两个词定义如下。

  • 数据库:物理操作系统文件或其他形式文件类型的集合。在MySQL数据库中,数据库文件可以是frm、MYD、MYI、ibd结尾的文件【1验证】。当使用NDB引擎时,数据库的文件可能不是操作系统上的文件,而是存放与内存之中的文件,但是定义仍然不变。
  • 实例:MySQL数据库由后台线程以及一个共享内存区组成。共享内存可以被运行的后台线程所共享。共享内存可以被运行的后台线程所共享。需要牢记的是,数据库实例才是真正用于操作数据库文件的。

【1验证】MySQL数据库是都会有一个配置文件(后续会讲到),配置文件包含了MySQL编译时的默认参数设置。在配置文件中有一行存储路径是用来表示数据库文件的物理存储路径的。在Linux操作系统下,配置文件路径是/etc/my.cnf【注意这里由于是系统级文件,需要使用root权限访问】在配置文件中,datadir正是表示数据库文件的物理存储路径的。

[root@VM-20-12-centos mysql]# cat /etc/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html

[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
`datadir=/var/lib/mysql`
socket=/var/lib/mysql/mysql.sock

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

skip-grant-tables

character-set-server=utf8
default-storage-engine=innodb

当我们进入到这个路径下时,我们就可以看到数据库中的文件。我们进入任意一个数据库,就可以看到很多.frm,.MYD结尾的文件

[root@VM-20-12-centos mysql]# cd 104_db_lesson3
[root@VM-20-12-centos 104_db_lesson3]# ll
total 992
-rw-r----- 1 mysql mysql   8614 Apr 12 08:14 class.frm
-rw-r----- 1 mysql mysql  98304 Apr 12 08:15 class.ibd
-rw-r----- 1 mysql mysql     61 Apr 12 08:03 db.opt
-rw-r----- 1 mysql mysql   8605 Apr 12 09:23 student.frm
-rw-r----- 1 mysql mysql 114688 Apr 12 09:24 student.ibd
-rw-r----- 1 mysql mysql   8588 Apr 12 08:17 t1.frm
-rw-r----- 1 mysql mysql  98304 Apr 12 08:18 t1.ibd
-rw-r----- 1 mysql mysql   8588 Apr 12 08:21 t2.frm
-rw-r----- 1 mysql mysql  98304 Apr 12 08:21 t2.ibd
-rw-r----- 1 mysql mysql   8632 Apr 12 08:30 t3.frm
-rw-r----- 1 mysql mysql  98304 Apr 12 08:30 t3.ibd
-rw-r----- 1 mysql mysql   8578 Apr 12 08:41 t4.frm
-rw-r----- 1 mysql mysql  98304 Apr 12 08:42 t4.ibd
-rw-r----- 1 mysql mysql   8601 Apr 12 08:57 t5.frm
-rw-r----- 1 mysql mysql  98304 Apr 12 08:57 t5.ibd
-rw-r----- 1 mysql mysql   8620 Apr 12 09:00 t6.frm
-rw-r----- 1 mysql mysql  98304 Apr 12 09:02 t6.ibd
-rw-r----- 1 mysql mysql   8586 Apr 12 09:08 t7.frm
-rw-r----- 1 mysql mysql  98304 Apr 12 09:09 t7.ibd

这两个词被设计为一个单进程多线程架构的数据库,说白了,MySQL数据库实例在系统上的表示就是一个进程。

在Linux操作系统中通过命令可以启动MySQL数据库实例,通过ps命令可以观察MySQL数据库启动后的进程情况:

[root@VM-20-12-centos 104_db_lesson3]# ps -aux| grep mysqld
mysql    17022  0.0  9.3 1514312 192008 ?      Sl   Apr06   3:43 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid

字段解释:
USER:创建进程的用户
PID:进程ID
%CPU:进程占用CPU的百分比
%MEM:进程占用物理内存的百分比
VSZ:进程占用虚拟内存的大小(单位KB)
RSS:进程占用实际物理内存的大小(单位KB)
TTY:进程在哪个终端运行。
STAT:进程状态
START:进程开始启动的时间
TIME:进程使用的CPU(运算)时间
COMMAND:调用进程的命令

这个进程号为17022的进程,该进程就是MySQL的实例。当启动实例时,MySQL数据库会去读取配置文件,根据配置文件的参数来启动数据库实例。在MySQL数据库中,可以没有配置文件,在这种情况下,MySQL会按照编译时的默认参数设置启动实例。用下面这个命令可以查看当MySQL数据库实例启动时,会在那些位置查找配置文件。

[root@VM-20-12-centos 104_db_lesson3]# mysql --help | grep my.cnf
                      order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf 

可以看到,MySQL数据库是按照/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf 的顺序读取配置文件的。当有多个配置文件中都有同一个参数,MySQL数据库会以读取到最后一个配置文件中的参数为准。在Linux环境下,配置文件一般会放在/ect/my.cnf下。在Windows环境下,配置文件的后缀名可能是.cnf.ini。例如在Windows操作系统下运行mysql--help可以看到以下内容(如下展示的为我Windows系统安装的MySQL)

Default options are read from the following files in the given order:
C:\WINDOWS\my.ini C:\WINDOWS\my.cnf C:\my.ini C:\my.cnf C:\Program Files\MySQL\MySQL Server 8.0\my.ini C:\Program Files\MySQL\MySQL Server 8.0\my.cnf

1.2MySQL体系结构

在上一节我们提到了我不能把MySQL既理解是数据库,也是数据库实例。从概念上来说,数据库是文件的集合,是依照某种数据模型组织起来并存放于二级存储器中的数据集合;数据库实例是程序,是位于用户与操作系统之间的一层数据管理软件,用户对数据库数据的任何操作,包括数据库定义,数据查询,数据维护,数据库运行控制等都是在数据库实例下进行的,应用程序只有通过数据库实例才能和数据库打交道。

如果这样还不是很好理解,用一种直白的方式进行解释:数据库是由一个个文件组成(一般来说都是二进制的文件)的,要对这些文件执行诸如SELECT,INSERT,UPDATE和DELETE之类的数据库操作是不能通过简单的操作文件来更改数据库的内容,需要通过数据库实例来完成对数据库的操作。所以,用户把MySQL简单的理解成数据库可能有失偏颇的,虽然在实际使用中并不会这么强调两者之间的区别。在了解复杂枯燥的定义之后,现在来看看MySQL数据库的体系结构[如图1.2-1]

在这里插入图片描述

从图[1.2-1]可以发现,MySQL由以下几个部分组成:

  • 连接池组件
  • 管理服务和工具组件
  • SQL接口组件
  • 查询分析器组件
  • 优化器组件
  • 缓冲Cache组件
  • 插件式存储引擎
  • 物理文件

MySQL数据库区别于其他数据库的最重要的一个特点就是其插件式的表存储引擎。MySQL插件式的存储引擎架构提供了一系列标准的管理和服务支持,这些标准与存储引擎本身无关,可能是每个数据库系统本身都必需的,如SQL分析器和优化器等,而存储引擎是底层物理结构的实现,每个存储引擎开发者可以按照自己的意愿来进行开发。需要特别注意的是,存储引擎是基于表的,而不是数据库.

1.3MySQL存储引擎

通过1.2节大致了解了MySQL数据库独有的插件式体系结构,并了解到存储引擎是MySQL区别于其他数据库的一个最重要特性。存储引擎的好处是,每个存储引擎都有各自的特点,能够根据具体的应用建立不同存储引擎表。对于开发人员来说,存储引擎对其是透明的,但了解各种存储引擎的区别对于开发人员来说也是有好处的。

1.3.1InnoDB存储引擎

InnoDB存储引擎支持事务,其设计目的主要面向在线事务处理(OLTP)的应用。其特点是行锁设计,支持外键,并支持非锁定读。即默认读取不会产生锁。从MySQL数据库5.5.8版本开始,InnoDB存储引擎是默认的存储引擎。

InnoDB存储引擎将数据放在一个逻辑的表空间中,这个表空间就像黑盒一样由InnoDB存储引擎自身进行管理。从MySQL4.1(包括4.1)版本开始,它可以将每个InnoDB存储引擎的表单独存放在一个ibd文件中。此外,InnoDB存储引擎支持用裸设备(row disk)用来建立其表空间。

InnoDB通过使用多版本并发控制(MVCC)来获得高并发性,并且实现了SQL标准的4中隔离级别,默认为REPEATABLE级别。同时,使用一种被称为next-key-locking的策略来避免幻读phantom现象的产生。除此之外,InnoDB存储引擎还提供了插入缓存insert buffer,二次写double write,自适应哈希索引adaptive hash index,预读read ahead等高性能和高可用的功能。

对于表中数据的存储,InnoDB存储引擎采用了聚集clustered的方式,因此每张表的存储都是按主键的顺序进行存放。如果没有显式地在表定义时指定主键,InnoDB存储引擎会为每一行生成一个6字节地ROWID,并以此作为主键。

1.3.2MyISAM存储引擎

MyISAM存储引擎不支持事务,表锁设计,支持全文索引,主要面向一些OLAP数据库应用。在MySQL5.5.8版本之前MyISAM存储引擎时默认的存储引擎(除Windows版本之外)。数据库系统与文件系统很大的一个不同之处在于对事务的支持,然而MyISAM存储引擎是不支持事务的。究其根本,这也不是很难理解。试想用户是否在所有的应用中都需要事务呢?答案是非也。在数据库仓库中,如果欸有ETL这些操作,只是简单的报表查询是否还需要事务的支持呢?此外,MyISAM存储引擎的另一个与众不同的地方是它的缓冲池只缓存cache索引文件,而不缓冲数据文件,这点和大多数的数据库都非常不同。

MyISAM存储引擎表由MYDMYI组成,MYD用来存放数据文件,MYI用来存放索引文件。在MySQL 5.0版本之前,MyISAM默认支持的表大小为4GB,如果需要支持大于4GBMyISAM表时,则需要制定MAX_ROWSAVG_ROW_LENGTH属性。从MySQL 5.0版本开始,MyISAM默认支持256TB的表单数据,这足够满足一般应用需求。


注意:对于MyISAM存储引擎表,MySQL数据库只缓存其索引文件,数据文件的缓存交由操作系统本身来完成,这与其它使用LRU算法缓存数据的大部分数据库大不相同。此外,在MySQL 5.1.23版本之前。无论是在32位还是64位操作系统环境下,缓存索引的缓冲区最大只能设置为4GB。在之后的版本中,64位系统可以支持大于4GB的索引缓冲区。


1.3.3NDB存储引擎

NDB存储引擎是一个集群存储引擎。NDB的特点是数据全部放在内存中(从MySQL5.1版本开始,可以将非索引数据放在磁盘上),因此主键查找速度极快,并且通过添加NDB数据存储节点可以线性地提高数据库性能,是高可用,高性能地集群系统。

NDB存储引擎的连接操作是在MySQL数据库层完成的,而不是在存储引擎层完成的。这意味着,复杂的连接操作需要巨大的网络开销,因此查询速度很慢。

1.3.4 Memory存储引擎

Memory存储引擎将表中的数据存放在内存中,如果数据库重启或发生崩溃,表中的数据都将丢失。它非常适合于存储临时数据的临时表,以及数据仓库中的维度表。Memory存储引擎默认使用哈希索引,而不是我们B+树索引。

虽然Memory存储引擎速度非常快,但在使用上还是有一定的限制。比如,只支持表锁,并发性能较差,并且不支持TEXTBLOB列类型。最重要的是,存储变长字段(varchar)时是按照定常字段(char)的方式进行的,因此会浪费内存。

此外有一点容易被忽视,MySQL数据库使用Memory存储引擎作为临时表来存放查询的中间结果集。如果中间结果集大于Memory存储引擎表的容量设置,又或者中间结果含有TEXTBLOB列类型字段,则MySQL数据库会把其转换到MyISAM存储引擎表而存放到磁盘中。之前提到的MyISAM不缓存数据文件,因此这时产生的临时表的性能对于查询会有损失。

1.3.5其他存储引擎

除了上面提到的这几种存储引擎,MySQL数据库还有很多其他的存储引擎,他们都有各自使用的场合,这里不再一一介绍。在了解了MySQL的多种存储引擎后我们回答

  • 为什么MySQL数据库不支持全文索引? 不!MySQL支持,MyISAM,InnoDB和Sphinx存储引擎都支持全文索引

  • MySQL数据库速度快是因为不支持事务? 错!虽然MySQLMyISAM存储引擎不支持事务,但是InnoDB支持。"快"是相对于不同应用来说,对于ETL这种操作,MyISAM会有其优势,但在OLTP环境中,InnoDB存储引擎的效率更好

  • 当表的数据量大于1000万时MySQL的性能会急剧下降吗? 不!MySQL是数据库,不是文件,随着数据行数的增加,性能当然会有所下降,但是这些下降不是线性的,如果用户选择了正确的存储引擎,以及正确的配置,再多的数据量MySQL也能承受。如官方手册上提及到的,MytrixIncInnoDB上存储超过1TB的数据,还有一些其他网站使用InnoDB存储引擎,处理插入/更新的操作平均800次/秒

1.4各存储引擎之间的比较

通过1.3节的介绍,我们了解了存储引擎是MySQL体系结构的核心。这里将通过简单比较几个存储引擎来让读者更直观地理解存储引擎地概念。图1-2取于MySQL的官方手册,展现了一些常用MySQL存储引擎之间的不同之处,包括存储容量的限制,事务支持,锁的粒度,MVCC支持,支持的索引,备份和复制等。

在这里插入图片描述

通过SHOW ENGINES语句查看当前使用的MySQL数据库所支持的存储引擎,也可以通过查找information_schema架构下的ENGINES

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.02 sec)

mysql> show engines \G
*************************** 1. row ***************************
      Engine: InnoDB
     Support: DEFAULT
     Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
          XA: YES
  Savepoints: YES
*************************** 2. row ***************************
      Engine: MRG_MYISAM
     Support: YES
     Comment: Collection of identical MyISAM tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 3. row ***************************
      Engine: MEMORY
     Support: YES
     Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 4. row ***************************
      Engine: BLACKHOLE
     Support: YES
     Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 5. row ***************************
      Engine: MyISAM
     Support: YES
     Comment: MyISAM storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 6. row ***************************
      Engine: CSV
     Support: YES
     Comment: CSV storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 7. row ***************************
      Engine: ARCHIVE
     Support: YES
     Comment: Archive storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 8. row ***************************
      Engine: PERFORMANCE_SCHEMA
     Support: YES
     Comment: Performance Schema
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 9. row ***************************
      Engine: FEDERATED
     Support: NO
     Comment: Federated MySQL storage engine
Transactions: NULL
          XA: NULL
  Savepoints: NULL
9 rows in set (0.00 sec)

1.5连接MySQL

本节将介绍连接MySQL数据库的常用方式。需要理解的是,连接MySQL操作时一个连接进程和MySQL数据库实例进行通信。从程序设计的角度来说,本质上是进程通信。如果对进程通信比较了解,可以知道常用的进程通信方式有管道,命名管道,命名字,TCP/IP套接字,UNIX域套接字。MySQL数据库提供的连接方式从本质上看都是上述提及的进程通信方式。

1.5.1 TCP/IP

TCP/IP套接字方式是MySQL数据库在任何平台下都提供的连接方式,也是网络中使用的最多的一种方式。这种方式在TCP/IP连接上一个基于网络的连接请求,一般情况下客户端(client)在一台服务器上,而MySQL实例(server)在另一台服务器上,这两台机器通过一个TCP/IP网络连接。例如用户可以在Windows服务器下请求一台远程Linux服务器下的MySQL实例,如下所示:

[Lxy@VM-20-12-centos ~]$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 24
Server version: 5.7.41 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

这里的客户端是Windows,它向一台Host IPxxxxMySQL实例发起了TCP/IP连接请求,并且连接成功。之后就可以对MySQL数据库进行一些数据库操作,如DDL和DML等。

这里需要注意的是,在通过TCP/IP连接到MySQL实例时,MySQL数据库会先检查一张权限视图,用来判断发起请求的客户端IP是否允许连接到MySQL实例。该视图在mysql架构下,表名为user,如下图所示:

mysql> select host,user,authentication_string from user \G
*************************** 1. row ***************************
                 host: localhost
                 user: root
authentication_string: *0C52BA2F284F417CE062039FC850F7BC1349882C
*************************** 2. row ***************************
                 host: localhost
                 user: mysql.session
authentication_string: *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE
*************************** 3. row ***************************
                 host: localhost
                 user: mysql.sys
authentication_string: *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE
3 rows in set (0.01 sec)

1.5.2命名管道和共享内存

如果两个需要进程通信的进程在一台服务器上,那么可以使用命名管道,SQl Server数据库默认安装后的本地连接也是使用命名管道。在MySQL数据库中须在配置文件中启用--enable-named-pipe选择。在MySQL 4.1之后的版本中,MySQL还提供了共享内存的连接方式,这是通过在配置文件中添加 --shared-memory实现的。如果想使用共享内存的方式,在连接时,MySQL客户端还必须使用--protocol=memory选项。

1.5.3UNIX域套接字

LinuxUNIX环境下,还可以使用UNIX域套接字。UNIX域套接字其实不是一个网络协议,所以只能在MySQL客户端和数据库实例在一台服务器上的情况下使用。用户可以在配置文件中指定套接字文件的路径,如 --socket=/tmp/mysql.sock。当数据库实例启动后,用户可以通过下列命令来进行UNIX域套接字文件的查找:

mysql> show variables like 'socket' \G
*************************** 1. row ***************************
Variable_name: socket
        Value: /var/lib/mysql/mysql.sock
1 row in set (0.00 sec)

在知道了UNIX域套接字文件的路径后,就可以使用该方式进行连接了,如下图所示:

[Lxy@VM-20-12-centos ~]$ mysql -u root -S /var/lib/mysql/mysql.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 27
Server version: 5.7.41 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

(本章完)

猜你喜欢

转载自blog.csdn.net/qq_58325487/article/details/130162931