精通 PHPMyAdmin 3.4 高效 MySQL 管理(三)
原文:
zh.annas-archive.org/md5/3B102B7D75B6F6D265E7C3CE6613ECC1译者:飞龙
第十二章:生成多表查询
“数据库”或“表”视图中的搜索页面适用于单表查找。本章介绍了“数据库”视图中可用的多表**查询示例(QBE)**功能。
许多 phpMyAdmin 用户在“表”视图中逐个表地工作,因此往往忽视了多表查询生成器,这是一个用于微调查询的精彩功能。查询生成器不仅在多表情况下有用,也在单表情况下有用。它使我们能够为列指定多个条件,这是“表”视图中的搜索页面所不具备的功能。
注意
本章的示例假定已经进行了 phpMyAdmin 配置存储的多用户安装(参见第一章),并且在第九章的练习中创建的book-copy表仍然存在于marc_book数据库中。
要打开此功能的页面,我们转到特定数据库的“数据库”视图(查询生成器一次只支持对一个数据库的操作),然后点击查询。
以下屏幕截图显示了初始的 QBE 页面。它包含以下元素:
-
可视化构建器链接(本章末尾介绍)
-
条件列
-
添加条件行的界面
-
添加条件列的界面
-
表选择器
-
查询区域
-
更新或执行查询的按钮
选择表
初始选择包括所有表。因此,列选择器包含大量列。对于我们的示例,我们将仅使用author和book表。因此,我们只从使用表选择器中选择这两个。
然后我们点击更新查询按钮。这将刷新屏幕并减少列选择器中可用的列数。我们可以随时使用浏览器的多选机制(通常是控制点击)后来更改所选的表。
探索列条件
默认情况下提供了三个条件列。本节讨论了我们编辑它们的条件的选项。这些选项包括选择列、对单个列进行排序、输入单个列的条件等。
列选择器:单列或所有列
列选择器包含所选表的所有单独列,以及以星号(*)结尾的特殊选择,表示选择了所有列。
要显示author表中的所有列,我们会选择**author并勾选显示复选框,而不在排序和条件框中输入任何内容。在我们的情况下,我们选择author.name**,因为我们想为作者的姓名输入一些条件。
排序列
对于每个选定的单独列,我们可以指定排序(升序或降序),或让该行保持不变(无排序,这是默认行为)。如果我们选择了多个排序列,排序将从左到右进行。
注意
当我们要求对列进行排序时,通常会勾选显示复选框。但这并非必需,因为我们可能只想进行排序操作而不显示该列。
显示列
我们勾选Show复选框,以便在结果中看到该列。有时,我们可能只想在列上应用一个条件,而不包括它在结果页面中。在这里,我们添加了phone列,要求对其进行排序,并选择同时显示姓名和电话号码。我们还要求按照姓名的升序进行排序。如果姓名相同,则首先按姓名排序,然后按电话号码排序。这是因为姓名在左侧的列条件中,因此具有更高的优先级。
更新查询
在任何时候,我们都可以点击Update Query按钮来查看我们生成的查询的进展。在执行查询之前,我们必须至少点击一次。现在,让我们点击它,看看在查询区域生成的查询。在接下来的示例中,我们将在每次修改后点击Update Query按钮。
我们已经选择了两个表,但尚未从book表中选择任何列。因此,生成的查询中没有提到这个表。
向条件框添加条件
在Criteria框中,我们可以为每个相应的列输入一个条件(遵守 SQL WHERE子句的语法)。默认情况下,我们有两行条件。为了找到所有名字中带有Smith的作者,我们使用LIKE条件**(LIKE '%SMITH%')并点击Update Query**。
我们还有另一行可用于输入额外的条件。假设我们想要找到作者Maria Sunshine。这次,我们使用**=条件。两个条件行将由默认从界面左侧选择的Or**运算符连接。
为了更好地展示Or运算符如何连接两个条件行,让我们现在在电话号码上添加一个条件LIKE '%8%',如下截图所示:
通过检查AND和OR运算符的定位,我们可以看到条件的第一行是由AND(因为在name列下选择了AND)运算符连接的,而条件的第二行是由OR运算符连接的。我们刚刚添加的条件**'(LIKE %8%)**并不是为了找到任何人,因为我们已经将所有名为“Smith”的作者的电话号码更改为“444-5555”(在第十一章中)。
如果我们想在同一列上添加另一个条件,我们只需添加一个条件行。
调整条件行的数量
条件行的数量可以通过两种方式进行更改。首先,我们可以在Criteria下选择Ins复选框来添加一个条件行(在点击Update Query后)。由于此复选框一次只能添加一行条件,因此我们将取消选中它,然后使用Add/Delete criteria rows对话框。在此对话框中,我们选择添加两行。
再次点击Update Query按钮会产生以下屏幕:
现在,您可以看到有两行额外的条件(目前为空)。我们也可以删除条件行。这可以通过在我们要删除的行旁边勾选Del复选框来完成。让我们删除刚刚添加的两行,因为我们现在不需要它们。Update Query按钮将根据指定的调整刷新页面。
调整条件列的数量
使用类似的机制,我们可以通过在修改对话框中的每列下方的插入或删除复选框,或者添加/删除列对话框来添加或删除列。我们已经有一个未使用的列(在前面的图像中未显示)。在这里,我们使用了位于未使用列下方的插入复选框添加了一列(这次我们将需要它):
生成自动连接(内部关系)
phpMyAdmin 可以生成查询中表之间的连接,前提是已经定义了内部关系。现在让我们用我们book表的title和genre列填充我们的两个未使用的列,看看当我们更新查询时会发生什么。
现在有两个与**book.title和book.genre列相关的额外条件列。phpMyAdmin 利用其对表之间定义的关系的知识生成了一个LEFT JOIN子句(在上面的屏幕截图中突出显示),该子句在author_id**关键列上。当前版本的一个缺点是只检查了内部关系,而没有检查InnoDB关系。
注意
可能涉及到多于两个表的连接。
执行查询
单击提交查询按钮发送查询以执行。在下面的屏幕截图中,您可以看到上部的完整生成的查询,以及下部的结果数据行:
在我们提交查询后,除了使用浏览器的返回按钮之外,没有简单的方法返回到查询生成页面。第十四章讨论了如何保存生成的查询以供以后执行。
可视化生成器
从 3.4 版本开始,提供了另一种查询构建方法。它利用了Designer界面,可能更熟悉于用户,将查询生成与其结合起来。我们可以通过单击切换到可视化生成器链接来打开此界面,这将产生一个初始屏幕,如下面的屏幕截图所示:
我们现在应该通过单击全部展开/收起图标来打开所有表的列列表。
每列都有一个左侧复选框和一个右侧选项图标。复选框用于指示我们希望成为结果的哪一列;而选项图标允许打开一个面板,在面板中我们将指定要应用于此列的条件。例如,如果我们想选择超过 200 页的书,我们将单击page_count列旁边的选项图标,并填写条件对话框,如下面的屏幕截图所示:
单击确定保存此查询选项;现在它可以在右侧的活动选项对话框下找到,如果需要查看或删除选项。
为了构建查询,我们使用构建查询图标,生成一个如下屏幕截图所示的屏幕:
此时,我们要么使用附加选项来完善查询,要么单击提交查询以获取结果。
摘要
本章涵盖了包括打开查询生成器、选择表、输入列条件、排序和显示列、修改条件行或列的数量等各种方面。我们还学习了如何使用AND和OR运算符来定义行和列之间的关系,以及如何在表之间使用自动连接。Designer集成的可视化查询生成器也被介绍了。
下一章将向您展示如何在服务器之间同步数据以及如何管理复制。
第十三章:同步数据和支持复制
在本章中,我们将介绍 phpMyAdmin 3.3.0 版本中发布的两个功能。第一个功能是同步数据库的能力,这是开发人员要求的,他们在多个服务器上工作。第二个功能允许管理 MySQL 复制,在性能和数据安全性重要的环境中使用。这些功能有些相关,因为在设置复制过程时,通常需要将数据库同步到从服务器。
同步数据和结构
在较早的 phpMyAdmin 版本中,可以在同一服务器或不同服务器上的两个数据库之间实现一些结构和数据的同步,但这需要手动操作。可以从一个数据库导出结构和/或数据,然后导入到另一个数据库。我们甚至可以直观地比较两个表的结构,并根据需要进行调整。然而,必须由开发人员自己用眼睛比较两个数据库以确定需要导入的内容。此外,数据库之间的结构差异没有被考虑在内,可能导致目标表中缺少列时出现错误。
phpMyAdmin 的同步功能非常灵活,通过处理初始比较过程,当然也通过执行同步本身。我们将首先讨论同步的原因,然后检查并实验涉及的所有步骤。
同步的目标
尽管想要同步两个数据库的原因可能很多,但我们可以将它们分为以下几类。
在开发和生产服务器之间移动
一个良好的数据库开发策略包括在与生产服务器不同的服务器上进行开发和测试。如果没有单独的开发服务器,至少鼓励使用单独的开发数据库。随着时间的推移,测试和生产环境之间的结构差异会积累,这是正常的。例如,测试版本可能会添加一个列,或者字符列可能会被扩大。同步功能允许我们首先查看差异,然后根据需要将其应用到生产环境。
有时需要以相反的方式移动数据,例如,为了衡量性能而将真实生产数据填充到测试数据库中。
数据库设计师之间的协作
由于 MySQL 测试服务器可以轻松设置,可能会出现这样的情况,即开发团队的每个成员都有自己的服务器(或自己的数据库副本),在其中开发项目的某个方面。当需要协调每个人对同一表的更改时,同步功能是非常宝贵的。
为复制做准备
MySQL 支持主服务器和一个或多个从服务器之间的异步复制。这种数据复制被称为“异步”,因为主服务器和从服务器之间的连接不需要是永久的。然而,要启动复制过程(假设主服务器已经包含一些数据),就需要将所有数据复制到从服务器上。MySQL 手册中提供了一个完成此复制的建议,可以在dev.mysql.com/doc/refman/5.1/en/replication-howto.html找到,如下所述:
“如果您的主服务器已经有数据,并且您想使用它来同步您的从服务器,您需要创建一个数据快照。您可以使用mysqldump来创建一个快照(...)”
然而,这需要使用一个命令行工具,这取决于托管选项并不总是可能的。此外,数据库的某些部分可能已经存在于从属数据库;因此,同步功能非常方便,因为它集成到了 phpMyAdmin 中,并且它负责比较阶段。
查看同步过程
重要的原则是同步是从源数据库到目标数据库完成的。在此操作期间,源数据库保持不变。我们需要正确识别哪个数据库是源数据库,哪个是目标数据库(可能会被修改)。
整个过程被细分为可以在任何阶段停止的步骤:
-
服务器和数据库选择
-
比较
-
完整或选择性同步
我们可以选择出于以下原因之一停止该过程:
-
我们没有连接到其中一个服务器所需的凭据
-
我们发现两个数据库之间存在差异,并且还没有准备好进行同步,因为需要进一步研究
-
我们在比较阶段之后注意到目标数据库已经充分同步
在执行同步之前,我们将准备好必要的元素。
为同步练习做准备
由于我们只会操作author和book表,因此本练习将假定marc_book数据库中没有其他表。我们首先将marc_book数据库复制到marc_book_dev(有关如何执行此操作的确切方法,请参阅第九章)。然后我们打开marc_book_dev数据库并执行以下操作:
-
删除
book表 -
从
author表中删除一行 -
将
name列的类型从VARCHAR(30)更改为VARCHAR(29) -
从
author表中删除phone列
第五章介绍了如何执行前面的操作。
选择源和目标服务器和数据库
通过“服务器”视图中的同步菜单选项显示初始同步页面。请注意,这是唯一可以使用该菜单的地方。
第一个面板允许我们连接到服务器(如果需要)并选择正确的数据库。如果$cfg['AllowArbitraryServer']参数设置为其默认值false,则会出现以下面板:
这意味着我们只能使用在config.inc.php中已定义的服务器。如果允许任意服务器,则会看到一个不同的面板,如下面的截图所示:
对于源数据库和目标数据库,我们可以选择服务器位置。默认情况下,选择器放置在手动输入上,我们可以输入其主机名、端口、套接字名称、用户名、密码和数据库名称。在大多数情况下,端口应该保持默认的 3306,套接字名称应该保持为空。请注意,我们当前连接到一个 MySQL 服务器(通过正常的登录面板),这个面板可以让我们连接到另外两个服务器。
服务器位置的另一个选择是当前连接。这指的是我们连接的用于正常 phpMyAdmin 操作的服务器;其名称显示在主面板顶部。如果我们选择这个选项,启用 JavaScript 的浏览器会隐藏除了数据库名称之外的所有选项(在这种情况下,连接凭据是不必要的),并且会出现一个选择器,显示我们可以访问的所有数据库。
在源和目标两侧选择相同的服务器是完全可能的;然而,在这种情况下,我们至少会选择一个不同于目标的源数据库。另一个常见情况是选择当前服务器和某个数据库作为源,以及具有相同数据库的远程服务器作为目标,假设远程服务器是生产服务器,并且两个服务器都拥有同名的数据库。
在这个练习中,让我们为源和目标服务器都选择当前连接;然后我们可以选择marc_book作为源数据库,marc_book_dev作为目标数据库,如下面的截图所示:
点击Go后,phpMyAdmin 尝试连接服务器(如果需要)。此时可能会显示连接错误消息。但是,连接应该会成功,程序将开始比较两个数据库,然后显示结果。
分析比较结果
比较结果面板包含三个部分。第一部分显示了结构和数据的差异,并包含将用于启动选择性同步的图标:
如上部所示,红色的S图标触发结构同步,而绿色的D图标用于数据同步。然后,对于每个表,我们得到差异的摘要。在相应表的结构和数据相同的情况下,中央的差异列将为空。在这里,我们看到两个表的红色S和绿色D,但原因并不相同。
中部显示了作为同步过程一部分的计划操作(目前没有,如下面的截图所示):
下部包含一个复选框**(您是否要删除目标表中的所有先前行?)**和两个操作按钮。我们将在以下部分看到它们的用途:
请注意,书表在源一侧有一个加号(+),表示该表在源数据库中但不在目标数据库中。我们甚至在目标一侧看到了对该表的不存在注释。如果一个表在目标数据库中但不在源数据库中,它将在目标一侧标有减号(-)。
此时,我们可以决定我们对比较结果感到满意,不想继续进行;在这种情况下,我们只需在 phpMyAdmin 中选择一个数据库并恢复我们的工作。我们还有机会以一次性的方式同步数据库**(完整同步),或者以更细粒度的方式进行更改(选择性同步)**。让我们检查这两种方法。
执行完整同步
如果我们不想问自己太多问题,只需要完全同步,我们点击同步数据库。请注意,在这种情况下,我们不必使用任何红色的S或绿色的D图标。
注意
如果目标表中有一些行不在相应的源表中,这些行将保留在目标表中,除非我们勾选**是否要删除..**复选框。这是一个安全网,以避免意外数据丢失。但是,如果我们需要精确同步,我们应该选择此选项。
点击后,我们得到以下消息:目标数据库已与源数据库同步。在屏幕的下部,我们看到必须执行的查询以实现此操作。我们还得到了数据库现在已同步的视觉确认:
执行选择性同步
如果我们更喜欢更谨慎,并且想要对即将执行的操作进行初步反馈,我们可以同步选择的表。本节假设数据库的状态与为同步练习做准备部分结束时的状态相同,该部分在本章的前面部分已经涵盖。
如果我们点击描述author表的行上的红色S图标,这个S图标会变成灰色,屏幕中部会更新显示要执行的操作,如下面的截图所示:
实际上还没有对数据进行任何操作!我们仍然可以通过点击相同的图标来改变主意,这会使图中部分所示的建议更改消失,图标也会变回红色。
现在我们点击绿色的D图标,看到另一行建议的更改出现,如下面的截图所示:
author表中需要插入一行,因为目标数据库中少了一个作者。总共需要更新四行,因为我们在同一张表中删除了phone列。
现在我们可以点击应用所选更改按钮。**您想删除..**复选框不适用于此操作。
现在我们看到屏幕上部提出了更少的更改:
我们可以继续选择结构或数据更改,然后按照我们认为合适的顺序应用它们。
这结束了描述同步功能的部分。我们将继续介绍复制支持。
支持 MySQL 复制
在为复制做准备部分,我们看到了 MySQL 复制的概述。在本节中,我们将涵盖以下主题:
-
我们如何使用 phpMyAdmin 来配置复制
-
如何准备一个包含一个主服务器和两个从服务器的测试环境
-
如何发送命令来控制服务器
-
如何获取有关服务器、数据库和表的复制信息
phpMyAdmin 的界面提供了一个复制页面;然而,其他页面包含有关复制的信息或控制复制操作的链接。在涉及相关主题时,我们将指出每个适当的位置。
如何使用这一部分取决于我们手头有多少服务器。如果我们至少有两台服务器,并且想通过 phpMyAdmin 在主/从关系中配置它们,我们可以按照配置复制部分的步骤。如果我们只有一台服务器可以使用,那么我们应该从设置测试环境部分中获取建议,在同一台机器上安装多个 MySQL 服务器实例。
复制菜单
在服务器视图中,复制菜单只显示给特权用户,如 MySQL 根用户。当服务器已经配置为主服务器或从服务器(或两者兼有)时,复制页面用于显示状态信息并提供发送命令的链接。
配置复制
对于这个练习,我们假设服务器目前不占据主服务器或从服务器的角色。phpMyAdmin 不能直接配置 MySQL 复制的所有方面。原因是,与通过向 MySQL 服务器发送查询来操作数据库结构和数据不同,复制配置包括(部分)存储在 MySQL 配置文件中的命令行,通常命名为my.cnf。作为一个 Web 应用程序,phpMyAdmin 无法访问这个文件。这是 MySQL 服务器开发人员打算的配置方式——在配置文件级别上。
在这种情况下,phpMyAdmin 能做的最好的就是通过根据我们的偏好生成(在屏幕上)正确的命令行来指导我们,然后由我们将这些行复制到它们需要去的地方并重新启动服务器。phpMyAdmin 甚至不能读取当前的复制配置行;它只能通过一些SHOW命令推断服务器状态。
让我们进入“复制”菜单,看看会发生什么:
主服务器配置
现在我们选择通过点击适当的“配置”链接将服务器配置为主服务器。出现的面板给了我们详细的建议:
第一段确认了这个服务器目前没有配置为复制过程中的主服务器。我们想要实现这个配置,但首先我们需要考虑我们想要的复制类型。所有数据库都应该被复制,除了其中一些吗?还是我们想要相反的?一个方便的下拉列表为我们提供了这些选择:
-
复制所有数据库;忽略:
-
忽略所有数据库;复制:
第一个选择(默认)意味着一般情况下所有数据库都被复制;我们甚至不需要在配置文件中列举它们。在这种情况下,数据库选择器用于指定我们想要从复制过程中排除的数据库。让我们选择“mysql”数据库,看看在我们启用 JavaScript 的浏览器中会发生什么:
我们注意到出现了一行,说明binlog_ignore_db=mysql。这是一个 MySQL 服务器指令(而不是 SQL 语句),告诉服务器忽略将关于这个数据库的事务发送到二进制日志。让我们来解释其他行的含义。server-id是由 phpMyAdmin 生成的唯一 ID;参与复制的每个服务器都必须有一个唯一的服务器 ID。因此,我们要么手动跟踪服务器 ID,确保它们的唯一性,要么简单地使用 phpMyAdmin 随机生成的数字。我们还看到了log-bin和log-error指令;实际上,为了进行任何复制,二进制日志记录是强制性的。
我们可以通过使用Ctrl + 点击或Command + 点击在列表中添加其他数据库名称,具体取决于我们工作站的操作系统。然而,phpMyAdmin 所做的只是生成正确的行;要使它们生效,我们仍然需要遵循给定的建议,并将这些行粘贴到我们的 MySQL 配置文件的[mysqld]部分的末尾。然后我们应该重新启动 MySQL 服务器进程——如何做这取决于我们的环境。
在我们的服务器重新启动后,我们回到“复制”菜单;此时,我们会看到关于主服务器的不同面板:
我们可以使用“显示主服务器状态”链接来获取有关主服务器的一些信息,包括当前的二进制日志名称和位置,以及先前指定的要复制或忽略的数据库的信息。
“显示已连接的从服务器”链接目前不会报告任何内容,因为还没有从服务器连接到这个主服务器。
现在是使用“添加从服务器复制用户”链接的时候了,因为这个主服务器需要有一个专门用于复制的单独账户。从服务器将使用在主服务器上创建的这个账户来连接到它。点击这个链接会显示以下面板,其中正在创建一个名为“replic”的用户账户,密码由我们选择:
点击“Go”后,phpMyAdmin 会负责创建这个用户并设置正确的权限。
从服务器配置
现在,在将作为复制过程中从服务器的机器上,我们启动 phpMyAdmin。在“复制”菜单中,我们点击以下对话框中的“配置”:
从服务器配置面板显示如下截图所示:
与主配置一样,我们在从服务器的配置文件中得到了关于在配置文件中具有唯一服务器 ID 的建议,我们应该遵循这个建议。
在此面板中,我们输入在主服务器上创建的专用复制帐户的用户名和密码。我们还必须指示与主服务器对应的主机名和端口号。在填写此面板并单击“Go”后,phpMyAdmin 将向从服务器发送适当的CHANGE MASTER命令,将此服务器置于从服务器模式。
设置测试环境
复制过程发生在至少两个 MySQL 服务器实例之间。在生产中,这通常意味着至少需要两台物理服务器来获得这些好处:
-
更好的性能
-
增加冗余
但是,由于 MySQL 的可配置端口号(默认为 3306)、数据目录和套接字,可能在同一台服务器上有多个 MySQL 实例。此设置可以手动配置,也可以通过安装系统(如 MySQL Sandbox)进行配置。这是一个位于mysqlsandbox.net的开源项目。使用这个工具,我们可以非常快速地设置一个或多个 MySQL 服务器。通过使用强大的make_replication_sandbox Linux shell 命令,我们可以安装一个包含一个主服务器和两个从服务器的环境。每个服务器可以单独启动或停止。
以下练习假定 MySQL Sandbox 已安装在您的服务器上,并且 phpMyAdmin 的config.inc.php包含对这些 Sandbox 服务器的引用,如下面的代码块所示(请根据自己的环境调整套接字名称):
$i++;
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['socket'] = '/tmp/mysql_sandbox25562.sock';
$cfg['Servers'][$i]['verbose'] = 'master';
$i++;
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['socket'] = '/tmp/mysql_sandbox25563.sock';
$cfg['Servers'][$i]['verbose'] = 'slave1';
$i++;
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['socket'] = '/tmp/mysql_sandbox25564.sock';
$cfg['Servers'][$i]['verbose'] = 'slave2';
在这里,我们使用$cfg['Servers'][$i]['verbose']指令为每个实例提供一个唯一的名称,因为所有这些实例的真实服务器名称都是localhost。每个 Sandbox 服务器最初包含两个数据库:mysql和test。
控制从服务器
在这里,我们假设 Sandbox 测试环境已经设置。但是,这些解释对于所有具有从服务器的情况都是有用的。连接到从服务器并再次打开“复制”菜单后,我们看到:
有以下选项可用:
-
“查看从服务器状态表”链接允许我们接收有关此从服务器复制相关的所有系统变量的信息。
-
“控制从服务器:”链接显示更多选项;其中一些可以在停止和启动条件之间切换。
-
“全面停止”选项用于停止 IO 线程(负责从主服务器接收更新并将其写入从服务器的中继日志的 MySQL 服务器的一部分)和 SQL 线程(从中继日志读取更新并执行它们)
-
“重置从服务器”选项停止从服务器,发送
RESET SLAVE命令导致其忘记在主服务器的二进制日志中的复制位置,然后重新启动从服务器 -
“仅停止 SQL 线程”选项和“仅停止 IO 线程”选项用于仅停止各自的线程
-
错误管理:链接允许告诉从服务器跳过主服务器发送的一些事件(更新)。有关更多详细信息,请参阅
dev.mysql.com/doc/refman/5.1/en/set-global-sql-slave-skip-counter.html。 -
更改或重新配置主服务器:链接可用于指定此从服务器现在应该接收来自不同主服务器的更新。
获取复制信息
除了复制菜单之外,phpMyAdmin 的其他屏幕也会向我们提供有关复制的信息。这些屏幕在其他复制对话框中找不到;相反,它们分散在各个页面上,在相应页面的上下文中显示复制信息。
收集复制状态
通过进入服务器视图中的状态面板,我们首先会得到一个简短的消息,例如:
“这个 MySQL 服务器在复制过程中作为主服务器工作。有关服务器复制状态的更多信息,请访问复制部分。”
在这个页面上有一些复制链接,它们向我们展示了主服务器或从服务器的状态变量,以及一些关于连接的从服务器主机数量和复制状态的信息。
已复制的数据库
在主服务器上,查看服务器视图中的数据库菜单会显示一些数据库可能会被复制,主复制列中会有一个绿色的勾号:
这是因为这台服务器配置了二进制日志,而这些数据库没有被排除在复制之外。
由于我们在主服务器的配置文件的[mysqld]部分中有以下代码行,我们可以排除影响mysql数据库的所有事务不记录到二进制日志中:
binlog_ignore_db=mysql
因此,数据库页面的输出显示了mysql数据库旁边的红色图标。
如果这是一个从服务器,将显示一个服务器复制列。
提示
请注意,从服务器本身可以有一个二进制日志;因此,在这种情况下,主复制和从复制列都会显示出来。这意味着这个从服务器可以成为另一个从服务器的主服务器。
已复制的表
假设在主服务器上,我们在test数据库中创建了一个名为employee的表。此时,复制会发挥其魔力,我们可以在从服务器上查看test数据库:
在这里,复制列显示为提醒。我们不应该直接在从服务器上修改这个表,因为它的存在只是为了复制目的。如果我们决定直接修改它,我们的更改只会在这个表中进行,导致主服务器和从服务器之间的不一致,这不是一个好主意。
总结
在本章中,我们学习了如何将一个数据库的结构和数据同步到另一个数据库,无论是在同一台服务器上还是在不同的服务器上。我们涵盖了同步的目标以及如何执行完整或选择性的同步。然后我们研究了如何使用 phpMyAdmin 来引导我们进行复制设置,包括主服务器和从服务器;如何使用 MySQL Sandbox 准备测试环境,以及如何控制从服务器。
下一章将向您展示如何保留您的查询的永久书签。
第十四章:使用查询书签
本章介绍了查询书签——phpMyAdmin 配置存储的一个功能。能够为查询添加标签,并通过标签进行检索,可以节省真正的时间。书签是具有以下属性的查询:
-
永久存储
-
可查看
-
可擦除
-
与一个数据库相关
-
仅作为用户操作的结果记录
-
已标记
-
默认情况下是私有的(仅对创建它们的用户可用),但可能是公共的
如本章后面的向书签传递参数部分所述,书签也可以具有可变部分。
没有用于管理书签的书签页面。相反,书签的各种操作可在特定页面上进行,例如结果页面或查询框页面。
比较书签和查询历史功能
在第十一章中,我们了解了 SQL 历史功能,它会自动存储查询(临时或永久)。存储在历史中的查询和书签之间存在相似之处。毕竟,这两个功能都旨在存储查询以供以后执行。然而,关于查询的存储方式和触发查询记录的操作,存在重要的区别。
查询历史的存储是自动的;而查询被保存为书签是通过用户的显式请求。此外,存储在永久历史中的查询数量有可配置的限制(参见第十一章);然而,书签的数量没有限制。最后,历史功能按照查询发送的时间的倒序呈现查询。然而,书签是按标签显示的(不直接显示查询文本)。
总之,当我们既不打算回忆查询,也不希望记住我们输入的查询时,自动查询历史是有用的。这与书签功能形成对比,我们故意要求系统记住一个查询,甚至给它一个名称(标签)。因此,我们可以通过书签做更多事情,而不仅仅是查询历史,但是这两个功能都有其重要性。
创建书签
有两种情况下可以创建书签——在执行查询后(在这种情况下,我们不需要提前计划其创建),以及在将查询发送到 MySQL 服务器执行之前。这两个选项在以下部分中进行了探讨。
在成功查询后创建书签
初始书签创建是通过收藏此 SQL 查询按钮实现的。此按钮仅在执行生成结果的查询后出现(至少找到一行时);因此,此方法仅存储SELECT语句。例如,由多表查询生成器生成的复杂查询(如第十二章中所示)可以以这种方式存储为书签,前提是它找到了一些结果。
让我们看一个例子。在book表的搜索页面上,我们选择要在结果中显示的列,并输入如下截图所示的搜索值:
点击Go后,我们看到结果页面显示了一个书签对话框。我们仅为此书签输入一个标签作者 1 的书籍,然后点击收藏此 SQL 查询以将此查询保存为书签。书签保存在由$cfg['Servers'][$i]['bookmarktable']定义的表中。
这个书签对话框可以在包含结果的任何页面上看到。作为测试,我们可以只需点击一个表的浏览以获取结果,然后将此查询存储为书签。然而,将一个可以轻松点击完成的查询存储为书签并没有太多意义。
在发送查询之前存储书签
我们已经看到,在生成结果的SELECT语句执行后很容易创建一个书签。有时,即使查询没有找到任何结果,我们也可能希望存储一个书签。如果查询所指的数据尚未存在,或者查询是除SELECT之外的语句,就可能出现这种情况。为了实现这一点,我们在Database视图、Table视图和查询窗口的SQL选项卡中提供了将此 SQL 查询设为书签对话框。
现在我们转到book表的SQL页面,输入一个检索法语书籍的查询,并直接将法语书籍书签标签放入将此 SQL 查询设为书签对话框中。如果此书签标签以前已被使用,除非我们选中替换同名现有书签复选框,否则将创建一个同名的新书签。书签带有内部识别号,以及用户选择的标签。
单击Go后,查询将被执行并存储为书签。即使查询没有找到任何内容也没关系。这就是我们可以为非SELECT查询生成书签的方法,例如UPDATE, DELETE, CREATE TABLE等。
注意
这种技术也可以用于SELECT语句,无论是返回结果还是不返回结果。
将书签设为公开
我们创建的所有书签默认都是私有的。创建书签时,我们登录的用户名将与书签一起存储。假设我们勾选了如下屏幕截图中显示的让每个用户访问此书签复选框:
这将产生以下效果:
-
所有访问同一数据库(当前数据库)的用户都将可以访问该书签。
-
用户能够从书签中看到有意义的结果,这取决于他们在书签中引用的表上的权限。
-
任何用户都可以删除该书签。
-
用户将被允许通过在发送查询之前存储此书签并使用替换同名现有书签选项来更改书签的查询。
公共书签在调用时会显示**(共享)**后缀。
表的默认初始查询
在先前的示例中,我们根据自己的喜好选择了书签标签。但是,按照惯例,如果私有书签与表同名,当单击此表的浏览时,它将被执行。因此,我们将看到书签的结果,而不是此表的正常浏览结果。
假设我们有兴趣查看(默认情况下,以浏览模式)所有页数少于 300 页的书。我们首先生成适当的查询,可以从搜索页面轻松完成,然后在结果页面上使用book作为书签标签。
在此操作之后,每当创建此书签的用户浏览book表时,他将看到以下屏幕截图:
多查询书签
单个书签还可以存储多个查询(用分号分隔)。这对于非SELECT查询非常有用。例如,假设我们需要定期清理有关作者的数据,以删除电话号码中的无效区号。此操作总是会跟随author表的显示。
为了实现这一目标,我们存储了一个包含这些查询的书签(在发送执行之前):
update author set phone = replace(phone,'(123)', '(456)');
select * from author;
在书签中,我们可以放置许多数据修改语句,例如INSERT, UPDATE或DELETE,然后可以选择性地跟随一个SELECT语句。堆叠大量SELECT语句不会产生预期的结果,因为我们只会看到最后一个SELECT语句获取的数据。
从书签列表中调用书签
创建的任何书签都可以在以下页面找到:
-
表视图:marc_book的任何表的SQL页面
-
查询窗口:SQL 历史选项卡
-
数据库视图:marc_book数据库的SQL页面
在调用书签时有三个选择——提交、仅查看和删除(提交是默认选项)。
执行书签
选择一个书签并点击Go执行存储的查询并显示其结果。书签执行后的页面没有另一个对话框来创建书签,因为这将是多余的。
注意
我们得到的结果不一定与创建书签时相同。它们反映了数据库的当前内容。只有查询被存储为书签。
操作书签
有时,我们可能只想确定书签的内容。这可以通过选择书签并选择仅查看来完成。然后查询将被显示,我们有机会重新编辑其内容。这样做,我们将编辑原始书签查询的副本。为了保留这个新的编辑查询,我们可以将其保存为书签。同样,即使我们选择相同的书签标签,这将创建另一个书签,除非我们明确要求替换原始书签。
可以使用删除选项来删除书签。没有确认对话框来确认删除书签。我们现在应该继续删除我们的book书签。
向书签传递参数
如果我们再次查看我们创建的第一个书签(查找作者 1的所有书),我们会意识到,虽然它很有用,但只能找到一个作者,总是相同的那个。
特殊的查询语法使得可以向书签传递参数。这种语法利用了 SQL 注释/*和*/在 MySQL 中被忽略的特性。如果查询中存在/*[VARIABLE]*/结构,它将在执行时用提供的值进行扩展。
创建一个带参数的书签
假设我们想要找到给定作者的所有书,但不知道作者的id。我们首先输入以下查询:
SELECT author.name, author.id, book.title
FROM book, author
WHERE book.author_id = author.id
/* AND author.name LIKE '%[VARIABLE]%' */
注释字符(/* */)之间的部分将在以后扩展,并且标签将被移除。我们将这个查询标记为一个名为按姓名查找作者的书签(在执行之前),然后点击Go。查询的第一次执行只是存储了书签,同时检索了所有作者的所有书,因为这次我们没有向查询传递参数。
在这个例子中,我们在WHERE子句中有两个条件,其中一个包含特殊语法。如果我们在WHERE子句中的唯一条件需要一个参数,我们可以使用诸如/* WHERE author_id = [VARIABLE] */的语法。
传递参数值
为了测试书签,我们像往常一样调用它,并在变量对话框中输入一个值。
当我们点击Go时,我们看到了扩展的查询和作者 Smith 的书。
总结
在本章中,我们看到了如何记录书签(在发送查询之前或之后),如何操作它们,以及如何使一些书签公开。本章还向我们介绍了浏览模式的默认初始查询。它还涵盖了向书签传递参数。
下一章将解释如何通过 phpMyAdmin 提供的工具生成解释数据库结构的文档。
第十五章:系统文档
生成并维护有关数据结构的良好文档对于项目的成功至关重要,特别是在团队项目中。事实上,能够向其他团队成员展示当前数据字典和建议的列更改是一种有价值的沟通手段。此外,表间关系的图形显示可以快速展示数据库的内部工作原理。幸运的是,phpMyAdmin 具有处理这些事情的文档功能。
生成结构报告
从数据库或表视图的结构页面,打印视图链接可用于生成有关数据库结构的报告。此外,数据库视图中的数据字典链接会生成不同的报告。这些将在以下部分详细介绍。
创建可打印的报告
当 phpMyAdmin 生成结果时,总是有一个打印视图链接,可用于生成数据的可打印报告。打印视图功能也可用于生成基本的结构文档。这是通过两个步骤完成的。首次单击打印视图会在屏幕上显示报告,并在页面末尾有一个打印按钮。稍后,此打印按钮会生成格式化为打印机的报告。
数据库打印视图
单击数据库的结构页面上的打印视图会生成一个表格列表。此列表包含每个表的行数、存储引擎、大小、注释和创建日期,如下面的屏幕截图所示:
选择性数据库打印视图
有时,我们更喜欢为表的子集获取报告。这可以通过从数据库的结构页面选择我们想要的表,然后从下拉菜单中选择打印视图来完成,如下面的屏幕截图所示:
表打印视图
对于每个表,结构页面上也有一个打印视图链接。单击此链接会生成有关表的列和索引的信息,如下面的示例所示:
使用数据字典准备完整报告
从数据库视图的结构页面可以获取有关数据库中表和列的更完整的报告。我们只需单击数据字典链接即可获取此报告,部分内容如下屏幕截图所示:
MIME列在我们向某些列添加 MIME 相关信息之前为空(如第十六章中所述)。
生成关系模式
在第十章中,我们定义了book和author表之间的关系。这些关系用于各种外键功能(例如,在插入模式中获取可能值的列表)。现在,我们将研究一项功能,它使我们能够为我们的表生成定制的关系模式,以流行的 PDF 格式和其他格式。此功能要求正确安装和配置 phpMyAdmin 配置存储。
向我们的模型添加第三个表
为了获得更完整的模式,我们现在将向我们的数据库添加另一个表country。以下代码块显示了其导出文件的内容:
CREATE TABLE IF NOT EXISTS `country` (
`code` char(2) NOT NULL,
`description` varchar(50) NOT NULL,
PRIMARY KEY (`code`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `country` (`code`, `description`) VALUES
('ca', 'Canada'),
('uk', 'United Kingdom');
现在,我们将此表链接到author表。首先,在country表的关系视图中,我们指定要显示的列,然后单击保存。
然后,我们向author表添加一个country_code列(与country表中的code列相同类型和大小),并在关系视图中将其链接到新创建的country表。
注意
我们必须记得点击“保存”以记录关系。
对于这个例子,不需要为作者输入任何国家数据,因为我们只对关系模式感兴趣。
生成模式页面
每个关系模式称为“页面”。我们可以通过在“数据库”视图的“操作”页面上点击“编辑或导出关系模式”来创建或编辑页面。
页面规划
关系模式不能跨越多个数据库。但即使只使用一个数据库,表的数量可能很大。以清晰的方式表示各种表之间的关系可能是一个挑战。这就是为什么我们可能会使用许多页面,每个页面显示一些表及其关系。
我们还必须考虑最终输出的尺寸。在信纸大小的纸张上打印给我们更少的空间来显示所有的表,并且仍然有一个可读的模式。
创建一个新页面
由于没有现有页面,我们需要创建一个。由于我们最重要的表是“书籍”,我们还将把这个页面命名为“书籍”。
我们将选择希望在关系模式中看到的表。我们可以逐个选择每个表。但是,为了一个良好的开始,建议勾选适当的“自动布局”复选框。这样做会将数据库中所有相关的表放入要包括在模式中的表列表中。然后生成适当的坐标,使表格将以螺旋布局的方式出现在模式中,从模式的中心开始。这些坐标以毫米表示,其中(0, 0)位于左上角。然后点击“开始”:
编辑页面
现在我们得到了一个有三个不同部分的页面。第一个是页面菜单,我们可以从下拉菜单中选择要操作的页面。我们也可以删除所选的页面。我们最终也可以创建第二个模式(页面)。
接下来的部分是表的放置部分。我们现在可以看到“自动布局”功能的好处——我们已经选择了我们的三个表,并填写了“X”和“Y”坐标列。我们可以添加一个表(在最后一行),删除一个表(使用复选框),并更改坐标(表示模式上每个表的左上角位置):
为了帮助设置精确的坐标,JavaScript 启用的浏览器可以使用可视化编辑器。当单击“切换草稿板”按钮一次时,编辑器将出现。当再次单击此按钮时,它将消失。我们可以在草稿板上拖放表格,坐标将相应更改。草稿板上表格的外观提供了最终 PDF 输出的粗略指南。有些人更喜欢在草稿板上只看到表格名称(而不是每个列名称)。这可以通过取消选择“列名称”复选框然后点击“保存”来完成。以下图片显示了这个草稿板的例子:
注意
当我们对布局感到满意时,必须点击“保存”。
为了显示导出页面
屏幕的最后部分是报告生成对话框。现在我们已经创建了一个页面,“显示关系模式”显示一个对话框,如下面的屏幕截图所示:
可用的选项有:
| 选项 | 描述 |
|---|---|
| 选择导出关系类型允许选择要导出的文件格式(PDF、SVG、DIA、Visio 或 EPS)。 | |
| 显示网格 | 模式将具有显示坐标的网格层。在设计和测试模式时很有用。 |
| 显示颜色 | 链接、表名和特殊列(主键和显示列)将以颜色显示。 |
| 显示表的尺寸 | 在表标题中显示每个表的视觉尺寸(例如,32x30)。这在设计和测试模式时很有用。 |
| 显示所有具有相同宽度的表 | 所有表将使用相同的宽度显示。(通常,宽度会根据表和列名的长度自动调整。) |
| 数据字典 | 数据字典,本章前面介绍过的,将包含在报告的开头。 |
| 仅显示键 | 不显示未定义索引的列。 |
| 方向 | 在这里,我们选择报告的打印方向。 |
| 纸张尺寸 | 更改此选项将影响模式和草稿板的尺寸。 |
在config.inc.php中,以下参数定义了可用的纸张尺寸和默认选择:
$cfg['PDFPageSizes'] = array('A3', 'A4', 'A5', 'letter', 'legal');
$cfg['PDFDefaultPageSize'] = 'A4';
以下屏幕截图显示了生成报告的最后一页(模式页面)的 PDF 格式。前四页包含数据字典以及其他功能。
箭头指向相应外部表的方向。如果显示颜色复选框已被选中,则主键显示为红色,显示列显示为蓝色,如下面的屏幕截图所示:
以下屏幕截图提供了从相同的book表的 PDF 页面定义生成的另一个示例。这次显示了网格,但没有颜色:
更改 PDF 模式中的字体
我们在 PDF 模式中看到的所有文本都是使用特定字体绘制的。phpMyAdmin 使用DejaVuSans字体(dejavu.sourceforge.net),该字体涵盖了广泛的字符。
对于实际的 PDF 生成,phpMyAdmin 依赖于tcpdf库(tcpdf.sourceforge.net)。该库有两种使用字体的方式——嵌入和非嵌入。嵌入字体会产生更大的 PDF 文件,因为整个字体都包含在 PDF 文件中。这是 phpMyAdmin 选择的默认选项,因为该库不依赖于客户操作系统中特定的TrueType字体的存在。
字体位于phpMyAdmin主目录下的libraries/tcpdf/fonts中。
要使用不同的字体文件,我们必须首先将其添加到库中(工具在原始tcpdf工具包中,www.fpdf.org网站上有教程),然后修改 phpMyAdmin 的libraries/schema/ Pdf_Relation_Schema.class.php源代码。
使用设计者功能布置模式
设计者功能(在数据库视图中可用)提供了一种更精细的在屏幕上移动表的方式,因为列链接会跟随表的移动。因此,设计者保存的表的坐标和模式的坐标之间存在接口。让我们进入设计者,并点击小的 PDF 标志。
这将带我们到一个面板,在这里我们可以选择(现有的)模式名称和我们想要执行的操作——在我们的情况下,将设计者坐标导出到模式定义中。我们还可以使用新页面名称对话框,输入页面名称,然后点击Go创建一个空白页面。从这里,我们随后可以导出从设计者工作区保存的坐标:
注
设计者和编辑或导出关系模式功能管理的表的跨度存在差异。设计者默认情况下操作数据库的每个表,而编辑或导出关系模式面板为我们提供了表的选择,使我们能够表示关系的子集,如果有很多表的话。
总结
本章介绍了 phpMyAdmin 提供的文档功能,包括数据库或表的打印视图以及完整列列表的数据字典。本章还涵盖了关系模式。特别是,它着重介绍了如何创建、修改和导出模式页面,以及如何使用可视化编辑器(scratchboard)。
下一章将解释如何对数据应用转换,以便在查看时自定义数据格式。
第十六章:使用 MIME 转换数据
在本章中,我们将介绍 phpMyAdmin 的一个强大功能——它能够根据称为转换的特定规则,在表浏览期间转换列的内容。通常,浏览表只显示其中存储的原始数据。然而,基于 MIME 的转换允许改变显示格式。
请注意,这种转换并不像通过UPDATE语句进行的永久数据更改那样产生相同的效果。转换后的数据不会被写回到 MySQL 服务器;它只是被发送到浏览器以供显示目的。
浏览数据而不进行转换
通常,每行的确切内容都会被显示,只是:
-
TEXT和CHARACTER列可能会根据
$cfg['LimitChars']而被截断,取决于我们是否选择查看完整文本。 -
BLOB和与几何相关的列可能会被替换为诸如**[BLOB - 1.5 KB]**的消息
我们将使用术语单元格来指示特定行的特定列。当前显示的包含“未来纪念品”书籍封面照片的单元格(一个BLOB列)目前显示为像**‰PNG\r\n\Z\n\0\0\0\rIHDR\0这样的加密数据,或者显示BLOB**列的大小的消息。在 phpMyAdmin 中直接看到图片的缩略图(如下面的截图中所示)以及可能的全尺寸图片本身将是很有趣的。通过适当的转换,这将成为可能。
切换显示选项
在浏览模式下,选项链接会显示一个滑块,其中包括一个隐藏浏览器转换复选框。我们可以在想要在查看单元格的真实数据和转换后的版本之间切换时使用它。
启用转换
我们将转换定义为一种机制,通过该机制,与某一列相关的所有单元格在浏览时都会进行转换,使用为该列定义的元数据。只有当前结果页面上可见的单元格会被转换。
这个功能的使用受config.inc.php中的$cfg['BrowseMIME']指令的控制。该指令的默认值为TRUE,表示启用了转换。然而,phpMyAdmin 配置存储必须就位(参见第一章),因为转换所需的元数据在官方 MySQL 表结构中是不可用的。这是专门为 phpMyAdmin 添加的附加功能。
注意
转换逻辑本身是通过 PHP 脚本编码的,存储在libraries/transformations中,并使用插件架构进行调用。在 phpMyAdmin 官方网站的文档部分(当前位于www.phpmyadmin.net/home_page/docs.php))中,有一个指向额外信息的链接,供希望了解插件内部结构以编写自己的转换的开发人员参考。
配置 MIME 列的设置
如果我们转到book表的结构页面的表视图,并点击cover_photo列的更改链接,我们会看到三个额外的属性(假设启用了转换功能):
-
MIME 类型
-
浏览器转换
-
转换选项
如下截图所示:
对于特定列,可能只能指定一种类型的转换。在这里,该列是一个BLOB。因此,它可以容纳任何类型的数据。为了使 phpMyAdmin 能够正确解释和处理数据,必须通知转换系统数据格式和预期结果。因此,我们必须确保上传的数据始终遵循相同的文件格式。
我们将首先了解这些属性的目的,然后在本章后面的转换示例部分尝试一些可能性。
选择 MIME 类型
MIME 规范(en.wikipedia.org/wiki/MIME)已被选择为元数据属性,用于对列持有的数据类型进行分类。多用途互联网邮件扩展(MIME),最初设计用于扩展邮件,现在也用于描述其他协议的内容类型。在 phpMyAdmin 的上下文中,当前可能的值是:
-
image/jpeg
-
image/png
-
text/plain
-
application/octetstream
text/plain类型可用于包含任何类型文本(例如 XHTML 或 XML 文本)的列。在转换示例部分,您将看到需要选择哪种 MIME 类型以实现特定效果。
浏览器转换
这是我们设置要执行的确切转换的地方。每种 MIME 类型可能支持多个转换。例如,对于image/jpeg MIME 类型,我们有两种可用的转换:image/jpeg: inline用于图像的可点击缩略图,以及image/jpeg: link用于仅显示链接。
以下屏幕截图显示了可用转换的列表:
单击转换选项旁边的问号图标,然后单击出现的转换描述链接,可以获得更完整的转换说明和可能的选项列表。
将值分配给转换选项
在转换示例部分,我们将看到一些转换接受选项。例如,我们可以指定生成图像的转换的像素宽度和高度。逗号用于在选项列表中分隔值,并且某些选项可能需要用引号括起来。
一些选项具有默认值,我们必须小心遵守选项的文档顺序。例如,如果有两个选项,我们只想为第二个选项指定一个值,我们可以使用空引号作为第一个选项的占位符,让系统使用其默认值。
图像生成的要求
普通缩略图生成需要 Web 服务器上存在一些组件,并且config.inc.php中的参数正确配置。
配置 GD2 库可用性验证
phpMyAdmin 使用一些内部函数来创建缩略图。这些函数需要 PHP 服务器上存在 GD2 库。
phpMyAdmin 可以检测到正确的 GD2 库的存在,但这种检测需要一些时间。它不是每个会话一次,而是几乎每次在 phpMyAdmin 中执行操作时都会进行。
在config.inc.php中将$cfg['GD2Available']参数设置为其默认值'auto'表示需要检测库的存在和版本。
如果我们知道 GD2 库可用,将$cfg['GD2Available']设置为yes将使执行更快。如果 GD2 库不可用,建议将此参数设置为no。
要找出服务器上有哪个 GD2 库,我们可以转到 phpMyAdmin 的主页,然后单击显示 PHP 信息。如果没有此链接,则需要将$cfg['ShowPhpInfo']参数设置为true。然后查找一个名为gd的部分,并验证识别的版本。在下面的屏幕截图中,一切都很好,因为我们可以看到 GD 版本是 2.X,并且支持 JPEG 和 PNG:
确认支持 JPEG 和 PNG 库
如果我们想为这些类型的图像生成缩略图,我们的 Web 服务器中的 PHP 组件需要支持 JPEG 和 PNG 图像。有关更多详细信息,请参阅php.net/manual/en/ref.image.php。
评估内存限制的影响
在一些服务器上,php.ini中memory_limit的默认值为8M,表示 8 MiB。这对于正确的图像处理来说太低了,因为用于生成最终图像的 GD 函数需要工作内存。例如,在一个测试中,需要将memory_limit的值设置为11M才能从一个 300 KiB 的 JPEG 图像生成缩略图。此外,如果同时查看多行,将需要更多的工作内存。
转换示例
我们现在将讨论一些转换示例。显示了典型的选项值,并建议调整它们,直到达到期望的结果。根据 phpMyAdmin 的版本,可能会提供更多的转换。
可点击的缩略图(JPEG 或 PNG)
我们将首先将cover_photo列的类型从BLOB更改为LONGBLOB,以确保我们可以上传大小超过 65 KiB 的照片。然后,我们输入以下截图中显示的属性:
这里,选项以宽度和高度的形式呈现。如果我们省略选项,那么默认值为 100 和 100。缩略图生成代码保留图像的原始宽高比。因此,输入的值是生成图像的最大宽度和高度。然后,我们在一个单元格中上传一个.jpeg文件(使用第五章的说明)。结果,我们在该表的浏览模式下得到以下屏幕:
这个缩略图可以点击以显示全尺寸的照片。
注意
缩略图不会存储在任何地方,而是每次我们进入这组行的浏览模式时生成。在一个双 Xeon 3.2 GHz 服务器上,我们通常每秒可以生成六张 JPEG 图像。phpMyAdmin 不提供这些缩略图的缓存。
对于.png文件,我们必须在MIME 类型对话框中使用image/png,并在浏览转换对话框中使用image/png: inline。
向图像添加链接
为了提供没有缩略图的链接,我们使用image/jpeg: link转换。没有转换选项。这个链接可以用来查看照片(通过左键单击链接),然后可能下载它(通过右键单击照片本身)。
日期格式化
在我们的book表中有一个名为date_published的列;让我们将其类型更改为DATETIME。然后,我们将其 MIME 类型设置为text/plain,并将浏览器转换设置为text/plain: dateformat。下一步是编辑“未来纪念品”书籍的行,并在date_published列中输入2003-01-01 14:56:00。当我们浏览表时,我们现在看到该列已被格式化。将鼠标悬停在上面会显示未格式化的原始内容,如下截图所示:
这个转换接受两个选项。第一个是要添加到原始值的小时数(默认为零)。如果我们存储基于协调世界时(UTC)的所有时间值,但想要为特定时区(例如 UTC+5)显示它们,添加小时数可能会很有用。第二个选项是我们想要使用的时间格式,使用任何 PHP strftime参数指定(更多细节请参阅php.net/strftime)。因此,如果我们在转换选项中放入**'0','Year: %Y'**,我们将得到以下输出:
文本链接
假设我们在book表的description列中放入了一个完整的 URL — http://domain.com/abc.pdf。在浏览表时,链接的文本将被显示,但我们无法点击它。现在我们将看到在这种情况下使用text/plain MIME 类型的用法。
text/plain: link
如果我们在刚才提到的场景中使用text/plain MIME 类型和text/plain: link浏览器转换,我们仍然会看到链接的文本,并且可以点击。
如果我们要指向的所有文档都位于一个共同的 URL 前缀下,我们可以将这个前缀(例如,domain.com/)放在第一个转换选项中,用引号括起来。然后,我们只需要在每个单元格中放入 URL 的最后部分(abc.pdf)。
第二个转换选项用于设置标题。这将在浏览模式中显示,而不是 URL 内容,但点击后仍会带我们到预期的 URL。
如果我们只使用第二个转换选项,我们必须将第一个选项的值设为引号。可以这样做:'','this is the title'。
text/plain: imagelink
text/plain: imagelink转换与前一个类似,只是在单元格中放置一个指向图像的 URL。该图像将被获取并与链接文本一起显示在单元格中。图像可以位于网络上的任何地方,包括我们的本地服务器。
在这里,我们有以下三个选项可用:
-
常见的 URL 前缀(比如
text/plain: link的前缀) -
图像的宽度(默认值:100 像素)
-
高度(默认值:50)
对于我们的测试 URL,您应该输入以下选项:
'','100','123'
如果链接的文本太长,转换就不会发生。默认情况下选择部分文本显示选项。
在这种情况下,我们可以切换到完整文本以显示完整的链接。然后我们可以看到完整的图片。
其他转换,如image/jpeg: inline和image/png: inline,指定了图像的确切 MIME 类型。在这些情况下,phpMyAdmin 使用 GD2 库函数进行缩略图生成。然而,在text/plain: imagelink转换中包含的链接可能指向任何浏览器支持的图像类型。因此,phpMyAdmin 只显示一个调整大小的图像,带有 HTML 的img标签,并根据转换中定义的大小选项设置width和height属性。要查看原始图像,我们可以点击链接或缩略图。
保留原始格式
通常,当显示文本时,phpMyAdmin 会转义特殊字符。例如,如果我们在一个书籍的description列中输入This book is good,在浏览表时通常会看到This book is good。但是,如果我们对该列使用text/plain: formatted转换,那么在浏览时会得到以下输出:
在这个例子中,结果是正确的。但是,列中输入的其他 HTML 标记可能会产生意想不到的结果(包括无效的 HTML 页面)。例如,由于 phpMyAdmin 使用 HTML 表呈现结果,列中的未转义的</table>标记会破坏输出。
显示文本的部分
text/plain: substr转换用于仅显示文本的一部分。以下是选项:
-
文本的起始位置(默认值:0)
-
有多少个字符(默认值:剩余文本的所有字符)
-
显示截断发生时的后缀;默认情况下显示省略号(...)
请记住,$cfg['LimitChars']对于每个非数字列都会进行字符截断。因此,text/plain: substr是一种逐列微调的机制。
显示下载链接
假设我们想在 MySQL 中为每本书存储一个小的音频评论。我们向book表中添加一个新列,名为audio_contents,类型为MEDIUMBLOB。我们将其MIME 类型设置为application/octetstream,并选择application/octetstream: download 转换。在转换选项中,我们插入**'comment.wav'**。
这个 MIME 类型和扩展名将告知我们的浏览器有关传入数据,并且浏览器应该打开适当的播放器。要插入评论,我们首先以.wav格式记录它,然后将文件内容上传到其中一个书籍的audio_contents列中。在浏览我们的表时,我们可以看到一个名为comment.wav的音频评论链接:
十六进制表示
字符以数字数据的形式存储在 MySQL(以及计算机一般),并转换为屏幕或打印机上的有意义的内容。用户有时会从另一个应用程序剪切和粘贴数据到 phpMyAdmin,如果字符不直接受 MySQL 支持,可能会导致意外结果。phpMyAdmin 的帮助论坛中报告了一个案例,涉及在 Microsoft Word 文档中输入特殊引号并粘贴到 phpMyAdmin 中。通过使用application/octetstream: hex转换,可以看到确切的十六进制代码。
在以下示例中,此转换将应用于我们book表的title列。当浏览包含Future souvenirs标题的行时,我们可以看到以下屏幕:
由于我们知道这一列使用的字符集,我们可以将其内容与描述每个字符的图表进行比较。例如,en.wikipedia.org/wiki/Latin1描述了 Latin1 字符集。
SQL 漂亮打印
术语漂亮打印(en.wikipedia.org/wiki/Pretty_printing)指的是一种“美化”源代码的方式(在我们的情况下是 SQL 语句)。在 phpMyAdmin 配置存储中,pma_bookmark.query 和 pma_history.sqlquery 列包含 SQL 语句。通过为这些列定义text/plain: sql 转换,当浏览表时,这些 SQL 语句将以带有语法高亮的颜色显示。
IP 地址
IP(v4)地址可以编码为长整型(例如,通过 PHP 的iptolong()函数),并存储到 MySQL 的UNSIGNED INT列中。要将其转换回熟悉的点分字符串(例如,127.0.0.1),可以使用text/plain: longToIpv4转换。
通过外部应用程序转换数据
先前描述的转换是直接从 phpMyAdmin 中实现的。然而,一些转换最好通过现有的外部应用程序执行。
text/plain: external 转换使我们能够将单元格的数据发送到另一个应用程序,该应用程序将在 Web 服务器上启动,捕获此应用程序的输出,并在单元格位置显示此输出。
注意
此功能仅在 Linux 或 UNIX 服务器上受支持(在 Microsoft Windows 下,输出和错误重定向不能轻松地被 PHP 进程捕获)。此外,PHP 不应该运行在安全模式下。因此,该功能可能在托管服务器上不可用。
出于安全原因,无法从 phpMyAdmin 内部设置应用程序的确切路径和名称作为转换选项。应用程序名称直接设置在 phpMyAdmin 脚本中的一个。
首先,在 phpMyAdmin 安装目录中,我们编辑libraries/transformations/中的text_plain__external.inc.php文件,并找到以下部分:
$allowed_programs = array();
//$allowed_programs[0] = '/usr/local/bin/tidy';
//$allowed_programs[1] = '/usr/local/bin/validate';
默认情况下,没有配置外部应用程序,我们必须明确添加我们自己的应用程序。
注意
转换脚本的名称采用以下格式构建——MIME 类型,双下划线,然后是指示应进行哪种转换的部分。
每个允许的程序,以及其完整路径,都必须在此处用从 0 开始的索引号描述。然后我们保存对此脚本的修改,如果需要的话将其放回服务器。其余的设置是从面板完成的,我们在那里选择其他浏览器转换的选项。
当然,我们现在在转换菜单中选择text/plain: external。
作为第一个选项,我们放置应用程序编号(例如,0 表示整理应用程序)。第二个选项包含我们需要传递给此应用程序的参数。如果我们希望 phpMyAdmin 对结果应用htmlspecialchars()函数,我们将1作为第三个参数——这是默认值。我们可以将0放在那里,以避免用htmlspecialchars()保护输出。
如果我们想避免重新格式化单元格的行,我们将1作为第四个参数。这将使用NOWRAP修饰符,默认情况下会这样做。
外部应用示例:单元格排序
这个例子展示了如何对单个单元格的文本内容进行排序。我们首先修改text_plain__external.inc.php脚本,如前一节所述,添加sort程序:
$allowed_programs[0] = '/bin/sort';
请注意,我们的新程序带有索引号0。
然后,我们向我们的book表添加一个名为keywords的TEXT列。最后,我们填写与 MIME 相关的信息,输入**'0','-r'**作为转换选项,如下截图所示:
这里的**'0'是指sort的索引号,'-r'**是sort的参数,使程序以相反的顺序排序。
接下来,我们编辑书籍“A hundred years of cinema (volume 1)”的行,以任意顺序输入一些关键词(如下截图所示),然后点击Go以保存更改:
为了测试外部程序的效果,我们浏览表格并查看排序后的单元格关键词:
请注意,关键词以相反的排序顺序显示。
总结
在本章中,我们学习了如何通过各种方法转换数据来改善浏览体验。特别是,我们看到了如何从.jpeg和.png的BLOB列中显示缩略图和全尺寸图像的概述,如何生成链接,格式化日期,仅显示文本的部分,以及如何执行外部程序来重新格式化单元格内容。
下一章将介绍 phpMyAdmin 对 MySQL 5.0 和 5.1 版本中的新功能的支持。
第十七章:MySQL 5 中添加的支持功能
MySQL 5.0 引入了许多新功能,平息了许多声称 MySQL 不如竞争对手产品的开发人员和行业观察者的声音。视图、存储过程、触发器、标准的information_schema,以及(最近)性能分析机制现在都存在于 MySQL 的范围内。这些功能在本章中进行了介绍。
在 MySQL 5.1 的新功能中,与 Web 界面相关的功能(例如,分区和事件)也受到 phpMyAdmin 的支持,并在本章中进行了介绍。
支持视图
MySQL 5.0 引入了对命名和可更新视图的支持(更多详细信息可在dev.mysql.com/doc/refman/5.5/en/views.html)找到)。视图是一个派生表(将其视为虚拟表),其定义存储在数据库中。对一个或多个表(甚至是视图)执行的SELECT语句可以存储为视图,并且也可以进行查询。
视图可以用于:
-
限制列的可见性(例如,不显示薪资信息)
-
限制行的可见性(例如,不显示特定世界地区的数据)
-
隐藏更改后的表结构(以便旧应用程序可以继续工作)
与在许多表上定义繁琐的特定列权限相比,更容易准备一个包含这些表中有限列集的视图。然后我们可以授予整个视图的权限。
在从 5.0 之前的版本升级后,要在服务器上激活对视图的支持,管理员必须执行mysql_upgrade程序,如 MySQL 手册中所述(dev.mysql.com/doc/refman/5.0/en/upgrading-from-previous-series.html)。
注意
每个用户必须具有适当的SHOW_VIEW或CREATE_VIEW权限才能查看或操作视图。这些权限存在于全局(服务器)、数据库和表级别。
创建视图意味着用户对涉及的表具有权限,或者至少具有SELECT或UPDATE等权限来操作视图中提到的所有列。
从结果创建视图
我们可以利用 phpMyAdmin 的搜索(在表级别)或查询(在数据库级别)功能来构建一个相当复杂的查询,执行它,然后轻松地从结果中创建一个视图。我们将看到这是如何完成的。
我们提到视图可以用来限制列(实际上也包括表)的可见性。假设一本书的页数是高度机密的信息。我们打开book表,点击搜索,并选择不包括page_count列的列子集(我们可能需要打开选项滑块)。
点击Go会生成一个结果页面,在查询结果操作部分我们会看到一个CREATE VIEW链接。我们使用这个链接来访问视图创建面板,其中已经有了AS框中的基础查询。我们需要为这个视图选择一个名称(这里我们使用book_public_info),并且我们可以选择为它设置不同的列名(这里我们使用number, title),如下截图所示:
其他选项可能会影响视图的行为,并在 MySQL 手册中有解释(dev.mysql.com/doc/refman/5.5/en/create-view.html)。LOCAL CHECK OPTION子句会影响可更新视图的行为(这在前面引用的 MySQL 手册页面中有解释)。
点击Go生成我们要求的视图。此时,视图已经创建。如果我们刷新浏览器的页面,然后访问marc_book数据库,我们将看到以下截图:
在主面板中,我们看到了新创建的视图的信息。目前视图的行数指示为~0(稍后在本章的控制行计数以提高性能部分中会详细介绍),类型列中显示视图。视图没有排序或大小相关联。
主面板和视图
由于视图与表相似,它的名称与普通表的名称一样。单击视图名称时,会显示一个类似于表的面板,但是菜单选项比普通表少。事实上,有些操作在视图上是没有意义的,例如导入。这是因为视图实际上不包含数据。但是,其他操作,如浏览,是完全可以接受的。
让我们浏览以下截图中显示的视图:
我们注意到,在生成的 SQL 查询中,我们没有看到原始的CREATE VIEW语句。原因是我们正在使用SELECT语句从视图中进行选择,隐藏了我们从视图中提取数据的事实。然而,导出视图的结构将显示 MySQL 如何内部存储我们的视图:
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `book_public_info` AS
select `book`.`isbn` AS `number`,`book`.`title` AS `title` from `book`;
主面板的菜单可能看起来类似于表的菜单。但是在必要时,phpMyAdmin 会生成处理视图的适当语法。
注意
要对现有视图执行操作,用户需要在视图级别具有适当的权限,但不一定需要在涉及此视图的表上具有任何权限。这是我们可以实现列和表的隐藏。
控制行计数以提高性能
phpMyAdmin 有一个配置参数$cfg['MaxExactCountViews'],用于控制 phpMyAdmin 的行计数阶段。有时,一个视图包含许多巨大的表,浏览它会导致大量的虚拟行出现。因此,该参数的默认值为 0 确保视图不进行行计数。在这种情况下,当浏览视图时,我们会看到相当奇怪的结果:显示行 0 - -1(共 0 行,查询耗时 0.0006 秒)。这比减慢服务器速度更可接受。
尽管如此,如果我们希望看到视图的更准确的行数,我们可以在该参数中放入一个较大的值,该值作为行计数阶段的上限。
支持例程-存储过程和函数
phpMyAdmin 在开始支持存储过程和函数之前花了一些时间。原因是这些是作为数据库的一部分保存的代码块(类似于子程序)。作为一个 Web 界面的 phpMyAdmin 更倾向于使用鼠标快速执行的操作。
尽管如此,phpMyAdmin 有一些功能允许开发人员创建这样的例程,保存它们,调用它们进行一些修改,并删除它们。
通过CALL语句访问存储过程,我们可以传递参数(更多细节请参阅dev.mysql.com/doc/refman/5.5/en/call.html))。另一方面,函数可以从 SQL 语句(例如SELECT)中访问,并且类似于其他 MySQL 内部函数,因此返回一个值。
需要CREATE ROUTINE和ALTER ROUTINE权限才能创建、查看和删除存储过程或函数。需要EXECUTE权限来运行例程,尽管该权限通常会自动授予例程的创建者。
创建存储过程
我们将创建一个过程,通过添加特定数量的页面来更改特定书籍的页数。该过程的输入参数是书籍的 ISBN 和要添加的页数。我们正在使用 SQL 查询框(参考第十一章)来输入这个过程。
更改分隔符
标准的 SQL 分隔符是分号,这个字符将被用来在我们的存储过程中分隔 SQL 语句。然而,CREATE PROCEDURE语句本身就是一个 SQL 语句;因此,我们必须想办法告诉 MySQL 解析器这个语句在哪里结束。查询框中有一个分隔符输入框,默认包含一个分号。因此,我们将其更改为另一个字符串,按照惯例是双斜杠"//"。
输入存储过程
然后我们在主查询框中输入存储过程的代码:
CREATE PROCEDURE `add_page`(IN param_isbn VARCHAR(25),
IN param_pages INT, OUT param_message VARCHAR(100))
BEGIN
IF param_pages > 100 THEN
SET param_message = 'the number of pages is too big';
ELSE
UPDATE book SET page_count = page_count + param_pages WHERE
isbn=param_isbn;
SET param_message = 'success';
END IF;
END
//
点击Go,如果语法正确,我们会收到一个成功消息。如果不正确,那么是时候检查我们的打字能力或调试我们的语法了。不幸的是,MySQL 没有存储过程调试器。
测试存储过程
同样,在查询框中,我们通过输入以下语句来测试我们的存储过程。在这里,我们使用了一个 SQL 变量@message,它将接收OUT参数param_message的内容:
call add_page('1-234567-22-0', 4, @message);
SELECT @message;
如果一切顺利,我们应该看到**@message变量包含success**。
然后我们可以验证这本书的页数是否增加了。我们还需要测试有问题的情况:
call add_page('1-234567-22-0', 101, @message);
SELECT @message;
现在可以调用这个存储过程(例如)从您的 PHP 脚本中使用mysqli扩展,这是推荐的访问 MySQL 4.1 及以上版本提供的所有功能的扩展。
操作存储过程和函数
存储过程存储在数据库中,不与特定表绑定。因此,用于操作存储过程和函数的接口可以在数据库级别找到,在结构页面下的例程滑块下,如果已经定义了至少一个例程,则会出现该滑块。
第一个图标将这个存储过程的文本带入查询框进行编辑。第二个图标用于删除这个存储过程。在编辑存储过程时,我们注意到文本已经被稍微修改。
DROP PROCEDURE `add_page`//
CREATE DEFINER=`marc`@`%` PROCEDURE `add_page`(IN param_isbn VARCHAR(25), IN param_pages INT, OUT param_message VARCHAR(100))
BEGIN
IF param_pages > 100 THEN
SET param_message = 'the number of pages is too big';
ELSE
UPDATE book SET page_count = page_count + param_pages WHERE
isbn=param_isbn;
SET param_message = 'success';
END IF;
END
首先出现一个DROP PROCEDURE语句。这是正常的,因为 MySQL 没有提供一个允许更改存储过程主体的语句。因此,我们必须每次想要更改它时删除一个存储过程。ALTER PROCEDURE语句确实存在,但它只能改变存储过程的特性,例如添加注释。然后,显示了一个DEFINER子句。它是在创建时生成的,指示谁创建了这个存储过程。
在这一点上,我们对代码进行任何需要的更改,并点击Go来保存这个存储过程。
注意
也许会有诱惑打开结构页面上的book表,查找操作这个表的存储过程列表,比如我们的add_page()存储过程。然而,所有存储过程都存储在数据库级别,代码本身(UPDATE book)和存储过程存储的地方之间没有直接的链接。
手动创建一个函数
函数类似于存储过程。然而,函数可能只返回一个值,而存储过程可以有多个OUT参数。另一方面,从SELECT语句中使用存储函数可能更自然,因为它避免了需要一个中间的 SQL 变量来保存OUT参数的值。
函数的目标是什么?例如,函数可以用来计算订单的总成本,包括税费和运费。将这个逻辑放在数据库中而不是在应用程序级别有助于记录应用程序-数据库接口。它还避免了在每个需要处理这个逻辑的应用程序中重复业务逻辑。
我们不应该混淆 MySQL 5.0 函数和UDF(用户定义函数),它们存在于 MySQL 5.0 之前。UDF 由用 C 或 C++编写的代码组成,编译成共享对象,并通过CREATE FUNCTION语句和SONAME关键字引用。
phpMyAdmin 对函数的处理在许多方面类似于我们在例程中所涵盖的内容:
-
一个查询框,用于输入函数
-
使用分隔符
-
操作已定义的函数的机制
让我们定义一个函数,根据其代码检索国家名称。我更喜欢在函数定义内清楚地标识参数使用param_前缀和局部变量使用var_前缀。我们将使用我们信任的 SQL 查询框再次输入函数的代码,并指示该框使用//作为分隔符。
CREATE FUNCTION get_country_name(param_country_code CHAR(2))
RETURNS VARCHAR(50)
READS SQL DATA
BEGIN
DECLARE var_country_name VARCHAR(50) DEFAULT 'not found';
SELECT description
FROM country
WHERE code = param_country_code
INTO var_country_name;
RETURN var_country_name;
END
//
我们应该注意,我们新创建的函数可以在数据库的结构页面上看到,以及它的朋友add_page过程:
手动创建函数
测试函数
要测试我们刚刚创建的函数,请在查询框中输入以下查询(参见[第十一章]:(ch11.html "第十一章。输入 SQL 语句"))
SELECT CONCAT('ca->', get_country_name('ca'), ', zz->',
get_country_name('zz')) as test;
这将产生以下结果:
ca->Canada, zz->not found
导出存储过程和函数
在导出数据库时,存储过程和函数会出现在 SQL 导出中。这是因为在导出页面的对象创建选项对话框中默认选择了添加 CREATE PROCEDURE / FUNCTION / EVENT复选框(在自定义导出模式中可以看到)。以下是与存储过程和函数相关的导出文件部分:
DELIMITER $$
--
-- Procedures
--
CREATE DEFINER=`marc`@`%` PROCEDURE `add_page`(IN param_isbn
VARCHAR(25), IN param_pages INT, OUT param_message VARCHAR(100))
BEGIN
IF param_pages > 100 THEN
SET param_message = 'the number of pages is too big';
ELSE
UPDATE book SET page_count = page_count + param_pages WHERE
isbn=param_isbn;
SET param_message = 'success';
END IF;
END$$
--
-- Functions
--
CREATE DEFINER=`marc`@`%` FUNCTION `get_country_name`
(param_country_code CHAR(2)) RETURNS varchar(50) CHARSET latin1
READS SQL DATA
BEGIN
DECLARE var_country_name VARCHAR(50) DEFAULT 'not found';
SELECT description into var_country_name FROM country WHERE
code = param_country_code;
RETURN var_country_name;
END$$
DELIMITER ;
执行触发器代码
触发器是我们与表关联的代码,当发生某些操作时执行,例如,在book表中的新INSERT语句之后。操作不需要在 phpMyAdmin 中发生。
与与整个数据库相关的例程不同,每个表的触发器可以从该特定表的结构页面访问。
注意
在 MySQL 5.1.6 之前,我们需要SUPER权限来创建和删除触发器。在 5.1.6 版本中,特权系统中添加了TRIGGER表级特权。因此,用户不再需要强大的SUPER权限来执行这些任务。
为了执行以下练习,我们将需要在我们的author表中添加一个新的INT列total_page_count。
这里的想法是,每次创建一本书时,它的页数将被添加到该作者的书的总页数中。有些人可能主张最好不要为总数保留单独的列,而是在需要时每次计算总数。实际上,在处理这种情况时必须做出设计决策。我们是否需要非常快速地检索总页数,例如用于网页目的?从具有数千行的生产表中计算此值的响应时间是多少?无论如何,由于我需要它作为一个例子,这里的设计决策很容易做出。
我们不要忘记,在将其添加到表的结构后,total_page_count列应该最初用正确的总数进行填充。(但是,这不是我们触发器的目的。)
手动创建触发器
当前的 phpMyAdmin 版本没有触发器创建界面。因此,我们在查询框中输入触发器定义时要特别注意在分隔符框中输入//:
CREATE TRIGGER after_book_insert AFTER INSERT ON book
FOR EACH ROW
BEGIN
UPDATE author
SET total_page_count = total_page_count + NEW.page_count
WHERE id = NEW.author_id;
END
//
稍后,我们的book表的结构页面显示了一个新的触发器部分,可以像例程一样使用,用于编辑或删除触发器,如下面的屏幕截图所示:
手动创建触发器
测试触发器
与测试存储过程或函数相反,触发器中没有CALL序列,也没有在SELECT语句中执行触发器的函数。每当发生定义的操作(例如书籍INSERT)时,代码将执行(在我们的案例中是在插入后)。因此,我们只需插入一本新书,就可以看到author.total_page_count列被更新。
当然,完全自动管理此列将涉及在book表上创建AFTER UPDATE和AFTER DELETE触发器。
使用 information_schema
在 SQL:2003 标准中,通过称为information_schema的结构提供对数据字典(或数据库元数据)的访问。由于这是标准的一部分,并且已经存在于其他数据库系统中,决定将此功能实现到 MySQL 中是一个非常好的决定。
注意
MySQL 添加了一些标准之外的信息,例如INFORMATION_SCHEMA.COLUMNS.COLUMN_TYPE。请注意,如果您在软件项目中使用此信息,可能无法在其他 SQL 实现中移植。
phpMyAdmin 用户将information_schema视为包含视图的普通数据库。这些视图描述了托管在此服务器上的数据库结构的许多方面。以下屏幕截图显示了可以看到的部分内容(实际上,对于此数据库唯一可能的操作是SELECT):
在内部,phpMyAdmin 可以调用information_schema,而不是相应的SHOW语句来检索元数据。这种行为由$cfg['Servers'][$i]['DisableIS']指令控制。当服务器托管数百个数据库或表时,一些涉及information_schema上WHERE子句的SELECT操作非常慢(等待时间长达几分钟),而 MySQL 团队尚未解决这个问题;这就是为什么此指令默认设置为true,从而避免使用information_schema。
$cfg['Servers'][$i]['hide_db']参数可用于隐藏这个对于对 MySQL 水平不够熟悉的用户来说突然出现的数据库。这可能取决于他们在 MySQL 中的专业水平。在 phpMyAdmin 的多用户安装中,我们无法满足每个人对于此参数值的期望。
分区
MySQL 5.1 提供了用户定义的分区(参考dev.mysql.com/doc/refman/5.1/en/partitioning.html)。它允许我们根据需要设置规则,将表的部分分布到文件系统中。在 phpMyAdmin 中使用此功能需要了解其语法,因为有许多分区类型。此外,对于每种分区类型,分区的数量和与每个分区关联的值过于随机,无法在 Web 界面上轻松表示。
创建带有分区的表
让我们尝试通过创建名为test的表并添加一个id列来测试。在连接到 MySQL 5.1 服务器时,如果在表创建面板上,phpMyAdmin 会显示一个分区定义对话框,如下屏幕截图所示:
在这里,我们输入一个PARTITION BY RANGE子句,它将在id列上创建分区:
PARTITION BY RANGE (id) (
PARTITION p0 VALUES LESS THAN (1000),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN (30000)
);
维护分区
对于已定义分区的表,操作页面显示了一个分区维护对话框,我们可以:
-
选择一个分区,然后请求一个操作,比如重建
-
移除分区
导出分区定义
最后,在 SQL 模式下导出此test表会生成带有嵌入式注释的语句,MySQL 5.1 服务器将识别并解释这些语句以重新创建相同的分区:
CREATE TABLE `test` (
`id` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN (1000) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (2000) ENGINE = MyISAM,
PARTITION p2 VALUES LESS THAN (3000) ENGINE = MyISAM) */;
探索事件调度程序
事件调度程序(dev.mysql.com/doc/refman/5.1/en/events.html),是 MySQL 5.1 的另一个新功能,允许创建根据时间表自动运行的任务。时间表非常灵活,允许例如,从 2011 年 5 月 18 日午夜开始,每十秒运行一次语句。这些可以是一次性事件或定期事件。
激活调度程序
我们应该首先验证调度程序是否在我们的服务器上处于活动状态。如果没有,我们需要激活它。否则,什么也不会发生!我们将首先在查询框中输入以下语句:
SHOW VARIABLES LIKE 'event%';
接下来,我们在结果中查找名为event_scheduler的变量。如果此变量设置为OFF,我们需要要求系统管理员(或具有SUPER特权的人)执行以下语句:
SET GLOBAL event_scheduler = ON;
授予 EVENT 权限
每个想要创建或删除事件的用户都需要EVENT权限,可以是全局的,也可以是计划添加事件的数据库上的权限。有关授予此类权限的详细信息,请参阅第十九章。
创建事件
当前的 phpMyAdmin 版本没有一个界面,我们可以在其中选择CREATE EVENT语句的各个部分。因此,唯一剩下的方法是使用 SQL 查询框来输入语句并理解其语法!在这里,我们将使用一个完全虚构的例子:
CREATE EVENT add_page_count
ON SCHEDULE
EVERY 1 MINUTE
DO
UPDATE author set total_page_count = total_page_count + 1
WHERE id = 1;
现在,您可以偶尔浏览author表,看到作者 1 的计数器递增,从而获得一些乐趣。
操作事件
事件与单个数据库相关,这就是为什么在marc_book数据库的Structure页面上看到一个Events滑块。激活它会显示以下面板:
事实上,这是一个经常发生的事件。我们可以使用第一个图标来编辑事件(这将导致删除和重新创建事件),使用第二个图标来删除事件。
导出
可以通过选择Add CREATE PROCEDURE / FUNCTION / EVENT选项,在 SQL 数据库导出文件的末尾生成与事件相关的语句。请记住,一些事件可能有过期时间。因此,除非在创建事件时使用了ON COMPLETION PRESERVE子句,否则它们可能在您创建它们和尝试导出它们之间消失。
总结
MySQL 5.0 的新功能帮助产品符合标准。尽管 phpMyAdmin 对这些功能的支持有限(尤其是缺乏面向语法的编辑器),但它具有一组基本的功能,可用于处理视图、例程、触发器和information_schema。phpMyAdmin 还支持 MySQL 5.1 的分区和事件。
下一章介绍了使用跟踪功能,允许通过 phpMyAdmin 记录对 MySQL 数据库所做的更改。
第十八章:跟踪变化
本章将研究如何使用跟踪机制,以记录从 phpMyAdmin 界面进行的结构和数据更改,并获取有关此类更改的报告。
了解跟踪系统的目标
每个软件应用程序都有自己的想法,对于其用户来说,跟踪哪些变化是重要的。本节描述了其他应用程序中存在的跟踪系统,并将它们与 phpMyAdmin 提供的系统进行了比较。
其他软件应用程序中的跟踪
访问显示信息系统的所有更改的历史数据是许多软件产品中被视为理所当然的功能。任何严肃的文字处理软件的“撤消”功能就是能够回到过去的一个例子,尽管是一步一步的。更复杂的例子是 MediaWiki 的历史功能(维基百科的核心软件)。它使我们能够回到给定页面的任何状态,查看任何两个版本之间的更改,甚至将任何旧版本标记为当前版本。跟踪信息包括作者(或 IP 地址)、更改的日期和时间以及评论。
在 MySQL 本身中,日志系统(binlog)记录对数据库所做的所有更改;但是,在这种情况下,目标是双重的:
-
允许主从同步
-
通过
mysqlbinlog命令行实用程序启用恢复
phpMyAdmin 中的跟踪
phpMyAdmin 的跟踪系统允许用户指定要跟踪的表,因此可以称为选择加入系统。默认情况下,除非开发人员选择这样做,否则不会跟踪任何表;当开发人员为表激活跟踪时,即使由其他人执行,更改也开始记录。只记录通过 phpMyAdmin 进行的更改。
此外,对于给定的表,我们可以指示我们有兴趣跟踪哪些语句。语句列表分为两组:数据定义和数据操作。
假设一个团队正在进行涉及对表结构进行更改的项目。启用跟踪并假设每个开发人员都使用自己的帐户登录到 MySQL,现在我们可以访问历史数据,包括有关哪个开发人员删除了一些关键列的信息!当然,这种跟踪并不是防篡改的;毕竟,它存储在 MySQL 表中,因此此跟踪信息的安全性取决于谁可以访问跟踪表。
先决条件
phpMyAdmin 配置存储包含跟踪机制的所有元数据。如果我们之前实现了此存储(例如,对于以前的 phpMyAdmin 版本,如 3.1 或更早版本),我们可以使用当前 phpMyAdmin 版本的scripts/create_tables.sql来升级配置存储,以添加缺少的表(在我们的情况下,pma_tracking表)。原因是该脚本通过使用CREATE TABLE IF NOT EXISTS pma_tracking``语句谨慎地创建此表,从而确保如果表已经存在,则不会创建该表。
注意
在 phpMyAdmin 3.3.3 中,pma_tracking中的data_sql列的类型从TEXT更改为LONGTEXT,在create_tables.sql脚本中。因此,如果我们在 3.3.3 版本之前运行了此脚本,重要的是在我们自己的pma_tracking表中手动进行此更改。
配置基本跟踪机制
在config.inc.php中,对于特定 MySQL 服务器的配置,$cfg['Servers'][$i]['tracking']应包含跟踪表的名称;建议的名称是pma_tracking,以匹配scripts/create_tables.sql中的默认值。
注意
如果此指令留空,则在此服务器上无法进行跟踪(我们将看不到跟踪菜单)。
默认情况下,跟踪必须针对每个表进行激活。如果我们希望跟踪机制自动开启所有未来的表和视图,可以将$cfg['Servers'][$i]['tracking_version_auto_create']设置为TRUE。请注意,这仅适用于未来的表和视图——我们仍然需要为现有的表激活跟踪。
使用自动创建的优势在于我们不必考虑它;跟踪是从表的诞生开始的。这种不便之处是我们无法选择要跟踪的语句;这些将从默认列表中获取(请参阅本章后面的“选择要跟踪的语句”部分)。
其他配置指令将在相关部分中讨论。
原则
本节定义了跟踪机制的重要原则:版本控制、快照和跟踪信息的归档问题。
版本控制
使用版本号是我们熟悉的事情;例如,本书描述了 phpMyAdmin 版本 3.4.x。然而,在这一点上,我们必须确切地理解为什么要使用版本号。
关于软件版本控制的良好参考资料可以在维基百科的en.wikipedia.org/wiki/Software_versioning找到。这篇文章提到可以使用版本名称,但版本号更常见。更重要的是,它指出版本号“对应于软件的新发展”。
如果我们将这个原则应用到数据库开发中,那么当一个表即将发生重大变化时,决定是否为该表创建新版本应该由开发团队做出。触发新版本的变化有多重要是团队内部解释的问题。至少有一个决定是容易做出的:版本 1 始终代表我们首次为特定表启用跟踪的时刻。
在跟踪数据操作语句的情况下,我们还应该注意到变化可能与数据本身有关,而不一定与结构有关。
注意
phpMyAdmin 的跟踪系统只使用正整数作为版本号;不可能使用小数点,比如"1.1"。
拍摄当前结构的快照
每次创建新版本时,跟踪系统都会拍摄表的当前结构和索引的快照,并在跟踪系统中创建一个新条目。在这个条目中存储了数据库名称、表名称、版本号、创建日期和完整的结构信息。
注意
这个跟踪快照不包含表的数据!因此,跟踪系统不能替代备份系统。
在快照被拍摄后,表的整个生命周期中,所有被跟踪的语句都会与这个快照一起存储。因此,表的跟踪版本包括快照以及在拍摄快照后进行的所有更改,直到启动新版本。
理解归档问题
当一个表被删除时,它的跟踪信息会被保留,除非我们决定将其删除。这个影响将在后面的“删除跟踪信息”部分中讨论。
启动单个表的跟踪
在这一部分,我们将在“表”视图中使用“跟踪”菜单来开始收集author表发生的变化。因此,我们打开author表,然后点击“跟踪”,会出现以下屏幕:
这个面板告诉我们,我们即将创建表的版本 1;这是我们预期的。我们可以选择数据定义和数据操作语句;现在我们将它们全部标记,然后点击“创建版本”按钮。下一部分将解释如何指定要在上面显示的面板中出现的语句。
创建版本 1 后,会显示以下确认面板:
我们注意到发生了两个不同的动作:
-
版本 1 本身的创建
-
为这个表激活跟踪
实际上,一个表可能存在一个或多个版本,每个版本包含从某个时间点开始的快照和自此快照以来的更改;但这与表是否处于跟踪状态并且更改正在记录无关。
在这个面板中,我们看到将在选择要跟踪的语句和停用和启用跟踪部分中涵盖的子面板。
选择要跟踪的语句
$cfg['Servers'][$i]['tracking_default_statements']包含一个由逗号分隔的字符串。这些是在我们可以选择要跟踪哪些语句的面板中提供的语句。默认语句列表定义如下;请注意 PHP 中允许字符串连接的点字符的存在:
$cfg['Servers'][$i]['tracking_default_statements'] =
'CREATE TABLE,ALTER TABLE,DROP TABLE,RENAME TABLE,' .
'CREATE INDEX,DROP INDEX,' .
'INSERT,UPDATE,DELETE,TRUNCATE,REPLACE,' .
'CREATE VIEW,ALTER VIEW,DROP VIEW,' .
'CREATE DATABASE,ALTER DATABASE,DROP DATABASE';
测试跟踪机制
我们现在准备验证这个跟踪系统是否真的有效!由于系统应该跟踪ALTER TABLE语句,我们将进行一个轻微的结构更改,看看会发生什么。我们转到作者表的结构面板,选择姓名列,并将其大小从30增加到40个字符(详细步骤请参阅第五章)。
我们会收到一条消息,如下截图所示:
我们将执行另一个动作,这次与数据本身有关——将作者John Smith的电话号码更改为111-2222。
为了确保这些动作被跟踪系统记录下来,让我们编制一份报告。
跟踪报告
回到跟踪面板(仍然在作者的表视图中),我们点击版本 1 的跟踪报告,生成如下截图所示的报告:
实际上,报告是附加在主要跟踪信息之前的;我们可以点击关闭,回到之前的位置。
我们可以看到,在跟踪报告标题下,显示了被跟踪的语句列表。然后我们有一个选择器,确定我们是否要在报告中查看与之对应的语句:
-
结构和数据
-
仅结构
-
仅数据
我们还可以指定要生成报告的日期和时间范围。还可以指示我们要报告的用户(星号代表所有用户)。
报告的主要部分包括语句本身;这里我们看到四个语句。第一个语句是一个DROP TABLE语句,如果我们需要导出这个版本并将其重新导入,这将有用。第二个语句(CREATE TABLE)包含了在初始化版本 1 时拍摄的快照。然后我们看到对应于我们执行的操作的ALTER TABLE和UPDATE语句。
如何导出结构将在本章后面的导出版本部分中介绍。
确定跟踪状态
让我们覆盖界面中所有可以确定表的跟踪活动的地方。首先,在表视图中,我们可以看到一个消息,位于菜单选项卡下方,说明对于这个表,跟踪已激活,如下截图所示:
在跟踪面板本身,状态列告诉我们最新版本的跟踪是激活还是未激活。实际上,当我们为表创建另一个版本时,我们会发现只有当前版本可以具有激活的跟踪状态,因为以前的版本现在只包含历史数据。
在数据库视图中,系统跟踪的每个表(具有活跃或非活跃状态)都显示为一个眼睛图标,颜色或灰色取决于其状态。在下面的示例中,眼睛是彩色的:
这个眼睛图标是可点击的,可以将我们带到这个特定表的跟踪面板。
最后,在数据库视图中,跟踪菜单为我们提供了所有表的概览。首先呈现被跟踪的表,然后是未被跟踪的表。对于任何一类别,我们都有链接可以查看更多信息或开始跟踪:
对于被跟踪的表,以下表格提供了所呈现信息的细分,以及可用的链接:
| 标题或链接 | 描述 |
|---|---|
| 数据库 | 表位于哪个数据库 |
| 表 | 被跟踪的表 |
| 最新版本 | 最新的被跟踪版本;看到这个表有多少版本存在很有趣 |
| 创建时间 | 此版本创建时间 |
| 更新时间 | 上次为此表存储的跟踪语句是什么时候 |
| 状态 | 活跃或非活跃 |
| 操作 | 删除链接可用于删除所有跟踪(请参阅本章后面的删除跟踪信息部分) |
| 显示 | 版本 | 进入此表的表视图,并显示跟踪版本 |
| 显示 | 跟踪报告 | 进入此表的表视图,并显示跟踪报告 |
| 显示 | 结构快照 | 进入此表的表视图,并显示结构快照(请参阅本章后面的结构快照部分) |
对于未被跟踪的表,跟踪表链接允许我们直接在跟踪面板中进入此表的表视图,从而创建版本 1 以开始跟踪机制。
停用和激活跟踪
从特定表的跟踪页面,立即停用按钮(作为切换,变为立即激活) 是我们希望停止(暂时或永久)进一步存储跟踪语句的按钮。存储的过去语句将保持不变,与当前版本相关的跟踪数据。
结构快照
在表视图的跟踪面板中,结构快照链接显示了在创建此版本时表的过去状态。该面板显示了存储的 SQL 代码以及熟悉的 phpMyAdmin 结构面板格式的可视化表示。
导出版本
由于在创建特定版本时存储了完整的 SQL 代码以及自那时起发生的所有跟踪语句,我们可能希望以可执行形式重用它们。在跟踪报告面板的底部,有一个导出为对话框可用,提供了三种导出变体。如果我们选择**SQL 转储(文件下载)**菜单选项,那么为此版本存储的所有语句将转移到一个文件中,我们可以保存到我们的工作站。对于author表,这将产生一个包含以下行的文件:
# Tracking report for table `author`
# 2011-10-14 14:24:12
DROP TABLE IF EXISTS `author`;
CREATE TABLE `author` (
`id` int(11) NOT NULL,
`name` varchar(30) NOT NULL,
`phone` varchar(30) CHARACTER SET latin1 DEFAULT NULL,
`country_code` char(2) NOT NULL,
`total_page_count` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `author` CHANGE `name` `name` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
UPDATE `author` SET `phone` = '111-2222' WHERE `author`.`id` = 1;
如果我们选择SQL 转储选项,语句将显示在屏幕上的文本区域中;从这一点上,我们可以剪切和粘贴 SQL 代码或点击Go来运行它。作为预防措施,额外的语句会在代码的顶部生成;这些语句处理了在其中表将被创建的另一个数据库的创建。当然,用户必须有创建此数据库的权限。
最后,SQL 执行选项允许直接执行当前数据库中存储的语句。但是,由于这些语句可能反映表的旧状态,因此会发出警告消息;我们可能不想恢复到这个旧状态。此外,默认情况下,第一个语句是DROP TABLE,这取决于是否有外键约束阻止删除表。
创建一个新版本
如前所述,我们可以决定为某个表标记一个新的里程碑;换句话说,我们可以开始一个新版本。现在我们将创建一个新版本作为练习。
在author表的跟踪面板中,我们看到了创建版本 2的对话框(因为最高的是当前版本 1):
我们注意到每个版本可以跟踪自己的一组语句;在这方面,版本是彼此独立的。在这里,我们决定版本 2 将仅跟踪数据定义语句。现在我们看到了与这些版本的状态相关的一些有趣的东西,如下面的屏幕截图所示:
实际上,版本 1 被自动标记为不活跃;它进入了某种历史状态。我们还可以查看版本 2 的快照,其中反映了name列是VARCHAR(40)。
快速访问跟踪信息
当我们在一个表的跟踪面板中时,一个快捷对话框允许我们直接转到任何其他已跟踪表的跟踪面板。
为了探索这个功能,让我们现在创建book表的版本 1。完成后,我们检查显示版本按钮旁边的下拉列表,如下面的屏幕截图所示:
这个列表与查看跟踪面板中数据库marc_book的已跟踪表部分时所看到的类似,但无需返回到此面板。
删除跟踪信息
跟踪系统的一个特性可能不明显的是,当相应的表被删除时,表的所有版本以及其整个生命周期的跟踪信息仍然保留。原因是保持历史信息完整,以防我们以后创建具有相同名称的表。
让我们复制author表(如果需要,请参阅第九章),并将其命名为author_copy。然后我们在这个新表上激活跟踪。最后一个操作是删除author_copy表。即使我们在正常的表列表中不再看到它,在数据库marc_book的跟踪面板中却不同。
此时,我们可以回到过去,看看已删除表的版本的跟踪报告和快照。如果我们真的想要删除表曾经存在的所有证据,那么我们可以使用删除链接来销毁跟踪数据(在随后的确认面板中单击确定后)。
总结
在本章中,我们概述了语句跟踪功能所带来的好处,然后介绍了用于创建和维护表版本的所有面板。
下一章将涵盖 MySQL 服务器的管理,重点是管理用户帐户和权限。
第十九章:管理 MySQL 服务器
本章讨论了系统管理员如何使用 phpMyAdmin 服务器管理功能进行日常用户帐户维护、服务器验证和服务器保护。还涵盖了非管理员如何从 phpMyAdmin 获取服务器信息的主题。
服务器管理主要通过服务器视图完成,可以通过 phpMyAdmin 主页上可用的菜单选项卡访问。
管理用户及其权限
权限页面(仅在我们以特权用户身份登录时可见)包含了管理 MySQL 用户帐户的对话框。它还包含了管理全局、数据库和表级别权限的对话框。此页面是分层的。在编辑用户的权限时,我们可以看到全局权限以及特定于数据库的权限。然后,在查看用户的特定于数据库的权限时,我们可以查看并编辑该用户在该数据库中的任何表的权限。
用户概述
当我们进入权限页面时显示的第一页称为用户概述。这显示了所有用户帐户及其全局权限的摘要,如下面的屏幕截图所示:
从这个页面,我们可以:
-
通过编辑权限链接编辑用户的权限
-
通过用户导出链接导出用户的权限定义
-
使用复选框通过删除所选用户对话框删除用户
-
访问添加新用户对话框可用的页面
显示的用户列表具有以下特征的列:
| 列 | 特征 |
|---|---|
| 用户 | 我们正在定义的用户帐户。 |
| 主机 | 此用户帐户将连接到 MySQL 服务器的机器名称或 IP 地址。这里的**%**值表示所有主机。 |
| 密码 | 如果定义了密码,则包含是,如果没有定义,则包含否。密码本身无法从 phpMyAdmin 的界面或直接查看mysql.user表中看到,因为它是使用单向哈希算法加密的。 |
| 全局权限 | 用户的全局权限列表。 |
| 授权 | 如果用户可以将他/她的权限授予他人,则包含是。 |
| 操作 | 包含一个链接,用于编辑此用户的权限或导出它们。 |
导出权限
这个功能在我们需要在另一个 MySQL 服务器上创建具有相同密码和权限的用户时非常有用。单击导出用户marc会产生以下面板:
然后只需选择这些GRANT语句,并将它们粘贴到另一个已登录到另一个 MySQL 服务器的 phpMyAdmin 窗口的 SQL 框中。
权限重新加载
在用户概述页面底部显示了以下消息:
Note: phpMyAdmin gets the users' privileges directly from MySQL's privilege tables. The content of these tables may differ from the privileges the server uses, if they have been changed manually. In this case, you should reload the privileges before you continue.
在这里,“重新加载权限”文本是可点击的。有效权限(服务器基于其访问决策的权限)是位于服务器内存中的权限。从用户概述页面进行的权限修改在内存中和mysql数据库中都进行了修改。直接对mysql数据库进行的修改不会立即生效。重新加载权限操作会从数据库中读取权限,并使其在内存中生效。
添加用户
添加新用户链接打开了一个用户帐户创建对话框。首先,我们看到的是我们将描述帐户本身的面板,如下面的屏幕截图所示:
添加新用户对话框的第二部分是我们将指定用户的全局权限的地方,这些权限适用于整个服务器(请参阅本章的分配全局权限部分),如下面的屏幕截图所示:
输入用户名
用户名菜单提供两个选择。我们可以选择使用文本字段:并在框中输入用户名,或者我们可以选择任何用户来创建匿名用户(空用户)。有关匿名用户的更多详细信息,请参见dev.mysql.com/doc/refman/5.5/en/connection-access.html。让我们选择使用文本字段:并输入bill。
分配主机值
默认情况下,此菜单设置为任何主机,主机值为**%。本地选择意味着localhost。使用主机表选择(在主机字段中创建空值)意味着在mysql.host表中查找特定于数据库的权限。选择使用文本字段:允许我们输入我们想要的确切主机值。让我们选择本地**。
设置密码
即使可以创建一个没有密码的用户(选择无密码选项),最好还是有一个密码。我们必须输入两次(因为我们看不到输入的内容)以确认预期的密码。安全密码应该有超过八个字符,并且应该包含大写和小写字母,数字和特殊字符的混合。因此,建议使用 phpMyAdmin 生成密码-这在启用 JavaScript 的浏览器中是可能的。在生成密码对话框中,点击生成按钮会在屏幕上输入一个随机密码(明文),并在密码和重新输入输入字段中填入生成的密码。在这一点上,我们应该记住密码,以便将其传递给用户。
理解数据库创建的权限
一个常见的约定是将用户的权限分配给与该用户同名的数据库。为了实现这一点,用户数据库部分提供了创建具有相同名称并授予所有权限的数据库单选按钮。选择此复选框会自动化该过程,通过创建数据库(如果尚不存在)并分配相应的权限。请注意,使用此方法,每个用户将被限制为一个数据库(用户bill,数据库bill)。
另一种可能性是允许用户创建具有与其用户名相同前缀的数据库。因此,另一个选择授予通配符名称(username_%)的所有权限通过分配通配符权限来执行此功能。有了这个设置,用户bill可以创建数据库bill_test, bill_2, bill_payroll等;在这种情况下,phpMyAdmin 不会预先创建数据库。
分配全局权限
全局权限决定用户对所有数据库的访问权限。因此,有时这些被称为超级用户权限。普通用户不应该拥有这些权限,除非有充分的理由。此外,如果拥有全局权限的用户帐户受到损害,损害可能会更大。
如果我们真的在创建一个超级用户,我们将选择他或她需要的每个全局权限。这些权限进一步分为数据,结构和管理组。
在我们的例子中,bill将不会拥有任何全局权限。
限制使用的资源
我们可以限制此用户在此服务器上使用的资源(例如,每小时的最大查询数)。零表示没有限制。我们不会对bill施加任何资源限制。
以下屏幕截图显示了在点击创建用户之前创建此用户定义的屏幕状态(其余字段设置为默认值):
编辑用户配置文件
每当我们在用户概述页面上为用户点击编辑权限时,用于编辑用户配置文件的页面就会出现。让我们尝试为我们新创建的用户bill尝试一下。此页面有四个部分,每个部分都有自己的Go按钮。因此,每个部分都是独立操作的,并且具有不同的目的。
编辑全局权限
编辑用户权限的部分与添加新用户对话框看起来一样,并用于查看和更改全局权限。
分配特定于数据库的权限
在这个部分,我们定义用户可以访问的数据库,以及他/她在这些数据库上的确切权限。
如前面的截图所示,我们看到None,因为我们尚未定义任何权限。定义数据库权限有两种方式。首先,我们可以从下拉菜单中选择一个现有的数据库,如下截图所示:
这仅为所选数据库分配权限。其次,我们还可以选择**使用文本字段:**并输入数据库名称。我们可以输入一个不存在的数据库名称,以便用户稍后可以创建它(前提是我们在下一个面板中给予他/她CREATE权限)。我们还可以使用特殊字符,如下划线和百分号,作为通配符。
例如,在这里输入bill会使他能够创建一个bill数据库,输入bill%会使他能够创建以bill开头的任何名称的数据库。在我们的例子中,我们将输入bill并点击Go。
下一个屏幕用于设置bill在bill数据库上的权限,并创建特定于表的权限。
要了解特定权限的含义,我们可以将鼠标悬停在权限名称上(始终为英文),并且会出现关于此权限的解释。我们在这个数据库上给予bill SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX和DROP权限,然后点击Go。
在分配了权限之后,界面仍停留在原地,以便我们可以进一步细化这些权限。目前我们无法分配特定于表的权限,因为数据库尚不存在。
要返回到bill的一般权限页面,请点击**'bill'@'localhost'**标题。
这将使我们回到以下熟悉的页面,除了一个部分的变化:
我们看到bill在bill数据库上的现有权限(我们可以点击编辑权限链接进行编辑,或点击撤销链接进行撤销),并且我们可以为bill在另一个数据库上添加权限。我们还可以看到bill在bill数据库上没有特定于表的权限。
更改密码
更改密码对话框是编辑用户页面的一部分,我们可以使用它来更改bill的密码或删除密码。删除密码将使bill可以无密码登录。对话框提供了密码哈希选项的选择,并建议保持默认的**MySQL 4.1+**哈希。有关哈希的更多详细信息,请访问dev.mysql.com/doc/refman/5.1/en/password-hashing.html。
更改登录信息或复制用户
此对话框可用于更改用户的登录信息,或将其登录信息复制到新用户。例如,假设 Bill 打电话告诉我们,他更喜欢登录名billy而不是bill。我们只需在用户名后添加一个y,然后选择从用户表中删除旧的单选按钮,如下截图所示:
点击Go, bill后,mysql数据库中将不再存在bill。此外,他的所有权限,包括对bill数据库的权限,都将被转移到新用户billy。但是,bill的用户定义仍将存在于内存中,因此仍然有效。如果我们选择了从用户表中删除旧用户并重新加载权限选项,bill的用户定义将立即失效。
或者,我们可以基于bill创建另一个用户,通过使用保留旧用户选项。我们可以通过选择不更改密码选项将密码转移到新用户,或者通过两次输入新密码来更改密码。**撤销所有活动权限…**选项立即终止了该用户的当前有效权限,即使他或她当前已登录。
删除用户
从权限页面的用户概述部分删除用户。我们选择要删除的用户。然后(在删除选定的用户中)我们可以选择删除与要删除的用户同名的数据库选项,以删除以这些用户命名的任何数据库。点击Go有效地删除了选定的用户。
数据库信息
数据库页面旨在创建新数据库,并快速获取每个数据库的权限信息。还可以用来获取这些数据库的全局统计信息,而无需在导航面板中单击每个数据库。当我们进入数据库页面时,我们会看到现有数据库的列表:
我们还看到一个启用统计信息链接。默认情况下,统计信息是未启用的,因为计算所有数据库中所有表的数据和索引大小可能会消耗宝贵的 MySQL 服务器资源。
启用统计信息
如果我们点击启用统计信息链接,会出现一个修改后的页面。对于每个数据库,我们可以得到该数据库中表的默认排序规则,以及该数据库中表的数量和所有表的总行数。接下来是有关表数据部分使用的空间的信息,然后是所有索引占用的空间,以及所有表的总空间。接下来,在开销列标题下呈现了通过优化该数据库中的一些表可以回收的空间。最后,我们可以看到复制信息,然后是检查权限链接:
排序统计信息
默认情况下,统计信息列表按数据库名称按升序排序。如果我们需要找到具有最多表的数据库或占用最多空间的数据库,只需简单点击表或总计列标题,列表将相应地排序。第二次点击将反转排序顺序。
检查数据库权限
点击检查权限图标或链接会显示特定数据库上的所有权限。用户的全局权限可能会显示在这里,因为它也允许他或她访问这个数据库。我们还可以看到特定于这个数据库的权限。编辑权限链接会带我们到另一个页面,用于编辑用户的权限。
我们注意到这个面板还包含添加新用户链接。点击这个链接是创建一个具有对我们当前正在检查的数据库的权限的用户的便捷方式。事实上,在从这个链接进入用户创建面板后,数据库创建或授予权限对话框中显示并默认选择了第四个选项,如下截图所示:
删除选定的数据库
要删除一个或多个数据库,我们转到服务器视图,单击数据库菜单选项;在要删除的数据库名称旁边打勾;然后单击所选项下的删除链接。然后我们会得到一个确认屏幕。两个数据库(mysql和虚拟的information_schema)不能被选择;第一个是为了避免犯大错并删除所有我们的账户,第二个不能被选择,因为这不是一个真正的数据库。
注意
这是一个不应轻率对待的操作,可能明智的是首先将整个数据库导出备份。
服务器信息
管理员和普通用户都可以从监控服务器并获取有关其一般配置和行为的信息中受益。状态,变量和进程菜单选项可用于获取有关 MySQL 服务器的信息,或者对特定进程进行操作。
验证服务器状态
服务器状态统计反映了 MySQL 服务器的总活动,包括(但不限于)从 phpMyAdmin 发送的查询生成的活动。
单击状态菜单选项会生成有关服务器的运行时信息。页面有几个部分。首先,我们获取有关已运行时间和启动时间的信息。然后,我们获取流量和连接的总值和平均值(其中ø表示平均值),如下面的屏幕截图所示:
接下来,显示有关查询的统计信息(在屏幕截图中部分显示)。每小时、每分钟和每秒的平均查询次数很好地指示了服务器的负载。
查询统计后是有关执行的每个 MySQL 语句的统计信息,包括:
-
每个语句执行的绝对次数
-
执行的小时平均值
-
与所有语句相比,该语句的执行百分比
演示顺序按利用率降序排列;在下面的屏幕截图中,我们看到set option语句是此服务器上最常接收的语句,占37.40%:
在查询统计之后,单击显示查询图表链接会生成一个显示此服务器上流行查询类型的图表,如下面的屏幕截图所示:
根据 MySQL 版本,还会显示许多其他包含服务器信息的部分。
服务器变量
变量页面显示了 MySQL 服务器的各种设置,这些设置可以在my.cnf MySQL 配置文件中定义。这些值无法在 phpMyAdmin 内更改。
服务器进程
进程页面可供超级用户和普通用户使用。普通用户只能看到属于他们自己的进程,而超级用户可以看到所有进程。
此页面列出了服务器上的所有活动进程。有一个终止链接,允许我们终止特定进程,如下面的屏幕截图所示:
此示例仅有两个正在运行的进程,包括由SHOW PROCESSLIST命令本身创建的进程。此进程无法终止,因为当我们看到页面时,它已经不再运行。在繁忙的服务器上,我们会看到更多正在运行的进程。
存储引擎
有关各种存储引擎的信息以两级格式提供。首先,引擎选项卡显示了当前 MySQL 版本的可能引擎的概述。在此服务器上启用的引擎的名称是可点击的。
其次,单击一个引擎名称会显示有关其设置的详细面板。将鼠标悬停在上标数字上会显示有关特定设置的更多信息。
可用字符集和校对规则
主页上的“字符集”菜单选项卡打开了“服务器”视图的“字符集”页面,其中列出了 MySQL 服务器支持的字符集和校对规则。每个字符集的默认校对规则显示为不同的背景颜色(使用在$cfg['BrowseMarkerColor']中定义的行标记颜色)。
检查二进制日志
如果我们的服务器上激活了 MySQL 的二进制日志记录,那么“服务器”视图中的菜单会发生变化,出现一个“二进制日志”选项卡。该选项卡通过SHOW BINLOG EVENTS命令提供了访问接口。该命令生成了更新了我们服务器上数据的 SQL 语句列表。这个列表可能非常庞大,目前 phpMyAdmin 没有使用分页技术限制其显示。因此,我们可能会达到浏览器的内存限制,这取决于我们使用的特定浏览器。
在下面的截图中,我们选择要检查的二进制日志(除非服务器只有一个二进制日志),然后显示语句:
总结
本章介绍了系统管理员可以使用的各种功能,如用户帐户管理、权限管理、数据库权限检查和服务器状态验证。适当的了解 MySQL 权限系统对于充分维护 MySQL 服务器至关重要,本章提出了围绕用户及其权限概念的练习。
附录,故障排除和支持,描述了在哪里获取支持以使 phpMyAdmin 高效运行。