1 MySQL 体系结构和存储引擎
1.1 数据库和数据库实例
- 数据库:物理操作系统文件活其他形式文件类型的集合
实例:MySQL数据库是由后台线程以及一个共享内存区组成
通常两者是一一对应。
MySQL数据库实例在系统上的表现就是一个进程
-
ps -ef | grep mysqld
查看mysql数据库启动后的进程情况 -
在 MySQL 数据库中,可以没有配置文件, 在这种情况下, MySQL 会按照编泽时的默认参数设置启动实例。 用以下命令可以査看当 MySQL 数据库实例启动时, 会在哪些位置査找配置文件。
[root@xen-server bin 】 # mysql --help | grep my.cnf order of preference, my.cnf, SQL_TCP_PORT, /etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf
MySQL 数据库会以读取到的最后一个配置文件中的参数为准。 在 Linux 环境下, 配置文件一般放在/etc/my.cnf 下。
-
配置文件中有一个参数 datadir, 该参数指定了数据库所在的路径。 在 Linux 操作系统下默认 datadir 为 /usr/local/mysql/data, .
mysql>SHOW VARIABLES LIKE • datadir,\G; #可以查看该变量
1.2 MySQL体系结构
从概念上来说, 数据库是文件的集合依照某种数据模型组织起来并存放于二级存储器中的数据集合 ; 数据库实例是程序是位于用户与操作系统之间的一层数据管理软件,用户对数据库数据的任何操作,包括数据
库定义、 数据査询、 数据维护、 数据库运行控制等都是在数据库实例下进行的, 应用程序只有通过数据库实例才能和数据库打交道。
可以发现, MySQL 由以下几部分组成:
□ 连接池组件
□ 管理服务和工具组件
□ SQL 接口组件
□ 査询分析器组件
□ 优化器组件
□ 缓冲 (Cache) 组件
□ 插件式存储引擎
□ 物理文件
需要特别注意的是, 存储引擎是基于表的, 而不是数据库。
1.3 MySQL存储引擎
由于 MySQL 数据库的开源特性, 用户可以根据 MySQL 预定义的存储引擎接口编写自己的存储引擎。
由于 MySQL 数据库开源特性, 存储引擎可以分为 MySQL 官方存储引擎和第三方存储引擎。 有些第三方存储引擎很强大, 如大名鼎鼎的 InnoDB 存储引擎( 最早是第三方存储引擎, 后被 Oracle 收购),
1.3.1 InnoDB 存储引擎
InnoDB 存储引擎支持事务, 其设计目标主要面向在线事务处理(OLTP) 的应用。其特点是行锁设计、 支持外键, 并支持类似于 Oracle 的非锁定读, 即默认读取操作不会产生锁。 从 MySQL 数据库 5.5.8 版本开始, InnoDB 存储引擎是默认的存储引擎。
InnoDB 存储引擎将数据放在一个逻辑的表空间中, 这个表空间就像黑盒一样由InnoDB 存储引擎自身进行管理。 从 MySQL 4.1 (包括 4.1 ) 版本开始, 它可以将每个InnoDB 存储引擎的表单独存放到一个独立的 ibd 文件中。 此外, InnoDB 存储引擎支持用裸设备( rowdisk) 用来建立其表空间。
InnoDB 通过使用多版本并发控制( MVCC) 来获得高并发性, 并且实现了 SQL标准的 4 种隔离级别, 默认为 REPEATABLE 级别。 同时, 使用一种被称为 next-keylocking 的策略来避免幻读( phantom ) 现象的产生。 除此之外, InnoDB 储存引擎还提供了插人缓冲( insert buffer)、 二次写( double write)、 自适应哈希索引( adaptive hash index)、 预读( read ahead ) 等高性能和高可用的功能。
对于表中数据的存储, InnoDB 存储引擎采用了聚集( clustered) 的方式, 因此每张表的存储都是按主键的顺序进行存放。 如果没有显式地在表定义时指定主键, InnoDB 存储引擎会为每一行生成一个 6 字节的 ROWID, 并以此作为主键。
1.3.2 MylSAM 存储引擎
MylSAM 存储引擎不支持事务、 表锁设计, 支持全文索引, 主要面向一些 OLAP数据库应用。 在 MySQL 5.5.8 版本之前 MylSAM 存储引擎是默认的存储引擎( 除Windows 版本外)。 数据库系统与文件系统很大的一个不同之处在于对事务的支持, 然而 MylSAM 存储引擎是不支持事务的。 究其根本, 这也不是很难理解。 试想用户是否在所有的应用中都需要事务呢? 在数据仓库中, 如果没有 ETL 这些操作, 只是简单的报表査询是否还需要事务的支持呢?
此外, MylSAM 存储引擎的另一个与众不同的地方是它的缓冲池只缓存 (cache) 索引文件, 而不缓冲数据文件, 这点和大多数的数据库都非常
不同。
MylSAM 存储引擎表由 MYD 和 MYI 组成, MYD 用来存放数据文件, MYI 用来存放索引文件。 可以通过使用 myisampack 工具来进一步压缩数据文件, 因为 myisampack工具使用赫夫曼( Huffman) 编码静态算法来压缩数据, 因此使用 myisampack 工具压缩后的表是只读的, 当然用户也可以通过 myisampack 来解压数据文件。
在 MySQL 5.0 版本之前, MylSAM 默认支持的表大小为 4GB, 如果需要支持大于 4GB 的 MylSAM 表时, 则需要制定 MAX_ROWS 和 AVG_ROW_LENGTH 属性。 从MySQL 5.0 版本开始, MylSAM 默认支持 256TB 的单表数据, 这足够满足一般应用需求。
1.3.3 NDB 存储引擎
NDB NDB 存储引擎是一个集群存储引擎 。NDB 的特点是数据全部放在内存中 (MySQL5.1后,非索引数据放在磁盘),因此通过主键查找极快。
NDB 存储引擎的连接操作(JOIN) 是在 MySQL 数据库层完成的, 而不是在存储引擎层完成的。 这意味着, 复杂的连接操作需要巨大的网络开销, 因此査询速度很慢。
1.3.4 Memory 存储引擎
Memory 存储引擎( 之前称 HEAP 存储引擎) 将表中的数据存放在内存中, 如果数据库重启或发生崩溃, 表中的数据都将消失。 它非常适合用于存储临时数据的临时表,以及数据仓库中的纬度表。 Memory 存储引擎默认使用哈希索引, 而不是我们熟悉的 B十树索引。
虽然 Memory 存储引擎速度非常快, 但在使用上还是有一定的限制。 比如, 只支持表锁, 并发性能较差, 并且不支持 TEXT 和 BLOB 列类型。 最重要的是, 存储变长字段(varchar) 时是按照定常字段(char) 的方式进行的, 因此会浪费内存(这个问题之前已经提到, eBay 的工程师 Igor Chernyshev 已经给出了 patch 解决方案)。
此外有一点容易被忽视, MySQL 数据库使用 Memory 存储引擎作为临时表来存放査询的中间结果集( intermediate result)。 如果中间结果集大于 Memory 存储引擎表的容量设置, 又或者中间结果含有 TEXT 或 BLOB 列类型字段, 则 MySQL 数据库会把其转换到 MylSAM 存储引擎表而存放到磁盘中。 之前提到 MylSAM 不缓存数据文件, 因此这时产生的临时表的性能对于査询会有损失。
。。。
1.4 各存储引擎之间的比较
MySQL 的官方手册, 展现了 一些常用 MySQL 存储引擎之间的不同之处, 包括存储容量的限制、 事务支持、 锁的粒度、 MVCC 支持、 支持的索引、 备份和复制等。
SHOW ENGINES 语句査看当前使用的 MySQL 数据库所支持的存储引擎
1.5 连接 MySQL
连接 MySQL 操作是一个连接进程和 MySQL 数据库实例进行通信 。本质上是进程通信。
1.5.1 TCP/IP
这种方式在 TCP/IP 连接上建立一个基于网络的连接请求, 一
般情况下客户端( client) 在一台服务器上, 而 MySQL 实例( server) 在另一台服务器上, 这两台机器通过一个 TCP/IP 网络连接。 例如用户可以在 Windows 服务器下请求一台远程 Linux 服务器下的 MySQL 实例, 如下所示:
C:\>mysql -h192.168.0.101 -u root -P
在通过 TCP/IP 连接到 MySQL 实例时, MySQL 数据库会先检
查一张权限视图, 用来判断发起请求的客户端 IP 是否允许连接到 MySQL 实例。 该视图在 mysql 架构下, 表名为 user, 如下所示
mysql>USE mysql;
Database changed
mysql>SELECT host,user,password FROM user;
***1 .row***
host: 192.168.24.%
user: root
password: *75DBD4FA548120B54FE693006C41AA9A16DE8FBE
*** 2• row***
host: nineyouO-43
user: root
password: *75DBD4FA548120B54FE693006C41AA9A16DE8FBE
*** 3.row* *
host: 127•0.0.1
user: root
password: *75DBD4FA548120B54FE693006C41AA9A16DE8FBE
*** 4.row ***
host: 192.168.0.100
user: z l m
password: *DAE0939275CC7CD8E0293812A31735DA9CF0953C
* * 5 • row* *
host: %
user: david
password:
5 rows in set (0.00 sec)
从这张权限表中可以看到, MySQL 允许 david 这个用户在任何 IP 段下连接该实例,并且不需要密码。 此外, 还给出了 root 用户在各个网段下的访问控制权限。
1.5.2 命名管道和共享内存
在 MySQL 数据库中须在配置文件中启用-enable-named-pipe 选项。
在 MySQL 4.1 之后的版本中, MySQL 还提供了共享内存的连接方式, 这是通过在配置文件中添加-shared-memory 实现的。 如果想使用共享内存的方式, 在连接时, MySQL 客户端还必须使用-protocol=memory 选项。
1.5.3 UNIX 域套接字
在 Linux 和 UNIX 环境下, 还可以使用 UNIX 域套接字。 UNIX 域套接字其实不是一个网络协议, 所以只能在 MySQL 客户端和数据库实例在一台服务器上的情况下使用。
用户可以在配置文件中指定套接字文件的路径, 如--sockeh=/tmp/mysql.sock
。 当数据库实例启动后, 用户可以通过下列命令来进行 UNIX 域套接字文件的査找 :
mysql>SHOW VARIABLES LIKE 1socket 1;
Variable_name: socket
Value: /tmp/mysql.sock
1 row in set (0.00 sec)
在知道了 UNIX 域套接字文件的路径后, 就可以使用该方式进行连接了, 如下所示:
[root@stargazer~] # mysql -udavid -S /tmp/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 20333
Server version: 5.0.77-log MySQL Community Server (GPL)
Type 'help' or '\h' for help.Type 1 '\c' to clear the buffer.
mysql>