我的时光,停在了你的角落…~
Posts tagged DB
MySQL 索引详解
Jul 14th
本文介绍了数据库索引,及其优、缺点。针对MySQL索引的特点、应用进行了详细的描述。分析了如何避免MySQL无法使用,如何使用EXPLAIN分析查询语句,如何优化MySQL索引的应用。
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
注:
[1]索引不是万能的!
索引可以加快数据检索操作,但会使数据修改操作变慢。每修改数据记录,索引就必须刷新一次。为了在某种程序上弥补这一缺陷,许多SQL命令都有一个DELAY_KEY_WRITE项。这个选项的作用是暂时制止MySQL在该命令每插入一条新记录和每修改一条现有之后立刻对索引进行刷新,对索引的刷新将等到全部记录插入/修改完毕之后再进行。在需要把许多新记录插入某个数据表的场合,DELAY_KEY_WRITE选项的作用将非常明显。
[2]另外,索引还会在硬盘上占用相当大的空间。
因此应该只为最经常查询和最经常排序的数据列建立索引。注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
从理论上讲,完全可以为数据表里的每个字段分别建一个索引,但MySQL把同一个数据表里的索引总数限制为16个。
1. InnoDB数据表的索引
与MyISAM数据表相比,索引对InnoDB数据的重要性要大得多。在InnoDB数据表上,索引对InnoDB数据表的重要性要在得多。在 InnoDB数据表上,索引不仅会在搜索数据记录时发挥作用,还是数据行级锁定机制的苊、基础。”数据行级锁定”的意思是指在事务操作的执行过程中锁定正在被处理的个别记录,不让其他用户进行访问。这种锁定将影响到(但不限于)SELECT…LOCK IN SHARE MODE、SELECT…FOR UPDATE命令以及INSERT、UPDATE和DELETE命令。
出于效率方面的考虑,InnoDB数据表的数据行级锁定实际发生在它们的索引上,而不是数据表自身上。显然,数据行级锁定机制只有在有关的数据表有一个合适的索引可供锁定的时候才能发挥效力。
2. 限制
如果WEHERE子句的查询条件里有不等号(WHERE coloum != …),MySQL将无法使用索引。
类似地,如果WHERE子句的查询条件里使用了函数(WHERE DAY(column) = …),MySQL也将无法使用索引。
在JOIN操作中(需要从多个数据表提取数据时),MySQL只有在主键和外键的数据类型相同时才能使用索引。
如果WHERE子句的查询条件里使用比较操作符LIKE和REGEXP,MySQL只有在搜索模板的第一个字符不是通配符的情况下才能使用索引。比如说,如果查询条件是LIKE ‘abc%’,MySQL将使用索引;如果查询条件是LIKE ‘%abc’,MySQL将不使用索引。
在ORDER BY操作中,MySQL只有在排序条件不是一个查询条件表达式的情况下才使用索引。(虽然如此,在涉及多个数据表查询里,即使有索引可用,那些索引在加快ORDER BY方面也没什么作用)
如果某个数据列里包含许多重复的值,就算为它建立了索引也不会有很好的效果。比如说,如果某个数据列里包含的净是些诸如”0/1″或”Y/N”等值,就没有必要为它创建一个索引。
普通索引、唯一索引和主索引
1. 普通索引
普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHERE column = …)或排序条件(ORDER BY column)中的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。
2. 唯一索引
普通索引允许被索引的数据列包含重复的值。比如说,因为人有可能同名,所以同一个姓名在同一个”员工个人资料”数据表里可能出现两次或更多次。
如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。这么做的好处:一是简化了MySQL对这个索引的管理工作,这个索引也因此而变得更有效率;二是MySQL会在有新记录插入数据表时,自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了;如果是,MySQL将拒绝插入那条新记录。也就是说,唯一索引可以保证数据记录的唯一性。事实上,在许多场合,人们创建唯一索引的目的往往不是为了提高访问速度,而只是为了避免数据出现重复。
3. 主索引
在前面已经反复多次强调过:必须为主键字段创建一个索引,这个索引就是所谓的”主索引”。主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是PRIMARY而不是UNIQUE。
4. 外键索引
如果为某个外键字段定义了一个外键约束条件,MySQL就会定义一个内部索引来帮助自己以最有效率的方式去管理和使用外键约束条件。
5. 复合索引
索引可以覆盖多个数据列,如像INDEX(columnA, columnB)索引。这种索引的特点是MySQL可以有选择地使用一个这样的索引。如果查询操作只需要用到columnA数据列上的一个索引,就可以使用复合索引INDEX(columnA, columnB)。不过,这种用法仅适用于在复合索引中排列在前的数据列组合。比如说,INDEX(A, B, C)可以当做A或(A, B)的索引来使用,但不能当做B、C或(B, C)的索引来使用。
6. 索引的长度
在为CHAR和VARCHAR类型的数据列定义索引时,可以把索引的长度限制为一个给定的字符个数(这个数字必须小于这个字段所允许的最大字符个数)。这么做的好处是可以生成一个尺寸比较小、检索速度却比较快的索引文件。在绝大多数应用里,数据库中的字符串数据大都以各种各样的名字为主,把索引的长度设置为10~15个字符已经足以把搜索范围缩小到很少的几条数据记录了。
在为BLOB和TEXT类型的数据列创建索引时,必须对索引的长度做出限制;MySQL所允许的最大索引长度是255个字符。
全文索引
文本字段上的普通索引只能加快对出现在字段内容最前面的字符串(也就是字段内容开头的字符)进行检索操作。如果字段里存放的是由几个、甚至是多个单词构成的较大段文字,普通索引就没什么作用了。这种检索往往以LIKE %word%的形式出现,这对MySQL来说很复杂,如果需要处理的数据量很大,响应时间就会很长。
这类场合正是全文索引(full-text index)可以大显身手的地方。在生成这种类型的索引时,MySQL将把在文本中出现的所有单词创建为一份清单,查询操作将根据这份清单去检索有关的数据记录。全文索引即可以随数据表一同创建,也可以等日后有必要时再使用下面这条命令添加:ALTER TABLE tablename ADD FULLTEXT(column1, column2) 有了全文索引,就可以用SELECT查询命令去检索那些包含着一个或多个给定单词的数据记录了。
下面是这类查询命令的基本语法:
| SELECT * FROM tablename WHERE MATCH(column1, column2) AGAINST(’word1′, ‘word2′, ‘word3′) |
上面这条命令将把column1和column2字段里有word1、word2和word3的数据记录全部查询出来。
注解:InnoDB数据表不支持全文索引。
查询和索引的优化
只有当数据库里已经有了足够多的测试数据时,它的性能测试结果才有实际参考价值。如果在测试数据库里只有几百条数据记录,它们往往在执行完第一条查询命令之后就被全部加载到内存里,这将使后续的查询命令都执行得非常快–不管有没有使用索引。只有当数据库里的记录超过了1000条、数据总量也超过了 MySQL服务器上的内存总量时,数据库的性能测试结果才有意义。
在不确定应该在哪些数据列上创建索引的时候,人们从EXPLAIN SELECT命令那里往往可以获得一些帮助。这其实只是简单地给一条普通的SELECT命令加一个EXPLAIN关键字作为前缀而已。有了这个关键字,MySQL将不是去执行那条SELECT命令,而是去对它进行分析。MySQL将以表格的形式把查询的执行过程和用到的索引(如果有的话)等信息列出来。
在EXPLAIN命令的输出结果里,第1列是从数据库读取的数据表的名字,它们按被读取的先后顺序排列。type列指定了本数据表与其它数据表之间的关联关系(JOIN)。在各种类型的关联关系当中,效率最高的是system,然后依次是const、eq_ref、ref、range、index和 All(All的意思是:对应于上一级数据表里的每一条记录,这个数据表里的所有记录都必须被读取一遍–这种情况往往可以用一索引来避免)。
possible_keys数据列给出了MySQL在搜索数据记录时可选用的各个索引。key数据列是MySQL实际选用的索引,这个索引按字节计算的长度在key_len数据列里给出。比如说,对于一个INTEGER数据列的索引,这个字节长度将是4。如果用到了复合索引,在key_len数据列里还可以看到MySQL具体使用了它的哪些部分。作为一般规律,key_len数据列里的值越小越好(意思是更快)。
ref数据列给出了关联关系中另一个数据表里的数据列的名字。row数据列是MySQL在执行这个查询时预计会从这个数据表里读出的数据行的个数。row数据列里的所有数字的乘积可以让我们大致了解这个查询需要处理多少组合。
最后,extra数据列提供了与JOIN操作有关的更多信息,比如说,如果MySQL在执行这个查询时必须创建一个临时数据表,就会在extra列看到using temporary字样。
本文摘自《MySQL 5权威指南》(3rd)的8.9节。(2007.07.05最后更新)
MySQL Query Cache 小结
Jul 2nd
最近经常有人问我 MySQL Query Cache 相关的问题,就整理一点 MySQL Query Cache 的内容,以供参考。
顾名思义,MySQL Query Cache 就是用来缓存和 Query 相关的数据的。具体来说,Query Cache 缓存了我们客户端提交给 MySQL 的 SELECT 语句以及该语句的结果集。大概来讲,就是将 SELECT 语句和语句的结果做了一个 HASH 映射关系然后保存在一定的内存区域中。
在大部分的 MySQL 分发版本中,Query Cache 功能默认都是打开的,我们可以通过调整 MySQL Server 的参数选项打开该功能。主要由以下5个参数构成:
- query_cache_limit:允许 Cache 的单条 Query 结果集的最大容量,默认是1MB,超过此参数设置的 Query 结果集将不会被 Cache
- query_cache_min_res_unit:设置 Query Cache 中每次分配内存的最小空间大小,也就是每个 Query 的 Cache 最小占用的内存空间大小
- query_cache_size:设置 Query Cache 所使用的内存大小,默认值为0,大小必须是1024的整数倍,如果不是整数倍,MySQL 会自动调整降低最小量以达到1024的倍数
- query_cache_type:控制 Query Cache 功能的开关,可以设置为0(OFF),1(ON)和2(DEMAND)三种,意义分别如下:
- 0(OFF):关闭 Query Cache 功能,任何情况下都不会使用 Query Cache
- 1(ON):开启 Query Cache 功能,但是当 SELECT 语句中使用的 SQL_NO_CACHE 提示后,将不使用Query Cache
- 2(DEMAND):开启 Query Cache 功能,但是只有当 SELECT 语句中使用了 SQL_CACHE 提示后,才使用 Query Cache
- query_cache_wlock_invalidate:控制当有写锁定发生在表上的时刻是否先失效该表相关的 Query Cache,如果设置为 1(TRUE),则在写锁定的同时将失效该表相关的所有 Query Cache,如果设置为0(FALSE)则在锁定时刻仍然允许读取该表相关的 Query Cache。
Query Cache 如何处理子查询的?
这是我遇到的最为常见的一个问题。其实 Query Cache 是以客户端请求提交的 Query 为对象来处理的,只要客户端请求的是一个 Query,无论这个 Query 是一个简单的单表查询还是多表 Join,亦或者是带有子查询的复杂 SQL,都被当作成一个 Query,不会被分拆成多个 Query 来进行 Cache。所以,存在子查询的复杂 Query 也只会产生一个Cache对象,子查询不会产生单独的Cache内容。UNION[ALL] 类型的语句也同样如此。
Query Cache 是以 block 的方式存储的数据块吗?
不是,Query Cache 中缓存的内容仅仅只包含该 Query 所需要的结果数据,是结果集。当然,并不仅仅只是结果数据,还包含与该结果相关的其他信息,比如产生该 Cache 的客户端连接的字符集,数据的字符集,客户端连接的 Default Database等。
Query Cache 为什么效率会非常高,即使所有数据都可以 Cache 进内存的情况下,有些时候也不如使用 Query Cache 的效率高?
Query Cache 的查找,是在 MySQL 接受到客户端请求后在对 Query 进行权限验证之后,SQL 解析之前。也就是说,当 MySQL 接受到客户端的SQL后,仅仅只需要对其进行相应的权限验证后就会通过 Query Cache 来查找结果,甚至都不需要经过 Optimizer 模块进行执行计划的分析优化,更不许要发生任何存储引擎的交互,减少了大量的磁盘 IO 和 CPU 运算,所以效率非常高。
客户端提交的 SQL 语句大小写对 Query Cache 有影响吗?
有,由于 Query Cache 在内存中是以 HASH 结构来进行映射,HASH 算法基础就是组成 SQL 语句的字符,所以必须要整个 SQL 语句在字符级别完全一致,才能在 Query Cache 中命中,即使多一个空格也不行。
一个 SQL 语句在 Query Cache 中的内容,在什么情况下会失效?
为了保证 Query Cache 中的内容与是实际数据绝对一致,当表中的数据有任何变化,包括新增,修改,删除等,都会使所有引用到该表的 SQL 的 Query Cache 失效。
为什么我的系统在开启了 Query Cache 之后整体性能反而下降了?
当开启了 Query Cache 之后,尤其是当我们的 query_cache_type 参数设置为 1 以后,MySQL 会对每个 SELECT 语句都进行 Query Cache 查找,查找操作虽然比较简单,但仍然也是要消耗一些 CPU 运算资源的。而由于 Query Cache 的失效机制的特性,可能由于表上的数据变化比较频繁,大量的 Query Cache 频繁的被失效,所以 Query Cache 的命中率就可能比较低下。所以有些场景下,Query Cache 不仅不能提高效率,反而可能造成负面影响。
如何确认一个系统的 Query Cache 的运行是否健康,命中率如何,设置量是否足够?
MySQL 提供了一系列的 Global Status 来记录 Query Cache 的当前状态,具体如下:
- Qcache_free_blocks:目前还处于空闲状态的 Query Cache 中内存 Block 数目
- Qcache_free_memory:目前还处于空闲状态的 Query Cache 内存总量
- Qcache_hits:Query Cache 命中次数
- Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次数,也就是没有命中的次数
- Qcache_lowmem_prunes:当 Query Cache 内存容量不够,需要从中删除老的 Query Cache 以给新的 Cache 对象使用的次数
- Qcache_not_cached:没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache 的 SQL
- Qcache_queries_in_cache:目前在 Query Cache 中的 SQL 数量
- Qcache_total_blocks:Query Cache 中总的 Block 数量
可以根据这几个状态计算出 Cache 命中率,计算出 Query Cache 大小设置是否足够,总的来说,我个人不建议将 Query Cache 的大小设置超过256MB,这也是业界比较常用的做法。
MySQL Cluster 是否可以使用 Query Cache?
其实在我们的生产环境中也没有使用 MySQL Cluster,所以我也没有在 MySQL Cluster 环境中使用 Query Cache 的实际经验,只是 MySQL 文档中说明确实可以在 MySQL Cluster 中使用 Query Cache。从 MySQL Cluster 的原理来分析,也觉得应该可以使用,毕竟 SQL 节点和数据节点比较独立,各司其职,只是 Cache 的失效机制会要稍微复杂一点。
作者: Sky.Jian 发布在:www.jianzhaoyang.com 欢迎 订阅本站Feed
Copyright © 2004-2008, 可以任意转载, 但转载时务必以超链接形式标明文章原始出处 和 作者信息 及 版权声明
链接:http://isky000.com/database/mysql-query-cache-summary )
linux下C连接MySql
Jun 22nd
相对于Window下的设置,Linux要简单的很多。
1. 示例程序
$ vi mysql-c-api.c
#include
#include "mysql/mysql.h"
int main(){
MYSQL mysql;
mysql_init(&mysql);
mysql_options(&mysql,MYSQL_OPT_COMPRESS,0);
mysql_options(&mysql,MYSQL_INIT_COMMAND,"SET autocommit=0");
if (!mysql_real_connect(&mysql,"10.2.3.4","user","passwd","database",0,NULL,0))
{
fprintf(stderr, "Failed to connect to database: Error: %sn",
mysql_error(&mysql));
}
return 0;
}
2. 编译命令
在MySQL编译后的二进制文件中,有一个很有用的二进制文件“mysql_config”(一般和mysql命令在同一个目录下),我们可以通过这个程序找到需要的头文件和连接库:
$ gcc -o a.out $(mysql_config --cflags) mysql-c-api.c $(mysql_config --libs)
$ ./a.out
from:http://www.orczhou.com/index.php/2010/01/linux-c-mysql-api/
在MySQL中拷贝表的几种方式
Jun 12th
假如我们有以下这样一个表:
引用
id username password
———————————–
1 admin *************
2 sameer *************
3 stewart *************
CREATE TABLE IF NOT EXISTS `admin` (
`id` int(6) unsigned NOT NULL auto_increment,
`username` varchar(50) NOT NULL default ”,
`password` varchar(100) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
1. 下面这个语句会拷贝表结构到新表newadmin中。 (不会拷贝表中的数据)
引用
CREATE TABLE newadmin LIKE admin
2. 下面这个语句会拷贝数据到新表中。 注意:这个语句其实只是把select语句的结果建一个表。所以newadmin这个表不会有主键,索引。
引用
CREATE TABLE newadmin AS
(
SELECT *
FROM admin
)
3. 如果你要真正的复制一个表。可以用下面的语句。
引用
CREATE TABLE newadmin LIKE admin;
INSERT INTO newadmin SELECT * FROM admin;
4. 我们可以操作不同的数据库。
引用
CREATE TABLE newadmin LIKE shop.admin;
CREATE TABLE newshop.newadmin LIKE shop.admin;
5. 我们也可以拷贝一个表中其中的一些字段。
引用
CREATE TABLE newadmin AS
(
SELECT username, password FROM admin
)
6. 我们也可以讲新建的表的字段改名。
引用
CREATE TABLE newadmin AS
(
SELECT id, username AS uname, password AS pass FROM admin
)
7. 我们也可以拷贝一部分数据。
引用
CREATE TABLE newadmin AS
(
SELECT * FROM admin WHERE LEFT(username,1) = ‘s’
)
8. 我们也可以在创建表的同时定义表中的字段信息。
引用
CREATE TABLE newadmin
(
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY
)
AS
(
SELECT * FROM admin
)
from:linux社区
MySQL 关于分页查询一个非常有用的查询参数
Apr 13th
MySQL 的 SELECT 语句中有这么一个参数:SQL_CALC_FOUND_ROWS,这个参数可以配合 MySQL 提供的函数 FOUND_ROWS() 来使用。
当我们使用 LIMIT ?,? 进行分页查询时,返回的只是你想要的记录,例如 LIMIT 10 则是返回前 10 条记录,但是整个查询涉及多少条记录我们不知道,需要再次发送一个不带 LIMIT 的查询来获取记录数,以便进行翻页处理。
而利用 FOUND_ROWS() 函数就无需这么麻烦了,试试执行下面的 SQL 语句:
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name -> WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();
这个方法在 MySQL 的命令行模式是可行的,在 Navicat 中一起执行也是可行的,但分开执行就不对。
另外,FOUND_ROWS 函数只能在执行 SQL 语句后执行一次,再次执行的话,返回就是 1 。
最后,这个参数和函数都是 MySQL 独有的,如果应用需要支持多种数据库,建议不要使用。
from:http://www.linuxidc.com/Linux/2010-04/25438.htm
MySQL触发器的使用
Apr 3rd
1、创建触发器:
语法:
CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name
FOR EACH ROW
BEGIN
trigger_stmt
END;
CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name
FOR EACH ROW
BEGIN
trigger_stmt
END;
例子
CREATE TRIGGER SetUserHome after insert ON users
FOR EACH ROW
BEGIN
update `users` set homeLocationX = 128,
homeLocationY=128, homeLocationZ=30
where uuid = NEW.uuid
END
以上的例子是错误的, 让本表进行触发时进行更新会让程序进入死循环。
系统会报这样的错误:it is already used by statement which invoked this stored function/trigger.
应该改成以下语句:
CREATE TRIGGER SetUserHome before insert ON users
FOR EACH ROW
BEGIN
set New.homeLocationX = 128;
set New.homeLocationY = 128;
set New.homeLocationZ=30;
END
大写的为关键字
trigger_name:触发器的名字,我常用的命名规则t_name_tableName_(b|a)(i|u|d),t:触发器标识,name:英文名,tableName:表名,b(BEFORE):标识是触发事件之前,a(AFTER):标识触发事件之后,i(insert):标识insert事件,u(update):标识update事件,d(delete):标识delete事件;
trigger_time:触发时间(BEFORE或AFTER)
trigger_event:事件名(insert或update或delete)
tbl_name:表名(必须是永久性表)
trigger_stmt:执行语句(可以是复合语名),使用别名OLD和NEW,能够引用与触发程序相关的表中的列。
2、删除解发器
语法:
DROP TRIGGER [schema_name.]trigger_name;
注意:以上操作均需SUPER权限
示例:
DROP TRIGGER t_wiley_hotelComment_bu;
delimiter //
CREATE TRIGGER t_wiley_hotelComment_bu BEFORE UPDATE ON hotel_comment
FOR EACH ROW
BEGIN
IF OLD.ispass=0 && NEW.ispass=1 THEN
UPDATE hotel_info SET sumcomment=sumcomment+1,sumconsume=sumconsume+NEW.consume,sumservice=sumservice+NEW.service, sumroom=sumroom+NEW.room,sumentiron=sumentiron+NEW.entironment,total=total+(NEW.service+NEW.room+NEW.entironment) WHERE hotel_id=NEW.hotel_id;
ELSEIF OLD.ispass=1 && NEW.ispass=0 THEN
UPDATE hotel_info SET sumcomment=sumcomment-1,sumconsume=sumconsume-NEW.consume,sumservice=sumservice-NEW.service, sumroom=sumroom-NEW.room,sumentiron=sumentiron-NEW.entironment,total=total-(NEW.service+NEW.room+NEW.entironment) WHERE hotel_id=NEW.hotel_id;
END IF;
END;//
delimiter ;
MySQL 触发器简单实例
Apr 3rd
1、语法:
CREATE TRIGGER <触发器名称> –触发器必须有名字,最多64个字符,可能后面会附有分隔符.它和MySQL中其他对象的命名方式基本相象.
{ BEFORE | AFTER } –触发器有执行的时间设置:可以设置为事件发生前或后。
{ INSERT | UPDATE | DELETE } –同样也能设定触发的事件:它们可以在执行insert、update或delete的过程中触发。
ON <表名称> –触发器是属于某一个表的:当在这个表上执行插入、 更新或删除操作的时候就导致触发器的激活. 我们不能给同一张表的同一个事件安排两个触发器。
FOR EACH ROW –触发器的执行间隔:FOR EACH ROW子句通知触发器 每隔一行执行一次动作,而不是对整个表执行一次。
<触发器SQL语句> –触发器包含所要触发的SQL语句:这里的语句可以是任何合法的语句, 包括复合语句,但是这里的语句受的限制和函数的一样。
–你必须拥有相当大的权限才能创建触发器(CREATE TRIGGER),如果你已经是Root用户,那么就足够了。这跟SQL的标准有所不同。
2、简单实例:
example1:
–创建表tab1
DROP TABLE IF EXISTS tab1;
CREATE TABLE tab1(
tab1_id varchar(11)
);
–创建表tab2
DROP TABLE IF EXISTS tab2;
CREATE TABLE tab2(
tab2_id varchar(11)
);
–创建触发器:t_afterinsert_on_tab1
–作用:增加tab1表记录后自动将记录增加到tab2表中
DROP TRIGGER IF EXISTS t_afterinsert_on_tab1;
CREATE TRIGGER t_afterinsert_on_tab1
AFTER INSERT ON tab1
FOR EACH ROW
BEGIN
insert into tab2(tab2_id) values(new.tab1_id);
END;
–测试一下
INSERT INTO tab1(tab1_id) values(’0001′);
–看看结果
SELECT * FROM tab1;
SELECT * FROM tab2;
example2:
–创建触发器:t_afterdelete_on_tab1
–作用:删除tab1表记录后自动将tab2表中对应的记录删去
DROP TRIGGER IF EXISTS t_afterdelete_on_tab1;
CREATE TRIGGER t_afterdelete_on_tab1
AFTER DELETE ON tab1
FOR EACH ROW
BEGIN
delete from tab2 where tab2_id=old.tab1_id;
END;
–测试一下
DELETE FROM tab1 WHERE tab1_id=’0001′;
–看看结果
SELECT * FROM tab1;
SELECT * FROM tab2;
MySQL从压缩文件恢复数据
Mar 24th
一个方便的命令行,可以大大的节省数据库服务器的空间。MySQL从压缩文件恢复数据。
mysql -uroot -p’passwd’ database < <(zcat database.sql.gz)
我的数据库学习“曲线”【转】
Mar 16th
作者简介:
牛新庄博士,研究方向为数据仓库和数据挖掘。是IBM官方资深培训讲师(培训DB2,AIX,MQ,WebSphere和CICS)。2002年获IBM 杰出软件专家 奖,2006年获“首届中国杰 出数据库工 程师奖”、“2006年IT168技术卓越奖”。是中信银行、山东农信、广东农信等公司资深技术顾问,中国建设银行总行特聘资深技术专家。拥有OCP, AIX,DB2,HP-UX,MQ,CICS和WebSphere等二十多项国际认证。著有《Oracle数据库开发讲座—— Oracle9i Jdeveloper与J2EE实务应用》、《DB2应用开发实战指导》、《循序渐进DB2-系统管理、运行维护与应用案 例》、《深入解析DB2-高级管理、内部体系结构与诊断案例》和《DB2性能调整与优化》等书。
选定发展方向
1999年,我在开始读研时就给自己确定了以后的发展方向。
当时有两个方向:网络,数据库技术。因为在2000年之时,网络大热,市场上拥有CCNP、CCIE证书的人特别牛。所以我当时也考下了CCNP证书,但 后来发现网络方向涉及很多硬件层面的东西,这些都对厂商的依赖性太强,个人发挥空间不大。而我喜欢钻研,所以慢慢开始转向专攻数据库技术。
在认准数据库这个方向后,我开始深入学习数 据库理论方面的知识。当时,人大王珊教授的《数据库系统原理教程》一书,我读了几十遍。在学 习数据库理论的同时,我开始接触并深入学习DB2和 Oracle,并从1999年开始使用DB2 V5.2。那时,市场上关于DB2方面的技术书籍几乎没有,互联网也不像现在这么发达。因为我的导师做一个 课题需要用到DB2数据库,但是我只能依靠查看 DB2随机文档来学习。那时,我还自己兼职,通过帮别人做些小软件赚钱,外加课题经费,以支付考OCP认 证和DB2认证的费用。
到现在为止,我一直认为考认证是一个很好的学习动力。因为考试费用不菲,如果不想浪费钱只能拼命看书。我在读 研的2000年就通过了OCP 8i认证,后来又陆续通过DB2 V5.2认证。这些认证极大地增强了我的自信。同时,在帮助导师用PB、Delphi等编程工具做应用开发时,我有 意识地增强对SQL的 学习,这对我后来的性能调优工作非常有帮助。
这里我想说的是,做好一个时期的人生规划非常重要。我们 首先 要有一个明确的努力方向和规划,然后有意识的往这个方向努力。这种积极主动的学习要比被动学习效率高很多。
第一次做培训
“机遇偏爱于有准备的头脑”,这句话虽是老生常谈,却是人生真谛。记得2000年底,我在网上看到一个帖 子说需要一个人去安装DB2数据库,差旅报销,每 天500元,我喜出望外。因为这项工作需要有DB2认证才能去,而我那时DB2高级系统管理和应用开发的认证都有,所以很快就通过了对方的审核。但是当我 到客户现场时才发现,不是安装DB2而是要给客户讲课,当时我就傻眼了,因为讲课需要的知识远比安装配 置数据库要难得多,更何况我之前根本没有讲过课。没办法,压力也是动力,只能前一天夜里看教材备课到凌晨5点。短短睡了两个小时后,8点半去讲课。四天讲 课下来,我总共休息了12个小时。还好自己毕竟有 DB2应用开发经验和DB2认证做基础,总算勉强应付了过去。只是没想到的是,这次并不算顺利的培训, 竟是我未来几年培训生涯的开始。
将培训当学习的动力
经过第一次讲课后,我看到了自己的差距,知道仅有认证是不够的。客户的很多问题,书本上没有答案,需要自己在实践经验上做努力。另外,讲课前讲师需要把一 些原理、概念性的东西弄清楚,也需要对数据库进行深入学习。
后来,IBM培训部通过一些渠道知道我能讲DB2且拥有相关证书,就找我讲授DB2系列课程。所以,从2001年开始,我就经常作为IBM官方讲师讲授 DB2系列的所有课程。我自认为讲课是一个很好的学习过程,因为课前要深入了解概念,对于自己的理论深入学习有很大帮助。同时,课堂上学员的实际 操作问 题也会强迫自己做更深入的研究。
我对培训有这样的认识:学员听你讲三个小时,要远远胜过自己看3小时的书。 如果把一堂课的内容比喻成 一杯水,那老师至少应该提前储备一桶水。所以,在讲课之前,我精心准备实验,深入和学员交流。我讲课从不照本宣科,而 是自己准备了很多教材外比较实用的知 识来扩展教材内容。同时争取上课过程中把一些概念用浅显易懂的例子来讲解。要想做到这些,首先自己必须对这个概念有深刻的理解才行,这一切都在客观上促进 了自己的学习。
随着培训的增多,有部分客户开始找我做实际的调优工作。记得我第一次去为客户现场调优是2001年,去大连大通证券解决锁等待问题。客户环境用的是AIX 和CICS。当时虽然问题解决了,但自己心里还是比较虚,因为对AIX和CICS不了解,万一是这两个方面有问题, 自己就没办法搞定了;这让我认识到一个复杂系统的调整往往需要具备多方面的知识。这件事之后,我在网上买了一个140的IBM工作站小机,自己安装AIX 并开始学习。
数据库学习Tips
根据我对数据库的理解,目前市场上虽然有Oracle,DB2, Informix,Sybase和SQL Server数据库,但Informix数据库已经被IBM收购,而Sybase数据库在技术和市场上正走向没 落,占据市场主要份额的就是 Oracle,DB2和SQL Server数据库。SQL Server数据库非常好,但是很遗憾的是只能在 Windows平台使用。所以如果你深入研究SQL Server数据库,我只能说获取高薪的概率稍低,而且坦白的说,使用SQL Sever数据库的企业一 般是中小企业居多。而国内做Oracle数据库的人太多,如果你想在Oracle领域出人头地,难度极大。但是,做DB2数据库的人反而不太多,物以稀为 贵。况且,DB2数据库广泛应用在银行、电信、制造行业、零售行业、保险行业等“高薪”领域中,所以我强烈建议学习DB2数据库,做IBM技术一 般获取高 薪的概率相对会大一些。我们的时间精力是有限的,所以必须选择好方向然后努力为之。除了SQL Server,这几个数据库我都在使用,我个人感觉除了功 能外,对于运行稳定而言,相对于Oracle不太稳定的优化器,DB2无疑是最稳定的,它的优化器无比强大。如果能在锁方面再有更先进的技术,那么DB2 将是完美的。
这期间,我一边学习,一边通过了AIX的全部认证。记得非常清楚的是,为了做HA的实验,我花费了很大工夫。因为那时小型机不像 今天这么普及,无法搞到7133阵列。后来我又学习了CICS、WebSphere、MQ和存储。就这样,在我培训的过程中,发现自己哪方面薄弱并且 感觉这个方向有前途,我就会开始学习。不过,那时我的技术主要还是围绕IBM产品为主。由于自己对培训比较用心且颇受客户好评,找我做培训的国内培训机构 开始变多。这个期间我自己的技术水平也增长很快。
2002年11月,我参加了首届 “IBM DeveloperWorksLive! China 2002”大会,并获得IBM首次在国内评选的“杰出软件技术专家”奖,当时在6名获奖 者中名列第2。这个奖项客观上对我在客户群的拓展方面起到很大帮助。找我解决问题的人更多了,所以2002—2003年也成了我技术提升最快的两年。
这两年内,我陆续学习了HP-UX、WebSphere和MQ并通过认证。我自己的感觉是,如果你把一门技术研究得非常深、非常透,由于触类旁通 的缘故, 再去学习另一门技术时就很轻松。所以,我在学完AIX再去学习HP-UX时,感觉非常轻松。同样,在学习ORACLE和DB2后再去学 习 Informix 也同样很容易。通过这种纵向的深入和横向的比较,各种产品的所长所短也会非常清楚,自己的技术视野无意间更加全面化。而且通过对一个产 品的深入,你往往能够发现这个产品的缺点和需要改进的地方。就拿DB2来说,每次版本更新的新特性,在新版本未上市前我就可以猜得差不多了。这主要有三个 原因:一是我贴近真实用户,了解他们的真正需求;二是自己一直在用且不断总结思考;三是这些特性别的数据库有,而DB2没有,那在下个版本就会增加。所以 相对来说,我自身对新版本的新特性学习就非常轻松了。就DB2而言,我拥有DB2 V5.2 、V7.1、V8.1和DB2 V9的全部认证,而且我应该 是国内第一个把DB2 V8认证全部通过的人,当然,这其中也有巧合的成分。
重要的一点是:学 习过程中,要不断地把实践和理论融合,知其然更知其所以然,这样提升就会快很多。
现场救援“赶场”记
2004—2005年 是我最忙碌的两年,那时候找我讲课的培训机构和需要性能调优的客户非常多,基本上整天在天上飞。培训机构找我讲课常常需要提前一个月预约。那两年内,除了 过年几天,其他时间都是在做培训和诊断、调优,足迹遍及国内主要城市。我自己基本上是国内六大银行开发中心和数据中心培训的指定讲师,并为北京银信科技、 山东农信、广东农信,交行大集中IBP等项目做数据库技术顾问。
那时的我年轻、精力充沛。记得最刺激的一次是2004年9月的一天, 上午9点为上海移动IT部门做AIX动态逻辑分区(DLPAR)培训,结束时是17 点。之后,立刻坐出租车前往扬州,于20点到达扬州供电局并协助他们 进行电力负荷控制系统项目上线,一直奋战到凌晨3点半。接着,又连夜乘出租车赶往上海,在凌晨6点到达酒店。休息两小时后,8点出发,准时出现在上海移动 培训现场。那时我对报酬不太在意,想的主要是用心积累技术经验和客户资源。在我看来,能够不断通过实践让自己成长是第一要义。而且,去的客户现场 越多,处 理的问题就越多,也就越多地发现自己的不足,然后再拼命学习,不断积累、总结和思考,进入了一个良性循环。
至今我仍然怀念那段充实、 紧张而充满激情的光辉岁月。2004年和2005年,一方面因为以独立咨询顾问的个人身份无法出具发票;另一方面,项目越做越大,尤其是很多银行的数据库 架构和维护项目涉及合同金额也越来越大,需要签订正式公司合同。于是,我就分别在上海、北京注册了公司。当然这些年我并非都是一帆风顺,也犯过一些重大错 误,例如:我曾经在2002年5月1日把海南美兰机场的数据库调死,导致机场航班信息管理系统瘫痪。早期也曾经因为调整某证券系统宕机而影响股民交易,这 些都对客户造成了影响,但这些都是成长必须要走的路。经过这两次事件后,我自己也思考、总结了很多,在之后的调优工作中我基本上再没有犯过错误。
我 的秘诀:学习、积累、规划
2006年8月我获得“2006年中国首届杰出数据库工程师”称号,算是对我多年学习数据库的一个总结。自2007年开始,我专注于做一些大客户的运维工 作,并相应减少了培训次数。2008年, 我被建设银行以年薪217万聘请为资深技术专家来维护Oracle和Informix数据库。就做技术 而言,以一己之力能挣到年薪几百万常常令我感到自 豪,也让我感受到技术的魅力,觉得自己多年来对技术的钻研得到了认可。
之所以讲述我的技术之路,主要目的是给大家一些参考,尽可能多地去了解社会的需求,有意识给自己制定人生规划。我自己认为,多年来能取得这样的成绩,勤 奋、努力和坚持一直是我最看重的。因为有了这些,才不至于当机遇光顾时,你却不知所措。
现在很多年轻人,恰恰缺少的就是这样的忘我与痴迷,在我熟悉的数据库技术领域,很多年轻人越来越早地将注意力集中在薪水和职位上,这是很不明智的行为。其 实,往往那些将诸如高薪与职位忘怀的人反而能更快地取得成功。“不经一番寒彻骨,安得梅花扑鼻香?”这样的道理人人都懂,可能够真正去实践的人却并不多。 结合我的学习经验与感悟,我总结有16字要诀:去除浮躁,认真学习,不断积累,寻找机遇。
最后,我用这句话与大家共勉:古之成大事者,不唯有超世之才,亦唯有坚韧不拔之志也!
原文:我的数据库学习“曲线”
利用MySQL的注射点得到更多MySQL的信息
Feb 12th
当注射MySQL库的输入点的时候,我们可以通过version()/user()/database()/password()等内置函数来得到MySQL的相关信息,其实我们在注射的时候可以利用MySQL内置的变量来得到更多的MySQL信息
其中version()可以写成@@version来把version当做变量来读取,这样一样可以得到,其他的内置是不可以写成变量的形式.
大家都应该用过利用pangolin来注入MySQL库的注射点,认真的朋友都应该知道可以的得到basedir和datadir这两个变量的信息,其实还有更多的变量在注射的时候可以利用
我整理了几个在注射的时候可以利用到,收集更多关于MySQL的配置信息
@@have_openssl 如果MySQLd支持客户端/服务器协议的SSL(加密)则为YES
@@version_compile_os 判断系统类型
@@max_allowed_packet 包或任何生成的/中间字符串的最大大小
@@max_user_connections MySQL账户允许的最大同时连接数,0表示没限制
@@skip_networking 如果服务器只允许本地(非TCP/IP)连接,该值为ON
@@table_type 默认表类型(存储引擎)
@@basedir MySQL安装基准目录
@@character_set_database 默认数据库使用的字符集
@@datadir 数据库存储的地方
@@expire_logs_days 二进制日志自动删除的天数,默认是0,表示”没有自动删除”
@@group_concat_max_len 允许group_concat()函数结果的最大长度
@@log_error 错误日志的位置
@@lower_case_file_system 该变量说明是否数据目录所在的文件系统对文件名的大小写敏感.
ON说明对文件名的大小写不敏感,OFF表示敏感
@@lower_case_table_names 如果设置为1,表名用小写保存到硬盘上,并且表名比较时不对大小写敏感.
如果设置为2,按照指定的保存表名,但按照小写来比较
@@plugin_dir 插件目录的路径
@@tmpdir 保存临时文件和临时表的目录
@@tmp_table_size 如果内存内的临时表超过该值,MySQL自动将它转换为硬盘上的MyISAM表
@@sql_mode 当前服务器的sql模式
@@tx_isolation 默认事务隔离级别。默认值为REPEATABLE-READ
@@Connections 连接MySQL数据库服务器的次数(不管成功还是失败)
@@max_write_lock_count 最大写锁数量
@@old_passwords 是否启用MySQL323加密方式(就是MySQL用户密码的hash是16位的)
@@Uptime 服务器已经运行的时间
其中我感觉basedir/version_compile_os/log_error/group_concat_max_len这四个变量的作用很大,大家看上面的注视
group_concat_max_len这个变量涉及到group_concat()的返回字符长度,所以在使用group_concat()来注射时候要注意长度的限制.
tips:group_concat()函数的利用如下
url and 1=2 union select 1,group_concat(schema_name),3,4 from information_schema.schemata
这样的话,就可以把当前用户中建立数据库名全部显示出来,在注射表名、字段名、字段属性都可以使用,这样的话又省了不少体力活
同时group_concat()还可以绕过不能使用limit的现实,当然不嫌累的话,可以使用”!=”的形式来绕过limit的限制
from:mysql社区
MySQL Show命令的使用
Dec 14th
show tables或show tables from database_name;
解释:显示当前数据库中所有表的名称
show databases;
解释:显示mysql中所有数据库的名称
show processlist;
解释:显示系统中正在运行的所有进程,也就是当前正在执行的查询。大多数用户可以查看
他们自己的进程,但是如果他们拥有process权限,就可以查看所有人的进程,包括密码。
show table status;
解释:显示当前使用或者指定的database中的每个表的信息。信息包括表类型和表的最新更新时间
show columns from table_name from database_name; 或show columns from database_name.table_name;
解释:显示表中列名称
show grants for user_name@localhost;
解释:显示一个用户的权限,显示结果类似于grant 命令
show index from table_name;
解释:显示表的索引
show status;
解释:显示一些系统特定资源的信息,例如,正在运行的线程数量
show variables;
解释:显示系统变量的名称和值
show privileges;
解释:显示服务器所支持的不同权限
show create database database_name;
解释:显示create database 语句是否能够创建指定的数据库
show create table table_name;
解释:显示create database 语句是否能够创建指定的数据库
show engies;
解释:显示安装以后可用的存储引擎和默认引擎。
show innodb status;
解释:显示innoDB存储引擎的状态
show logs;
解释:显示BDB存储引擎的日志
show warnings;
解释:显示最后一个执行的语句所产生的错误、警告和通知
show errors;
解释:只显示最后一个执行语句所产生的错误
from:http://www.ccvita.com/356.html
MySQL数据库的授权原则
Dec 8th
本文讲述了如何为用户分配合适的权限,几个重要的原则就是给用户分配仅够使用的最小权限,尽量不在影响整个数据库的user表中分配权限。有些权限是有危险的,例如FILE、GRANT、PROCESS,管理员要慎重使用。
服务器重新启动的情况
当mysqld启动时,所有的授权表内容被读进存储器并且从那时开始生效。
被服务器立即应用的情况
用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。
直接修改授权表的情况
如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否则你的改变将不生效,除非你重启服务器。
对现有客户连接的影响情况
当服务器注意到授权表被改变了时,现存的客户连接有如下影响:
·表和列权限在客户的下一次请求时生效。
·数据库权限改变在下一个USE db_name命令生效。
·全局权限的改变和口令改变在下一次客户连接时生效。
授权原则
无论怎么小心都难免在给用户授权时留有漏洞,希望下面的内容能给你一些帮助,你一般应该遵守这些规则。
只有root用户拥有授权表的改写权
不要把授权表的改写权授予除root用户之外的其它用户(当然,如果你可以用另一个用户代替root用户进行管理,以增加安全性)。因为这样,用户可以通过改写授权表而推翻现有的权限。产生安全漏洞。
一般情况下,你可能不会犯这个错误,但是在安装新的分发, 初始授权表之后。这个漏洞是存在的,如果你不了解这时授权表的内容你可能会犯错误。
在Unix(Linux)上,在按照手册的指令安装好MySQL后,你必须运行mysql_install_db脚本建立包含授权表的mysql数据库和初始权限。在Windows上,运行分发中的Setup程序初始化数据目录和mysql数据库。假定服务器也在运行。
当你第一次在机器上安装MySQL时,mysql数据库中的授权表是这样初始化的:
·你可以从本地主机(localhost)上以root连接而不指定口令。root用户拥有所有权限(包括管理权限)并可做任何事情。(顺便说明,MySQL超级用户与Unix超级用户有相同的名字,他们彼此毫无关系。)
·匿名访问被授予用户可从本地连接名为test和任何名字以test_开始的数据库。匿名用户可对数据库做任何事情,但无管理权限。
一般地,建议你删除匿名用户记录:
mysql> DELETE FROM user WHERE User=”";
更进一步,同时删除其他授权表中的任何匿名用户,有User列的表有db、tables_priv和columns_priv。
另外要给root用户设置密码。
关于用户、口令及主机的设置
·对所有MySQL用户使用口令。
记住,如果other_user没有口令,任何人能简单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通过编辑 mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令,象这样:
shell> mysql -u root mysql
mysql> UPDATE user SET Password=PASSWORD(‘new_password’)
-> WHERE user=’root’;
mysql> FLUSH PRIVILEGES;
·删除匿名用户
匿名用户的存在不仅不仅容易引起存取拒绝错误,更会产生严重的安全漏洞,安装授权表后,自动安装匿名用户。缺省时你可以用任何用户名连接,不需要密码,并且具有修改授权表权限。
你可以这样删除匿名用户:
shell>mysql –u root –p mysql
mysql>delete from user where User=””;
·留意使用通配符的主机名,尽量缩小主机名的范围,适合用户的主机就足够了,不要让用户不使用的主机留在授权表里。
·如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则上讲,–secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常小心地使用包含通配符的主机名!
授予用户合适的权限
·授权用户足够使用的权限,不要赋予额外的权限。
例如,对于用户只需要检索数据表的需求,赋予SELECT权限即可,不可赋予UPDATE、INSERT等写权限,不要怕被说成时吝啬鬼。
·可能会产生安全漏洞的权限
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并有grant权限的用户可以合并权限。
alter权限可以用于通过重新命名表来推翻权限系统。因为ALTER权限可能以你没有设想的任何方法被使用。例如,一个用户user1能访问table1,但不能访问table2。但是如果用户user1带有ALTER权限可能通过使用ALTER TABLE将table2重命名为table1来打乱你的设想。
shutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务 。
·可能会产生严重安全漏洞的权限
不要把PROCESS权限给所有用户。mysqladmin processlist的输出显示出当前执行的查询正文,如果另外的用户发出一个UPDATE user SET password=PASSWORD(‘not_secure’)查询,被允许执行那个命令的任何用户可能看得到。mysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用户能登录并检查,即使所有的正常连接在使用。
不要把FILE权限给所有的用户。有这权限的任何用户能在拥有mysqld守护进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT … INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的文件。
FILE权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文件。这可能被滥用,因为不仅有该服务器主机帐号的用户可以读取它们,而且有FILE权限的任何客户机也可以通过网络读取它们。你的数据库目录和系统的各种文件可能成为全球范围共享的文件!例如,通过使用LOAD DATA装载“/etc/passwd”进一个数据库表,然后它能用SELECT被读入。
下面的过程说明如何进行此项操作:
1、建具有LONGBLOB列的表:
mysql> USE test;
mysql> CREATE TABLE temp (b LONGBLOB);
2、用此表读取你要窃取的文件的内容:
mysql>LOAD DATA INFILE “/etc/passwd” INTO TABLE temp
->FIELDS ESCAPED BY “” LINES TERMINATED BY “”;
mysql>SELECT * FROM temp;
3、可以这样窃取你的数据表data:
mysql>LOAD DATA INFILE“./other_db/data.frm” INTO TABLE temp
->FIELDS ESCAPED BY“”LINES TERMINATED BY“”;
mysql>SELECT * FROM temp INTO OUTFILE“./another_db/data.frm”
->FIELDS ESCAPED BY“”LINES TERMINATED BY“”;
mysql>DELETE FROM temp;
mysql>LOAD DATA INFILE“./other_db/data.MYD” INTO TABLE temp
->FIELDS ESCAPED BY“”LINES TERMINATED BY“”;
mysql>SELECT * FROM temp INTO OUTFILE“./another_db/data.MYD”
->FIELDS ESCAPED BY“”LINES TERMINATED BY“”;
mysql>DELETE FROM temp;
mysql>LOAD DATA INFILE“./other_db/data.MYI” INTO TABLE temp
->FIELDS ESCAPED BY“”LINES TERMINATED BY“”;
mysql>SELECT * FROM temp INTO OUTFILE“./another_db/data.MYI”
->FIELDS ESCAPED BY“”LINES TERMINATED BY“”;
mysql>DELETE FROM temp;
然后用户就拥有的一个新表another.data,可以对它进行完全访问。
MySQL权限系统无法完成的任务
有一些事情你不能用MySQL权限系统做到:
你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹配一个用户并且然后拒绝连接。
你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建或抛弃数据库本身。
from:MySQL社区

最新评论