Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3327984
  • 博文数量: 631
  • 博客积分: 10716
  • 博客等级: 上将
  • 技术积分: 8397
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-01 22:35
文章分类

全部博文(631)

文章存档

2020年(2)

2019年(22)

2018年(4)

2017年(37)

2016年(22)

2015年(1)

2013年(12)

2012年(20)

2011年(19)

2010年(20)

2009年(282)

2008年(190)

分类: Mysql/postgreSQL

2009-06-11 15:34:03

13.3. MySQL实用工具语句

13.3.1. DESCRIBE语法(获取有关列的信息)

{DESCRIBE | DESC} tbl_name [col_name | wild]

DESCRIBE可以提供有关表中各列的信息。它是SHOW COLUMNS FROM的快捷方式。这些语句也可以显示语句,用于阅览。

13.5.4.3节,“SHOW COLUMNS语法”

col_name可以是一个列名称,或一个包含‘%’和‘_’的通配符的字符串,用于获得对于带有与字符串相匹配的名称的各列的输出。没有必要在引号中包含字符串,除非其中包含空格或其它特殊字符。

mysql> DESCRIBE city;
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| Id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name       | char(35) | NO   |     |         |                |
| Country    | char(3)  | NO   | UNI |         |                |
| District   | char(20) | YES  | MUL |         |                |
| Population | int(11)  | NO   |     | 0       |                |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

NULL字段指示是否NULL可以被存储在列中。

Key字段指示是否该列已编制索引。PRI的值指示该列是表的主键的一部分。UNI指示,该列是UNIQUE索引的一部分。MUL值指示,在列中某个给定值多次出现是允许的。

MUL将被显示在UNIQUE索引中,原因之一是多个列会组合成一个复合UNIQUE索引;尽管列的组合是唯一的,但每个列仍可以多次出现同一个给定值。注意,在复合索引中,只有索引最左边的列可以进入Key字段中。

默认字段指示,默认值被赋予该列。

Extra字段包含可以获取的与给定列有关的附加信息。在我们的例子中,Extra字段指示,Id列使用AUTO_INCREMENT关键词创建。

如果列类型与您预计的依据CREATE TABLE语句得出的列类型不同,则请注意,MySQL有时会改变列类型。请参见13.1.5.1节,“沉寂的列规格变更”

DESCRIBE语句被设立出来,用于与Oracle相兼容。

SHOW CREATE TABLESHOW TABLE STATUS语句也可以提供有关表的信息。请参见13.5.4节,“SHOW语法”

13.3.2. USE语法

USE db_name

USE db_name语句可以通告MySQLdb_name数据库作为默认(当前)数据库使用,用于后续语句。该数据库保持为默认数据库,直到语段的结尾,或者直到发布一个不同的USE语句:

mysql> USE db1;
mysql> SELECT COUNT(*) FROM mytable;   # selects from db1.mytable
mysql> USE db2;
mysql> SELECT COUNT(*) FROM mytable;   # selects from db2.mytable

使用USE语句为一个特定的当前的数据库做标记,不会阻碍您访问其它数据库中的表。下面的例子可以从db1数据库访问作者表,并从db2数据库访问编辑表:

mysql> USE db1;
mysql> SELECT author_name,editor_name FROM author,db2.editor
    ->        WHERE author.editor_id = db2.editor.editor_id;

USE语句被设立出来,用于与Sybase相兼容。

13.4. MySQL事务处理和锁定语句

MySQL通过SET AUTOCOMMIT, START TRANSACTION, COMMITROLLBACK等语句支持本地事务(在给定的客户端连接中)。请参见13.4.1节,“START TRANSACTION, COMMIT和ROLLBACK语法”XA事务支持还可以允许MySQL参与分布式事务。请参见13.4.7节,“XA事务”

13.4.1. START TRANSACTION, COMMIT和ROLLBACK语法

START TRANSACTION | BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT = {0 | 1}

START TRANSACTIONBEGIN语句可以开始一项新的事务。COMMIT可以提交当前事务,是变更成为永久变更。ROLLBACK可以 回滚当前事务,取消其变更。SET AUTOCOMMIT语句可以禁用或启用默认的autocommit模式,用于当前连接。

自选的WORK关键词被支持,用于COMMITRELEASE,与CHAINRELEASE子句。CHAINRELEASE可以被用于对事务完成进行附加控制。Completion_type系统变量的值决定了默认完成的性质。请参见5.3.3节,“服务器系统变量”

AND CHAIN子句会在当前事务结束时,立刻启动一个新事务,并且新事务与刚结束的事务有相同的隔离等级。RELEASE子句在终止了当前事务后,会让服务器断开与当前客户端的连接。包含NO关键词可以抑制CHAINRELEASE完成。如果completion_type系统变量被设置为一定的值,使连锁或释放完成可以默认进行,此时NO关键词有用。

默认情况下,MySQL采用autocommit模式运行。这意味着,当您执行一个用于更新(修改)表的语句之后,MySQL立刻把更新存储到磁盘中。

如果您正在使用一个事务安全型的存储引擎(如InnoDB, BDBNDB簇),则您可以使用以下语句禁用autocommit模式:

SET AUTOCOMMIT=0;

通过把AUTOCOMMIT变量设置为零,禁用autocommit模式之后,您必须使用COMMIT把变更存储到磁盘中,或着如果您想要忽略从事务开始进行以来做出的变更,使用ROLLBACK

如果您想要对于一个单一系列的语句禁用autocommit模式,则您可以使用START TRANSACTION语句:

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;

使用START TRANSACTIONautocommit仍然被禁用,直到您使用COMMITROLLBACK结束事务为止。然后autocommit模式恢复到原来的状态。

BEGINBEGIN WORK被作为START TRANSACTION的别名受到支持,用于对事务进行初始化。START TRANSACTION是标准的SQL语法,并且是启动一个ad-hoc事务的推荐方法。BEGIN语句与BEGIN关键词的使用不同。BEGIN关键词可以启动一个BEGIN...END复合语句。后者不会开始一项事务。请参见20.2.7节,“BEGIN ... END复合语句”

您也可以按照如下方法开始一项事务:

START TRANSACTION WITH CONSISTENT SNAPSHOT;

WITH CONSISTENT SNAPSHOT子句用于启动一个一致的读取,用于具有此类功能的存储引擎。目前,该子句只适用于InnoDB。该子句的效果与发布一个START TRANSACTION,后面跟一个来自任何InnoDB表的SELECT的效果一样。请参见15.2.10.4节,“一致的非锁定读”

开始一项事务会造成一个隐含的UNLOCK TABLES被执行。

为了获得最好的结果,事务应只使用由单一事务存储引擎管理的表执行。否则,会出现以下问题:

·         如果您使用的表来自多个事务安全型存储引擎(例如InnoDBBDB),并且事务隔离等级不是SERIALIZABLE,则有可能当一个事务提交时,其它正在进行中的、使用同样的表的事务将只会发生由第一个事务产生的变更。也就是,用混合引擎不能保证事务的原子性,并会造成不一致。(如果混合引擎事务不经常有,则您可以根据需要使用SET TRANSACTION ISOLATION LEVEL把隔离等级设置到SERIALIZABLE。)

·         如果您在事务中使用非事务安全型表,则对这些表的任何变更被立刻存储,不论autocommit模式的状态如何。

如果您在更新了事务中一个事务表之后,发布一个ROLLBACK语句,则会出现一个ER_WARNING_NOT_COMPLETE_ROLLBACK警告。对事务安全型表的变更被 回滚,但是对非事务安全型表没有变更。

每个事务被存储在一个组块中的二进制日志中,在COMMIT之上。被回滚的事务不被计入日志。(例外情况:对非事务表的更改不会被 回滚。如果一个被回滚的事务包括对非事务表的更改,则整个事务使用一个在末端的ROLLBACK语句计入日志,以确保对这些表的更改进行复制。)见5.11.3节,“二进制日志”

您可以使用SET TRANSACTION ISOLATION LEVEL更改事务的隔离等级。请参见13.4.6节,“SET TRANSACTION语法”

回滚可以慢速运行。在用户没有明确要求时,也可以进行回滚(例如,当错误发生时)。因此,在明确地和隐含的(ROLLBACK SQL命令)回滚时,SHOW PROCESSLIST会在Stage列中显示Rolling back,用于连接。

13.4.2. 不能回滚的语句

有些语句不能被回滚。通常,这些语句包括数据定义语言(DDL)语句,比如创建或取消数据库的语句,和创建、取消或更改表或存储的子程序的语句。

您在设计事务时,不应包含这类语句。如果您在事务的前部中发布了一个不能被回滚的语句,则后部的其它语句会发生错误,在这些情况下,通过发布ROLLBACK语句不能 回滚事务的全部效果。

13.4.3. 会造成隐式提交的语句

以下语句(以及同义词)均隐含地结束一个事务,似乎是在执行本语句前,您已经进行了一个COMMIT

·         ALTER FUNCTION, ALTER PROCEDURE, ALTER TABLE, BEGIN, CREATE DATABASE, CREATE FUNCTION, CREATE INDEX, CREATE PROCEDURE, CREATE TABLE, DROP DATABASE, DROP FUNCTION, DROP INDEX, DROP PROCEDURE, DROP TABLE, LOAD MASTER DATA, LOCK TABLES, RENAME TABLE, SET AUTOCOMMIT=1, START TRANSACTION, TRUNCATE TABLE, UNLOCK TABLES.

·         当当前所有的表均被锁定时,UNLOCK TABLES可以提交事务。

·         CREATE TABLE, CREATE DATABASE DROP DATABASE, TRUNCATE TABLE, ALTER FUNCTION, ALTER PROCEDURE, CREATE FUNCTION, CREATE PROCEDURE, DROP FUNCTIONDROP PROCEDURE等语句会导致一个隐含提交。

·         InnoDB中的CREATE TABLE语句被作为一个单一事务进行处理。这意味着,来自用户的ROLLBACK不会撤销用户在事务处理过程中创建的CREATE TABLE语句。

事务不能被嵌套。这是隐含COMMIT的结果。当您发布一个START TRANSACTION语句或其同义词时,该COMMIT被执行,用于任何当前事务。

13.4.4. SAVEPOINT和ROLLBACK TO SAVEPOINT语法

SAVEPOINT identifier
ROLLBACK [WORK] TO SAVEPOINT identifier
RELEASE SAVEPOINT identifier

InnoDB支持SQL语句SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT和自选的用于ROLLBACKWORK关键词。

SAVEPOINT语句用于设置一个事务保存点,带一个标识符名称。如果当前事务有一个同样名称的保存点,则旧的保存点被删除,新的保存点被设置。

ROLLBACK TO SAVEPOINT语句会向以命名的保存点回滚一个事务。如果在保存点被设置后,当前事务对行进行了更改,则这些更改会在 回滚中被撤销。但是,InnoDB不会释放被存储在保存点之后的存储器中的行锁定。(注意,对于新插入的行,锁定信息被存储在行中的事务ID承载;锁定没有被分开存储在存储器中。在这种情况下,行锁定在撤销中被释放。)在被命名的保存点之后设置的保存点被删除。

如果语句返回以下错误,则意味着不存在带有指定名称的保存点:

ERROR 1181: Got error 153 during ROLLBACK

RELEASE SAVEPOINT语句会从当前事务的一组保存点中删除已命名的保存点。不出现提交或 回滚。如果保存点不存在,会出现错误。

如果您执行COMMIT或执行不能命名保存点的ROLLBACK,则当前事务的所有保存点被删除。

13.4.5. LOCK TABLES和UNLOCK TABLES语法

LOCK TABLES
    tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
    [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ...
UNLOCK TABLES

LOCK TABLES可以锁定用于当前线程的表。如果表被其它线程锁定,则造成堵塞,直到可以获取所有锁定为止。UNLOCK TABLES可以释放被当前线程保持的任何锁定。当线程发布另一个LOCK TABLES时,或当与服务器的连接被关闭时,所有由当前线程锁定的表被隐含地解锁。

  表锁定只用于防止其它客户端进行不正当地读取和写入。保持锁定(即使是读取锁定)的客户端可以进行表层级的操作,比如DROP TABLE

注意,下面是对事务表使用LOCK TABLES的说明:

·         在尝试锁定表之前,LOCK TABLES不是事务安全型的,会隐含地提交所有活性事务。同时,开始一项事务(例如,使用START TRANSACTION),会隐含地执行UNLOCK TABLES。(见13.4.3节,“会造成隐式提交的语句”

·         对事务表(如InnoDB)使用LOCK TABLES的正确方法是,设置AUTOCOMMIT=0并且不能调用UNLOCK TABLES,直到您明确地提交事务为止。当您调用LOCK TABLES时,InnoDB会内部地取其自己的表锁定,MySQL取其自己的表锁定。InnoDB在下一个提交时释放其表锁定,但是,对于MySQL,要释放表锁定,您必须调用UNLOCK TABLES。您不应该让AUTOCOMMIT=1,因为那样的话,InnoDB会在调用LOCK TABLES之后立刻释放表锁定,并且很容易形成死锁定。注意,如果AUTOCOMMIT=1,我们根本不能获取InnoDB表锁定,这样就可以帮助旧的应用软件避免不必要的死锁定。

·         ROLLBACK不会释放MySQL的非事务表锁定。

要使用LOCK TABLES,您必须拥有相关表的LOCK TABLES权限和SELECT权限。

使用LOCK TABLES的主要原因是仿效事务,或在更新表时加快速度。这将在后面进行更详细的解释。

如果一个线程获得对一个表地READ锁定,该线程(和所有其它线程)只能从该表中读取。如果一个线程获得对一个表的WRITE锁定,只有保持锁定的线程可以对表进行写入。其它的线程被阻止,直到锁定被释放时为止。

READ LOCALREAD之间的区别是,READ LOCAL允许在锁定被保持时,执行非冲突性INSERT语句(同时插入)。但是,如果您正打算在MySQL外面操作数据库文件,同时您保持锁定,则不能使用READ LOCAL。对于InnoDB表,READ LOCALREAD相同。

当您使用LOCK TABLES时,您必须锁定您打算在查询中使用的所有的表。虽然使用LOCK TABLES语句获得的锁定仍然有效,但是您不能访问没有被此语句锁定的任何的表。同时,您不能在一次查询中多次使用一个已锁定的表——使用别名代替,在此情况下,您必须分别获得对每个别名的锁定。

mysql> LOCK TABLE t WRITE, t AS t1 WRITE;
mysql> INSERT INTO t SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> INSERT INTO t SELECT * FROM t AS t1;

如果您的查询使用一个别名引用一个表,那么您必须使用同样的别名锁定该表。如果没有指定别名,则不会锁定该表。

mysql> LOCK TABLE t READ;
mysql> SELECT * FROM t AS myalias;
ERROR 1100: Table 'myalias' was not locked with LOCK TABLES

相反的,如果您使用一个别名锁定一个表,您必须使用该别名在您的查询中引用该表。

mysql> LOCK TABLE t AS myalias READ;
mysql> SELECT * FROM t;
ERROR 1100: Table 't' was not locked with LOCK TABLES
mysql> SELECT * FROM t AS myalias;

WRITE锁定通常比READ锁定拥有更高的优先权,以确保更新被尽快地处理。这意味着,如果一个线程获得了一个READ锁定,则另一个线程会申请一个WRITE锁定,后续的READ锁定申请会等待,直到WRITE线程获得锁定并释放锁定。您可以使用LOW_PRIORITY WRITE锁定来允许其它线程在该线程正在等待WRITE锁定时获得READ锁定。只有当您确定最终将有一个时机,此时没有线程拥有READ锁定时,您才应该使用LOW_PRIORITY WRITE锁定。

LOCK TABLES按照如下方式执行:

1.    按照内部定义的顺序,对所有要被锁定的表进行分类。从用户的角度,此顺序是未经定义的。

2.    如果使用一个读取和一个写入锁定对一个表进行锁定,则把写入锁定放在读取锁定之前。

3.    一次锁定一个表,直到线程得到所有锁定为止。

该规则确保表锁定不会出现死锁定。但是,对于该规则,您需要注意其它的事情:

如果您正在对一个表使用一个LOW_PRIORITY WRITE锁定,这只意味着,MySQL等待特定的锁定,直到没有申请READ锁定的线程时为止。当线程已经获得WRITE锁定,并正在等待得到锁定表清单中的用于下一个表的锁定时,所有其它线程会等待WRITE锁定被释放。如果这成为对于应用程序的严重的问题,则您应该考虑把部分表转化为事务安全型表。

您可以安全地使用KILL来结束一个正在等待表锁定的线程。请参见13.5.5.3节,“KILL语法”

注意,您不能使用INSERT DELAYED锁定任何您正在使用的表,因为,在这种情况下,INSERT由另一个线程执行。

通常,您不需要锁定表,因为所有的单个UPDATE语句都是原子性的;没有其它的线程可以干扰任何其它当前正在执行的SQL语句。但是,在几种情况下,锁定表会有好处:

·         如果您正在对一组MyISAM表运行许多操作,锁定您正在使用的表,可以快很多。锁定MyISAM表可以加快插入、更新或删除的速度。不利方面是,没有线程可以更新一个用READ锁定的表(包括保持锁定的表),也没有线程可以访问用WRITE锁定的表(除了保持锁定的表以外)。

有些MyISAM操作在LOCK TABLES之下更快的原因是,MySQL不会清空用于已锁定表的关键缓存,直到UNLOCK TABLE被调用为止。通常,关键缓存在每个SQL语句之后被清空。

·         如果您正在使用MySQL中的一个不支持事务的存储引擎,则如果您想要确定在SELECTUPDATE之间没有其它线程,您必须使用LOCK TABLES。本处所示的例子要求LOCK TABLES,以便安全地执行:

·                mysql> LOCK TABLES trans READ, customer WRITE;
·                mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;
·                mysql> UPDATE customer
·                    ->     SET total_value=sum_from_previous_statement
·                    ->     WHERE customer_id=some_id;
·                mysql> UNLOCK TABLES;

如果没有LOCK TABLES,有可能另一个线程会在执行SELECTUPDATE语句之间在trans表中插入一个新行。

通过使用相对更新(UPDATE customer SET value=value+new_value)或LAST_INSERT_ID()函数,您可以在许多情况下避免使用LOCK TABLES。请参见1.8.5.3节,“事务和原子操作”

通过使用用户层级的顾问式锁定函数GET_LOCK()RELEASE_LOCK(),您也可以在有些情况下避免锁定表。这些锁定被保存在服务器中的一个混编表中,使用pthread_mutex_lock() pthread_mutex_unlock(),以加快速度。请参见12.9.4节,“其他函数”

要了解更多有关锁定规则的说明,请参见7.3.1节,“锁定方法”

您可以使用FLUSH TABLES WITH READ LOCK语句锁定位于所有带有读取锁定的数据库中的所有表。请参见13.5.5.2节,“FLUSH语法”。如果您有一个可以及时拍摄快照的文件系统,比如Veritas,这是获得备份的一个非常方便的方式。

注释:如果您对一个已锁定的表使用ALTER TABLE,该表可能会解锁。请参见A.7.1节,“与ALTER TABLE有关的问题”

13.4.6. SET TRANSACTION语法

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

本语句用于设置事务隔离等级,用于下一个事务,或者用于当前会话。

在默认情况下,SET TRANSACTION会为下一个事务(还未开始)设置隔离等级。如果您使用GLOBAL关键词,则语句会设置全局性的默认事务等级,用于从该点以后创建的所有新连接。原有的连接不受影响。要进行此操作,您需要SUPER权限。使用SESSION关键测可以设置默认事务等级,用于对当前连接执行的所有将来事务。

要了解对每个InnoDB事务隔离等级的描述,请参见15.2.10.3节,“InnoDB和TRANSACTION ISOLATION LEVEL”InnoDB支持MySQL 5.1中的各个等级。默认的等级是REPEATABLE READ

您可以使用--transaction-isolation选项,对mysqld设置初始的默认全局隔离等级。请参见5.3.1节,“mysqld命令行选项”

13.4.7. XA事务

对于InnoDB存储引擎,可以获得对XA事务的支持。MySQL XA的执行依据X/Open CAE文件Distributed Transaction Processing: The XA Specification。本文件由Open Group出版,可以从获取。在I.5节,“对XA事务的限制”对当前XA执行的限制进行了描述。

在客户端方面,没有特殊要求。连接MySQL服务器的XA接口由以XA关键词开头的SQL语句组成。MySQL客户端必须能发送SQL语句,并能理解XA语句接口的语义,但是它们不需要被链接到特定的MySQL客户库上。

当前,在MySQL连接器当中,MySQL连接器/J 5.0.0直接支持XA(也就是,通过一个可以控制XA SQL语句接口的等级接口)。

XA支持分布式的事务,具备能力,让多个独立的事务资源参加全局的事务。事务资源通常是RDBMSs,不过也可以是其它种类的资源。

一个全局事务会涉及到多个行动,这些行动本身是事务性的。不过,所有行动都必须作为一个群组成功完成,或者作为一个群组被回滚。实际上,这会延伸ACID性质,“提高等级”,这样,多个ACID事务就可以一起执行,相当于也拥有ACID性质的全局操作的组件。(但是,对于一个分布式事务,您必须使用SERAILIZABLE隔离等级,以实现ACID性质。对于一个非分布式事务,使用REPEATABLE READ就足够了。但是对于分布式事务,使用REPEATABLE READ是不够的。)

分布式事务的部分示例:

·         应用程序相当于一个把消息传递服务和RDBMS组合在一起的整合工具。应用程序可以确保,所有进行消息发送、回收和处理的事务(同时包含一个事务数据库)均在一个全局事务中发生。您可以把这看作是“事务电子邮件。”

·         应用程序执行的行动会涉及到不同数据库服务器,比如MySQL服务器和Oracle服务器(或多个MySQL服务器)。涉及到多个服务器的行动必须作为一个全局事务的一部分发生,而不是作为针对每个服务器的独立的本地事务发生。

·         银行把帐户信息保存在RDBMS中,并通过自动取款机(ATMs)分发和收取欠款。必须要确保ATM行动被正确地反映到帐户中,但是这不能只由RDBMS单独完成。全局事务管理器会整合ATM和数据库资源,以确保财务事务的整体一致性。

使用全局事务的应用程序涉及一个或多个资源管理器和一个事务管理器:

·         资源管理器(RM)用于提供通向事务资源的途径。数据库服务器是一种资源管理器。该管理器必须可以提交或 回滚由RM管理的事务。

·         事务管理器(TM)用于协调作为一个全局事务一部分的事务。TM与管理每个事务的RMs进行通讯。一个全局事务中各个单个事务均是全局事务的“分支”。全局事务和各分支通过一种命名方法进行标识。这种命名方法在后面进行讲述。

MySQL执行XA MySQL时,MySQL服务器相当于一个用于管理全局事务中的XA事务的资源管理器。与MySQL服务器连接的客户端相当于事务管理器。

要执行一个全局事务,必须知道涉及到了哪些组件,并且把每个组件引到一点,在此时,组件可以被提交或回滚时。根据每个组件报告的有关组件效能的内容,这些组件必须作为一个原子性群组全部提交或 回滚。即,要么所有的组件必须提交,要么所有的组件必须回滚。要管理一个全局事务,必须要考虑任何组件或连接网络可能会故障。

用于执行全局事务的过程使用两阶段提交(2PC),发生时间在由全局事务的分支进行的行动已经被执行之后。

1.    在第一阶段,所有的分支被预备好。即,它们被TM告知要准备提交。通常,这意味着用于管理分支的每个RM会记录对于被稳定保存的分支的行动。分支指示是否它们可以这么做。这些结果被用于第二阶段。

2.    在第二阶段,TM告知RMs是否要提交或 回滚。如果在预备分支时,所有的分支指示它们将能够提交,则所有的分支被告知要提交。如果在预备时,有任何分支指示它将不能提交,则所有分支被告知 回滚。

在有些情况下,一个全局事务可能会使用一阶段提交(1PC)。例如,当一个事务管理器发现,一个全局事务只由一个事务资源组成(即,单一分支),则该资源可以被告知同时进行预备和提交。

13.4.7.1. XA事务SQL语法

要在MySQL中执行XA事务,应使用以下语句:

XA {START|BEGIN} xid [JOIN|RESUME]
 
XA END xid [SUSPEND [FOR MIGRATE]]
 
XA PREPARE xid
 
XA COMMIT xid [ONE PHASE]
 
XA ROLLBACK xid
 
XA RECOVER

对于XA STARTJOINRESUME子句不被支持。

对于XA ENDSUSPEND [FOR MIGRATE]子句不被支持。

每个XA语句以XA关键词为开头,多数语句要求一个xid值。 xid是一个XA事务标识符。它指示该语句适用于哪个事务。xid值由客户端提供,或由MySQL服务器生成。xid值包含一到三个部分:

xid: gtrid [, bqual [, formatID ]]

gtrid是一个全局事务标识符,bqual是一个分支限定符,formatID是一个数字,用于标识由gtridbqual值使用的格式。根据语法的表示,bqualformatID是自选的。如果没有给定,默认的bqual值是''。如果没有给定,默认的fromatID值是1

gtridbqual必须为字符串文字,每个的长度最多为64字节(不是字符)。gtridbqual可以用多种方法指定。您可以使用带引号的字符串('ab'),十六进制字符串(0x6162, X'ab'),或位值(b'nnnn')

formatID是一个无符号的整数。

通过MySQL服务器的带下划线的XA支持子程序,gtridbqual值被理解为以字节为单位。但是,在包含XA语句的SQL语句正在被分析的同时,服务器会去操作一些特定的字符集。为了安全,把gtridbqual作为十六进制字符串写入。

通常,xid值由事务管理器生成。由一个TM生成的值必须与由其它TMs生成的值不同。一个给定的TM必须能识别自己的xid值。这些值位于由XA RECOVER语句返回的值清单中。

XA START xid用于启动一个带给定xid值的XA事务。每个XA事务必须有一个唯一的xid值,因此该值当前不能被其它的XA事务使用。使用gtridbqual值评估唯一性。所有下列的用于XA事务的XA语句必须使用与XA START语句中给定的相同的xid值进行指定。如果您使用这些语句,但是指定的xid值与部分原有的XA事务不对应的话,会发生错误。

一项或多项XA事务可以是同一个全局事务的一部分。在一个给定的全局事务中的所有XA事务必须在xid值中使用同样的gtrid值。出于这个原因,gtrid值必须为全局唯一的,这样,有关一个给定的XA事务是哪个全局事务的一部分的问题就不会含糊不清。对于一个全局事务中的每个XA事务,xid值中的bqual部分必须不一样。(bqual值应不一样,这个要求是当前执行MySQL XA的一个限制条件。这不是XA规约的一部分。)

对于在MySQL服务器上的处于PREPARED状态的XA事务,XA RECOVER语句会返回信息。(见13.4.7.2节,“XA事务状态”.。)输出包括一个行,该行用于服务器上的每个这类XA事务,不论是哪个客户端启动了它。

XA RECOVER输出行看上去像这样(例如,xid值包括'abc', 'def'7等部分):

mysql> XA RECOVER;
+----------+--------------+--------------+--------+
| formatID | gtrid_length | bqual_length | data   |
+----------+--------------+--------------+--------+
|        7 |            3 |            3 | abcdef |
+----------+--------------+--------------+--------+

输出列有以下意义:

·         formatID是事务xidformatID部分

·         gtrid_lengthxidgtrid部分的长度,以字节为单位

·         bqual_lengthxidbqual部分的长度,以字节为单位

·         dataxidgtrid部分和bqual部分的串联

13.4.7.2. XA事务状态

XA事务在以下状态下进展:

1.    使用XA START来启动一个XA事务,并把它放入ACTIVE状态。

2.    对于一个ACTIVE XA事务,发布构成事务的SQL语句,然后发布一个XA END语句。XA END把事务放入IDLE状态。

3.    对于一个IDLE XA事务,您可以发布一个XA PREPARE语句或一个XA COMMITONE PHASE语句:

·         XA PREPARE把事务放入PREPARED状态。在此点上的XA RECOVER语句将在其输出中包括事务的xid值,因为XA RECOVER会列出处于PREPARED状态的所有XA事务。

·         XA COMMITONE PHASE用于预备和提交事务。xid值将不会被XA RECOVER列出,因为事务终止。

4.    对于一个PREPARED XA事务,您可以发布一个XA COMMIT语句来提交和终止事务,或者发布XA ROLLBACK来回滚并终止事务。

下面是一个简单的XA事务,该事务把一行作为一个全局事务的一部分插入一个表中。

mysql> XA START 'xatest';
Query OK, 0 rows affected (0.00 sec)
 
mysql> INSERT INTO mytable (i) VALUES(10);
Query OK, 1 row affected (0.04 sec)
 
mysql> XA END 'xatest';
Query OK, 0 rows affected (0.00 sec)
 
mysql> XA PREPARE 'xatest';
Query OK, 0 rows affected (0.00 sec)
 
mysql> XA COMMIT 'xatest';
Query OK, 0 rows affected (0.00 sec)

根据一个给定的客户端连接的语境,XA事务和本地(非XA)事务互相排斥。举例说明,如果已经发布了XA START来开始一项XA事务,则本地事务不会被启动,直到XA事务已经被提交或被 回滚为止。相反的,如果已经使用START TRANSACTION启动一个本地事务,则XA语句不能被使用,直到该事务被提交或被 回滚为止。

13.5. 数据库管理语句

13.5.1. 账户管理语句

13.5.1.1. CREATE USER语法

CREATE USER user [IDENTIFIED BY [PASSWORD] 'password']
    [, user [IDENTIFIED BY [PASSWORD] 'password']] ...

CREATE USER用于创建新的MySQL账户。要使用CREATE USER,您必须拥有mysql数据库的全局CREATE USER权限,或拥有INSERT权限。对于每个账户,CREATE USER会在没有权限的mysql.user表中创建一个新记录。如果 账户已经存在,则出现错误。

使用自选的IDENTIFIED BY子句,可以为账户给定一个密码。user值和 密码的给定方法和GRANT语句一样。特别是,要在纯文本中指定密码,需忽略PASSWORD关键词。要把 密码指定为由PASSWORD()函数返回的混编值,需包含关键字PASSWORD。请参见13.5.1.3节,“GRANT和REVOKE语法”

13.5.1.2. DROP USER语法

DROP USER user [, user] ...

DROP USER语句用于删除一个或多个MySQL账户。要使用DROP USER,您必须拥有mysql数据库的全局CREATE USER权限或DELETE权限。使用与GRANTREVOKE相同的格式为每个 账户命名;例如,'jeffrey'@'localhost'。 账户名称的用户和主机部分与用户表记录的UserHost列值相对应。

使用DROP USER,您可以取消一个账户和其权限,操作如下:

DROP USER user;

该语句可以删除来自所有授权表的帐户权限记录。

要点:DROP USER不能自动关闭任何打开的用户对话。而且,如果用户有打开的对话,此时取消用户,则命令不会生效,直到用户对话被关闭后才生效。一旦对话被关闭,用户也被取消,此用户再次试图登录时将会失败。这是有意设计的。

13.5.1.3. GRANT和REVOKE语法

GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
    ON [object_type] {tbl_name | * | *.* | db_name.*}
    TO user [IDENTIFIED BY [PASSWORD] 'password']
        [, user [IDENTIFIED BY [PASSWORD] 'password']] ...
    [REQUIRE
        NONE |
        [{SSL| X509}]
        [CIPHER 'cipher' [AND]]
        [ISSUER 'issuer' [AND]]
        [SUBJECT 'subject']]
    [WITH with_option [with_option] ...]

object_type =
    TABLE
  | FUNCTION
  | PROCEDURE

with_option =
    GRANT OPTION
  | MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
    ON [object_type] {tbl_name | * | *.* | db_name.*}
    FROM user [, user] ...

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

GRANTREVOKE语句允许系统管理员创建MySQL用户 账户,授予权限和撤销权限。

MySQL账户信息存储在mysql数据库的表中。在第5章:数据库管理中对本数据库和访问控制系统进行了详尽的讨论。要了解更多详细信息,您应该查询此章。

如果授权表拥有含有mixed-case数据库或表名称的权限记录,并且lower_case_table_names系统变量已设置,则不能使用REVOKE撤销权限,必须直接操纵授权表。(当lower_case_table_names已设置时,GRANT将不会创建此类记录,但是此类记录可能已经在设置变量之前被创建了。)

授予的权限可以分为多个层级:

·         全局层级

全局权限适用于一个给定服务器中的所有数据库。这些权限存储在mysql.user表中。GRANT ALL ON *.*REVOKE ALL ON *.*只授予和撤销全局权限。

·         数据库层级

数据库权限适用于一个给定数据库中的所有目标。这些权限存储在mysql.dbmysql.host表中。GRANT ALL ON db_name.*REVOKE ALL ON db_name.*只授予和撤销数据库权限。

·         表层级

表权限适用于一个给定表中的所有列。这些权限存储在mysql.talbes_priv表中。GRANT ALL ON db_name.tbl_nameREVOKE ALL ON db_name.tbl_name只授予和撤销表权限。

·         列层级

列权限适用于一个给定表中的单一列。这些权限存储在mysql.columns_priv表中。当使用REVOKE时,您必须指定与被授权列相同的列。

·         子程序层级

CREATE ROUTINE, ALTER ROUTINE, EXECUTEGRANT权限适用于已存储的子程序。这些权限可以被授予为全局层级和数据库层级。而且,除了CREATE ROUTINE外,这些权限可以被授予为子程序层级,并存储在mysql.procs_priv表中。

当后续目标是一个表、一个已存储的函数或一个已存储的过程时,object_type子句应被指定为TABLEFUNCTIONPROCEDURE。当从旧版本的MySQL升级时,要使用本子句,您必须升级您的授权表。请参见2.10.2节,“升级授权表”

要使用GRANTREVOKE,您必须拥有GRANT OPTION权限,并且您必须用于您正在授予或撤销的权限。

要撤销所有权限,需使用以下语法。此语法用于取消对于已命名的用户的所有全局层级、数据库层级、表层级和列层级的权限。

REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

要使用本REVOKE语法,您必须拥有mysql数据库的全局CREATE USER权限或UPDATE权限。

对于GRANTREVOKE语句,priv_type可以被指定为以下任何一种:

权限

意义

ALL [PRIVILEGES]

设置除GRANT OPTION之外的所有简单权限

ALTER

允许使用ALTER TABLE

ALTER ROUTINE

更改或取消已存储的子程序

CREATE

允许使用CREATE TABLE

CREATE ROUTINE

创建已存储的子程序

CREATE TEMPORARY TABLES

允许使用CREATE TEMPORARY TABLE

CREATE USER

允许使用CREATE USER, DROP USER, RENAME USERREVOKE ALL PRIVILEGES

CREATE VIEW

允许使用CREATE VIEW

DELETE

允许使用DELETE

DROP

允许使用DROP TABLE

EXECUTE

允许用户运行已存储的子程序

FILE

允许使用SELECT...INTO OUTFILELOAD DATA INFILE

INDEX

允许使用CREATE INDEXDROP INDEX

INSERT

允许使用INSERT

LOCK TABLES

允许对您拥有SELECT权限的表使用LOCK TABLES

PROCESS

允许使用SHOW FULL PROCESSLIST

REFERENCES

未被实施

RELOAD

允许使用FLUSH

REPLICATION CLIENT

允许用户询问从属服务器或主服务器的地址

REPLICATION SLAVE

用于复制型从属服务器(从主服务器中读取二进制日志事件)

SELECT

允许使用SELECT

SHOW DATABASES

SHOW DATABASES显示所有数据库

SHOW VIEW

允许使用SHOW CREATE VIEW

SHUTDOWN

允许使用mysqladmin shutdown

SUPER

允许使用CHANGE MASTER, KILL, PURGE MASTER LOGSSET GLOBAL语句,mysqladmin debug命令;允许您连接(一次),即使已达到max_connections

UPDATE

允许使用UPDATE

USAGE

“无权限”的同义词

GRANT OPTION

允许授予权限

当从旧版本的MySQL升级时,要使用EXECUTE, CREATE VIEW, SHOW VIEW, CREATE USER, CREATE ROUTINEALTER ROUTINE权限,您必须首先升级您的授权表。请参见2.10.2节,“升级授权表”

REFERENCES权限目前未被使用。

当您想要创建一个没有权限的用户时,可以指定USAGE

使用SHOW GRANTS来确定帐户拥有什么权限。请参见13.5.4.10节,“SHOW GRANTS语法”

您可以通过使用ON *.*语法赋予全局权限,或通过使用ON db_name.*语法赋予数据库层级权限。如果您指定了ON *并且您已经选择了一个默认数据库,则权限被赋予到这个数据库中。(警告:如果您指定了ON *同时您没有选择一个默认数据库,则权限是全局的。)

FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHOW DATABASES, SHUTDOWNSUPER权限是管理性权限,只能进行全局授权(使用ON *.*语法)。

其它权限可以被全局授权,或被赋予为其它层级。

对于一个表,您可以指定的priv_type值只能是SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT OPTION, INDEXALTER

对于一个列(也就是,当您使用一个column_list子句时),您可以指定的priv_type值只能是SELECT, INSERTUPDATE

在子程序层级,您可以指定的priv_type值只能是ALTER ROUTINE, EXECUTEGRANT OPTIONCREATE ROUTINE不是一个子程序层级的权限,因为您必须拥有此权限,才能创建一个子程序。

对于全局、数据库、表和子程序层级,GRANT ALL只能赋予在您正在授权的层级中存在的权限。例如,如果您使用GRANT ALL ON db_name.*,这是一个数据库层级语句,因此不会授予全局权限,如FILE等。

MySQL允许您对不存在的数据库目标授予权限。在此情况下,将被授予的权限必须包括CREATE权限。这个性质是有意设计的,目的是允许数据库管理员为将在此后被创建的数据库目标预备用户 账户和权限。

要点:当您取消一个表或数据库时,MySQL不会自动撤销任何权限。但是,如果您取消一个子程序,则被赋予该子程序的所有子程序层级的权限都被撤销。

注意:GRANT语句用于在全局层级或数据库层级赋予权限。当在GRANT语句中指定数据库名称时,允许使用‘_’和‘%’通配符。这意味着,如果您想要使用‘_’字符作为一个数据库名称的一部分,您应该在GRANT语句中指定它为‘\_’,以防止用户可以访问其它符合此通配符格式的数据库;例如,GRANT ... ON `foo\_bar`.* TO ...

为了接纳对来自任意主机的用户授权的权利,MySQL支持以user_name@host_name的形式指定user值。如果一个user_namehost_name与一个不加引号的标识符一样是合法的,那么您不需要对它加引号。不过,要指定一个包含特殊字符(如‘-’)的user_name字符串,或一个包含特殊字符或通配字符(如‘%’),则引号是必要的;例如,'test-user'@'test-hostname'。分别对usernamehostname加引号。

您可以在hostname中指定通配符。例如user_name@'%.loc.gov'适用于在loc.gov域中的任何主机的user_name。同时user_name@'144.155.166.%'适用于144.155.166 C级子网中的任何主机的user_name

简单形式user_nameuser_name@'%'的同义词。

MySQL不支持usernames中的通配符。通过把带有User=''的登录项插入到mysql.user表中,或通过使用GRANT语句创建一个带有空名称的用户,可以定义匿名用户:

mysql> GRANT ALL ON test.* TO ''@'localhost' ...

当把带引号的值是,需使用反勾号(`)为数据库、表、列和子程序名称加引号。使用单引号(')hostnamesusernames和 密码加引号。

警告:如果您允许匿名用户连接到MySQL服务器,则您应该同时向所有本地用户授予user_name@localhost权限。否则,当有名称的用户试图从本地机器登录MySQL服务器时,mysql.user表中的用于localhost的匿名用户帐户会被使用。

您可以通过执行以下查询来确定是否这适合于您。以下查询列举了所有匿名用户:

mysql> SELECT Host, User FROM mysql.user WHERE User='';

如果您想要删除本地匿名用户账户,以避免出现刚才谈到的问题,则需使用以下语句:

mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User='';
mysql> FLUSH PRIVILEGES;

GRANT支持最长为60个字符的hostnames。数据库、表、列和子程序名称最长可为64个字符。Usernames最长可为16个字符。 注释:不能通过更改mysql.user表来改变usernames的允许长度。如果试图这么做,会导致出现不可预见的问题,可能会造成用户无法登录MySQL服务器。除了采用由MySQL公司提供的用于升级MySQL服务器的mysql_fix_privilege_tables原稿之外,请您不要以任何方式变更授权表。

对于表或列的权限是作为各个权限层级的逻辑OR权限被附加形成的。例如,如果mysql.user表指定一个用户拥有全局SELECT权限,则该权限不能被数据库、表或列层级的登录项定义。

可以按下列方法计算列权限:

global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges

在多数情况下,您只在一个权限层级下向用户授予权利,所以寿命通常不是那么复杂。有关权限检查规程的细节,请参见5.7节,“MySQL访问权限系统”

如果您对一个在mysql.user表中不存在的username/hostname组合授予权限,则增加一个登录项并保持在此处,直到使用DELETE语句删除为止。换句话说,GRANT可以创建用户表登录项,但是REVOKE不会取消它们;您必须使用DROP USERDELETE明确地操作。

如果创建了一个新的用户,或者如果您拥有全局授权权限,则用户密码被设置为由IDENTIFIED BY子句指定的密码(如果给定了一个)。如果用户已拥有了一个密码,则此密码被新密码替代。

警告:如果您创建了一个新用户,但是不指定IDENTIFIED BY子句,则用户没有 密码。这是很不安全的。不过,您可以启用NO_AUTO_CREATE_USER SQL模式,来防止GRANT创建一个新用户(否则GRANT会这么做),除非给定了IDENTIFIED BY来为新用户提供一个密码。

使用SET PASSWORD语句也可以设置密码。请参见13.5.1.5节,“SET PASSWORD语法”

IDENTIFIED BY子句中,密码应被作为文字密码只被给定。没有必要使用PASSWORD()函数,因为该函数用于SET PASSWORD语句。例如:

GRANT ... IDENTIFIED BY 'mypass';

如果您不想以明白的文字发送密码,并且您知道PASSWORD()返回给密码的混编值,则您可以指定混编值,前面加入关键词PASSWORD

GRANT ...
IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';

在一个C程序中,您可以通过使用make_scrambled_password() C API函数得到混编值。

如果您为一个数据库授予权限,则在mysql.db表中,会根据需要创建登录项。如果使用REVOKE删除了所有的数据库权限,则本登录项被删除。

如果一个用户不拥有表权限,则当用户申请表清单时(例如,使用SHOW TABLES语句),表名称不显示。

SHOW DATABASES权限允许账户通过发布SHOW DATABASE语句来观看数据名称。不拥有此权限的账户只能看到他们拥有部分权限的数据库,并且如果使用--skip-show-database选项启动服务器,则根本不能使用本语句。

WITH GRANT OPTION子句给予用户能力,可以在指定的权限层级,向其它用户给定其拥有的任何权限。您应该留心您给予了谁GRANT OPTION权限,因为拥有不同权限的两个用户可以联合使用权限!

您不能向其它用户授予您自己没有的权限;GRANT OPTION权限只允许您赋予您自己拥有的权限。

要注意,当您在某个特定权限层级向一个用户授予GRANT OPTION权限时,用户拥有的该层级的任何权限(或未来将被给定的权限)也可以由该用户授予。假设您向一个用户赋予了数据库INSERT权限。如果您然后赋予数据库SELECT权限,并指定了WITH GRANT OPTION,则该用户不仅可以向其它用户给予SELECT权限,还可以给予INSERT。如果您然后向用户授予数据库UPDATE权限,则用户可以授予INSERT, SELECTUPDATE

您不应该向一个常规用户授予ALTER权限。如果您这么做,则该用户可以尝试通过对表重新命名来破坏授权系统!

The MAX_QUERIES_PER_HOUR count, MAX_UPDATES_PER_HOUR count, and MAX_CONNECTIONS_PER_HOUR count options limit the number of queries, updates, and logins a user can perform during any given one-hour period. If count is 0 (the default), this means that there is no limitation for that user.      MAX_QUERIES_PER_HOUR count, MAX_UPDATES_PER_HOUR countMAX_CONNECTIONS_PER_HOUR count选项限制了在任何给定的一小时期间,用户可以执行的查询、更新和登录的数目。如果count0(默认值),这意味着,对该用户没有限制。

MAX_USER_CONNECTIONS count选项限制了账户可以同时进行的连接的最大数目。如果count0(默认值),则max_user_connections系统可以决定该 账户同时连接的数目。

注释:要对一个原有的用户指定任何这类资源限制型选项,同时又不影响原有的权限,需使用GRANT USAGE ON *.* ... WITH MAX_...

5.8.4节,“限制账户资源”

除了根据username和密码进行常规鉴定外,MySQL还可以检查X509证明属性。要为MySQL账户指定与SSL有关的选项,需使用GRANT语句的REQUIRE子句。(要了解有关在MySQL中使用SSL的背景信息,请参见5.8.7节,“使用安全连接”。)

对于一个给定的账户,有多种可能性可以限制连接类型:

·         如果账户没有SSLX509要求,并且如果username和 密码是有效的,则允许不加密连接。但是,如果客户端有正确的证明和关键文件,则根据客户端的选择,也可以使用加密连接。

·         REQUIRE SSL选项用于告知服务器,对于该账户只允许SSL加密连接。注意,如果有允许任何非SSL连接的访问控制记录,则本选项可以被忽略。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;

·         REQUIRE X509意味着客户端必须拥有一个有效证明,除非不需要确切的证明、发布者和主题。唯一的要求是,应可以使用CA证明其中之一来验证签名。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret' REQUIRE X509;

·         REQUIRE ISSUER 'issuer'用于对连接尝试进行限定,客户端必须出示一个由CAissuer’发布的有效的X509证明。如果客户端出示的证明是有效的,但是有一个不同的发布者,则服务器会拒绝连接。使用X509证明就意味着要加密,所以在这种情况下,SSL选项是不必要的。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret'
·                    -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
·                       O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';

注意,ISSUER值应被作为一个单一字符串输入。

·         REQUIRE SUBJECT 'subject'用于对连接尝试进行限定,客户端必须出示一个包含主题subject的有效的X509证明。如果客户端出示的证明是有效的,但是有一个不同的主题,则服务器会拒绝连接。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret'
·                    -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
·                       O=MySQL demo client certificate/
·                       CN=Tonu Samuel/Email=tonu@example.com';

注意,SUBJECT值应被作为一个单一字符串输入。

·         需要REQUIRE CIPHER 'cipher'来确认使用了密码和足够长度的关键字。如果使用了采用短型加密关键字的旧算法,SSL本身会比较脆弱。使用本选项,您可以要求使用特定的密码方法来许可一个连接。

·                mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
·                    -> IDENTIFIED BY 'goodsecret'
·                    -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';

SUBJECT, ISSUERCIPHER选项可以在REQUIRE子句中结合,如下:

mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
    -> IDENTIFIED BY 'goodsecret'
    -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
       O=MySQL demo client certificate/
       CN=Tonu Samuel/Email=tonu@example.com'
    -> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
       O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
    -> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';

注意,SUBJECTISSUER值各自应被作为一个单一字符串输入。

REQUIRE各选项之间,AND关键词是自选的。

选项的顺序无所谓,但是选项不能被指定两次。

mysqld启动后,所有的权限被读入存储器中。要了解详细说明,请参见5.7.7节,“权限更改何时生效”

注意,如果您正在使用表权限或列权限,即使只对一个用户使用,服务器也会对所有用户检查表权限和列权限,这会略微降低MySQL的速度。与此类似,如果您对某些用户限制查询、更新或连接的数目,则服务器必须监测这些值。

标准SQL版本和MySQL版本的GRANT之间的最大区别是:

·         MySQL中,权限与hostnameusername的组合有关,与 单一的username无关。

·         标准SQL不拥有全局层级或数据库层级权限,也不支持MySQL支持的所有权限类型。

·         MySQL不支持标准SQL TRIGGERUNDER权限。

·         标准SQL权限以一种分等级的方式进行组织。如果您取消一个用户,则用户被授予的所有权限都被撤销。在MySQL中,如果您使用DROP USER,也会如此。请参见13.5.1.2节,“DROP USER语法”

·         在标准SQL中,当您取消一个表时,对一个表的所有权限会被撤销。在标准SQL中,当您撤销一个权限时,根据该权限被授予的所有权限也会被撤销。在MySQL中,只有使用明确的REVOKE语句,或通过操作存储在MySQL授权表中的值,才能取消权限。

·         MySQL中,可以只对一个表中的部分列拥有INSERT权限。在此情况下,如果您忽略您不拥有INSERT权限的那些列,,您仍然可以对表执行INSERT语句。如果没有启用严格的SQL模式,则被忽略的列被设置为各自隐含的默认值。在严格模式下,如果某个被忽略的列没有默认值,则该语句被拒绝。5.3.2节,“SQL服务器模式”对严格模式进行了讨论。13.1.5节,“CREATE TABLE语法”对隐含默认值进行了讨论。

您不拥有INSERT权限的列被设置为各自的默认值。标准SQL要求您拥有所有列的INSERT权限。

MySQL中,如果您只拥有一个表中的部分列的INSERT权限,同时,如果您从INSERT语句中忽略您不拥有权限的列,则您仍然可以对表执行INSERT语句;那些列将被设置为各自的默认值。在严格模式下(即当sql_mode='traditional'时,如果某些被忽略的列没有默认值,则INSERT语句将被拒绝。

13.5.1.4. RENAME USER语法

RENAME USER old_user TO new_user
    [, old_user TO new_user] ...

RENAME USER语句用于对原有MySQL账户进行重命名。要使用RENAME USER,您必须拥有全局CREATE USER权限或mysql数据库UPDATE权限。如果旧 账户不存在或者新账户已存在,则会出现错误。old_usernew_user值的给定方法与GRANT语句一样。

13.5.1.5. SET PASSWORD语法

SET PASSWORD = PASSWORD('some password')
SET PASSWORD FOR user = PASSWORD('some password')

SET PASSWORD语句用于向一个原有MySQL用户 账户赋予一个密码。

第一个语法为当前用户设置密码。已使用一个非匿名账户连接到服务器上的任何客户即都可以更改该账户的密码。

第二个语法为当前服务器主机上的一个特定账户设置密码。只有拥有mysql数据库UPDATE权限的客户端可以这么做。user值应以的格式被给定,此处user_namehost_namemysql.user表登录项的UserHost列中列出的完全一样。举例说明,如果您有一个

mysql> SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');

这相当于以下语句:

mysql> UPDATE mysql.user SET Password=PASSWORD('newpass')
    -> WHERE User='bob' AND Host='%.loc.gov';
mysql> FLUSH PRIVILEGES;

注释:如果您正在使用一个4.1以前的客户端连接到一个MySQL 4.1MySQL 4.1以后的服务器,则在阅读5.7.9节,“MySQL 4.1中的密码哈希处理”之前,不能使用前面的SET PASSWORDUPDATE语句。 密码格式在MySQL 4.1中变更了,并且在特定情况下,如果您更改密码,您可能无法在连接到服务器上。

您可以通过执行SELECT CURRENT_USER()观看您当前的鉴定user@host登录项。

阅读(15259) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~