云文档网 - 专业文章范例文档资料分享平台

1.基础篇_修改by徐定翔2_去掉批注

来源:网络收集 时间:2024-05-04 下载这篇文档 手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xuecool-com或QQ:370150219 处理(尽可能给您提供完整文档),感谢您的支持与谅解。点击这里给我发消息

件夹属主和所属组都设置为mysql,且禁用其他所有用户(除了拥有超级权限的用户,如root)的读写权限。以防止数据或者日志文件被窃取或破坏。因为如果一个用户对MySQL的数据文件有读取权限的话,可以很容易将数据复制。binlog文件也很容易还原整个数据库。而如果有写权限的话就更糟了,因为有了写权限,数据或者日志文件就有被破坏或者删除的风险存在。保护好socket文件的安全,尽量不要使用默认的位置(如/tmp/mysql.sock),以防止被有意或无意的删除。

确保MySQL Server所在的主机上所必要运行的其他应用或者服务足够安全,避免因为其他应用或者服务存在安全漏洞而被入侵者攻破防线。

在OS层面还有很多关于安全方面的其他设置和需要注意的地方,但考虑到篇幅问题,这里就不做进一步分析了,有兴趣的读者可以参考各种不同OS在安全方面的专业书籍。

再次,就是最后第三道防线MySQL自身方面的安全设置注意事项。

到了最后这道防线上,我们有更多需要注意的地方。

用户设置。我们必须确保任何可以访问数据库的用户都有一个比较复杂的内容作为密码,而不是非常简单或者比较有规律的字符,以防止被使用字典破解程序攻破。在MySQL初始安装完成之后,系统中可能存在一个不需要任何密码的root用户,有些版本安装完成之后还会存在一个可以通过localhost登录的没有用户名和密码的帐号。这些帐号会给系统带来极大的安全隐患,所以我们必须在正式启用之前尽早删除,或者设置一个比较安全的密码。对于密码数据的存放,也不要存放在简单的文本文件之中,而应该使用专业密码管理软件来管理(如KeePass)。同时,就像之前在网络安全注意事项部分讲到的那样,尽可能为每一个帐户限定一定范围的可访问主机。尤其是拥有超级权限的MySQL root帐号,尽量确保只能通过localhost访问。

安全参数。在MySQL官方参考手册中也有说明,不论是从安全方面考虑还是从性能以及功能稳定性方面考虑,不需要使用的功能模块尽量都不要启用。例如,如果不需要使用用户自定义函数,就不要在启动的时候使用“--allow-suspicious-udfs”参数选项,以防止被别有居心的潜在威胁者利用此功能而对MySQL的安全造成威胁;不需要从本地文件中Load数据到数据库中,就使用“--local-infile=0”禁用掉可以从客户端机器上Load文件到数据库中;使用新的密码规则和校验规则(不要使用“--old-passwords”启动数据库),这项功能是为了兼容旧版本的密码校验方式的,如无额数必要,不要使用该功能,旧版本的密码加密方式要比新的方式在安全方面弱很多。

除了以上这三道防线,我们还应该让连接MySQL数据库的应用程序足够安全,以防止入侵者通过应用程序中的漏洞而入侵到应用服务器,最终通过应用程序中的数据库相关关配置而获取数据库的登录口令。

4.5 小结

安全无小事,一旦安全出了问题一切都完了。数据的安全是一个企业安全方面最核心最重要的内容,只有保障的数据的安全,企业才有可能真正“安全”。希望这一章 MySQL 安全

方面的内容能够对各位读者在构筑安全的企业级 MySQL 数据库系统中带来一点帮助。

第 5 章 MySQL 备份与恢复

前言

数据库的备份与恢复一直都是 DBA 工作中最为重要的部分之一,也是基本工作之一。任何正式环境的数据库都必须有完整的备份计划和恢复测试,本章内容将主要介绍 MySQL 数据库的备份与恢复相关内容。

5.1 数据库备份使用场景

你真的明白了自己所做的数据库备份是要面对什么样的场景的吗?

我想任何一位维护过数据库的人都知道数据库是需要备份的,也知道备份数据库是数据库维护必不可少的一件事情。那么是否每一个人都知道自己所做的备份到底是为了应对哪些场景的呢?抑或者说我们每个人是否都很清楚的知道,为什么一个数据库需要作备份呢?读到这里,我想很多读者朋友都会嗤之以鼻,“备份的作用不就是为了防止原数据丢失吗,这谁不知道?”。确实,数据库的备份很大程度上的作用,就是当我们的数据库因为某些原因而造成部分或者全部数据丢失后,方便找回丢失的数据。但是,不同类型的数据库备份,所能应付情况是不一样的,而且,数据库的备份同时也还具有其他很多的作用。而且我想,每个人对数据库备份的作用的理解可能都会有部分区别。

下面我就列举一下我个人理解的我们能够需要用到数据库备份的一些比较常见的情况吧。

一、数据丢失应用场景

1、人为操作失误造成某些数据被误操作; 2、软件BUG造成数据部分或者全部丢失; 3、硬件故障造成数据库数据部分或全部丢失;

4、安全漏洞被入侵数据被恶意破坏;

二、非数据丢失应用场景

5、特殊应用场景下基于时间点的数据恢复; 6、开发测试环境数据库搭建; 7、相同数据库的新环境搭建; 8、数据库或者数据迁移;

上面所列出的只是一些常见的应用场景而已,除了上面这几种场景外,数据库备份还会有很多其他应用场景,这里就不一一列举了。那么各位读者过曾经或是现在所做的数据库备份到底是为了应对以上哪一种(或者几种)场景?或者说,我们所做的数据库备份能够应对以上哪几种应用场景?不知道这个问题大家是否有考虑过。

我们必须承认,没有哪一种数据库备份能够解决所有以上列举的几种常见应用场景,即使仅仅只是数据丢失的各种场景都无法通过某一种数据库备份完美的解决,当然也就更不用

说能够解决所有的备份应用场景了。

比如当我们遇到磁盘故障,丢失了整个数据库的所有数据,并且无法从已经出现故障的硬盘上面恢复出来的时候,我们可能必须通过一个实时或者有短暂时间差的复制备份数据库存在。当然如果没有这样的一个数据库,就必须要有最近时间的整个数据库的物理或者逻辑备份数据,并且有该备份之后的所有物理或者逻辑增量备份,以期望尽可能将数据恢复到出现故障之前最近的时间点。而当我们遇到认为操作失误造成数据被误操作之后,我们需要有一个能恢复到错误操作时间点之前的瞬间的备份存在,当然这个备份可能是整个数据库的备份,也可以仅仅只是被误操作的表的备份。而当我们要做跨平台的数据库迁移的时候,我们所需要的又只能是一个逻辑的数据库备份,因为平台的差异可能使物理备份的文件格式在两个平台上无法兼容。

既然没有哪一种很多中数据库备份能够完美的解决所有的应用场景,而每个数据库环境所需要面对的数据库备份应用场景又可能各不一样,可能只是需要面对很多种场景中的某一种或几种,那么我们就非常有必要指定一个合适的备份方案和备份策略,通过最简单的技术和最低廉的成本,来满足我们的需求。

5.2 逻辑备份与恢复测试

5.2.1 什么样的备份是数据库逻辑备份呢? 大家都知道,数据库在返回数据给我们使用的时候都是按照我们最初所设计期望的具有一定逻辑关联格式的形式一条一条数据来展现的,具有一定的商业逻辑属性,而在物理存储的层面上数据库软件却是按照数据库软件所设计的某种特定格式经过一定的处理后存放。

数据库逻辑备份就是备份软件按照我们最初所设计的逻辑关系,以数据库的逻辑结构对象为单位,将数据库中的数据按照预定义的逻辑关联格式一条一条生成相关的文本文件,以达到备份的目的。

5.2.2 常用的逻辑备份

逻辑备份可以说是最简单,也是目前中小型系统最常使用的备份方式。在MySQL中我们常用的逻辑备份主要就是两种,一种是将数据生成可以完全重现当前数据库中数据的INSERT语句,另外一种就是将数据通过逻辑备份软件,将我们数据库表数据以特定分隔符进行分隔后记录在文本文件中。

1、生成INSERT语句备份 两种逻辑备份各有优劣,所针对的使用场景也会稍有差别,我们先来看一下生成INSERT语句的逻辑备份。

在MySQL数据库中,我们一般都是通过MySQL数据库软件自带工具程序中的mysqldump来实现声称INSERT语句的逻辑备份文件。其使用方法基本如下:

Dumping definition and data mysql database or table Usage: mysqldump [OPTIONS] database [tables]

OR mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...] OR mysqldump [OPTIONS] --all-databases [OPTIONS]

由于mysqldump的使用方法比较简单,大部分需要的信息都可以通过运行“mysqldump --help”而获得。这里我只想结合MySQL数据库的一些概念原理和大家探讨一下当我们使用mysqldump来做数据库逻辑备份的时候有些什么技巧以及需要注意一些什么内容。

我们都知道,对于大多数使用数据库的软件或者网站来说,都希望自己数据库能够提供尽可能高的可用性,而不是时不时的就需要停机停止提供服务。因为一旦数据库无法提供服务,系统就无法再通过存取数据来提供一些动态功能。所以对于大多数系统来说如果要让每次备份都停机来做可能都是不可接受的,可是mysqldump程序的实现原理是通过我们给的参数信息加上数据库中的系统表信息来一个表一个表获取数据然后生成INSERT语句再写入备份文件中的。这样就出现了一个问题,在系统正常运行过程中,很可能会不断有数据变更的请求正在执行,这样就可能造成在mysqldump备份出来的数据不一致。也就是说备份数据很可能不是同一个时间点的数据,而且甚至可能都没办法满足完整性约束。这样的备份集对于有些系统来说可能并没有太大问题,但是对于有些对数据的一致性和完整性要求比较严格系统来说问题就大了,就是一个完全无效的备份集。

对于如此场景,我们该如何做?我们知道,想数据库中的数据一致,那么只有两种情况下可以做到。

第一、同一时刻取出所有数据;

第二、数据库中的数据处于静止状态。

对于第一种情况,大家肯定会想,这可能吗?不管如何,只要有两个以上的表,就算我们如何写程序,都不可能昨晚完全一致的取数时间点啊。是的,我们确实无法通过常规方法让取数的时间点完全一致,但是大家不要忘记,在同一个事务中,数据库是可以做到所读取的数据是处于同一个时间点的。所以,对于事务支持的存储引擎,如Innodb或者BDB等,我们就可以通过控制将整个备份过程控制在同一个事务中,来达到备份数据的一致性和完整性,而且mysqldump程序也给我们提供了相关的参数选项来支持该功能,就是通过“--single-transaction”选项,可以不影响数据库的任何正常服务。

对于第二种情况我想大家首先想到的肯定是将需要备份的表锁定,只允许读取而不允许写入。是的,我们确实只能这么做。我们只能通过一个折衷的处理方式,让数据库在备份过程中仅提供数据的查询服务,锁定写入的服务,来使数据暂时处于一个一致的不会被修改的状态,等mysqldump完成备份后再取消写入锁定,重新开始提供完整的服务。mysqldump程序自己也提供了相关选项如“--lock-tables”和“--lock-all-tables”,在执行之前会锁定表,执行结束后自动释放锁定。这里有一点需要注意的就是,“--lock-tables”并不是一次性将需要dump的所有表锁定,而是每次仅仅锁定一个数据库的表,如果你需要dump的表分别在多个不同的数据库中,一定要使用“--lock-all-tables”才能确保数据的一致完整性。

当通过mysqldump生成INSERT语句的逻辑备份文件的时候,有一个非常有用的选项可以供我们使用,那就是“--master-data[=value]”。当添加了“--master-data=1”的时候,mysqldump会将当前MySQL使用到binlog日志的名称和位置记录到dump文件中,并且是被以CHANGE_MASTER语句的形式记录,如果仅仅只是使用“--master-data”或者“--master-data=2”,则CHANGE_MASTER语句会以注释的形式存在。这个选项在实施slave

的在线搭建的时候是非常有用的,即使不是进行在线搭建slave,也可以在某些情况下做恢复的过程中通过备份的binlog做进一步恢复操作。

在某些场景下,我们可能只是为了将某些特殊的数据导出到其他数据库中,而又不希望通过先建临时表的方式来实现,我们还可以在通过mysqldump程序的“—where='where-condition'”来实现,但只能在仅 dump一个表的情况下使用。

其实除了以上一些使用诀窍之外,mysqldump还提供了其他很多有用的选项供大家在不同的场景下只用,如通过“--no-data”仅仅dump数据库结构创建脚本,通过“--no-create-info”去掉dump文件中创建表结构的命令等等,感兴趣的读者朋友可以详细阅读mysqldump程序的使用介绍再自行测试。

2、生成特定格式的纯文本备份数据文件备份

除了通过生成INSERT命令来做逻辑备份之外,我们还可以通过另外一种方式将数据库中的数据以特定分隔字符将数据分隔记录在文本文件中,以达到逻辑备份的效果。这样的备份数据与INSERT命令文件相比,所需要使用的存储空间更小,数据格式更加清晰明确,编辑方便。但是缺点是在同一个备份文件中不能存在多个表的备份数据,没有数据库结构的重建命令。对于备份集需要多个文件,对我们产生的影响无非就是文件多了维护和恢复成本增加,但这些基本上都可以通过编写一些简单的脚本来实现

那我们一般可以使用什么方法来生成这样的备份集文件呢,其实MySQL也已经给我们实现的相应的功能。

在MySQL中一般都使用以下两种方法来获得可以自定义分隔符的纯文本备份文件。 1、通过执行SELECT ... TO OUTFILE FROM ...命令来实现

在MySQL中提供了一种SELECT语法,专供用户通过SQL语句将某些特定数据以指定格式输出到文本文件中,同时也提供了实用工具和相关的命令可以方便的将导出文件原样再导入到数据库中。正不正是我们做备份所需要的么?

该命令有几个需要注意的参数如下:

实现字符转义功能的“FIELDS ESCAPED BY ['name']” 将SQL语句中需要转义的字符进行转义;

可以将字段的内容“包装”起来的“FIELDS [OPTIONALLY] ENCLOSED BY 'name'”,如果不使用“OPTIONALLY”则包括数字类型的所有类型数据都会被“包装”,使用“OPTIONALLY”之后,则数字类型的数据不会被指定字符“包装”。

通过\可以设定每两个字段之间的分隔符;

而通过“LINES TERMINATED BY”则会告诉MySQL输出文件在每条记录结束的时候需要添加什么字符。

如以下示例:

root@localhost : test 10:02:02> SELECT * INTO OUTFILE '/tmp/dump.text' -> FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\ -> LINES TERMINATED BY '\\n' -> FROM test_outfile limit 100;

第 1 章 MySQL 基本介绍

前言:

作为最为流行的开源数据库软件之一,MySQL 数据库软件已经是广为人知了。但是为了照顾对MySQL还不熟悉的读者,这章我们将对 MySQL 做一个简单的介绍。主要内容包括 MySQL 各功能模块组成,各模块协同工作原理,Query 处理的流程等。

1.1 MySQL Server 简介 1.1.1 什么是 MySQL

MySQL 是由MySQL AB公司(目前已经被SUN公司收归麾下)自主研发的,目前IT行业最流行的开放源代码的数据库管理系统之一,它同时也是一个支持多线程高并发多用户的关系型数据库管理系统。

MySQL 数据库以其简单高效可靠的特点,在最近短短几年的时间就从一个名不见经传的数据库系统,变成一个在IT行业几乎是无人不知的开源数据库管理系统。从微型的嵌入式系统,到小型的web网站,至大型的企业级应用,到处都可见其身影的存在。为何一个开源的数据库管理系统会变得如此的流行呢?在我2003年第一次接触MySQL之前,也是非常的纳闷?或许在我大概的向您介绍一下其发展历程之后,心中的这个问题就会消失了。

1.1.2 艰难诞生

1985年,瑞典的几位志同道合小伙子(以David Axmark为首) 成立了一家公司,这就是MySQL AB的前身。这个公司最初并不是为了开发数据库产品,而是在实现他们想法的过程中,需要一个数据库。他们希望能够使用开源的产品。但在当时并没有一个合适的选择,没办法,那就自己开发吧。

在最初,他们只是自己设计了一个利用索引顺序存取数据的方法,也就是ISAM(Indexed Sequential Access Method)存储引擎核心算法的前身,利用ISAM结合mSQL来实现他们的应用需求。在早期,他们主要是为瑞典的一些大型零售商提供数据仓库服务。在系统使用过程中,随着数据量越来越大,系统复杂度越来越高,ISAM和mSQL的组合逐渐不堪重负。在分析性能瓶颈之后,他们发现问题出在mSQL上面。不得已,他们抛弃了mSQL,重新开发了一套功能类似的数据存储引擎,这就是ISAM 存储引擎。大家可能已经注意到他们当时的主要客户是数据仓库,应该也容易理解为什么直至现在,MySQL 最擅长的是查询性能,而不是事务处理(需要借助第三方存储引擎)。

软件诞生,自然该给她取一个好听并且容易记住的名字。时至今日,MySQL AB仍然没有公布当初为什么给这个数据库系统取名为MySQL。据传MySQL是取自创始人之一Monty Widenius的女儿的名字或许大家会认为这仅仅是我的猜测,不以为然,其实也并不是完全没有根据的。大家或许知道MySQL最近正在研发的用来替代MyISAM存储引擎的新一代存储引擎产品Maria,为什么叫Maria? 笔者对这个问题也比较感兴趣,曾经和MySQL前CTO David沟通过。得到的答案是,Maria 是以他小女儿的名字命名的。看来,这是几位MySQL的创始人为自己的软件命名的一个习惯。

在MySQL诞生之初,其功能还非常粗糙,和当时已经成熟稳定运营多年的商业数据库管理系统完全不能比。MySQL之所以能够成功,和几个创始人最初采用的策略关系非常大。

1.1.3 寻求发展

MySQL诞生的时候,正是互联网开始高速发展的时期。MySQL AB通过优化MySQL满足了互联网开发用者对数据库产品的需求:标准化查询语言的支持,高效的数据存取,不必关注事务完整性,简单易用,而且成本低廉。当时大量的小公司都愿意采用MySQL作为数据库应用系统的数据库管理系统,所以MySQL的用户数量不断的增长,进一步促进了 MySQL自身的不断改进和完善,进入了一个非常好的良性循环。

合理地把握需求, 准确地定位目标客户,为MySQL后面的发展铺平了道路。我们看到,MySQL一开始就没有拿大型的企业管理软件的数据库系统来定位自己,没有将所有的IT 行业定位为自己的目标用户,而是选择的当时并不受重视的一小部分Web开发者作为自己的客户来重点培养发展。这种做法或许值得我们的IT企业学习。

1.1.4 巨人崛起

可以说,正是MySQL最初抓住了互联网客户,造就了今天MySQL在互联网行业的巨大成功。当然,MySQL的高速发展,同时也离不开另外一个很关键的因素,那就是开放源代码。

在 2000年的时候,MySQL公布了自己的源代码,并采用GPL(GNU General Public License)许可协议,正式进入开源世界。虽然在当时的环境下,开源还没有现在这样流行,但是那是开源世界开始真正让大多数世人所接受并开始推崇的起步阶段。当然MySQL的成功并不仅仅是因为以上的这些原因,但我们不能否认正是MySQL这一战略性质的策略让MySQL在进一步拓展自己的客户群 的路上一路东风。此后MySQL的发展路程我想就不需要我继续再次罗嗦了,因为基本上都可以从MySQL的官方网站(http://www.mysql.com)得到相应的答案。

1.2 MySQL 与其他数据库的简单比较

前面我们简单介绍了MySQL的发展历程,从中了解了MySQL快速崛起的必要的条件。接下来,我们通过MySQL在功能,性能,以及其易用性方面和其他主流的数据库做一个基本的比较,来了解一下MySQL成为当下最流行的开源数据库软件的充分条件。

1.2.1 功能比较

作为一个成熟的数据库管理系统,要满足各种各样的商业需求,功能肯定是会被列入重点参考对象的。MySQL虽然在早期版本的时候功能非常简单,只能做一些很基础的结构化数据存取操作,但是经过多年的改进和完善之后,已经基本具备了所有通用数据库管理系统所需要的相关功能。

MySQL基本实现了ANSI SQL 92的大部分标准,仅有少部分并不经常被使用的部分没有实现。比如在字段类型支持方面,另一个著名的开源数据库PostGreSQL支持的类型是最完整的,而Oracle和其他一些商业数据库,比如DB2、Sybase等,较MySQL来说也要相对少

一些。这一点,我们可以通过TCX的crash-me测试套件所得出的测试报告得知。在事务支持方面,虽然MySQL自己的存储引擎并没有提供,但是已经通过第三方插件式存储引擎Innodb实现了SQL 92标准所定义的四个事务隔离级别的全部,只是在实现的过程中每一种的实现方式可能有一定的区别,这在当前商用数据库管理系统中都不多见。比如,大家所熟知的大名鼎鼎的Oracle数据库就仅仅实现了其中的两种(Serializable和Read Commited),而PostGreSQL,同样支持四种隔离级别。

不过在可编程支持方面,MySQL和其他数据库相比还有一定的差距,虽然最新版的MySQL已经开始提供一些简单的可编程支持,如开始支持 Procedure,Function,Trigger等,但是所支持的功能还比较有限,和其他几大商用数据库管理系统相比,还存在较大的不足。如Oracle有强大的PL/SQL,SQL Server 有T-SQL,PostGreSQL也有功能很完善的PL/PGSQL的支持。

整体来说,虽然在功能方面MySQL数据库作为一个通用的数据库管理系统暂时还无法和PostGreSQL相比,但是其功能完全可以满足我们的通用商业需求,提供足够强大的服务。而且不管是哪一种数据库在功能方面都不敢声称自己比其他任何一款商用通用数据库管理系统都强,甚至都不敢声称能够自己拥有某一数据库产品的所有功能。因为每一款数据库管理系统都有起自身的优势,也有起自身的限制,这只能代表每一款产品所倾向的方向不一样而已。

1.2.2 易用性比较

从系统易用性方面来比较,每一个使用过MySQL的用户都能够明显地感觉出MySQL在这方面与其他通用数据库管理系统之间的优势所在。尤其是相对于一些大型的商业数据库管理系统如Oracle、DB2以及Sybase来说,对于普通用户来说,操作的难易程度明显不处于一个级别。MySQL一直都奉行简单易用的原则,也正是靠这一特性,吸引了大量的初级数据库用户最终选择了MySQL。也正是这一批又一批的初级用户,在经过了几年时间的成长之后,很多都已经成为了高级数据库用户,而且也一直都在伴随着MySQL成长。

从安装方面来说,MySQL 安装包大小仅仅只有100MB左右,这几大商业数据库完全不在一个数量级。安装难易程度也要比 Oracle 等商业数据库简单很多,不论是通过已经编译好的二进制分发包还是源码编译安装,都非常简单。

再从数据库创建来比较,MySQL 仅仅只需要一个简单的 CREATE DATABASE 命令,即可在瞬间完成建库的动作,而 Oracle 数据库与之相比,创建一个数据库简直就是一个非常庞大的工程。当然,二者数据库的概念存在一定差别也不可否认。

1.2.3 性能比较 性能方面,一直是MySQL引以为自豪的一个特点。在权威的第三方评测机构多次测试较量各种数据库 TPCC 值的过程中,MySQL一直都有非常优异的表现,而且在其他所有商用的通用数据库管理系统中,仅仅只有Oracle数据库能够与其一较高下。至于各种数据库详细的性能数据,我这里就不便记录,大家完全可以通过网上第三方评测机构公布的数据了解具体细节信息。

MySQL一直以来奉行一个原则,那就是在保证足够的稳定性的前提下,尽可能的提高自

身的处理能力。也就是说,在性能和功能方面,MySQL第一考虑的要素主要还是性能,MySQL希望自己是一个在满足客户99%的功能需求的前提下,花掉剩下的大部分精力来性能努力,而不是希望自己是成为一个比其他任何数据库的功能都要强大的数据库产品。

1.2.4 可靠性

关于可靠性的比较,并没有太多详细的评测比较数据,但是从目前业界的交流中可以了解到,几大商业厂商的数据库的可靠性肯定是没有太多值得怀疑的。但是做为开源数据库管理系统的代表,MySQL也有非常优异的表现,而并不是像有些人心中所怀疑的那样,因为不是商业厂商所提供,就会不够稳定不够健壮。从当前最火的Facebook这样大型的网站都是使用MySQL数据库,就可以看出,MySQL在稳定可靠性方面,并不会比我们的商业厂商的产品有太多逊色。而且排在全球前10位的大型网站里面,大部分都有部分业务是运行在MySQL数据库环境上,如Yahoo,Google等。

总的来说,MySQL数据库在发展过程中一直有自己的三个原则:简单、高效、可靠。从上面的简单比较中,我们也可以看出,在MySQL自己的所有三个原则上面,没有哪一项是做得不好的。而且,虽然功能并不是MySQL自身所追求的三个原则之一,但是考虑到当前用户量的急剧增长,用户需求越来越越多样化,MySQL也不得不在功能方面做出大量的努力,来不断满足客户的新需求。比如最近版本中出现的Eent Scheduler(类似于Oracle的Job功能),Partition功能,自主研发的Maria存储引擎在功能方面的扩展,Falcon存储引擎对事务的支持等等,都证明了MySQL在功能方面也开始了不懈的努力。

任何一种产品,都不可能是完美的,也不可能适用于所有用户。我们只有衡量了每一种产品的各种特性之后,从中选择出一种最适合于自身的产品。

1.3 MySQL 的主要适用场景

据说目前MySQL用户已经达千万级别了,其中不乏企业级用户。可以说是目前最为流行的开源数据库管理系统软件了。任何产品都不可能是万能的,也不可能适用于所有的应用场景。那么MySQL到底在什么场景下适用什么场景下不适用呢?

1、Web网站系统

Web站点,是MySQL最大的客户群,也是MySQL发展史上最为重要的支撑力量,这一点在最开始的MySQL Server简介部分就已经说明过。

MySQL之所以能成为Web站点开发者们最青睐的数据库管理系统,是因为MySQL数据库的安装配置都非常简单,使用过程中的维护也不像很多大型商业数据库管理系统那么复杂,而且性能出色。还有一个非常重要的原因就是MySQL是开放源代码的,完全可以免费使用。

2、日志记录系统

MySQL数据库的插入和查询性能都非常的高效,如果设计地较好,在使用MyISAM存储引擎的时候,两者可以做到互不锁定,达到很高的并发性能。所以,对需要大量的插入和查询日志记录的系统来说,MySQL是非常不错的选择。比如处理用户的登录日志,操作日志等,都是非常适合的应用场景。

3、数据仓库系统

随着现在数据仓库数据量的飞速增长,我们需要的存储空间越来越大。数据量的不断增长,使数据的统计分析变得越来越低效,也越来越困难。怎么办?这里有几个主要的解决思路,一个是采用昂贵的高性能主机以提高计算性能,用高端存储设备提高I/O性能,效果理想,但是成本非常高;第二个就是通过将数据复制到多台使用大容量硬盘的廉价pc server上,以提高整体计算性能和I/O能力,效果尚可,存储空间有一定限制,成本低廉;第三个,通过将数据水平拆分,使用多台廉价的pc server和本地磁盘来存放数据,每台机器上面都只有所有数据的一部分,解决了数据量的问题,所有pc server一起并行计算,也解决了计算能力问题,通过中间代理程序调配各台机器的运算任务,既可以解决计算性能问题又可以解决I/O性能问题,成本也很低廉。在上面的三个方案中,第二和第三个的实现,MySQL都有较大的优势。通过MySQL的简单复制功能,可以很好的将数据从一台主机复制到另外一台,不仅仅在局域网内可以复制,在广域网同样可以。当然,很多人可能会说,其他的数据库同样也可以做到,不是只有 MySQL有这样的功能。确实,很多数据库同样能做到,但是MySQL是免费的,其他数据库大多都是按照主机数量或者cpu数量来收费,当我们使用大量的pc server的时候,license费用相当惊人。第一个方案,基本上所有数据库系统都能够实现,但是其高昂的成本并不是每一个公司都能够承担的。

4、嵌入式系统

嵌入式环境对软件系统最大的限制是硬件资源非常有限,在嵌入式环境下运行的软件系统,必须是轻量级低消耗的软件。

MySQL在资源的使用方面的伸缩性非常大,可以在资源非常充裕的环境下运行,也可以在资源非常少的环境下正常运行。它对于嵌入式环境来说,是一种非常合适的数据库系统,而且MySQL有专门针对于嵌入式环境的版本。

1.4 小结

从最初的诞生,到发展成为目前最为流行的开源数据库管理软件,MySQL 已经走过了较长的一段路,也正是这段不寻常的路,造就了今天 MySQL 的成就。

通过本章的信息,我想各位读者应该是比较清楚 MySQL 的大部分基本信息了,对于 MySQL 主要特长,以及适用场景,都有了一个初步的了解。在后续章节中我们将会针对这些内容做更为详细深入的介绍。

第 2 章 MySQL 架构组成

前言

2、 访问控制

当客户端连接通过用户管理模块的验证,可连接上MySQL Server之后,就会发送各种Query和Command给MySQL Server,以实现客户端应用的各种功能。当MySQL 接收到客户端的请求之后,访问控制模块是需要校验该用户是否满足提交的请求所需要的权限。权限校验过程是从最大范围的权限往最小范围的权限开始依次校验所涉及到的每个对象的每个权限。

在验证所有所需权限的时候,MySQL首先会查找存储在内存结构中的权限数据,首先查找 Global Level 权限,如果所需权限在 Global Level 都有定义(GRANT或者REVOKE),则完成权限校验(通过或者拒绝),如果没有找到所有权限的定义,则会继续往后查找 Database Level 权限,进行 Global Level 未定义的所需权限的校验,如果仍然没有能够找到所有所需权限的定义,MySQL会继续往更小范围的权限定义域查找,也就是 Table Level,最后则是 Column Level 或者 Routine Level。

下面我们就以客户端通过abc@localhost连接后请求如下Query我为例: SELECT id,name FROM test.t4 where status = 'deleted';

图4-3

在前面我们了解到MySQL的grant tables有mysql.user,mysql.db,mysql.host,mysql.table_priv和mysql.column_priv这五个,我想出了mysql.host之外的四个都是非

常容易理解的,每一个表针对MySQL中的一种逻辑对象,存放某一特定Level的权限,唯独mysql.host稍有区别。我们现在就来看看mysql.host权限表到底在MySQL的访问控制中充当了一个什么样的角色呢?

mysql.host在MySQL访问控制模块中所实现的功能比较特殊,和其他几个grant tables不太一样。首先是mysql.host中的权限数据不是(也不能)通过GRANT或者REVOKE来授予或者去除,必须通过手工通过INSERT、UPDATE和DELETE 命令来修改其中的数据。其次是其中的权限数据无法单独生效,必须通过和mysql.db权限表的数据一起才能生效。而且仅当mysql.db中存在不完整(某些场景下的特殊设置)的时候,才会促使访问控制模块再结合mysql.host中查找是否有相应的补充权限数据实现以达到权限校验的目的,就比如上图中所示。在mysql.db中无法找到满足权限校验的所有条件的数据(db.User = 'abc' AND db.host = 'localhost' AND db.Database_name = 'test'),则说明在mysql.db中无法完成权限校验,所以也不会直接就校验db.Select_priv的值是否为'Y'。但是mysql.db中有db.User = 'abc' AND db.Database_name = 'test' AND db.host = '' 这样一条权限信息存在,大家可能注意到了这条权限信息中的db.host中是空值,注意是空值而不是'%'这个通配符哦。当MySQL注意到有这样一条权限信息存在的时候,就该是mysql.host中所存放的权限信息出场的时候了。这时候,MySQL会检测mysql.host中是否存在满足如下条件的权限信息:host.Host = 'localhost' AND host.Db = 'test'。如果存在,则开始进行Select_priv权限的校验。由于权限信息存在于mysql.db和mysql.host两者之中,而且是两者信息合并才能满足要求,所以Select_priv的校验也需要两表都为'Y'才能满足要求,通过校验。

我们已经清楚,MySQL的权限是授予“username@hostname”的,也就是说,至少需要用户名和主机名二者才能确定一个访问者的权限。又由于hostname可以是一个含有通配符的域名,也可以是一个含有通配符的IP地址段。那么如果同一个用户有两条权限信息,一条是针对特定域名的,另外一个是含有通配符的域名,而且前者属于后者包含。这时候MySQL如何来确定权限信息呢?实际上MySQL永远优先考虑更精确范围的权限。在MySQL内部会按照username和hostname作一个排序,对于相同username的权限,其host信息越接近访问者的来源host,则排序位置越靠前,则越早被校验使用到。而且,MySQL在权限校验过程中,只要找到匹配的权限之后,就不会再继续往后查找是否还有匹配的权限信息,而直接完成校验过程。

大家应该也看到了在mysql.user这个权限表中有max_questions,max_updates,max_connections,max_user_connections这四列,前面三列是从MySQL4.0.2版本才开始有的,其功能是对访问用户进行每小时所使用资源的限制,而最后的max_user_connections则是从MySQL5.0.3版本才开始有的,他和max_connections的区别是限制耽搁用户的连接总次数,而不是每小时的连接次数。而要使这四项限制生效,需要在创建用户或者给用户授权的时候加上以下四种子句:

max_questions : WITH MAX_QUERIES_PER_HOUR n; max_updates : WITH MAX_UPDATES_PER_HOUR n; max_connections : WITH MAX_CONNECTIONS_PER_HOUR n; max_user_connections: MAX_USER_CONNECTIONS。

四个子句可以同时使用,如:

“WITH MAX_QUERIES_PER_HOUR 5000 MAX_CONNECTIONS_PER_HOUR 10 MAX_USER_CONNECTIONS 10000”。

4.3 MySQL 访问授权策略

在我们了解了影响数据库系统安全的相关因素以及MySQL权限系统的工作原理之后,就需要为我们的系统设计一个安全合理的授权策略。我想,每个人心里都清楚,要想授权最简单最简单方便,维护工作量最少,那自然是将所有权限都授予所有的用户来的最简单方便了。但是,我们大家肯定也都知道,一个用户所用有的权限越大,那么他给我们的系统所带来的潜在威胁也就越大。所以,从安全方面来考虑的话,权限自然是授予的越小越好。一个有足够安全意识的管理员在授权的时候,都会只授予必要的权限,而不会授予任何多余的权限。既然我们这一章是专门讨论安全的,那么我们现在也就从安全的角度来考虑如何设计一个更为安全合理的授权策略。

首先,需要了解来访主机。

由于MySQL数据库登录验证用户的时候是出了用户名和密码之外,还要验证来源主机。所以我们还需要了解每个用户可能从哪些主机发起连接。当然,我们也可以通过授权的时候直接通过“%”通配符来给所有主机都有访问的权限,但是这样作就违背了我们安全策略的原则,带来了潜在风险,所以并不可取。尤其是在没有局域网的防火墙保护的情况下,更是不能轻易允许可以从任何主机登录的用户存在。能通过具体主机名或者IP地址指定的尽量通过使用具体的主机名和IP地址来限定来访主机,不能用具体的主机名或者IP地址限定的也需要用尽可能小的通配范围来限定。

其次,了解用户需求。

既然是要做到仅授予必要的权限,那么我们必须了解每个用户所担当的角色,也就是说,我们需要充分了解每个用户需要连接到数据库上完成什么工作。了解该用户是一个只读应用的用户,还是一个读写都有的帐户;是一个备份作业的用户还是一个日常管理的帐户;是只需要访问特定的某个(或者某几个)数据库(Schema),还是需要访问所有的数据库。只有了解了需要做什么,才能准确的了解需要授予什么样的权限。因为如果权限过低,会造成工作无法正常完成,而权限过高,则存在潜在的安全风险。

再次,要为工作分类。 为了做到各司其职,我们需要将需要做的工作分门别类,不同类别的工作使用不同的用户,做好用户分离。虽然这样可能会带来管理成本方面的部分工作量增加,但是基于安全方面的考虑,这部分管理工作量的增加是非常值得的。而且我们所需要做的用户分离也只是一个适度的分离。比如将执行备份工作、复制工作、常规应用访问、只读应用访问和日常管理工作分别分理出单独的特定帐户来授予各自所需权限。这样,既可以让安全风险尽量降低,也可以让同类同级别的相似权限合并在一起,不互相交织在一起。对于PROCESS,FILE和SUPER这样的特殊权限,仅仅只有管理类帐号才需要,不应该授予其他非管理帐号。

最后,确保只有绝对必要者拥有GRANT OPTION 权限。

之前在权限系统介绍的时候我们已经了解到GRANT OPTION权限的特殊性,和拥有该权限之后的潜在风险,所以在这里也就不再累述了。总之,为了安全考虑,拥有GRANT OPTION权限的用户越少越好,尽可能只让拥有超级权限的用户才拥有GRANT OPTION权限。

4.4 安全设置注意事项

在前面我们了解了影响数据库系统安全的几个因素,也了解了MySQL权限系统的相关原理和实现,这一节我们将针对这些因素进行一些基本的安全设置讨论,了解一些必要的注意事项。

首先,自然是最外围第一层防线的网络方面的安全。

我们首先要确定我们所维护的MySQL环境是否真的需要提供网络服务?是否可以使我们的MySQL仅仅提供本地访问,而禁止网络服务?如果可以,那么我们可以在启动MySQL的时候通过使用“--skip-networking”参数选项,让MySQL不通过TCP/IP监听网络请求,而仅仅通过命名管道或共享内存(在Windows中)或Unix套接字文件(在Unix中)来和客户端连接交互。

当然,在本章最开始的时候,我们就已经讨论过,由于MySQL数据库在大部分应用场景中都是在网络环境下,通过网络连接提供服务。所以我们只有少部分应用能通过禁用网络监听来断绝网络访问以保持安全,剩下的大部分还是需要通过其他方案来解决网络方面存在的潜在安全威胁。

使用私有局域网络。我们可以通过使用私有局域网络,通过网络设备,统一私有局域网的出口,并通过网络防火墙设备控制出口的安全。

使用SSL加密通道。如果我们的数据对保密要求非常严格,可以启用MySQL提供的SSL访问接口,将传输数据进行加密。使网络传输的数据即使被截获,也无法轻易使用。

访问授权限定来访主机信息。在之前的权限系统介绍中我们已经了解到MySQL的权限信息是针对用户和来访主机二者结合定位的。所以我们可以在授权的时候,通过指定主机的主机名、域名或者IP地址信息来限定来访主机的范围。

其次,在第二层防线主机上面也有以下一些需要注意的地方。

OS安全方面。关闭MySQL Server主机上面任何不需要的服务,这不仅能从安全方面减少潜在隐患,还能减轻主机的部分负担,尽可能提高性能。使用网络扫描工具(如nmap等)扫描主机端口,检查除了MySQL需要监听的端口3306(或者自定义更改后的某个端口)之外,还有哪些端口是打开正在监听的,并去掉不必要的端口。严格控制OS帐号的管理,以防止帐号信息外泄,尤其是root和mysql帐号。对root和mysql等对mysql的相关文件有特殊操作权限的OS帐号登录后做出比较显眼的提示,并在Terminal的提示信息中输出当前用户信息,以防止操作的时候经过多次用户切换后出现人为误操作。

用非root用户运行MySQL。这在MySQL官方文档中也有非常明显的提示,提醒用户不要使用root用户来运行MySQL。因为如果使用root用户运行MySQL,那么mysqld的进程就会拥有root用户所拥有的权限,任何具有FILE权限的MySQL用户就可以在MySQL中向系统中的任何位置写入文件。当然,由于MySQL不接受操作系统层面的认证,所以任何操作系统层级的帐号都不能直接登录MySQL,这一点和Oracle的权限认证有些区别,所以在这一方面我们可以减少一些安全方面的顾虑。

文件和进程安全。合理设置文件的权限属性,MySQL相关的数据和日志文件和所在的文

图4-1

四、代码:

1、SQL语句相关安全因素:

“SQL注入攻击”这个术语我想大部分读者朋友都听说过了?指的就是攻击者根据数据库的SQL语句解析器的原理,利用程序中对客户端所提交数据的校验漏洞,从而通过程序动态提交数据接口提交非法数据,达到攻击者的入侵目的。

“SQL注入攻击”的破坏性非常的大,轻者造成数据被窃取,重者数据遭到破坏,甚至可能丢失全部的数据。如果读者朋友还不是太清楚何为“SQL 注入攻击”,建议通过互联网搜索一下,可以得到非常多非常详细的介绍及案例分析,这里有不做详细介绍了。

2、程序代码相关安全因素:

程序代码如果权限校验不够仔细而存在安全漏洞,则同样可能会被入侵者利用,达到窃取数据等目的。比如,一个存在安全漏洞的信息管理系统,很容易就可能窃取到其他一些系统的登入口令。之后,就能堂而皇之的轻松登录相关系统达到窃取相关数据的目的。甚至还可能通过应用系统中保存不善的数据库系统连接登录口令,从而带来更大的损失。

4.2 MySQL 权限系统介绍

4.2.1 权限系统简介

MySQL的权限系统在实现上比较简单,相关权限信息主要存储在几个被称为grant tables的系统表中,即:mysql.User,mysql.db,mysql.Host,mysql.table_priv和

mysql.column_priv。由于权限信息数据量比较小,而且访问又非常频繁,所以Mysql在启动的时候,就会将所有的权限信息都Load到内存中保存在几个特定的结构中。所以才有我们每次手工修改了权限相关的表之后,都需要执行“FLUSH PRIVILEGES”命令重新加载MySQL的权限信息。当然,如果我们通过GRANT,REVOKE或者DROP USER命令来修改相关权限,则不需要手工执行FLUSH PRIVILEGES命令,因为通过GRANT,REVOKE或者DROP USER命令所做的权限修改在修改系统表的同时也会更新内存结构中的权限信息。在MySQL5.0.2或更高版本的时候,MySQL还增加了CREATE USER命令,以此创建无任何特别权限(仅拥有初始USAGE权限)的用户,通过CREATE USER命令创建新了新用户之后,新用户的信息也会自动更新到内存结构中。所以,建议读者一般情况下尽量使用GRANT,REVOKE,CREATE USER以及DROP USER命令来进行用户和权限的变更操作,尽量减少直接修改grant tables来实现用户和权限变更的操作。

4.2.2 权限授予与去除

要为某个用户授权,可以使用GRANT命令,要去除某个用户已有的权限则使用REVOKE命令。当然,出了这两者之外还有一种比较暴力的办法,那就是直接更新grant tables系统表。当给某个用户授权的时候,不仅需要指定用户名,同时还要指定来访主机。如果在授权的时候仅指定用户名,则MySQL会自动认为是对'username'@'%'授权。要去除某个用户的的权限同样也需要指定来访主机。

可能有些时候我们还会需要查看某个用户目前拥有的权限,这可以通过两个方式实现,首先是通过执行“SHOW GRANTS FOR 'username'@'hostname'” 命令来获取之前该用户身上的所有授权。另一种方法是查询grant tables里面的权限信息。

4.2.3 权限级别

MySQL中的权限分为五个级别,分别如下: 1、Global Level:

Global Level的权限控制又称为全局权限控制,所有权限信息都保存在mysql.user表中。Global Level的所有权限都是针对整个mysqld的,对所有的数据库下的所有表及所有字段都有效。如果一个权限是以Global Level来授予的,则会覆盖其他所有级别的相同权限设置。比如我们首先给abc用户授权可以UPDATE 指定数据库如test的t表,然后又在全局级别REVOKE掉了abc用户对所有数据库的所有表的UPDATE权限。则这时候的abc用户将不再拥有用对test.t表的更新权限。Global Level主要有如下这些权限(见表4-1): 表 4-1 名称 ALTER ALTER ROUTINE CREATE CREATE ROUTINE 版本支持 ALL 5.0.3+ ALL 5.0.3+ 限制信息 表结构更改权限 procedure,function和trigger等的变更权限 数据库,表和索引的创建权限 procedure,function和trigger等的变更权限 临时表的创建权限 CREATE TEMPORARY 4.0.2+ TABLES CREATE USER CREATE VIEW DELETE DROP EXECUTE FILE INDEX INSERT LOCK TABLES PROCESS RELOAD 5.0.3+ 5.0.1+ All All 5.0.3+ All All All 4.0.2+ All All 创建用户的权限 创建视图的权限 删除表数据的权限 删除数据库对象的权限 procedure,function和trigger等的执行权限 执行LOAD DATA INFILE 和 SELECT ... INTO FILE的权限 在已有表上创建索引的权限 数据插入权限 执行LOCK TABLES命令显示给表加锁的权限 执行SHOW PROCESSLIST 命令的权限 执行FLUSH等让数据库重新Load某些对象或者数据的命令的权限 执行SHOW MASTER STATUS 和 SHOW SLAVE STATUS命令的权限 复制环境中Slave连接用户所需要的复制权限 数据查询权限 执行 SHOW DATABASES 命令的权限 执行 SHOW CREATE VIEW 命令查看view创建语句的权限 MySQL Server的shut down 权限(如通过mysqladmin执行 shutdown命令所使用的连接用户) 执行kill 线程,CHANGE MASTER, PURGE MASTER LOGS, and SET GLOBAL等命令的权限 更新数据的权限 新创建用户后不授任何权限的时候所拥有的最小权限 REPLICATION CLIENT 4.0.2+ REPLICATION SLAVE SELECT SHOW DATABASES SHOW VIEW SHUTDOWN 4.0.2+ All 4.0.2+ 5.0.1+ All SUPER 4.0.2+ UPDATE USAGE All All

要授予Global Level的权限,则只需要在执行GRANT命令的时候,用“*.*”来指定适用范围是Global的即可,当有多个权限需要授予的时候,也并不需要多次重复执行GRANT命令,只需要一次将所有需要的权限名称通过逗号(“,”)分隔开即可,如下:

root@localhost : mysql 05:14:35> GRANT SELECT,UPDATE,DELETE,INSERT ON *.* TO 'def'@'localhost';

Query OK, 0 rows affected (0.00 sec)

2、Database Level

Database Level是在Global Level之下,其他三个Level之上的权限级别,其作用域即为所指定整个数据库中的所有对象。与Global Level的权限相比,Database Level主要

少了以下几个权限:CREATE USER,FILE,PROCESS,RELOAD,REPLICATION CLIENT,REPLICATION SLAVE,SHOW DATABASES,SHUTDOWN,SUPER和USAGE这几个权限,没有增加任何权限。之前我们说过Global Level的权限会覆盖底下其他四层的相同权限,Database Level也一样,虽然他自己可能会被Global Level的权限设置所覆盖,但同时他也能覆盖比他更下层的Table,Column和Routine这三层的权限。

如果要授予Database Level的权限,则可以有两种实现方式:

1、在执行GRANT命令的时候,通过“database.*”来限定权限作用域为database整个数据库,如下:

root@localhost : mysql 06:06:26> GRANT ALTER ON test.* TO 'def'@'localhost'; Query OK, 0 rows affected (0.00 sec)

root@localhost : test 06:12:45> SHOW GRANTS FOR def@localhost;

+------------------------------------------------------------------+

| Grants for def@localhost | +------------------------------------------------------------------+ | GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'def'@'localhost' | | GRANT ALTER ON `test`.* TO 'def'@'localhost' | +------------------------------------------------------------------+

2、先通过USE命令选定需要授权的数据库,然后通过“*”来限定作用域,这样授权的作用域实际上就是当前选定的整个数据库。 root@localhost : mysql 06:14:05> USE test; Database changed

root@localhost : test 06:13:10> GRANT DROP ON * TO 'def'@'localhost'; Query OK, 0 rows affected (0.00 sec)

root@localhost : test 06:15:26> SHOW GRANTS FOR def@localhost;

+------------------------------------------------------------------+ | Grants for def@localhost | +------------------------------------------------------------------+ | GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'def'@'localhost' | | GRANT DROP, ALTER ON `test`.* TO 'def'@'localhost' | +------------------------------------------------------------------+

在授予权限的时候,如果有相同的权限需要授予多个用户,我们也可以在授权语句中一次写上多个用户信息,通过逗号(,)分隔开就可以了,如下:

root@localhost : mysql 05:22:32> grant create on perf.* to 'abc'@'localhost','def'@'localhost'; Query OK, 0 rows affected (0.00 sec)

root@localhost : mysql 05:22:46> SHOW GRANTS FOR def@localhost;

+------------------------------------------------------------------+ | Grants for def@localhost |

+------------------------------------------------------------------+ | GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'def'@'localhost' | | GRANT DROP, ALTER ON `test`.* TO 'def'@'localhost' | | GRANT CREATE ON `perf`.* TO 'def'@'localhost' |

+------------------------------------------------------------------+ 3 rows in set (0.00 sec)

root@localhost : mysql 05:23:13> SHOW GRANTS FOR abc@localhost;

+------------------------------------------------------------------+ | Grants for abc@localhost | +------------------------------------------------------------------+ | GRANT CREATE ON `perf`.* TO 'abc'@'localhost' | | GRANT SELECT ON `test`.* TO 'abc'@'localhost' | +------------------------------------------------------------------+ 3 rows in set (0.00 sec)

3、Table Level

Database Level之下就是Table Level的权限了,Table Level的权限可以被Global Level和Database Level的权限所覆盖,同时也能覆盖Column Level和Routine Level的权限。

Table Level的权限作用范围是授权语句中所指定数据库的指定表。如可以通过如下语句给test数据库的t1表授权:

root@localhost : test 12:02:15> GRANT INDEX ON test.t1 TO 'abc'@'%.jianzhaoyang.com';

Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost : test 12:02:53> SHOW GRANTS FOR 'abc'@'%.jianzhaoyang.com'; +----------------------------------------------------------+ | Grants for abc@*.jianzhaoyang.com | +----------------------------------------------------------+ | GRANT USAGE ON *.* TO 'abc'@'%.jianzhaoyang.com' | | GRANT INDEX ON `test`.`t1` TO 'abc'@'%.jianzhaoyang.com' | +----------------------------------------------------------+

上面的授权语句在测试给test数据库的t1表授予Table Level的权限的同时,还测试了将权限授予含有通配符“%”的所有“.jianzhaoyang.com”主机。其中的USAGE权限是每个用户都有的最基本权限。

Table Level的权限由于其作用域仅限于某个特定的表,所以权限种类也比较少,仅有ALTER,CREATE,DELETE,DROP,INDEX,INSERT,SELECT UPDATE这八种权限。

4、Column Level

Column Level的权限作用范围就更小了,仅仅是某个表的指定的某个(活某些)列。由于权限的覆盖原则,Column Level的权限同样可以被Global,Database,Table这三个级别的权限中的相同级别所覆盖,而且由于Column Level所针对的权限和Routine Level的权限作用域没有重合部分,所以不会有覆盖与被覆盖的关系。针对Column Level级别的权限仅有INSERT,SELECT和UPDATE这三种。Column Level的权限授权语句语法基本和Table Level差不多,只是需要在权限名称后面将需要授权的列名列表通过括号括起来,如下:

root@localhost : test 12:14:46> GRANT SELECT(id,value) ON test.t2 TO 'abc'@'%.jianzhaoyang.com';

Query OK, 0 rows affected(0.00 sec)

root@localhost : test 12:16:49> SHOW GRANTS FOR 'abc'@'%.jianzhaoyang.com';

+-----------------------------------------------------------------------+ | Grants for abc@*.jianzhaoyang.com | +-----------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'abc'@'%.jianzhaoyang.com' | | GRANT SELECT (value, id) ON `test`.`t2` TO 'abc'@'%.jianzhaoyang.com' | | GRANT INDEX ON `test`.`t1` TO 'abc'@'%.jianzhaoyang.com' |

+-----------------------------------------------------------------------+

注意:当某个用户在向某个表插入(INSERT)数据的时候,如果该用户在该表中某列上面没有INSERT权限,则该列的数据将以默认值填充。这一点和很多其他的数据库都有一些区别,是MySQL自己在SQL上面所做的扩展。

5、Routine Level

Routine Level的权限主要只有EXECUTE和ALTER ROUTINE两种,主要针对的对象是procedure和function这两种对象,在授予Routine Level权限的时候,需要指定数据库和相关对象,如:

root@localhost : test 04:03:26> GRANT EXECUTE ON test.p1 to 'abc'@'localhost'; Query OK, 0 rows affected (0.00 sec)

除了上面几类权限之外,还有一个非常特殊的权限GRANT,拥有GRANT权限的用户可以将自身所拥有的任何权限全部授予其他任何用户,所以GRANT权限是一个非常特殊也非常重要的权限。GRANT权限的授予方式也和其他任何权限都不太一样,通常都是通过在执行GRANT授权语句的时候在最后添加WITH GRANT OPTION子句达到授予GRANT权限的目的。

此外,我们还可以通过GRANT ALL 语句授予某个Level的所有可用权限给某个用户,如:

root@localhost : test 04:15:48> grant all on test.t5 to 'abc'; Query OK, 0 rows affected (0.00 sec)

root@localhost : test 04:27:39> grant all on perf.* to 'abc'; Query OK, 0 rows affected (0.00 sec)

root@localhost : test 04:27:52> show grants for 'abc'; +--------------------------------------------------+ | Grants for abc@% | +--------------------------------------------------+ | GRANT USAGE ON *.* TO 'abc'@'%' | | GRANT ALL PRIVILEGES ON `perf`.* TO 'abc'@'%' | | GRANT ALL PRIVILEGES ON `test`.`t5` TO 'abc'@'%' | +--------------------------------------------------+

在以上五个Level的权限中,Table、Column和Routine三者在授权中所依赖(或者引用)的对象必须是已经存在的,而不像Database Level的权限授予,可以在当前不存在该数据库的时候就完成授权。

4.2.4 MySQL访问控制实现原理

MySQL访问控制实际上由两个功能模块共同组成,从第一篇的第二章架构组成中可以看到,一个是负责“看守MySQL大门”的用户管理模块,另一个就是负责监控来访者每一个动作的访问控制模块。用户管理模块决定造访客人能否进门,而访问控制模块则决定每个客人进门能拿什么不能拿什么。下面是一张MySQL中实现访问控制的简单流程图(见图4-2):

图4-2

1、 用户管理

我们先看看用户管理模块是如何工作的。在MySQL中,用户访问控制部分的实现比较简单,所有授权用户都存放在一个系统表中:mysql.user,当然这个表不仅仅存放了授权用户的基本信息,还存放有部分细化的权限信息。用户管理模块需要使用的信息很少,主要就是Host,User,Password这三项,都在mysql.user表中,如下:

sky@localhost : (none) 12:35:04> USE mysql; Database changed

sky@localhost : mysql 12:35:08> DESC user;

+---------------+--------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------------+--------------------+------+-----+---------+-------+ | Host | char(60) | NO | PRI | | | | User | char(16) | NO | PRI | | | | Password | char(41) | NO | | | | ... ...

+---------------+--------------------+------+-----+---------+-------+

一个用户要想访问MySQL,至少需要提供上面列出的这三项数据,MySQL才能判断是否该让他“进门”。这三项实际上由量部分组成:访问者来源的主机名(或者主机IP地址信息)和访问者的来访“暗号”(登录用户名和登录密码),这两部分中的任何一个没有能够匹配上都无法让看守大门的用户管理模块乖乖开门。其中Host信息存放的是MySQL允许所对应的User的信任主机,可以是某个具体的主机名(如:mytest)或域名(如:www.domain.com),也可以是以“%”来充当通配符的某个域名集合(如:%.domain.com);也可以是一个具体的IP地址(如:1.2.3.4),同样也可以是存在通配符的域名集合(如:1.2.3.%);还可以用“%”来代表任何主机,就是不对访问者的主机做任何限制。如以下设置:

root@localhost : mysql 01:18:12> SELECT host,user,password FROM user ORDER BY user; +--------------------+------+-------------------------------------------+ | host | user | password | +--------------------+------+-------------------------------------------+ | % | abc | | | *.jianzhaoyang.com | abc | | | localhost | abc | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 | | 1.2.3.4 | abc | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 | | 1.2.3.* | def | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 | | % | def | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 | | localhost | def | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |

... ...

+--------------------+------+-------------------------------------------+

但是这里有一个比较特殊的访问限制,如果要通过localhost访问的话,必须要有一条专门针对localhost的授权信息,即使不对任何主机做限制也不行。如下例所示,存在def@%的用户设置,但是如果不使用-h参数来访问,则登录会被拒绝,因为mysql在默认情况下会连接localhost:

sky@sky:~$ mysql -u def -p Enter password:

ERROR 1045 (28000): Access denied for user 'def'@'localhost' (using password: YES)

但是当通过-h参数,明确指定了访问的主机地址之后就没问题了,如下: sky@sky:~$ mysql -u def -p -h 127.0.0.1 Enter password:

Welcome to the MySQL monitor. Commands end with ; or \\g. Your MySQL connection id is 17

Server version: 5.0.51a-log Source distribution

Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer. def@127.0.0.1 : (none) 01:26:04>

如果我们有一条localhost的访问授权则可以不使用-h参数来指定登录host而连接默认的localhost:

sky@sky:~$ mysql -u abc -p Enter password:

Welcome to the MySQL monitor. Commands end with ; or \\g. Your MySQL connection id is 18

Server version: 5.0.51a-log Source distribution

Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer. abc@localhost : (none) 01:27:19> exit Bye

如果MySQL正在运行之中的时候,我们对系统做了权限调整,那调整之后的权限什么时候会生效呢?

我们先了解何时MySQL存放于内存结构中的权限信息被更新:FLUSH PRIVILEGES会强行让MySQL更新Load到内存中的权限信息;GRANT、REVOKE或者CREATE USER和DROP USER操作会直接更新内存中俄权限信息;重启MySQL会让MySQL完全从grant tables中读取权限信息。

那内存结构中的权限信息更新之后对已经连接上的用户何时生效呢?

对于Global Level的权限信息的修改,仅仅只有更改之后新建连接才会用到,对于已经连接上的session并不会受到影响。而对于Database Level的权限信息的修改,只有当客户端请求执行了“USE database_name”命令之后,才会在重新校验中使用到新的权限信息。所以有些时候如果在做了比较紧急的Global和Database这两个Level的权限变更之后,可能需要通过“KILL”命令将已经连接在MySQL中的session 杀掉强迫他们重新连接以使用更新后的权限。对于Table Level和Column Level的权限,则会在下一次需要使用到该权限的Query被请求的时候生效,也就是说,对于应用来讲,这两个Level的权限,更新之后立刻就生效了,而不会需要执行“KILL”命令。

百度搜索“yundocx”或“云文档网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,云文档网,提供经典综合文库1.基础篇_修改by徐定翔2_去掉批注在线全文阅读。

1.基础篇_修改by徐定翔2_去掉批注.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印 下载失败或者文档不完整,请联系客服人员解决!
本文链接:https://www.yundocx.com/wenku/214356.html(转载请注明文章来源)
Copyright © 2018-2022 云文档网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:370150219 邮箱:370150219@qq.com
苏ICP备19068818号-2
Top
× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:7 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219