MySQL 简介

MySQL 的历史可以追溯到 1979 年,当时开发 MySQL 的公司 TcX 开始从事数据库程序。第一个版本是用 BASIC 编写的屏幕构建器/报告工具。当时,最先进的计算机拥有 4MHz Z80 处理器和 16KB 的 RAM。这个工具被移植到 UNIX,并在随后的几年中得到进一步开发。在 20 世纪 90 年代中期,我们开始遇到客户问题,他们喜欢该工具产生的结果,但想要一些他们以前听说过的东西(需要一个流行词)。因此,我们开始考虑为我们的底层库制作一个 SQL(一个合适的流行词)前端。我们找到了 mSQL,但它不适用于我们的目的。因此,我们开始从头开始编写一个 SQL 引擎。然而,由于 mSQL API 非常有用,我们将其用作我们自己 API 的基础。这使得移植我们需要的某些可用于 mSQL API 的应用程序变得容易。
由于这个工具可以被其他人使用,我们决定根据 Peter Deutsch 在 Aladdin Enterprises 使用 Ghostscript 开创的商业模式发布它。这个版权比 mSQL 版权自由得多,并允许商业用途,只要您不以商业方式分发 MySQL 服务器。
MySQL 名称的由来并不完全清楚。自 20 世纪 80 年代中期以来,我们一直将前缀“my”用于库和路径名。MySQL 主要开发人员的女儿名叫 My——在说瑞典语的芬兰人中,这是一个相当常见的名字——因此将我们的数据库命名为 MySQL 非常自然。
1996 年 5 月,MySQL 1.0 版本发布给一个有限的四人小组,1996 年 10 月,MySQL 3.11.1 版本作为 Solaris 的二进制发行版公开发布。一个月后,发布了 Linux 二进制文件和源代码发行版。MySQL 发行版包括源代码形式的 ODBC 驱动程序。其中还包括许多移植到 MySQL 的免费 MySQL 客户端。
MySQL 的初始版本仅在 Linux 和 Solaris 上运行。移植到其他平台的最大问题是 MySQL 需要一个可用的 POSIX 线程库;1997 年 1 月,MIT-pthreads 的修改版本包含在发行版中。
为了能够从您喜欢的语言中使用 MySQL,您需要一个 API。第一个 MySQL 版本仅包含 C 和 Perl API。现在有很多(见表 2)。除了 Java API 之外,所有这些都使用 C API 与 MySQL 服务器通信。因此,正如您所看到的,MySQL 可以从许多流行的语言中使用。
当我们获得一个不错的可用系统时,我们想针对旧版本和其他数据库对其进行测试,因此我们开始寻找好的基准测试。我们发现大多数基准测试(如 TCP 基准测试)将 SQL 服务器的性能表示为单个数字,通常为每秒事务数。我们认为这些几乎毫无价值,因为相对较少的用户运行与这些基准测试做相同事情的应用程序。通常无法从这种类型基准测试给出的数字中确定应用程序的性能。
MySQL 基准测试旨在展示 SQL 服务器对于常见操作(例如建立连接、执行简单插入或使用键连接两个表)的速度有多快。当您知道操作的混合时,这也可以计算网站上的负载。当然,您需要真正了解您自己的应用程序,才能使用任何数据库来判断其性能。
随着时间的推移,我们在 MySQL 邮件列表中收到了许多关于 MySQL 功能及其与其他数据库在功能方面如何比较的请求。由于 Michael(主要开发人员)不想深入研究旧的不准确的参考手册来找出这一点,他想到了一个程序,可以自动检测 SQL 服务器必须提供的功能。他还认为,当您开始向其发送“异常”查询时,这将是对 MySQL 代码稳定性的一个很好的测试。
在进行基准测试时,我们需要所有受支持数据库的功能列表。由于手动执行此操作 非常 繁琐,因此我们制作了一个工具来自动执行此操作。在某些不同的服务器上尝试此工具的早期版本时,发生了糟糕的事情——服务器崩溃了。所有这些崩溃导致我们将此工具命名为 crash-me。事实上,唯一通过此测试而没有崩溃的 SQL 服务器是 Oracle。当然,MySQL 中发现的所有错误都立即修复了。
crash-me(和基准测试)被实现为一个 Perl DBI/DBD 程序,它向数据库发送数千个查询,以找出事物在现实生活中的工作方式。通过这样做,它可以找到服务器中的许多限制,例如支持的列/查询/变量/索引长度。
crash-me 也是一个帮助您编写可移植 SQL 的好工具,因为它可以提供一个列表,其中列出了您希望使用的服务器中存在哪些函数、类型和限制。目前,我们有来自 Adabas-D、Access、DB2、Empress、Informix、MS-SQL、MySQL、Oracle、PostgreSQL、Solid 和 Sybase 的 crash-me 结果。由于 crash-me 表很大且非常详细,我们不会在此处包含它,但它可以在 https://mysqlserver.cn/crash-me-choose.htmy/ 找到。
基准测试测试哪些操作?首先也是最重要的,测试基本 SQL 操作:INSERT、UPDATE、DELETE 和 SELECT。其他测试包括连接后跟选择,以及创建表和索引。
各个测试应该很好地指示 SQL 服务器对于特定操作的速度有多快。不要使用“总时间”作为衡量 SQL 服务器价值的总体指标。这是因为测试没有相互加权。某些测试使用不同的选项和行数运行更多次。SQL 服务器可能在某些“不重要的事情”上非常糟糕,但在您实际打算使用它的事情上却非常好。
我们使用总时间来比较同一数据库引擎在不同操作系统上的运行情况。我们还使用它来查看新版本的 MySQL 与旧版本相比如何。
由于所有基准测试表都比 crash-me 结果占用更多空间,因此我们仅包含关于 MySQL 在不同平台上运行良好的少量观察结果。
在多 CPU 机器上,Linux 2.2 比 Linux 2.0 快得多。这是因为 Perl 和 MySQL 服务器在不同的处理器上运行,并且新的 SMP 代码更快。
在同一台机器上,Linux 比 Windows 98 快 7%,比 NT 快 49%。
在同一台机器上,Windows 98 比 NT 快 27%。
运行 Linux 2.2 的 Pentium II 400MHz 机器比运行 Solaris 2.7 的 Sun Ultrasparc 2/CPU 400MHz 机器快得多。造成这种差异的主要原因是 Linux 比 Solaris 更好地缓存文件系统;在高负载下,此结果可能会有所不同。我们将在下一代基准测试中包含线程测试,以测试此类情况。
如果您在 Solaris 上执行许多插入操作,则将处理器速度提高 100% 只会获得 22% 的速度提升。
使用 MyODBC 以及可能的任何 ODBC 驱动程序的开销至少为 19%。
请注意,在进行基准测试时,仍然可以在 Linux 机器上工作而没有任何问题。但是,NT 变得非常慢,以至于无法进行任何其他工作,甚至简单的编辑。启动一个新的 DOS 窗口大约需要 30 倍的时间,并且我们必须等待 10 秒左右,键入的字符才会显示出来。
对于 crash-me 和基准测试,还有许多事情要做。例如,我们希望 crash-me 报告是否存在执行相同操作的相同函数(例如,代替 CONCAT 可以使用“||”)。此外,应添加许多新测试来测试 SQL 服务器允许哪些子选择构造。当然,文档和结果的呈现方式可以大大改进。
这两个工具都为使用多个 SQL 服务器的任何开发人员提供了宝贵的信息。如果它们没有测试您需要的功能,请贡献一个新的测试。更多测试结果可以在 www.mysql.com/benchmark.html 找到。
如果您查看上面的基准测试页面,您会注意到 MySQL 在几乎所有方面都比竞争对手快很多倍。为什么会这样?一些速度来自 MySQL 中不支持的功能,例如事务、外键和触发器。
由于 MySQL 服务器主要由一位具有多年编码经验的人员编码,因此其中冗余代码很少。大多数基本算法也来自 CPU 速度慢且内存量小的时代。这些算法主要已扩展为在可用内存的情况下使用更大的缓存。
因此,MySQL 具有紧凑快速的设计(服务器的代码大小在 i386 上小于 1MB),通常使用非常少的内存,但可以配置为利用大量内存。
MySQL 有许多有用的优化,可实现最大速度。一些例子是
大多数连接都在一次扫描中完成。
很少有正常连接需要临时表。涉及 GROUP BY 和 ORDER BY(在 GROUP BY 部分之外的其他内容上)的连接将创建一个(通常是基于内存的)临时表。
基于内存的临时表具有动态哈希。
MySQL 具有用户可配置的键缓存和记录缓存,可快速扫描表。打开的表缓存在表缓存中。
索引优化器快速找到要用于特定 WHERE 子句的可能索引。
范围优化器查找索引的范围,然后将该范围用于查找匹配的行。范围优化器可以优化在键列上使用 >=、>、=、<=、< 和 LIKE(类型为“keyword%”)的查询。当可以使用多个可能的索引时,范围优化器将选择与最小行数匹配的索引。
连接优化器以最佳顺序重新排列 SELECT 语句中的表。在极少数情况下,MySQL 连接优化器出错,可以使用 STRAIGHT_JOIN 关键字强制优化器以特定顺序连接表。
对于每个子连接,都会构造一个简单的 WHERE,以便为每个子连接获得快速的 WHERE 评估,并尽快跳过记录。
WHERE 优化器删除常量条件。
早期检测会发现无效的常量表达式。MySQL 快速检测到某些 SELECT 语句是不可能的,并且不返回任何行。
SQL 函数通过高度优化的类库实现。几乎所有解析和计算都在本地内存存储中完成。小项不需要内存开销,并且避免了正常的慢速内存分配和释放。仅通过使用 malloc 和 free 为意外的大字符串分配内存。
在类型为
SELECT ... WHERE col IN (a,b,c,d,e,f,...)
的查询中,IN 部分被排序并通过二分查找进行检查。
索引列上的 MIN/MAX 是通过一次键获取完成的。当一个人在 WHERE 条件中指定了所有前面的索引列时,MIN/MAX 优化器也可以找到最佳值
SELECT MAX(index_part2) FROM tbl_name WHERE index_part_1=constant;
没有 WHERE 的单个表上的 COUNT(*) 直接从表信息中检索。
如果某些表的所有使用的列都是数字并且构成某个键的最左前缀,则可以从索引树而不是数据文件中检索这些值,以获得更快的速度。
索引用于查找与以下项匹配的行
WHERE index_column LIKE "prefix%".
GROUP BY 和 DISTINCT 通过创建临时 HEAP 表(以 GROUP BY(或整行)作为唯一索引)来优化。
INSERT DELAYED 将行插入到 SQL 服务器的队列中,如果您使用 MySQL 进行日志记录并且无法承受等待 INSERT 完成,这将非常有用。
索引压缩用于获得更小更快的索引。
导致最多问题的设计决策之一是缺少事务。当然,有些应用程序需要事务才能工作,但范围广泛的应用程序在没有事务的情况下也能很好地工作。
有些人认为,由于 MySQL 不支持事务,因此它无法支持许多并发用户。每个 MySQL 客户端都在 MySQL 服务器中获得一个专用线程,这允许不同的用户同时访问相同的表。所有 MySQL 操作都是原子性的:没有其他用户可以更改正在运行的查询的结果。
在设计 MySQL 时,我们对速度的需求大于对事务的需求。如果 SQL 服务器变得如此缓慢,以至于无法用于您需要完成的工作,那么拥有事务是毫无用处的。
另一个常见的误解是事务通过重做日志提供额外的健壮性。通过 MySQL 中的简单方法可以获得额外的安全性。也就是说,进行正常备份,然后将更新日志应用于备份。更新日志是一个包含所有更改任何数据的 SQL 语句的文件。
MySQL 还具有外部实用程序程序来检查、优化和修复单个表。
由于 MySQL 在全球拥有约 50 个镜像站点,并且我们没有从它们那里获得下载统计信息,因此很难说有多少 MySQL 安装。
https://mysqlserver.cn/ 的 WWW 和 FTP 日志为我们提供了表 3 和表 4 中显示的信息;所有计数均基于不同的 IP 数量。
在 Linux 社区中,许多站点使用 MySQL 作为动态网页的后端。其中包括 http://slashdot.org/、http://freshmeat.net/ 和 http://www.linux.com/。
在 linux.com 上,每个页面都会对数据库执行 10 到 20 个查询。并且 linux.com 每天的页面浏览量在 50 万到 80 万之间。他们在自己的服务器(一台双 Xeon 系统,具有大量 RAM 和硬盘空间)上运行 MySQL。
在撰写本文时,我询问了 Linux Journal 他们使用什么作为 Web 后端,并得知他们也使用 MySQL。在我们获得的奖项中,我们非常重视 Linux Journal 读者授予我们的 1998 年“最常用数据库”奖。
客户端/服务器
多线程、多用户且非常快速
许多不同语言的 API
一个好的、免费的 ODBC 驱动程序
非常便携
许多不同的列类型,支持所有 ANSI 92 和所有 ODBC 2.50 类型以及一些新的类型
支持几乎所有 ODBC 3.0 和 SQL ANSI92 函数
完全支持 SQL GROUP BY 和 ORDER BY 子句;支持组函数(COUNT、AVG、STD、SUM、MAX 和 MIN)
能够在同一查询中混合来自不同数据库的表
非常灵活的权限系统,其中权限基于主机和用户
支持使用 ANSI SQL 和 ODBC 语法的 LEFT OUTER JOIN
定长和变长记录
处理大型数据库;在 TcX,我们正在使用 MySQL,其中一些数据库包含超过 5000 万条记录。
非常健壮,没有内存泄漏;所有报告的内存泄漏都在非 MySQL 库中,最值得注意的是某些版本的 glibc。
能够配置许多不同的字符集,例如,日语/中文
提供多种语言的错误消息
许多实用程序和大量贡献的软件
MySQL 具有广泛的文档记录。大多数问题可以通过阅读 MySQL 手册来解决。我们尝试记录 所有内容,以避免在 MySQL 邮件列表中收到太多问题。当前的 手册最近得到了很大改进,这要归功于 Paul DuBois 的出色工作。
许多小的、非常有用的扩展,可帮助您完成工作
二进制可移植表格式——现在可以在不同的架构之间复制 MySQL 表文件。
更多和更长的索引——最大值为 32,长度可达 500 字节(以前为 16/128)。
更好的索引压缩——它更快并且使用更少的磁盘空间。
BLOB/TEXT 列上的索引,就像 CHAR 列一样。
支持文件系统上大于 4GB 的表,这些文件系统支持如此大的文件。新的限制约为 900 万 TB。
对于动态行格式,具有更好的碎片处理。
添加了具有哈希键的内存中表——一种拥有查找表的极快方法。
允许使用真实浮点列,其值如 1.0E+10。
包括示例 C 代码,用于分析 SELECT 结果的过程。
添加了更快的 SELECT DISTINCT 处理。
在 SHOW TABLE STATUS 中添加了许多有用的信息。
CREATE TABLE (...) SELECT * from a,c where something。这在一个步骤中使用来自 SELECT 的数据创建表。数据类型和字段名称从 SELECT 自动生成。
删除了旧的限制,即大的 GROUP BY 查询(使用 SQL_BIG_TABLES=0)导致“表已满”错误。
使用 LOAD_FILE 函数从文件加载 BLOBS。
支持 COUNT(DISTINCT)。
我们无意停止 MySQL 的开发。随着时间的推移,MySQL 将 100% 兼容 ANSI 92。由于我们仍然希望 MySQL 快速,我们将始终为用户提供指定删除使普通 SQL 服务器变慢的功能的选项。
例如,GRANT 系统不会对速度产生任何影响,除非您使用它来限制表或列访问。
当前的“TODO”列表可以在 MySQL 手册 www.mysql.com/doc.html 中找到。此列表中的所有内容都按照我们计划实现的顺序排列。
我们使用 GNU/BSD 和来自网络的其他程序工作了很多年,并且一直认为程序应该以源代码形式提供。因此,我们选择对 UNIX 上的 MySQL 服务器使用与 Aladdin GhostScript 相同的许可证,并且我们使客户端完全免费。
到本文发表时,应该有一个带有 GPL 版权的旧版本 MySQL (3.20) 可用。我们将继续在 GPL 下发布旧版本。
这意味着对于 UNIX 系统上的正常(甚至商业)内部使用,MySQL 不收取任何费用。如果您不想,则无需向我们付款。仅在以下情况下才需要许可证
您直接或作为另一产品或服务的一部分销售 MySQL 服务器。
您为在某些客户站点安装和维护 MySQL 服务器收费。
您将 MySQL 包含在不可再发行的发行版中,并且您为该发行版的某些部分收费。
您在 Win32(Windows 95、98、NT 或 Windows 2000)系统上使用 MySQL。
对于需要 MySQL 许可证的情况,每台运行 mysqld 服务器的机器都需要一个许可证。但是,多 CPU 机器只需要一个许可证,并且对可以在一台机器上运行的 MySQL 服务器数量或并发连接到在该机器上运行的服务器的客户端数量没有限制。
以下几点阐述了我们许可政策背后的理念
SQL 客户端库应该是完全免费的,以便它可以不受限制地包含在商业产品中。
想要免费访问我们投入大量工作的软件的人可以拥有它,只要他们不试图通过直接分发它来牟利。
想要保留自己的软件专有权,但也想要从我们的工作中获得价值的人,可以付费获得特权。
这意味着正常的内部使用是 免费的。但是,如果您将 MySQL 用于对您重要的用途,您可能希望通过购买支持合同或贡献文档、代码示例或其他内容来帮助进一步开发它。
我们的政策是,任何人都无需为正常升级付费。将来,我们可能会要求对具有主要新功能(如事务支持)的重大升级使用新许可证。这意味着从长远来看,与其他数据库相比,MySQL 将是一项非常好的投资。
由于 Win32 是一个高度商业化的操作系统,具有非常高的开发成本(和开发痛苦),因此我们认为除了仅向付费客户、以某种方式帮助过我们 MySQL 的用户或认为他们可以为 MySQL 的任何部分做出贡献的用户提供 MySQL-Win32 之外,别无选择。如果我们以任何其他方式这样做,我们将无法负担得起继续在 Win32 上开发 MySQL,甚至无法使此版本与 UNIX 版本保持同步。实际上,我们让运行 Win32 的用户为我们的其他操作系统的工具的开发付费。
David Axmark (david@detron.se) 与他的植物和计算机一起住在瑞典乌普萨拉。他担任软件顾问已有 15 年以上。
Michael Widenius 与他的妻子和他的两个孩子 My 和 Max 一起住在芬兰赫尔辛福斯。他也担任软件顾问已有 15 年以上。
两位作者从事过的项目包括:电力公司使用的一卡通计算机软件、视频租赁系统、最先进的市场研究系统、高级商业图形、可以处理 Z80 汇编程序+Basic 的文字处理器、8 位计算机 (Z80) 的完整操作系统以及许多其他项目。