-
MySQL 数据库中可以使用 DROP USER 语句来删除一个或多个用户账号以及相关的权限。语法格式:DROP USER <用户名1> [ , <用户名2> ]…使用 DROP USER 语句应该注意以下几点:DROP USER 语句可用于删除一个或多个 MySQL 账户,并撤销其原有权限。使用 DROP USER 语句必须拥有 MySQL 中的 MySQL 数据库的 DELETE 权限或全局 CREATE USER 权限。在 DROP USER 语句的使用中,若没有明确地给出账户的主机名,则该主机名默认为“%”。注意:用户的删除不会影响他们之前所创建的表、索引或其他数据库对象,因为 MySQL 并不会记录是谁创建了这些对象。【实例】使用 DROP USER 语句删除用户'jack'@'localhost'。输入的 SQL 语句和执行过程如下所示。mysql> DROP USER 'jack'@'localhost'; Query OK, 0 rows affected (0.00 sec)在 Windows 命令行工具中,使用 jack 和密码 lion 登录数据库服务器,发现登录失败,说明用户已经删除,如下所示。C:\Users\USER>mysql -h localhost -u jack -p Enter password: **** ERROR 1045 (28000): Access denied for user 'jack'@'localhost' (using password: YES)MySQL 数据库中可以使用 REVOKE 语句删除一个用户的权限,此用户不会被删除。语法格式有两种形式,如下所示:1) 第一种:REVOKE <权限类型> [ ( <列名> ) ] [ , <权限类型> [ ( <列名> ) ] ]…ON <对象类型> <权限名> FROM <用户1> [ , <用户2> ]…2) 第二种:REVOKE ALL PRIVILEGES, GRANT OPTIONFROM user <用户1> [ , <用户2> ]…语法说明如下:REVOKE 语法和 GRANT 语句的语法格式相似,但具有相反的效果。第一种语法格式用于回收某些特定的权限。第二种语法格式用于回收特定用户的所有权限。要使用 REVOKE 语句,必须拥有 MySQL 数据库的全局 CREATE USER 权限或 UPDATE 权限。【实例】使用 REVOKE 语句取消用户 testUser 的插入权限,输入的 SQL 语句和执行过程如下所示。mysql> REVOKE INSERT ON *.* -> FROM 'testUser'@'localhost'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT Host,User,Select_priv,Insert_priv,Grant_priv -> FROM mysql.user -> WHERE User='testUser'; +-----------+----------+-------------+-------------+------------+ | Host | User | Select_priv | Insert_priv | Grant_priv | +-----------+----------+-------------+-------------+------------+ | localhost | testUser | Y | N | Y | +-----------+----------+-------------+-------------+------------+ 1 row in set (0.00 sec)
-
在对 MySQL 的日常管理和实际操作中,为了避免用户恶意冒名使用 root 账号控制数据库,通常需要创建一系列具备适当权限的账号,应该尽可能地不用或少用 root 账号登录系统,以此来确保数据的安全访问。创建用户可以使用 CREATE USER 语句来创建一个或多个 MySQL 账户,并设置相应的口令。语法格式:CREATE USER <用户名> [ IDENTIFIED ] BY [ PASSWORD ] <口令>语法说明如下:1) <用户名>指定创建用户账号,格式为 'user_name'@'host_name'。这里user_name是用户名,host_name为主机名,即用户连接 MySQL 时所在主机的名字。若在创建的过程中,只给出了账户的用户名,而没指定主机名,则主机名默认为“%”,表示一组主机。2) PASSWORD可选项,用于指定散列口令,即若使用明文设置口令,则需忽略PASSWORD关键字;若不想以明文设置口令,且知道 PASSWORD() 函数返回给密码的散列值,则可以在口令设置语句中指定此散列值,但需要加上关键字PASSWORD。3) IDENTIFIED BY子句用于指定用户账号对应的口令,若该用户账号无口令,则可省略此子句。4) <口令>指定用户账号的口令,在IDENTIFIED BY关键字或PASSWOED关键字之后。给定的口令值可以是只由字母和数字组成的明文,也可以是通过 PASSWORD() 函数得到的散列值。使用 CREATE USER 语句应该注意以下几点:如果使用 CREATE USER 语句时没有为用户指定口令,那么 MySQL 允许该用户可以不使用口令登录系统,然而从安全的角度而言,不推荐这种做法。使用 CREATE USER 语句必须拥有 MySQL 中 MySQL 数据库的 INSERT 权限或全局 CREATE USER 权限。使用 CREATE USER 语句创建一个用户账号后,会在系统自身的 MySQL 数据库的 user 表中添加一条新记录。若创建的账户已经存在,则语句执行时会出现错误。新创建的用户拥有的权限很少。他们可以登录 MySQL,只允许进行不需要权限的操作,如使用 SHOW 语句查询所有存储引擎和字符集的列表等。如果两个用户具有相同的用户名和不同的主机名,MySQL 会将他们视为不同的用户,并允许为这两个用户分配不同的权限集合。【实例 1】使用 CREATE USER 创建一个用户,用户名是 james,密码是 tiger,主机是 localhost。输入的 SQL 语句和执行过程如下所示。mysql> CREATE USER 'james'@'localhost' -> IDENTIFIED BY 'tiger'; Query OK, 0 rows affected (0.12 sec)在 Windows 命令行工具中,使用新创建的用户 james 和密码 tiger 登录数据库服务器,如下所示。C:\Users\USER>mysql -h localhost -u james -p Enter password: ***** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 5 Server version: 5.7.20-log MySQL Community Server (GPL) Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
-
MySQL 数据库中事务是用户一系列的数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位。为什么要使用事务事务具有 4 个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持续性(Durability)。这 4 个特性简称为 ACID 特性。1) 原子性事务必须是原子工作单元,事务中的操作要么全部执行,要么全都不执行,不能只完成部分操作。原子性在数据库系统中,由恢复机制来实现。2) 一致性事务开始之前,数据库处于一致性的状态;事务结束后,数据库必须仍处于一致性状态。数据库一致性的定义是由用户负责的。例如,在银行转账中,用户可以定义转账前后两个账户金额之和保持不变。3) 隔离性系统必须保证事务不受其他并发执行事务的影响,即当多个事务同时运行时,各事务之间相互隔离,不可互相干扰。事务查看数据时所处的状态,要么是另一个并发事务修改它之前的状态,要么是另一个并发事务修改它之后的状态,事务不会查看中间状态的数据。隔离性通过系统的并发控制机制实现。4) 持久性一个已完成的事务对数据所做的任何变动在系统中是永久有效的,即使该事务产生的修改不正确,错误也将一直保持。持久性通过恢复机制实现,发生故障时,可以通过日志等手段恢复数据库信息。事务的 ACID 原则保证了一个事务或者成功提交,或者失败回滚,二者必居其一。因此,它对事务的修改具有可恢复性。即当事务失败时,它对数据的修改都会恢复到该事务执行前的状态。开始事务事务以 BEGIN TRANSACTION 开始。语法格式如下:BEGIN TRANSACTION <事务名称> |@<事务变量名称>语法说明如下:@<事务变量名称>是由用户定义的变量,必须用 char、varchar、nchar 或 nvarchar数据类型来声明该变量。BEGIN TRANSACTION 语句的执行使全局变量 @@TRANCOUNT 的值加 1。提交事务COMMIT 表示提交事务,即提交事务的所有操作。具体地说,就是将事务中所有对数据库的更新写回到磁盘上的物理数据库中,事务正常结束。提交事务,意味着将事务开始以来所执行的所有数据修改成为数据库的永久部分,因此也标志着一个事务的结束。一旦执行了该命令,将不能回滚事务。只有在所有修改都准备好提交给数据库时,才执行这一操作。语法格式如下:COMMIT TRANSACTION <事务名称> |@<事务变量名称>其中:COMMIT TRANSACTION语句的执行使全局变量 @@TRANCOUNT 的值减 1。撤销事务ROLLBACK 表示撤销事务,即在事务运行的过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库的所有已完成的操作全部撤销,回滚到事务开始时的状态。这里的操作指对数据库的更新操作。当事务执行过程中遇到错误时,使用 ROLLBACK TRANSACTION 语句使事务回滚到起点或指定的保持点处。同时,系统将清除自事务起点或到某个保存点所做的所有的数据修改,并且释放由事务控制的资源。因此,这条语句也标志着事务的结束。语法格式如下:ROLLBACK [TRANSACTION][<事务名称>| @<事务变量名称> | <存储点名称>| @ <含有存储点名称的变量名>语法说明如下:当条件回滚只影响事务的一部分时,事务不需要全部撤销已执行的操作。可以让事务回滚到指定位置,此时,需要在事务中设定保存点(SAVEPOINT)。保存点所在位置之前的事务语句不用回滚,即保存点之前的操作被视为有效的。保存点的创建通过“SAVING TRANSACTION<保存点名称>”语句来实现,再执行“ROLLBACK TRANSACTION<保存点名称>”语句回滚到该保存点。若事务回滚到起点,则全局变量 @@TRANCOUNT 的值减 1;若事务回滚到指定的保存点,则全局变量 @@TRANCOUNT 的值不变。
-
现在已经存在了很多优秀的商业数据库,如甲骨文(Oracle)公司的 Oracle 数据库、IBM 公司的 DB2 数据库、微软公司的 SQL Server 数据库和 Access 数据库。同时,还有很多优秀的开源数据库,如 MySQL 数据库,PostgreSQL 数据库等。下面介绍这些常见的数据库。1)OracleOracle 是甲骨文公司的一款关系型数据库管理系统,在数据库领域一直处于领先地位的产品,是目前世界上流行的关系型数据库之一,是一种高效率、可靠性好、适应高吞吐量的数据库方案。优点:Oracle 可移植性好,能在所有主流平台上运行(包括 Windows),完全支持所有工业标准。采用完全开放策略,使客户可以选择最适合解决方案。以及对开发商的全力支持。获得最高认证级别的 ISO 标准认证,安全性高。与其它数据库相比,Oracle 性能最高。保持着开放平台下 TPC-D 和 TPC-C 世界记录。多层次网络计算,支持多种工业标准,可以用 ODBC、JDBC、OCI 等网络客户连接 。完全向下兼容,因此被广泛应用,且风险低 。向下兼容指的是高版本支持低版本的或者说后期开发的版本支持和兼容早期开发的版本。缺点:对硬件的要求高价格比较昂贵管理维护麻烦操作比较复杂2)SQL ServerSQL Server 是 Microsoft(微软)公司推出的关系型数据库管理系统,主要应用于大型的管理系统中。优点:与微软的 Windows 系列操作系统的兼容性很好。高性能设计,可充分利用 WindowsNT 的优势。系统管理先进,支持 Windows 图形化管理工具,支持本地和远程的系统管理和配置。强壮的事务处理功能,采用各种方法保证数据的完整性。支持对称多处理器结构、存储过程、ODBC,并具有自主的 SQL 语言。缺点:SQL Server 只能在 Windows 系统上运行,没有丝毫开放性。没有获得任何安全证书。多用户时性能不佳 。只支持 C/S 模式,SQL Server C/S 结构只支持 Windows 客户用 ADO、DAO、OLEDB、ODBC 连接。3)MySQLMySQL 是一种开放源代码的关系型数据库管理系统,由瑞典 MySQL AB 公司开发,属于 Oracle 旗下产品。因为其速度、可靠性和适应性而备受关注。MySQL 是流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL 是最好的应用软件之一。优点:性能卓越服务稳定,很少出现异常宕机开放源代码且无版权制约,自主性强、使用成本低。历史悠久、社区及用户非常活跃,遇到问题,可以很快获取到帮助。软件体积小,安装使用简单,并且易于维护,安装及维护成本低。支持多种操作系统,提供多种 API 接口,支持多种开发语言。缺点:MySQL 最大的缺点是其安全系统,主要是复杂而非标准,只有调用 mysqladmin 来重读用户权限才会发生改变。MySQL 不允许调试存储过程,开发和维护存储过程很难。MySQL 不支持热备份。MySQL 的价格随平台和安装方式变化。4)AccessAccess 是由 Microsoft(微软)发布的小型关系数据库管理系统,是微软把数据库引擎的图形用户界面和软件开发工具结合在一起的一个数据库管理系统。优点:存储方式简单,易于维护管理。Access 的对象有表、查询、窗体、报表、页、宏和模块,以上对象都存放在后缀为(.mdb 或 .accdb)的数据库文件中,便于用户的操作和管理。Access 是一个面向对象的开发工具,这种基于面向对象的开发方式,使得开发应用程序更为简便。界面友好、易操作。Access 是一个可视化工具,风格与 Windows 完全一样,用户想要生成对象应用,只要使用鼠标进行拖放即可,非常直观方便。系统还提供了表生成器、查询生成器、报表设计器以及数据库向导、表向导、查询向导、窗体向导、报表向导等工具,使得操作简便,容易使用和掌握。集成环境,可以处理多种数据信息。Access 基于 Windows 操作系统下的集成开发环境,该环境集成了各种向导和生成器工具,极大地提高了开发人员的工作效率,使得建立数据库、创建表、设计用户界面、设计数据查询、报表打印等可以方便有序地进行。支持广泛,易于扩展,弹性大。Access 是一个既可以只用来存放数据的数据库,也可以作为一个客户端开发工具来进行数据库应用系统开发。即可以开发方便易用的小型软件,也可以用来开发大型的应用系统。缺点:不支持并发处理。数据库存储量小安全性不够高。Access 是小型数据库,当数据量过大时,一般百M以上(纯数据,不包括窗体、报表等客户端对象)性能会变差。虽然理论上支持 255 个并发用户,但实际上根本支持不了那么多,如果以只读方式访问大概在 100 个用户左右,而如果是并发编辑,则大概在10-20个用户。单表记录数过百万时,性能就会变得较差,如果加上设计不良,这个限度还要降低。不能编译成可执行文件(.exe),必须要安装 Access 运行环境才能使用。5)DB2DB2 是美国 IBM 公司开发的一款支持多媒体、Web 的关系型数据库管理系统。主要应用于大型应用系统,具有较好的可伸缩性,可支持从大型机到单用户环境。优点:相比较 MySQL 和 Oracle 两种数据库来说,DB2 提供了高层次的数据利用性、完整性、安全性、可恢复性,以及小规模到大规模地应用程序执行能力,具有与平台无关的基本功能和 SQL 命令。DB2 采用了数据分级技术,能够使大型数据很方便的下载到数据库服务器,使数据库本地化和远程连接透明化。拥有非常完备的查询优化器,改善了查询性能,并支持多任务并行查询。具有很好的网络支持能力,每个子系统可以连接十几万个分布式用户,可同时激活上千个活动线程,对大型分布式应用系统更加使用。DB2 可跨平台使用。缺点:配置文件和参数多,且命名不规范。一些 DB2 产品开发不方便。和 Oracle 相比,命令多,且没 Oracle 统一规范的好。由于其设计框架的问题,如果用户对数据库的本身优化和应用程序优化做的不足,那么 DB2 容易出现锁等待现象。6)PostgreSQLPostgreSQL 是一款富有特色的自由数据库管理系统,甚至可以说是最强大的自由软件数据库管理系统。该数据库管理系统支持了目前世界上最丰富的数据类型。是自由软件数据库管理系统中唯一支持事务、子查询、多版本并行控制系统、数据完整性检查等特性的自由软件。优点:PostgreSQL 遵循的是 BSD 协议,是一个完全开源、免费、同时非常强大的关系型数据库。与 PostgreSQL 配合的有很多分布式集群软件,如 pgpool、pgcluster、slony、plploxy 等等,很容易做读写分离、负载均衡、数据水平拆分等方案,而这些 MySQL 则比较难实现。PostgreSQL 源代码写的很清晰,易读性比 MySQL 强,所以很多公司基本都是以 PostgreSQL 做二次开发的。PostgreSQL 是多进程的,而 MySQL 是多线程的。并发不高时,MySQL处理速度快,但当并发高的时候,对于现在多核的单台机器上,MySQL 的总体处理性能不如 PostgreSQL,原因是 MySQL 的线程无法充分利用 CPU 的能力。PostgreSQL 有很强大的查询优化器,支持很复杂的查询处理。BSD 开源协议是一个给于使用者很大自由的协议。可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布。缺点:对于简单而繁重的读取操作,相比较其它数据库来说,PostgreSQL 性能较低。PostgreSQL 数据库扩容花费时间很长。
-
在正式学习 MySQL 数据库前,我们有必要先了解一下数据库中的专业术语。下面汇总了一些在学习 MySQL 过程中会遇到的专业术语。数据库管理系统(DBMS)是位于操作系统与用户之间的一种操纵和管理数据库的软件。关系型数据库通过关系数据库管理系统(RDBMS)进行管理。关系(Relational,即 RDBMS 里的 R)表示这是一种特殊的 DBMS,数据库中表与表之间要存在关系。数据库(DataBase,即 RDBMS 里的 DB)是一个用来存储和管理数据的仓库。它的存储空间很大,并且有一定的数据存放规则。通过由行和列组成的二维表(类似 Excel 工作表)来管理数据。数据库中可以同时存储多个表。管理系统(Management System,即 RDBMS 里的 MS)是一个软件,我们可以通过它来插入(insert)、查询(query)、修改(modify)或删除(delete)表中的数据。用来管理数据的二维表在关系数据库中简称为表(Table),每个表由多个行(Row)和列(Column)组成。表的列(垂直方向)称为字段,是具有相同数据类型的数据集合。表的行(水平方向)称为记录(Record),相当于一条数据。记录可以包含多项信息,表中的每一列都对应于其中的某一项。下图是一个统计学生信息的 student 表。可以看到,每个列都包含了所有学生的某个信息,比如 name(姓名)。而每行则包含了某个学生的所有信息,即 id(编号)、name(姓名)、 age (年龄)、stuno(学号)等。SQL(Structured Query Language,结构化查询语言)是用来操作关系型数据库的语言,使用 SQL 可以对数据库和表进行添加、删除、修改和查询等操作。与其它计算机语言一样,初次接触 SQL 的人肯定会觉得它很奇怪。例如,在创建表时,很多人都会把表与图表或图片联系起来,但是 MySQL 不是这样的。在 MySQL 中创建表时,你必须输入类似下面这样的内容。CREATE TABLE `student` ( `id` int(4), `name` varchar(20), `age` int(4), `stuno` int(11), PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;如果你对 SQL 还不太熟悉,可能会对以上语句心生畏惧。不过请放心,随着教程的深入学习,你会很快的熟练使用 SQL,并且对上述 SQL 语句的看法也会悄然地发生变化。它不再是一组怪诞地表达,而是一种有助于信息描述的强大工具。
-
MySQL处理数据的基本原则是“垃圾进来,垃圾出去”,通俗一点说就是你传给 MySQL 什么样的数据,它就会存储什么样的数据。如果在存储数据时没有对它们进行验证,那么在把它们检索出来时得到的就不一定是你所期望的内容。 有几种 SQL 模式可以在遇到“非正常”值时抛出错误,如果你对其他数据库管理系统比较熟悉,会发现这种行为和其他的数据库管理系统很像。 下面介绍 MySQL 默认情况下如何处理非正常数据和启用各种 SQL 模式时会对数据处理产生哪些影响。 默认情况下,MySQL 会按照以下规则来处理越界(即超出取值范围)的值和其他非正常值:对于数值列或 TIME 列,超出合法取值范围的那些值将被截断到取值范围最近的那个端点,并把结果值存储起来。对于除 TIME 列以外的其他类型列,非法值会被转换成与该类型一致的“零”值。对于字符串列(不包括 ENUM 或 SET),过长的字符串将被截断到该列的最大长度。给 ENUM 或 SET 类型列进行赋值时,需要根据列定义里给出的合法取值列表进行。如果把不是枚举成员的值赋给 ENUM 列,那么列的值就会变成空字符串。如果把包含非集合成员的子字符串的值赋给 SET 列,那么这些字符串会被清理,剩余的成员才会被赋值给列。 如果在执行增删改查等语句时发生了上述转换,那么 MySQL 会给出警告消息。在执行完其中的某一条语句之后,可以使用 SHOW WARNINGS 语句来查看警告消息的内容。 如果需要在插入或更新数据时执行更严格的检查,那么可以启用以下两种 SQL 模式中的一种:SET sql_mode = 'STRICT_ALL_TABLES' ;SET sql_mode = 'STRICT_TRANS_TABLES';对于支持事务的表,这两种模式都是一样的。如果发现某个值无效或缺失,那么会产生一个错误,并且语句会中止执行,并进行回滚,就像什么事都没发生过一样。 对于不支持事务的表,这两种模式有以下效果。 1) 对于这两种模式,如果在插入或修改第一个行时,发现某个值无效或缺失,那么结果会产生一个错误,语句会中止执行,就像什么事都未发生过一样。 这跟事务表的行为很相似。 2) 在用于插入或修改多个行的语句里,如果在第一行之后的某个行出现了错误,那么会出现某些行被修改的情况。这两种模式决定着,这条语句此时此刻是要停止执行,还是要继续执行。在 STRICT_ALL_TABLES 模式下,会抛出一个错误,并且语句会停止执行。因为受该语句影响的许多行都已被修改,所以这将会导致“部分更新”问题。在 STRICT_TRANS_TABLES 模式下,对于非事务表,MySQL 会中止语句的执行。只有这样做,才能达到事务表那样的效果。只有当第一行发生错误时,才能达到这样的效果。如果错误在后面的某个行上,那么就会出现某些行被修改的情况。由于对于非事务表,那些修改是无法撤销的,因此 MySQL 会继续执行该语句,以避免出现“部分更新”的问题。它会把所有的无效值转换为与其最接近的合法值。对于缺失的值,MySQL 会把该列设置成其数据类型的隐式默认值, 通过以下模式可以对输入的数据进行更加严格的检查:ERROR_ FOR_ DIVISION_ BY_ ZERO:在严格模式下,如果遇到以零为除数的情况,它会阻止数值进入数据库。如果不在严格模式下,则会产生一条警告消息,并插入 NULL。NO_ ZERO_ DATE:在严格模式下,它会阻止“零”日期值进入数据库。NO_ ZERO_ IN_ DATE:在严格模式下,它会阻止月或日部分为零的不完整日期值进入数据库。 简单来说,MySQL 的严格模式就是 MySQL 自身对数据进行的严格校验,例如格式、长度、类型等。比如一个整型字段我们写入一个字符串类型的数据,在非严格模式下 MySQL 不会报错。如果定义了 char 或 varchar 类型的字段,当写入或更新的数据超过了定义的长度也不会报错。 虽然我们会在代码中做数据校验,但一般认为非严格模式对于编程来说没有任何好处。MySQL开启严格模式从一定程序上来讲也是对我们代码的一种测试,如果我们没有开启严格模式并且在开发过程中也没有遇到错误,那么在上线或代码移植的时候将有可能出现不兼容的情况,因此在开发过程做最好开启 MySQL 的严格模式。 可通过select @@sql_mode;命令查看当前是严格模式还是非严格模式。 例如,如果想让所有的存储引擎启用严格模式,并对“被零除”错误进行检查,那么可以像下面这样设置 SQL 模式:SET sql_mode ‘STRICT_ALL_TABLES, ERROR_FOR_DIVISION_BY_ZERO' ; 如果想启用严格模式,以及所有的附加限制,那么最为简单的办法是启用 TRADITIONAL 模式:SET sql_ mode ‘TRADITIONAL' ;TRADITIONAL 模式的含义是“启用严格模式,当向 MySQL 数据库插入数据时,进行数据的严格校验,保证错误数据不能插入。用于事务表时,会进行事务的回滚”。 可以选择性地在某些方面弱化严格模式。如果启用了 SQL 的 ALLOW_ INVALID_ DATES 模式,那么MySQL将不会对日期部分做全面检查。相反,它只会要求月份值在 1~12 之间,而天数处于 1~31 之间,即允许像‘2000-02-30’或‘2000-06-31’这样的无效值。 另一个制止错误的办法是在 INSERT 或 UPDATE 语句里使用 IGNORE 关键字。这样那些会因无效值而导致错误的语句,将只会导致警告的出现。这些选项能让你灵活地为你的应用选择正确的有效性检查级别。
-
在忘记 MySQL 密码的情况下,可以通过 --skip-grant-tables 关闭服务器的认证,然后重置 root 的密码,具体操作步骤如下。步骤 1):关闭正在运行的 MySQL 服务。打开 cmd 进入 MySQL 的 bin 目录。步骤 2):输入mysqld --console --skip-grant-tables --shared-memory 命令。–skip-grant-tables 会让 MySQL 服务器跳过验证步骤,允许所有用户以匿名的方式,无需做密码验证就可以直接登录 MySQL 服务器,并且拥有所有的操作权限。步骤 3):上一个 DOS 窗口不要关闭,打开一个新的 DOS 窗口,此时仅输入 mysql 命令,不需要用户名和密码,即可连接到 MySQL。步骤 4):输入命令 update mysql.user set authentication_string=password('root') where user='root' and Host ='localhost'; 设置新密码。注意:MySQL 5.7 版本中的 user 表里已经去掉了 password 字段,改为了 authentication_string。步骤 5):刷新权限(必须步骤),输入flush privileges;命令。步骤 6):因为之前使用 --skip-grant-tables 启动,所以需要重启 MySQL 服务器去掉 --skip-grant-tables。输入无误后输入quit;命令退出 MySQL 服务。步骤 7):重启 MySQL 服务,使用用户名 root 和刚才设置的新密码 root 登录就可以了。
-
银行业务中,有一条记账原则,即有借有贷,借贷相等。为了保证这种原则,每发生一笔银行业务,就必须确保会计账目上借方科目和贷方科目至少各记一笔,并且这两笔账要么同时成功,要么同时失败。如果出现只记录了借方科目,或者只记录了贷方科目的情况,就违反了记账原则。会出现记错账的情况。在银行的日常业务中,只要是同一银行(如都是中国农业银行,简称农行),一般都支持账户间的直接转账。因此,银行转账操作往往会涉及两个或两个以上的账户。在转出账户的存款减少一定金额的同时,转入账户的存款就要增加相应的金额。下面,在 MySQL 数据库中模拟一下上述提及的转账问题。假如要从张三的账户直接转账 500 元到李四的账户。首先需要创建账户表,存放用户张三和李四的账户信息。创建账户表和插入数据的 SQL 语句和运行结果如下所示:mysql> CREATE DATABASE mybank; Query OK, 1 row affected (0.02 sec) mysql> USE mybank; Database changed mysql> CREATE TABLE bank( -> customerName VARCHAR(20), #用户名 -> currentMoney DECIMAL(10,2) #当前余额 -> )ENGINE=InnoDB DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.26 sec) mysql> INSERT INTO bank (customerName,currentMoney) VALUES('张三',1000);; Query OK, 1 row affected (0.07 sec) mysql> INSERT INTO bank (customerName,currentMoney) VALUES('李四',1); Query OK, 1 row affected (0.08 sec)查询 bank 数据表的 SQL 语句和运行结果如下:mysql> SELECT * FROM bank; +--------------+--------------+ | customerName | currentMoney | +--------------+--------------+ | 张三 | 1000.00 | | 李四 | 1.00 | +--------------+--------------+ 2 rows in set (0.02 sec)结果显示,张三和李四两个账户的余额总和为 1000+1=1001 元。下面开始模拟实现转账功能。从张三的账户直接转账 500 元到李四的账户,可以使用 UPDATE 语句分别修改张三的账户和李四的账户。张三的账户减少 500 元,李四的账户增加 500 元, SQL 语句如下所示:/*转账测试:张三转账给李四 500 元*/ #张三的账户少 500 元,李四的账户多 500 元 UPDATE bank SET currentMoney = currentMoney-500 WHERE customerName = '张三'; UPDATE bank SET currentMoney = currentMoney+500 WHERE customerName = '李四';正常情况下,执行以上的转账操作后,余额总和应保持不变,仍为 1001 元。但是,如果在这个过程的其中一个环节出现差错,如在张三的账户减少 500 元之后,这时发生了服务器故障,李四的账户没有立即增加 500 元,此时,第三方读取到两个账户的余额总和变为 500+1=501 元,即账户总额间少了 500 元。MySQL 为了解决此类问题,提供了事务。事务可以将一系列的数据操作**成一个整体进行统一管理,如果某一事务执行成功,则在该事务中进行的所有数据更改均会提交,成为数据库中的永久组成部分。如果事务执行时遇到错误,则就必须取消或回滚。取消或回滚后,数据将全部恢复到操作前的状态,所有数据的更改均被清除。MySQL 通过事务保证了数据的一致性。上述提到的转账过程就是一个事务,它需要两条 UPDATE 语句来完成。这两条语句是一个整体,如果其中任何一个环节出现问题,则整个转账业务也应取消,两个账户中的余额应恢复为原来的数据,从而确保转账前和转账后的余额总和不变,即都是 1001 元。
-
MySQL 服务器可以支持多种字符集,在同一台服务器、同一个数据库甚至同一个表的不同字段中,都可以使用不同的字符集。Oracle 等其它数据库管理系统都只能使用相同的字符集,相比之下,MySQL 明显存在更大的灵活性。MySQL 的字符集和校对规则有 4 个级别的默认设置,即服务器级、数据库级、表级和字段级。它们分别在不同的地方设置,作用也不相同。服务器字符集和校对规则修改服务器默认字符集和校对规则的方法如下。1)可以在 my.ini 配置文件中设置服务器字符集和校对规则,添加内容如下:[mysqld]character-set-server=字符集名称2)连接 MySQL 服务器时指定字符集:mysql --default-character-set=字符集名称 -h 主机IP地址 -u 用户名 -p 密码如果没有指定服务器字符集,MySQL 会默认使用 latin1 作为服务器字符集。如果只指定了字符集,没有指定校对规则,MySQL 会使用该字符集对应的默认校对规则。如果要使用字符集的非默认校对规则,需要在指定字符集的同时指定校对规则。可以用 SHOW VARIABLES LIKE 'character_set_server' 和 SHOW VARIABLES LIKE 'collation_server' 命令查询当前服务器的字符集和校对规则。mysql> SHOW VARIABLES LIKE 'character_set_server'; +----------------------+--------+ | Variable_name | Value | +----------------------+--------+ | character_set_server | gbk | +----------------------+--------+ 1 row in set, 1 warning (0.01 sec) mysql> SHOW VARIABLES LIKE 'collation_server'; +------------------+-------------------+ | Variable_name | Value | +------------------+-------------------+ | collation_server | gbk_chinese_ci | +------------------+-------------------+ 1 row in set, 1 warning (0.01 sec)数据库字符集和校对规则数据库的字符集和校对规则在创建数据库时指定,也可以在创建完数据库后通过 ALTER DATABASE 命令进行修改,需要注意的是,如果数据库里已经存在数据,修改字符集后,已有的数据不会按照新的字符集重新存放,所以不能通过修改数据库的字符集来修改数据的内容。在《MySQL修改字符集步骤详解》一节我们介绍了如何修改已存在数据字符集的方法。设置数据库字符集的规则如下:如果指定了字符集和校对规则,则使用指定的字符集和校对规则;如果指定了字符集没有指定校对规则,则使用指定字符集的默认校对规则;如果指定了校对规则但未指定字符集,则字符集使用与该校对规则关联的字符集;如果没有指定字符集和校对规则,则使用服务器字符集和校对规则作为数据库的字符集和校对规则。为了避免受到默认值的影响,推荐在创建数据库时指定字符集和校对规则。可以使用 SHOW VARIABLES LIKE 'character_set_database' 和 SHOW VARIABLES LIKE 'collation_database' 命令查看当前数据库的字符集和校对规则。mysql> SHOW VARIABLES LIKE 'character_set_database'; +------------------------+--------+ | Variable_name | Value | +------------------------+--------+ | character_set_database | latin1 | +------------------------+--------+ 1 row in set, 1 warning (0.00 sec) mysql> SHOW VARIABLES LIKE 'collation_database'; +--------------------+-------------------+ | Variable_name | Value | +--------------------+-------------------+ | collation_database | latin1_swedish_ci | +--------------------+-------------------+ 1 row in set, 1 warning (0.00 sec)表字符集和校对规则表的字符集和校对规则在创建表的时候指定,也可以在创建完表后通过 ALTER TABLE 命令进行修改同样,如果表中已有记录,修改字符集后,原有的记录不会按照新的字符集重新存放。表的字段仍然使用原来的字符集。设置表的字符集规则和设置数据库字符集的规则基本类似:如果指定了字符集和校对规则,使用指定的字符集和校对规则;如果指定了字符集没有指定校对规则,使用指定字符集的默认校对规则;如果指定了校对规则但未指定字符集,则字符集使用与该校对规则关联的字符集;如果没有指定字符集和校对规则,使用数据库字符集和校对规则作为表的字符集和校对规则。为了避免受到默认值的影响,推荐在创建表的时候指定字符集和校对规则。可以使用 SHOW CREATE TABLE 命令查看当前表的字符集和校对规则,SQL 语句和运行结果如下:mysql> SHOW CREATE TABLE tb_students_info \G *************************** 1. row *************************** Table: tb_students_info Create Table: CREATE TABLE `tb_students_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) DEFAULT NULL, `age` int(11) DEFAULT NULL, `sex` char(1) DEFAULT NULL, `height` float DEFAULT NULL, `course_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 1 row in set (0.00 sec)列字符集和校对规则MySQL 可以定义列级别的字符集和校对规则,主要是针对相同表的不同字段需要使用不同字符集的情况。一般遇到这种情况的几率比较小,这只是 MySQL 提供给我们一个灵活设置的手段。列字符集和校对规则的定义可以在创建表时指定,或者在修改表时调整。语法格式如下:ALTER TABLE 表名 MODIFY 列名 数据类型 CHARACTER SET 字符集名;例 1修改 tb_students_info 表中 name 列的字符集,并查看。SQL 语句和运行结果如下:mysql> ALTER TABLE tb_students_info MODIFY name VARCHAR(10) CHARACTER SET gbk; Query OK, 11 rows affected (0.11 sec) Records: 11 Duplicates: 0 Warnings: 0 mysql> SHOW CREATE TABLE tb_students_info \G *************************** 1. row *************************** Table: tb_students_info Create Table: CREATE TABLE `tb_students_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) CHARACTER SET gbk DEFAULT NULL, `age` int(11) DEFAULT NULL, `sex` char(1) DEFAULT NULL, `height` float DEFAULT NULL, `course_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 1 row in set (0.00 sec)结果显示,name 列字符集修改成功。如果在创建列的时候没有特别指定字符集和校对规则,默认使用表的字符集和校对规则。连接字符集和校对规则上面所讲的 4 种设置方式,确定的都是数据保存的字符集和校对规则。实际应用中,还需要设置客户端和服务器之间交互的字符集和校对规则。对于客户端和服务器的交互操作,MySQL 提供了 3 个不同的参数:character_set_client、character_set_connection 和 character_set_results,分别代表客户端、连接和返回结果的字符集。通常情况下,这 3 个字符集是相同的,这样可以确保正确读出用户写入的数据,尤其是中文字符。字符集不同时,容易导致写入的记录不能正确读出。设置客户端和服务器连接的字符集和校对规则有以下几种方法:1)在 my.ini 配置文件中,设置以下语句:[mysql]default-character-set=gbk这样服务器启动后,所有连接默认使用 GBK 字符集进行连接。2)可以通过以下命令来设置连接的字符集和校对规则,这个命令可以同时修改以上 3 个参数(character_set_client、character_set_connection 和 character_set_results)的值。SET NAMES gbk;使用这个方法可以“临时一次性地”修改客户端和服务器连接时的字符集为 gbk。3)MySQL 还提供了下列 MySQL 命令“临时地”修改 MySQL“当前会话的”字符集和校对规则。set character_set_client = gbk;set character_set_connection = gbk;set character_set_database = gbk;set character_set_results = gbk;set character_set_server = gbk;set collation_connection = gbk_chinese_ci;set collation_database = gbk_chinese_ci;set collation_server = gbk_chinese_ci;
-
在实际应用中,如果一开始没有正确的设置字符集,在运行一段时间以后,才发现当前字符集不能满足要求,需要进行调整,但又不想丢弃这段时间的数据,这个时候就需要修改字符集。ALTER DATABASE 或 ALTER TABLE 命令对已经存在的数据没有作用,只对新创建的表或记录生效。如果想修改已存在数据的字符集,需要先将数据导出,经过适当的调整后,再重新导入。例 以下模拟的是将 gb2312 字符集的数据库修改成 gbk 字符集的数据库的过程。1)创建 testset 数据库,设置其字符集为 gb2312,并添加数据。mysql> CREATE TABLE test.testset( -> id INT(11) DEFAULT NULL, -> name VARCHAR(25) DEFAULT NULL -> )CHARSET=gb2312; Query OK, 0 rows affected (0.10 sec) mysql> INSERT INTO test.testset VALUES (1,'C语言'); Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO test.testset VALUES (2,'Java语言'); Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO test.testset VALUES (3,'Python语言'); Query OK, 1 row affected (0.01 sec)2)导出 testset 表结构,命令如下:mysqldump -uroot -p --default-character-set=gbk -d test testset> D:\testset.sql其中,--default-character-set=gbk 表示以什么字符集连接;-d 表示只导出表结构,不导出数据。3)打开 testset.sql 文件,修改表结构定义中的字符集为新的字符集,如下图所示。4)确保表中的记录不再更新,导出所有记录。mysqldump -uroot -p --quick --no-create-info --extended-insert --default-character-set=gb2312 test testset> D:\testdata.sql--quick:该选项用于存储记录多的表。它强制 mysqldump 从服务器一次一行地查询表中的行,而不是查询所有行,并在输出前将它缓存到内存中。--extended-insert:使用 INSERT 插入多行数据语法。可以使文件更小,导入文件时加速插入。--no-create-info:不导出表的 CREATE TABLE 语句。--default-character-set=gb2312:按照原有的字符集导出所有数据。这样导出的文件中,所有中文都是可见的,不会保存成乱码。5)打开 testdata.sql,将 SET NAMES gb2312 修改成 SET NAMES gbk,如下图所示。6)使用新的字符集创建新的数据库。CREATE DATABASE test2 DEFAULT CHARSET gbk;7)创建表,执行 testset.sql。mysql -uroot -p test2 < D:\testset.sql8)导入数据,执行 testdata.sql。mysql -uroot -p test2 < D:\testdata.sql9)查看 testset 表结构是否修改了字符集,以及表内数据是否丢失或乱码,SQL 语句和运行结果如下:mysql> SHOW CREATE TABLE test2.testset \G *************************** 1. row *************************** Table: testset Create Table: CREATE TABLE `testset` ( `id` int(11) DEFAULT NULL, `name` varchar(25) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=gbk 1 row in set (0.00 sec) mysql> SELECT * FROM test2.testset; +------+------------+ | id | name | +------+------------+ | 1 | C语言 | | 2 | Java语言 | | 3 | Python语言 | +------+------------+ 3 rows in set (0.00 sec)注意:选择目标字符集的时候,要注意最好的是原字符集的超集,或者确定比原字符集的字库更大,否则如果目标字符集的字库小于原字符集的字库,那么目标字符集中不支持的字符导入后会变成乱码,丢失一部分数据。
-
索引的设计可以遵循一些已有的原则,创建索引的时候应尽量考虑符合这些原则,便于提升索引的使用效率,更高效的使用索引。我将介绍一些索引的设计原则。1. 选择唯一性索引唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。例如,学生表中学号是具有唯一性的字段。为该字段建立唯一性索引可以很快的确定某个学生的信息。如果使用姓名的话,可能存在同名现象,从而降低查询速度。2. 为经常需要排序、分组和联合操作的字段建立索引经常需要 ORDER BY、GROUP BY、DISTINCT 和 UNION 等操作的字段,排序操作会浪费很多时间。如果为其建立索引,可以有效地避免排序操作。3. 为常作为查询条件的字段建立索引如果某个字段经常用来做查询条件,那么该字段的查询速度会影响整个表的查询速度。因此,为这样的字段建立索引,可以提高整个表的查询速度。注意:常查询条件的字段不一定是所要选择的列,换句话说,最适合索引的列是出现在 WHERE 子句中的列,或连接子句中指定的列,而不是出现在 SELECT 关键字后的选择列表中的列。4. 限制索引的数目索引的数目不是“越多越好”。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。在修改表的内容时,索引必须进行更新,有时还可能需要重构。因此,索引越多,更新表的时间就越长。如果有一个索引很少利用或从不使用,那么会不必要地减缓表的修改速度。此外,MySQL 在生成一个执行计划时,要考虑各个索引,这也要花费时间。创建多余的索引给查询优化带来了更多的工作。索引太多,也可能会使 MySQL 选择不到所要使用的最佳索引。5. 尽量使用数据量少的索引如果索引的值很长,那么查询的速度会受到影响。例如,对一个 CHAR(100) 类型的字段进行全文检索需要的时间肯定要比对 CHAR(10) 类型的字段需要的时间要多。6. 数据量小的表最好不要使用索引由于数据较小,查询花费的时间可能比遍历索引的时间还要短,索引可能不会产生优化效果。7. 尽量使用前缀来索引如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT 和 BLOG 类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。8. 删除不再使用或者很少使用的索引表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。应该定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。总结选择索引的最终目的是为了使查询的速度变快,上面给出的原则是最基本的准则,但不能只拘泥于上面的准则。应该在学习和工作中不断的实践,根据应用的实际情况进行分析和判断,选择最合适的索引方式。
-
索引是 MySQL 数据库中的重要对象之一,用于快速找出某个列中有某一特定值的行。为什么要使用索引索引是 MySQL 中一种十分重要的数据库对象。它是数据库性能调优技术的基础,常用于实现数据的快速检索。索引就是根据表中的一列或若干列按照一定顺序建立的列值与记录行之间的对应关系表,实质上是一张描述索引列的列值与原表中记录行之间一一对应关系的有序表。在 MySQL 中,通常有以下两种方式访问数据库表的行数据:1) 顺序访问顺序访问是在表中实行全表扫描,从头到尾逐行遍历,直到在无序的行数据中找到符合条件的目标数据。这种方式实现比较简单,但是当表中有大量数据的时候,效率非常低下。例如,在几千万条数据中查找少量的数据时,使用顺序访问方式将会遍历所有的数据,花费大量的时间,显然会影响数据库的处理性能。2) 索引访问索引访问是通过遍历索引来直接访问表中记录行的方式。使用这种方式的前提是对表建立一个索引,在列上创建了索引之后,查找数据时可以直接根据该列上的索引找到对应记录行的位置,从而快捷地查找到数据。索引存储了指定列数据值的指针,根据指定的排序顺序对这些指针排序。例如,在学生基本信息表 students 中,如果基于 student_id 建立了索引,系统就建立了一张索引列到实际记录的映射表,当用户需要查找 student_id 为 12022 的数据的时候,系统先在 student_id 索引上找到该记录,然后通过映射表直接找到数据行,并且返回该行数据。因为扫描索引的速度一般远远大于扫描实际数据行的速度,所以采用索引的方式可以大大提高数据库的工作效率。索引的分类索引的类型和存储引擎有关,每种存储引擎所支持的索引类型不一定完全相同。根据存储方式的不同,MySQL 中常用的索引在物理上分为以下两类。1) B-树索引B-树索引又称为 BTREE 索引,目前大部分的索引都是采用 B-树索引来存储的。B-树索引是一个典型的数据结构,其包含的组件主要有以下几个:叶子节点:包含的条目直接指向表里的数据行。叶子节点之间彼此相连,一个叶子节点有一个指向下一个叶子节点的指针。分支节点:包含的条目指向索引里其他的分支节点或者叶子节点。根节点:一个 B-树索引只有一个根节点,实际上就是位于树的最顶端的分支节点。基于这种树形数据结构,表中的每一行都会在索引上有一个对应值。因此,在表中进行数据查询时,可以根据索引值一步一步定位到数据所在的行。B-树索引可以进行全键值、键值范围和键值前缀查询,也可以对查询结果进行 ORDER BY 排序。但 B-树索引必须遵循左边前缀原则,要考虑以下几点约束:查询必须从索引的最左边的列开始。查询不能跳过某一索引列,必须按照从左到右的顺序进行匹配。存储引擎不能使用索引中范围条件右边的列。2) 哈希索引哈希(Hash)一般翻译为“散列”,也有直接音译成“哈希”的,就是把任意长度的输入(又叫作预映射,pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。哈希索引也称为散列索引或 HASH 索引。MySQL 目前仅有 MEMORY 存储引擎和 HEAP 存储引擎支持这类索引。其中,MEMORY 存储引擎可以支持 B- 树索引和 HASH 索引,且将 HASH 当成默认索引。HASH 索引不是基于树形的数据结构查找数据,而是根据索引列对应的哈希值的方法获取表的记录行。哈希索引的最大特点是访问速度快,但也存在下面的一些缺点:MySQL 需要读取表中索引列的值来参与散列计算,散列计算是一个比较耗时的操作。也就是说,相对于 B- 树索引来说,建立哈希索引会耗费更多的时间。不能使用 HASH 索引排序。HASH 索引只支持等值比较,如“=”“IN()”或“<=>”。HASH 索引不支持键的部分匹配,因为在计算 HASH 值的时候是通过整个索引值来计算的。根据索引的具体用途,MySQL 中的索引在逻辑上分为以下 5 类:1) 普通索引普通索引是最基本的索引类型,唯一任务是加快对数据的访问速度,没有任何限制。创建普通索引时,通常使用的关键字是 INDEX 或 KEY。2) 唯一性索引唯一性索引是不允许索引列具有相同索引值的索引。如果能确定某个数据列只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字 UNIQUE 把它定义为一个唯一性索引。创建唯一性索引的目的往往不是为了提高访问速度,而是为了避免数据出现重复。3) 主键索引主键索引是一种唯一性索引,即不允许值重复或者值为空,并且每个表只能有一个主键。主键可以在创建表的时候指定,也可以通过修改表的方式添加,必须指定关键字 PRIMARY KEY。注意:主键是数据库考察的重点。注意每个表只能有一个主键。4) 空间索引空间索引主要用于地理空间数据类型 GEOMETRY。5) 全文索引全文索引只能在 VARCHAR 或 TEXT 类型的列上创建,并且只能在 MyISAM 表中创建。索引在逻辑上分为以上 5 类,但在实际使用中,索引通常被创建成单列索引和组合索引。单列索引就是索引只包含原表的一个列。组合索引也称为复合索引或多列索引,相对于单列索引来说,组合索引是将原表的多个列共同组成一个索引。提示:一个表可以有多个单列索引,但这些索引不是组合索引。一个组合索引实质上为表的查询提供了多个索引,以此来加快查询速度。比如,在一个表中创建了一个组合索引(c1,c2,c3),在实际查询中,系统用来实际加速的索引有三个:单个索引(c1)、双列索引(c1,c2)和多列索引(c1,c2,c3)。为了提高索引的应用性能,MySQL中的索引可以根据具体应用采用不同的索引策略。这些索引策略所对应的索引类型有聚集索引、次要索引、覆盖索引、复合索引、前缀索引、唯一索引等。索引的使用原则和注意事项虽然索引可以加快查询速度,提高 MySQL 的处理性能,但是过多地使用索引也会造成以下弊端:创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。除了数据表占数据空间之外,每一个索引还要占一定的物理空间。如果要建立聚簇索引,那么需要的空间就会更大。当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。注意:索引可以在一些情况下加速查询,但是在某些情况下,会降低效率。索引只是提高效率的一个因素,因此在建立索引的时候应该遵循以下原则:在经常需要搜索的列上建立索引,可以加快搜索的速度。在作为主键的列上创建索引,强制该列的唯一性,并组织表中数据的排列结构。在经常使用表连接的列上创建索引,这些列主要是一些外键,可以加快表连接的速度。在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,所以其指定的范围是连续的。在经常需要排序的列上创建索引,因为索引已经排序,所以查询时可以利用索引的排序,加快排序查询。在经常使用 WHERE 子句的列上创建索引,加快条件的判断速度。与此对应,在某些应用场合下建立索引不能提高 MySQL 的工作效率,甚至在一定程度上还带来负面效应,降低了数据库的工作效率,一般来说不适合创建索引的环境如下:对于那些在查询中很少使用或参考的列不应该创建索引。因为这些列很少使用到,所以有索引或者无索引并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度,并增大了空间要求。对于那些只有很少数据值的列也不应该创建索引。因为这些列的取值很少,例如人事表的性别列。查询结果集的数据行占了表中数据行的很大比例,增加索引并不能明显加快检索速度。对于那些定义为 TEXT、IMAGE 和 BIT 数据类型的列不应该创建索引。因为这些列的数据量要么相当大,要么取值很少。当修改性能远远大于检索性能时,不应该创建索引。因为修改性能和检索性能是互相矛盾的。当创建索引时,会提高检索性能,降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
-
索引的类型和存储引擎有关,每种存储引擎所支持的索引类型不一定完全相同。MySQL 索引可以从存储方式、逻辑角度和实际使用的角度来进行分类。存储方式区分根据存储方式的不同,MySQL 中常用的索引在物理上分为 B-树索引和 HASH 索引两类,两种不同类型的索引各有其不同的适用范围。1) B-树索引B-树索引又称为 BTREE 索引,目前大部分的索引都是采用 B-树索引来存储的。B-树索引是一个典型的数据结构,其包含的组件主要有以下几个:叶子节点:包含的条目直接指向表里的数据行。叶子节点之间彼此相连,一个叶子节点有一个指向下一个叶子节点的指针。分支节点:包含的条目指向索引里其他的分支节点或者叶子节点。根节点:一个 B-树索引只有一个根节点,实际上就是位于树的最顶端的分支节点。基于这种树形数据结构,表中的每一行都会在索引上有一个对应值。因此,在表中进行数据查询时,可以根据索引值一步一步定位到数据所在的行。B-树索引可以进行全键值、键值范围和键值前缀查询,也可以对查询结果进行 ORDER BY 排序。但 B-树索引必须遵循左边前缀原则,要考虑以下几点约束:查询必须从索引的最左边的列开始。查询不能跳过某一索引列,必须按照从左到右的顺序进行匹配。存储引擎不能使用索引中范围条件右边的列。2) 哈希索引哈希(Hash)一般翻译为“散列”,也有直接音译成“哈希”的,就是把任意长度的输入(又叫作预映射,pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。哈希索引也称为散列索引或 HASH 索引。MySQL 目前仅有 MEMORY 存储引擎和 HEAP 存储引擎支持这类索引。其中,MEMORY 存储引擎可以支持 B-树索引和 HASH 索引,且将 HASH 当成默认索引。HASH 索引不是基于树形的数据结构查找数据,而是根据索引列对应的哈希值的方法获取表的记录行。哈希索引的最大特点是访问速度快,但也存在下面的一些缺点:MySQL 需要读取表中索引列的值来参与散列计算,散列计算是一个比较耗时的操作。也就是说,相对于 B-树索引来说,建立哈希索引会耗费更多的时间。不能使用 HASH 索引排序。HASH 索引只支持等值比较,如“=”“IN()”或“<=>”。HASH 索引不支持键的部分匹配,因为在计算 HASH 值的时候是通过整个索引值来计算的。逻辑区分根据索引的具体用途,MySQL 中的索引在逻辑上分为以下 5 类:1) 普通索引普通索引是 MySQL 中最基本的索引类型,它没有任何限制,唯一任务就是加快系统对数据的访问速度。普通索引允许在定义索引的列中插入重复值和空值。创建普通索引时,通常使用的关键字是 INDEX 或 KEY。例 1下面在 tb_student 表中的 id 字段上建立名为 index_id 的索引。CREATE INDEX index_id ON tb_student(id);2) 唯一索引唯一索引与普通索引类似,不同的是创建唯一性索引的目的不是为了提高访问速度,而是为了避免数据出现重复。唯一索引列的值必须唯一,允许有空值。如果是组合索引,则列值的组合必须唯一。创建唯一索引通常使用 UNIQUE 关键字。例 2下面在 tb_student 表中的 id 字段上建立名为 index_id 的索引,SQL 语句如下:CREATE UNIQUE INDEX index_id ON tb_student(id);其中,id 字段可以有唯一性约束,也可以没有。3) 主键索引顾名思义,主键索引就是专门为主键字段创建的索引,也属于索引的一种。主键索引是一种特殊的唯一索引,不允许值重复或者值为空。创建主键索引通常使用 PRIMARY KEY 关键字。不能使用 CREATE INDEX 语句创建主键索引。4) 空间索引空间索引是对空间数据类型的字段建立的索引,使用 SPATIAL 关键字进行扩展。创建空间索引的列必须将其声明为 NOT NULL,空间索引只能在存储引擎为 MyISAM 的表中创建。空间索引主要用于地理空间数据类型 GEOMETRY。对于初学者来说,这类索引很少会用到。例 3下面在 tb_student 表中的 line 字段上建立名为 index_line 的索引,SQL 语句如下:CREATE SPATIAL INDEX index_line ON tb_student(line);其中,tb_student 表的存储引擎必须是 MyISAM,line 字段必须为空间数据类型,而且是非空的。5) 全文索引全文索引主要用来查找文本中的关键字,只能在 CHAR、VARCHAR 或 TEXT 类型的列上创建。在 MySQL 中只有 MyISAM 存储引擎支持全文索引。全文索引允许在索引列中插入重复值和空值。不过对于大容量的数据表,生成全文索引非常消耗时间和硬盘空间。创建全文索引使用 FULLTEXT 关键字。例 4在 tb_student 表中的 info 字段上建立名为 index_info 的全文索引,SQL 语句如下:CREATE FULLTEXT INDEX index_info ON tb_student(info);其中,index_info 的存储引擎必须是 MyISAM,info 字段必须是 CHAR、VARCHAR 和 TEXT 等类型。实际使用区分索引在逻辑上分为以上 5 类,但在实际使用中,索引通常被创建成单列索引和组合索引。1)单列索引单列索引就是索引只包含原表的一个列。在表中的单个字段上创建索引,单列索引只根据该字段进行索引。单列索引可以是普通索引,也可以是唯一性索引,还可以是全文索引。只要保证该索引只对应一个字段即可。例 5下面在 tb_student 表中的 address 字段上建立名为 index_addr 的单列索引,address 字段的数据类型为 VARCHAR(20),索引的数据类型为 CHAR(4)。SQL 语句如下:CREATE INDEX index_addr ON tb_student(address(4));这样,查询时可以只查询 address 字段的前 4 个字符,而不需要全部查询。2)多列索引组合索引也称为复合索引或多列索引。相对于单列索引来说,组合索引是将原表的多个列共同组成一个索引。多列索引是在表的多个字段上创建一个索引。该索引指向创建时对应的多个字段,可以通过这几个字段进行查询。但是,只有查询条件中使用了这些字段中第一个字段时,索引才会被使用。例如,在表中的 id、name 和 sex 字段上建立一个多列索引,那么,只有查询条件使用了 id 字段时,该索引才会被使用。例 6下面在 tb_student 表中的 name 和 address 字段上建立名为 index_na 的索引,SQL 语句如下:CREATE INDEX index_na ON tb_student(name,address);该索引创建好了以后,查询条件中必须有 name 字段才能使用索引。提示:一个表可以有多个单列索引,但这些索引不是组合索引。一个组合索引实质上为表的查询提供了多个索引,以此来加快查询速度。比如,在一个表中创建了一个组合索引(c1,c2,c3),在实际查询中,系统用来实际加速的索引有三个:单个索引(c1)、双列索引(c1,c2)和多列索引(c1,c2,c3)。
-
冷备份可以称为 Offline Backup(离线备份)。这种备份最为简单,一般只需要复制相关的数据库物理文件到另外的位置即可。由于 MySQL 服务器中的数据文件是基于磁盘的文本文件,所以最简单、最直接的备份操作,就是将数据文件直接复制出来。但是由于 MySQL 服务器的数据文件在运行时期,总是处于打开和使用状态,因此备份文件不一定有效。为了解决该问题,在复制数据文件时,需要先停止 MySQL 服务器。这样做的好处是可以保证数据库的完整性,备份过程简单且恢复速度相对快一些,但是关闭数据库会影响现有业务的进行。服务器停止运行期间,用户不能再继续访问网站。例如,一些电商网站店庆促销时,如果为了备份要停库,那么带来的代价损失将不可估量。所以冷备一般用于不是很重要、非核心的业务上面。冷备份的优点如下:备份简单、快速,只要复制相关文件即可。备份文件易于在不同操作系统,不同 MySQL 版本上进行恢复。恢复相当简单,只需要把文件恢复到指定位置即可。恢复速度快,不需要执行任何 SQL 语句,也不需要重建索引。低度维护,高度安全。冷备份的缺点如下:备份过程中,数据库不能做其它的工作,且必须是关闭状态。InnoDB 存储引擎冷备的文件通常比逻辑文件大很多,因为表空间存放着很多其它的数据,如 undo 段,插入缓冲等信息。若磁盘空间有限,只能拷贝到磁带等其它外部存储设备上,速度会很慢。冷备也不总是可以轻易的跨平台。操作系统、MySQL 的版本、文件大小写敏感和浮点数格式都会成为问题。数据库的物理文件主要由数据库的数据文件、日志文件以及配置文件等组成。MySQL 系统有一些共有的日志文件和系统表的数据文件。每种存储引擎的物理文件也不一样,冷备的备份与恢复过程也很简单。仅仅需要如下几步:1)为了保证所备份数据的完整性,在停止 MySQL 数据库服务器之前,需要先执行 FLUSH TABLES 语句将所有数据写入到数据文件的文本文件里。2)停掉 MySQL 服务,命令(2种方式)如下:mysqladmin -uroot -proot shutdownNET START mysql3)备份过程就是复制整个数据目录到远程备份机或者本地磁盘上,Linux 和 Windows 命令如下:Scp -r /data/mysql/ root@远程备份机ip:/新的目录Copy -r /data/mysql/ 本地新目录备份到本次磁盘也可以手动复制上述相关目录里的数据文件。4)恢复过程就更简单了,仅仅需要把已备份的数据目录替换原有的目录就可以了,最后重启 MySQL 服务。恢复数据是数据库维护中最常用的操作,利用备份文件可以将 MySQL 数据库服务器恢复到备份时的状态,这样就可以将管理员的非常操作和计算机的故障造成的相关损失降到最小。上面我们介绍了如何通过数据文件实现数据备份和恢复。需要注意的是,通过复制数据文件这种方式实现数据恢复时,必须保证两个 MySQL 数据库的主版本号一致。只有两个 MySQL 数据库主版本号相同时,才能保证它们的数据文件类型是相同的。关于 MySQL 数据库服务器的版本号第一个数字表示主版本号,例如 MySQL 5.5.21 和 MySQL 5.5.01 这两个版本的主版本号都是 5,所以这两个数据库拥有相同类型的数据文件。
-
与冷备份正好相反,热备份是在数据库处于运行状态时直接备份,不影响现有业务的正常进行。热备份又细分为逻辑备份和裸文件备份,下面我们介绍逻辑备份和冷备份以及它们常用的备份和恢复的方法。逻辑备份逻辑备份的最大优点就是对于各种存储引擎,都可以用同样的方法来备份。而冷备份则不同,不同的存储引擎的备份方法也各不相同。因此,对于不同存储引擎混合的数据库,用逻辑备份会更简单一些。逻辑备份可以说是最简单,也是目前中小型系统最常用的备份方法。逻辑备份主要有以下几种方法:1)mysqldumpmysqldump 是 MySQL 自带的逻辑备份工具。它的备份原理是通过协议连接到 MySQL 数据库,将需要备份的数据查询出来,然后将查询出的数据转换成对应的 INSERT 语句。当我们需要还原恢复这些数据时,只要执行这些 INSERT 语句,就能将对应的数据还原。所以有的资料也将这种备份方式称为 INSERT 备份。恢复数据时可以使用 mysql -uroot -p <backup.sql 直接调用备份文件执行所有命令,将数据完全恢复到备份时候的状态。如果已经连接上了 MySQL 服务器,那么可以通过 source /path/backup.sql 来进行恢复。2)SELECT INTO…OUTFILESELECT INTO…OUTFILE 语句可以把表数据导出到一个文本文件中,且能将数据库中的表数据以特定分隔符进行分隔后记录在文本文件中,以达到逻辑备份的效果。这种备份方式与 mysqldump 方法相比,使用的存储空间更小,数据格式更加清晰明确,编辑方便。但是这种方法只能导出或导入数据的内容,不包括表的结构,如果表的结构文件损坏,则必须先恢复原来的表的结构。而且这种方法不能在同一个备份文件中存在多个表的备份数据,增加了文件维护和恢复的成本。这种备份方法恢复起来会稍微麻烦一点,需要一个表一个表通过相关命令来进行恢复。当然如果是通过脚本来实现自动多表恢复也是比较方便的。恢复方法有 2 个,一个是通过 MySQL 的 LOAD DATA INFILE 命令来恢复数据,另一种方法就是通过 MySQL 提供的使用工具 mysqlimport 来进行恢复。3)mydumpermydumper 是针对 MySQL 数据库备份的一个轻量级第三方的开源工具,备份方式为逻辑备份。它支持多线程,备份速度远高于原生态的 mysqldump 以及其它众多优异特性。与其配套的相应恢复数据为 myloader 工具。DBA 称 mydumper 和 myloader 为备份界的“小钢炮”。我们可以看出所谓的逻辑备份就是备份 SQL 语句,然后恢复数据时执行备份 SQL,从而实现数据库数据的重现。逻辑备份完成后所形成的文件都可以直接编辑。逻辑备份的作用如下:通过逻辑备份,我们可以仅仅恢复备份中的部分数据而不需要全部恢复。不会影响不相关的数据;通过全库的逻辑备份,我们可以在新的 MySQL 环境下完全重建出一个与备份时完全一样的数据库,并且不受平台类型限制;通过特定条件的逻辑备份,我们可以将某些特定数据轻松迁移(或者同步)到其它的 MySQL 或另外的数据库环境。裸文件备份裸文件备份主要在底层复制数据文件,所以备份速度要比逻辑备份更快。我们利用 Percona 公司发布的一个 XtraBackup 热备份工具来完成裸文件备份,它是 Percona 公司的开源项目,据官方介绍它是世界上唯一 一款开源的能够对 InnoDB 和 XtraDB 数据库进行热备的工具。它的优点就是备份与恢复过程的速度很快,安全可靠,而且在备份过程中不会缩表,不影响现有业务。但它目前还是不能对表结构文件和其它非事务类型的表进行备份。
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签