-
2006-09-20
用mysqldump对MySQL数据库进行数据备份与恢复
用mysqldump对MySQL数据库进行数据备份与恢复
数据库备份是很重要的。如果定期做好备份,这样就可以在发生系统崩溃时恢复数据到最后一次正常的状态,把损失减小到最少。MySQLl提供了一个mysqldump命令,我们可以用它进行数据备份,下面假设要备份tm这个数据库:
#mysqldump -u root -p tm > tm_050519.sql
按提示输入密码,这就把tm数据库所有的表结构和数据备份到tm_050519.sql了,因为要总进行备份工作,如果数据量大会占用很大空间,这时可以利用gzip压缩数据,命令如下:
#mysqldump -u root -p tm | gzip > tm_050519.sql.gz
系统崩溃,重建系统时,可以这样恢复数据:
#mysql -u root -p tm < tm_050519.sql
从压缩文件直接恢复:
#gzip < tm_050519.sql.gz | mysql -u root -p tm
-
2006-08-30
linux操作系统下建立mysql镜像数据库
MySQL 版本:4.1
环境介绍:主库 192.168.0.205 从库 192.168.0.206
1、主库创建/etc/my.cnf,修改[mysqld]里边的键值增加
server-id=1
log-bin=binlog_name
2、主库增加用户,用于从库读取主库日志。
grant replication slave,reload,super on *.* to ’slave’@’192.168.0.206’ identified by ’123456’3、从库连接主库进行测试。
/opt/mysql/bin/mysql -u slave -p -h 192.168.0.205
4、停从库,修改从库/etc/my.cnf,增加选项:
[mysqld]
server-id=2
master-host=192.168.0.205
master-user=slave
master-password=1234565、启动从库,进行主从库数据同步
/opt/mysql/share/mysql/mysql start
/opt/mysql/bin/mysql -u root -p
mysql>load data from master;
说明:这一步也可以用数据库倒入或者直接目录考过来。6、进行测试:
主库创建表,
mysql>create database sampdb;
mysql>create table new (name char(20),phone char(20));
mysql>insert into new (’abc,’0532555555’);打开从库,察看:
/opt/mysql/bin/mysql -u root -p
mysql>show database;
mysql
sampdb
test
mysql>use sampdb;
mysql>show tables;
new
说明主从数据库创建成功。7、主从数据库相关命令:
slave stop; slave start ; 开始停止从数据库。
show slave status\G; 显示从库正读取哪一个主数据库二进制日志
purge master logs to ’binlog.000004’; 此命令非常小心,删除主数据库没用的二进制日志文件。如果误删除,那么从库就没有办法自动更新了。
change master; 从服务器上修改参数使用。 -
2006-01-18
mysql的几种超实用技巧
select now();return 当前时间 格式为YYYY-MM-DD hh:ii:ssNOW() 函数本身并无多大用处,但可将其用于表达式中。如比较当前日期和其他日期的差异。注:如果在查询中调用一个函数,在函数名和后跟的圆括号中间不允许有空格insert into table_name values(value1,value2,value3,...),(value11,value21,value31,...);自3.22.5 以来的MySQL版本允许通过指定多个值的列表,利用单个的INSERT语句将几行插入一个表中这比多个INSERT 语句的键入工作要少,而且服务器执行的效率也更高。insert into tabl_name (col1,col2) vlalues (value1,value2);insert into tabl_name (col1,col2) vlalues (value1,value2),(value3,value4);insert into tabl_name set col1=value1,col2=value2....以上这几种情况都是允许的数据库和表名有可能区分大小写的;这有取决服务器主机上使用的文件系统。在UNIX上运行的服务器对数据库名和表名是区分大小写的,因为UNIX 的文件名是区分大小写的。Windows 的文件名不区分大小写,因此运行在Windows 上的服务器对数据库名和表名不区分查找日期的时候可以用<>来比较 2005-01-02这种得数据。select * from tabl_name where info_date<2005-1-1 and (sqle='ma' or sqle='ba');WHERE 子句中的表达式可使用表1-1中的算术运算符、表1-2 的比较运算符和表1-3 的逻辑运算符。还可以使用圆括号将一个表达式分成几个部分。可使用常量、表列和函数来完成运算。NULL 值
NULL 值是特殊的;因为它代表“无值”。不可能以评估两个已知值的相同方式来将它与已知值进行评估。为了进行NULL 值的搜索,必须采用特殊的语法。不能用= 或!= 来测试等于NULL 或不等于NULL,取而代之的是使用IS NULL 或IS NOT NULL 来测试。MySQL3.23 及以后的版本具有一个特殊的MySQL专有的比较运算符“ < = >”,即使是NULL 与NULL 的比较,它相当于IS。如:select * from tabl_name where not (sqle<=>NULL);和select * from tabl_name where sqle is not NULL;是一样的limitLIMIT 也可以从查询结果中取出中间部分。为了做到这一点,必须指定两个值。第一个值为结果中希望看到的第一个记录(第一个结果记录的编号为0 而不是1)。第二个值为希望看到的记录个数。如select * from tabl_name limit 10,5;可按照一个公式来排序查询结果。例如,利用ORDER BYRAND( ) 与LIMIT 结合,从表中随机抽取一个记录如:select * from tabl_name order by rand() limit 1concat()select concat(province," ",city) as address,concat(info_date,",",check_id) as info;此查询把省份和城市连接起来,中间间隔一个空格,将地址名形成一个单一字符串,而且将出生时间和check_id连接在一起,中间隔一个逗号,形成出信息字段。
在利用表达式来计算列值时,此表达式被用作列标题。如果表达式很长(如前面的一些查询样例中那样),那么可能会出现一个很宽的列。为了处理这种情况,此列可利用AS name结构来重新命名标题。这样的名称为列别名。用这种方法可使上面的输出更有意义
日期运算在MySQL中使用日期时要记住的是,在表示日期时首先给出年份。1999 年7 月27 日表示为“1999 - 07 - 27”,而不是像通常那样表示为“ 07 - 27 - 1999”或“27 - 07 - 1999”。mysql中可以对格式为1999 - 07 - 27的日期进行大小比较如:select * from hy_users where 1 and '1998-01-02'<info_date<'1999-01-02'为了测试或检索日期的成分,可使用诸如YEAR( )、MONTH( ) 或DAYOFMONTH( ) 这样的函数。例如,可通过查找月份值为3 的日期,找出与笔者出生在相同月份(三月)的总统。如:select * from hy_com where 1 and MONTH(regist_time)=3此例查找注册时间为3月份的纪录此查询也可按月的名称写出:如:select * from hy_com where 1 and MONTH(regist_time)='march'为了更详细,详细到天,可组合测试MONTH( ) 和DAYOFMONTH( )如:select * from hy_com where 1 and MONTH(regist_time)=3 and DAYOFMONTH(regist_time)=5;这是一种可用来生成类似报纸上娱乐部分所刊登的那种“这些人今天过生日”清单的查询。但是,不必按前面的查询那样插入一个特殊的日期。为了查找每年的今天注册的人,只要将他们的注册日期与CURRENT _ DATE 进行比较即可:如:select * from hy_com where 1 and MONTH(regist_time)=MONTH(CURRENT_DATE) and DAYOFMONTH(regist_time)=DAYOFMONTH(CURRENT_DATE);可从一个日期减去另一个日期。这样可以知道日期间的间隔,这对于确定时间段是非常有用的。例如,为了确定哪位顾客注册时间最长,可将其最后登陆时间减去注册时间。为此,可利用函数TO_DAYS( ) 将最后登陆时间和注册时间转换为天数,求出差,然后除以365 得出注册年限:select FLOOR((TO_DAYS(last_time)-TO_DAYS(regist_time))/365) from hy_com as use_time limit 1;此查询中所用的FLOOR( ) 函数截掉了年龄的小数部分,得到一个整数。得出日期之差,还可以确定相对于某个特定日期有多长时间。如:select FLOOR((TO_DAYS(CURRENT_DATE)-TO_DAYS(regist_time))/365) from hy_com as use_time limit 1;模式匹配:MySQL允许查找与某个模式相配的值。这样,可以选择记录而不用提供精确的值。为了进行模式匹配运算,可使用特殊的运算符( LIKE 和NOT LIKE),并且指定一个包含通配符的串。字符“_”匹配任意单个字符,而“%”匹配任意字符序列(包括空序列)。使用L I K E或NOT LIKE 的模式匹配都是不区分大小写的。下列模式匹配以“W”或“w”开始的姓:select * form hy_usres where first_name like "w%";而select * form hy_usres where first_name = "w%"; 这种做法是严重错误的。此查询给出了一个常见的错误,它对一个算术比较运算符使用了模式。这种比较成功的惟一可能是相应的列确实包含串“ W %”或“w %”。下列模式匹配只有4个字符的姓:select * form hy_usres where first_name like "____";生成汇总:MySQL所能做的最有用的事情是浓缩大量的原始数据行并对其进行汇总。汇总的一种简单的形式是确定在一组值中哪些值是唯一值。利用DISTINCT 关键字来删除结果中的重复行。例如,不重复的列出会员的注册地:select DISTINCT state from companys;其他的汇总形式涉及计数,可利用COUNT( ) 函数。如果使用COUNT (*),它将给出查询所选择的行数。COUNT(*) 对选中的行进行计数。而COUNT(col_name) 只对非NULL 值进行计数select count(DISTINCT state) from companys;针对用于group by中的having句子,要纠正的是它没有提高查询效率的作用。但它是在查询结果已经选出后才应用的,用来缩减服务器实际送到客户机的结果。除了COUNT( ) 外还有许多汇总函数。MIN( )、MAX( )、SUM( ) 和AVG( ) 函数在确定列的最大、最小、总数和平均值时都非常有用,甚至可以同时使用它们。如:select event_id MIN(score) as minmum,MAX(score) as maximum,MAX(score)-MIN(score)+1 as range,SUM(score) as total,AVG(score) as average from score Group by event_id从多个表中检索信息在从多个表中选择信息时,需要执行一种称为连接(join)的操作。这是因为需要将一个表中的信息与其他表中的信息相连接来得出查询结果。即通过协调各表中的值来完成这项工作原文地址:http://www.ddvip.net/database/mysql/index1/4.htm某驼续貂:本篇文章是从上面那个连接地址里面总结归纳出来的.某驼对原文的实在作者佩服的五体投地,里面介绍的技巧都是非常实用和省力的,某驼看了大有相见恨晚之感觉.可惜原文太长了,边看边理解边关联,一天下来驼驼有点吐血了.归纳到这里,还差联合查询和group by这部分不完全了,某驼歇会儿先.换换感觉在回来接着总结. -
2005-12-23
MySQL与存储过程
MySQL是“世界上最为流行的开放性数据库”,至少对于MySQL Web站点会这样。但无论MySQL如此流行,很多公司都对MySQL的使用抱有抵触情绪。这种现象来自几个原因,其中有些人错误地认为开放性源代码只不过相当于小孩子的积木游戏,而另一些人认为任何免费的东西都不会是好东西。也许这些想法都是误解,然而有一种抱怨却是合理的,即与其它对应的产品不一样,比如Oracle或者 DB2,MySQL不能够支持存储过程(stored procedures)。
最新的MySQL 5.0能够支持存储过程。如果你对存储过程还没有熟悉,那么你可以认为它们只是存储在数据库服务器端的SQL命令和程序逻辑的集合。这些存储过程可以被应用程序调用,使得不同技术水平的开发人员能够建立自己的SQL。
优点
存储过程能够允许绝大部分的数据库访问逻辑与程序逻辑分离开来。使用存储过程的其中一个间接的优点是,程序的代码变得更加小巧和容易理解。存储过程的另一优点是,SQL可以被预先编译,由此提高了程序的速度。因为存储过程包含程序逻辑,可以在数据库服务器端更多地执行更多的处理。同样,当执行一个n-tier程序时,存储过程被用于将数据层与服务层分离开来。
安全性也是存储过程的另一优点。当不能直接访问表格时,程序可以将执行优先级别分配给存储过程。不幸的是,在这时候,MySQL不支持“授予执行(GRANT EXECUTE)”。这就意味着除非程序具有访问表格的权限,否则调用访问相同表格的一个存储过程也是不行的。使用这一特性有点像在做一个很有趣的赌博。
标准
与Oracle或者微软的相关数据库不一样,MySQL和IBM的DB2能够遵循存储程序的SQL:2003语法。在理论上这意味着,如果数据库结构相同,存储程序可以在不同数据库中使用。
可支持的SQL声明
虽然MySQL不能支持存储程序,但它却可以完成很多任务,如表A所示。除此之外,MySQL的stored procedure documentation(存储过程文档)描述了可用于Oracle的PL/SQL和SQL Server的 T-SQL的很多兼容特性。我对存储过程支持的印象是,它执行比较缓慢,目的是避免任何影响大型软件开发工程的步骤。
表A
声明
描述
CREATE PROCEDURE
建立一个存放在MySQL数据库的表格的存储过程。
CREATE FUNCTION
建立一个用户自定义的函数,尤其是返回数据的存储过程。
ALTER PROCEDURE
更改用CREATE PROCEDURE 建立的预先指定的存储过程,其不会影响相关存储过程或存储功能。.
ALTER FUNCTION
更改用CREATE FUNCTION 建立的预先指定的存储过程,其不会影响相关存储过程或存储功能。.
DROP PROCEDURE
从MySQL的表格中删除一个或多个存储过程。
DROP FUNCTION
从MySQL的表格中删除一个或多个存储函数。
SHOW CREATE PROCEDURE
返回使用CREATE PROCEDURE 建立的预先指定的存储过程的文本。这一声明是SQL:2003规范的一个MySQL扩展。
SHOW CREATE FUNCTION
返回使用CREATE FUNCTION建立的预先指定的存储过程的文本。这一声明是SQL:2003规范的一个MySQL扩展。
SHOW PROCEDURE STATUS
返回一个预先指定的存储过程的特性,包括名称、类型、建立者、建立日期、以及更改日期。这一声明是SQL:2003规范的一个MySQL扩展。
SHOW FUNCTION STATUS
返回一个预先指定的存储函数的特性,包括名称、类型、建立者、建立日期、以及更改日期。这一声明是SQL:2003规范的一个MySQL扩展。
CALL
调用一个使用CREATE PROCEDURE建立的预先指定的存储过程。
BEGIN ... END
包含一组执行的多声明。
DECLARE
用于指定当地变量、环境、处理器,以及指针。
SET
用于更改当地和全局服务器变量的值。
SELECT ... INTO
用于存储显示变量的纵列。
OPEN
用于打开一个指针。
FETCH
使用特定指针来获得下一列。
CLOSE
用于关闭和打开指针。
IF
一个An if-then-else-end if 声明。
CASE ... WHEN
一个 case声明的结构
LOOP
一个简单的循环结构;可以使用LEAVE 语句来退出。
LEAVE
用于退出IF,CASE,LOOP,REPEAT以及WHILE 语句。
ITERATE
用于重新开始循环。
REPEAT
在结束时测试的循环。
WHILE
在开始时测试的循环。
RETURNS
返回一个存储过程的值。
[/size][/b]
MySQL 5.0支持存储过程语句。 -
2005-12-23
mysql使用
一、连接MYSQL。
格式: mysql -h主机地址 -u用户名 -p用户密码
1、例1:连接到本机上的MYSQL。
首先在打开DOS窗口,然后进入目录 mysqlbin,再键入命令mysql -uroot - p,回车后提示你输密码,如果刚安装好MYSQL,超级用户root是没有密码的,故直接回车即可进入到MYSQL中了,MYSQL的提示符是: mysql>
2、例2:连接到远程主机上的MYSQL。假设远程主机的IP为:110.110.110.110,用户名为root,密码为abcd123。则键入以下命令:
mysql -h110.110.110.110 -uroot -pabcd123
(注:u与root可以不用加空格,其它也一样)
3、退出MYSQL命令: exit (回车)
二、修改密码。
格式:mysqladmin -u用户名 -p旧密码 password 新密码
1、例1:给root加个密码ab12。首先在DOS下进入目录mysqlbin,然后键入以下命令 (password 里面不要加命令符)
mysqladmin -uroot password ab12
注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。
2、例2:再将root的密码改为djg345。
mysqladmin -uroot -pab12 password djg345
三、增加新用户。(注意:和上面不同,下面的因为是MYSQL环境中的命令,所以后面都带一个分号作为命令结束符)
格式:grant select on 数据库.* to 用户名@登录主机 identified by "密码"
例1、增加一个用户test1密码为abc,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入MYSQL,然后键入以下命令:
grant select,insert,update,delete on *.* to test1@"%" Identified by "abc";
但例1增加的用户是十分危险的,你想如某个人知道test1的密码,那么他就可以在internet上的任何一台电脑上登录你的mysql数据库并对你的数据可以为所欲为了,解决办法见例2。
例2、增加一个用户test2密码为abc,让他只可以在localhost上登录,并可以对数据库mydb进行查询、插入、修改、删除的操作(localhost指本地主机,即MYSQL数据库所在的那台主机),这样用户即使用知道test2的密码,他也无法从internet上直接访问数据库,只能通过MYSQL主机上的web页来访问了。
grant select,insert,update,delete on mydb.* to test2@localhost identified by "abc";
如果你不想test2有密码,可以再打一个命令将密码消掉。
grant select,insert,update,delete on mydb.* to test2@localhost identified by "";
在上篇我们讲了登录、增加用户、密码更改等问题。下篇我们来看看MYSQL中有关数据库方面的操作。注意:你必须首先登录到MYSQL中,以下操作都是在MYSQL的提示符下进行的,而且每个命令以分号结束。
一、操作技巧
1、如果你打命令时,回车后发现忘记加分号,你无须重打一遍命令,只要打个分号回车就可以了。也就是说你可以把一个完整的命令分成几行来打,完后用分号作结束标志就OK。
2、你可以使用光标上下键调出以前的命令。但以前我用过的一个MYSQL旧版本不支持。我现在用的是mysql-3.23.27-beta-win。
二、显示命令
1、显示数据库列表。
show databases;
刚开始时才两个数据库:mysql和test。mysql库很重要它里面有MYSQL的系统信息,我们改密码和新增用户,实际上就是用这个库进行操作。
2、显示库中的数据表:
use mysql; //打开库,学过FOXBASE的一定不会陌生吧
show tables;
3、显示数据表的结构:
describe 表名;
4、建库:
create database 库名;
5、建表:
use 库名;
create table 表名 (字段设定列表);
6、删库和删表:
drop database 库名;
drop table 表名;
7、将表中记录清空:
delete from 表名;
8、显示表中的记录:
select * from 表名;
三、一个建库和建表以及插入数据的实例
drop database if exists school; file://如果存在SCHOOL则删除
create database school; file://建立库SCHOOL
use school; file://打开库SCHOOL
create table teacher file://建立表TEACHER
(
id int(3) auto_increment not null primary key,
name char(10) not null,
address varchar(50) default '深圳',
year date
); file://建表结束
file://以下为插入字段
insert into teacher values('','glchengang','深圳一中','1976-10-10');
insert into teacher values('','jack','深圳一中','1975-12-23');
注:在建表中
(1)将ID设为长度为3的数字字段:int(3)并让它每个记录自动加一:auto_increment并不能为空:not null而且让他成为主字段primary key
(2)将NAME设为长度为10的字符字段
(3)将ADDRESS设为长度50的字符字段,而且缺省值为深圳。varchar和char有什么区别呢,只有等以后的文章再说了。
(4)将YEAR设为日期字段。
如果你在mysql提示符键入上面的命令也可以,但不方便调试。你可以将以上命令原样写入一个文本文件中假设为school.sql,然后复制到c:\下,并在DOS状态进入目录\mysql\bin,然后键入以下命令:
mysql -uroot -p密码 school.bbb
注释:将数据库school备份到school.bbb文件,school.bbb是一个文本文件,文件名任取,打开看看你会有新发现。
后记:其实MYSQL的对数据库的操作与其它的SQL类数据库大同小异,您最好找本将SQL的书看看。我在这里只介绍一些基本的,其实我也就只懂这些了,呵呵。最好的MYSQL教程还是“晏子“译的“MYSQL中文参考手册“不仅免费每个相关网站都有下载,而且它是最权威的。可惜不是象"PHP4中文手册"那样是chm的格式,在查找函数命令的时候不太方便
-
2005-12-23
mysql规范
关系数据库设计之时是要遵守一定的规则的。尤其是数据库设计范式 现简单介绍1NF(第一范式),2NF(第二范式),3NF(第三范式)和BCNF,另有第四范式和第五范式留到以后再介绍。 在你设计数据库之时,若能符合这几个范式,你就是数据库设计的高手。
第一范式(1NF):在关系模式R中的每一个具体关系r中,如果每个属性值 都是不可再分的最小数据单位,则称R是第一范式的关系。例:如职工号,姓名,电话号码组成一个表(一个人可能有一个办公室电话 和一个家里电话号码) 规范成为1NF有三种方法:
一是重复存储职工号和姓名。这样,关键字只能是电话号码。
二是职工号为关键字,电话号码分为单位电话和住宅电话两个属性
三是职工号为关键字,但强制每条记录只能有一个电话号码。
以上三个方法,第一种方法最不可取,按实际情况选取后两种情况。第二范式(2NF):如果关系模式R(U,F)中的所有非主属性都完全依赖于任意一个候选关键字,则称关系R 是属于第二范式的。
例:选课关系 SCI(SNO,CNO,GRADE,CREDIT)其中SNO为学号, CNO为课程号,GRADEGE 为成绩,CREDIT 为学分。 由以上条件,关键字为组合关键字(SNO,CNO)
在应用中使用以上关系模式有以下问题:
a.数据冗余,假设同一门课由40个学生选修,学分就 重复40次。
b.更新异常,若调整了某课程的学分,相应的元组CREDIT值都要更新,有可能会出现同一门课学分不同。
c.插入异常,如计划开新课,由于没人选修,没有学号关键字,只能等有人选修才能把课程和学分存入。
d.删除异常,若学生已经结业,从当前数据库删除选修记录。某些门课程新生尚未选修,则此门课程及学分记录无法保存。
原因:非关键字属性CREDIT仅函数依赖于CNO,也就是CREDIT部分依赖组合关键字(SNO,CNO)而不是完全依赖。
解决方法:分成两个关系模式 SC1(SNO,CNO,GRADE),C2(CNO,CREDIT)。新关系包括两个关系模式,它们之间通过SC1中的外关键字CNO相联系,需要时再进行自然联接,恢复了原来的关系第三范式(3NF):如果关系模式R(U,F)中的所有非主属性对任何候选关键字都不存在传递信赖,则称关系R是属于第三范式的。
例:如S1(SNO,SNAME,DNO,DNAME,LOCATION) 各属性分别代表学号,
姓名,所在系,系名称,系地址。
关键字SNO决定各个属性。由于是单个关键字,没有部分依赖的问题,肯定是2NF。但这关系肯定有大量的冗余,有关学生所在的几个属性DNO,DNAME,LOCATION将重复存储,插入,删除和修改时也将产生类似以上例的情况。
原因:关系中存在传递依赖造成的。即SNO -> DNO。 而DNO -> SNO却不存在,DNO -> LOCATION, 因此关键辽 SNO 对 LOCATION 函数决定是通过传递依赖 SNO -> LOCATION 实现的。也就是说,SNO不直接决定非主属性LOCATION。
解决目地:每个关系模式中不能留有传递依赖。
解决方法:分为两个关系 S(SNO,SNAME,DNO),D(DNO,DNAME,LOCATION)
注意:关系S中不能没有外关键字DNO。否则两个关系之间失去联系。BCNF:如果关系模式R(U,F)的所有属性(包括主属性和非主属性)都不传递依赖于R的任何候选关键字,那么称关系R是属于BCNF的。或是关系模式R,如果每个决定因素都包含关键字(而不是被关键字所包含),则RCNF的关系模式。
例:配件管理关系模式 WPE(WNO,PNO,ENO,QNT)分别表仓库号,配件号,职工号,数量。有以下条件
a.一个仓库有多个职工。
b.一个职工仅在一个仓库工作。
c.每个仓库里一种型号的配件由专人负责,但一个人可以管理几种配件。
d.同一种型号的配件可以分放在几个仓库中。
分析:由以上得 PNO 不能确定QNT,由组合属性(WNO,PNO)来决定,存在函数依赖(WNO,PNO) -> ENO。由于每个仓库里的一种配件由专人负责,而一个人可以管理几种配件,所以有组合属性(WNO,PNO)才能确定负责人,有(WNO,PNO)-> ENO。因为 一个职工仅在一个仓库工作,有ENO -> WNO。由于每个仓库里的一种配件由专人负责,而一个职工仅在一个仓库工作,有 (ENO,PNO)-> QNT。
找一下候选关键字,因为(WNO,PNO) -> QNT,(WNO,PNO)-> ENO ,因此 (WNO,PNO)可以决定整个元组,是一个候选关键字。根据ENO->WNO,(ENO,PNO)->QNT,故(ENO,PNO)也能决定整个元组,为另一个候选关键字。属性ENO,WNO,PNO 均为主属性,只有一个非主属性QNT。它对任何一个候选关键字都是完全函数依赖的,并且是直接依赖,所以该关系模式是3NF。
分析一下主属性。因为ENO->WNO,主属性ENO是WNO的决定因素,但是它本身不是关键字,只是组合关键字的一部分。这就造成主属性WNO对另外一个候选关键字(ENO,PNO)的部 分依赖,因为(ENO,PNO)-> ENO但反过来不成立,而P->WNO,故(ENO,PNO)-> WNO 也是传递依赖。
虽然没有非主属性对候选关键辽的传递依赖,但存在主属性对候选关键字的传递依赖,同样也会带来麻烦。如一个新职工分配到仓库工作,但暂时处于实习阶段,没有独立负责对某些配件的管理任务。由于缺少关键字的一部分PNO而无法插入到该关系中去。又如某个人改成不管配件了去负责安全,则在删除配件的同时该职工也会被删除。
解决办法:分成管理EP(ENO,PNO,QNT),关键字是(ENO,PNO)工作EW(ENO,WNO)其关键字是ENO
缺点:分解后函数依赖的保持性较差。如此例中,由于分解,函数依赖(WNO,PNO)-> ENO 丢失了, 因而对原来的语义有所破坏。没有体现出每个仓库里一种部件由专人负责。有可能出现 一部件由两个人或两个以上的人来同时管理。因此,分解之后的关系模式降低了部分完整性约束。一个关系分解成多个关系,要使得分解有意义,起码的要求是分解后不丢失原来的信息。这些信息不仅包括数据本身,而且包括由函数依赖所表示的数据之间的相互制约。进行分解的目标是达到更高一级的规范化程度,但是分解的同时必须考虑两个问题:无损联接性和保持函数依赖。有时往往不可能做到既有无损联接性,又完全保持函数依赖。需要根据需要进行权衡。
1NF直到BCNF的四种范式之间有如下关系:
BCNF包含了3NF包含2NF包含1NF小结:
目地:规范化目的是使结构更合理,消除存储异常,使数据冗余尽量小,便于插入、删除和更新
原则:遵从概念单一化 "一事一地"原则,即一个关系模式描述一个实体或实体间的一种联系。规范的实质就是概念的单一化。
方法:将关系模式投影分解成两个或两个以上的关系模式。
要求:分解后的关系模式集合应当与原关系模式"等价",即经过自然联接可以恢复原关系而不丢失信息,并保持属性间合理的联系。注意:一个关系模式结这分解可以得到不同关系模式集合,也就是说分解方法不是唯一的。最小冗余的要求必须以分解后的数据库能够表达原来数据库所有信息为前提来实现。其根本目标是节省存储空间,避免数据不一致性,提高对关系的操作效率,同时满足应用需求。实际上,并不一定要求全部模式都达到BCNF不可。有时故意保留部分冗余可能更方便数据查询。尤其对于那些更新频度不高,查询频度极高的数据库系统更是如此。
在关系数据库中,除了函数依赖之外还有多值依赖,联接依赖的问题,从而提出了第四范式,第五范式等更高一级的规范化要求。在此,以后再谈。
各位朋友,你看过后有何感想,其实,任何一本数据库基础理论的书都会讲这些东西,考虑到很多网友是半途出家,来做数据库。特找一本书大抄特抄一把,各位有什么问题,也别问我了,自已去找一本关系数据库理论的书去看吧,说不定,对各位大有帮助。说是说以上是基础理论的东西,请大家想想,你在做数据库设计的时候有没有考虑过遵过以上几个范式呢,有没有在数据库设计做得不好之时,想一想,对比以上所讲,到底是违反了第几个范式呢?
我见过的数据库设计,很少有人做到很符合以上几个范式的,一般说来,第一范式大家都可以遵守,完全遵守第二第三范式的人很少了,遵守的人一定就是设计数据库的高手了,BCNF的范式出现机会较少,而且会破坏完整性,你可以在做设计之时不考虑它,当然在ORACLE中可通过触发器解决其缺点。以后我们共同做设计之时,也希望大家遵守以上几个范式。 -
2005-12-23
MySQL索引优化
一、什么是索引?
索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存。如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录。表里面的记录数量越多,这个操作的代价就越高。如果作为搜索条件的列上已经创建了索引,MySQL无需扫描任何记录即可迅速得到目标记录所在的位置。如果表有1000个记录,通过索引查找记录至少要比顺序扫描记录快100倍。
假设我们创建了一个名为people的表:
CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL );
然后,我们完全随机把1000个不同name值插入到people表。下图显示了people表所在数据文件的一小部分:
可以看到,在数据文件中name列没有任何明确的次序。如果我们创建了name列的索引,MySQL将在索引中排序name列:
对于索引中的每一项,MySQL在内部为它保存一个数据文件中实际记录所在位置的“指针”。因此,如果我们要查找name等于“Mike”记录的peopleid(SQL命令为“SELECT peopleid FROM people WHERE name=\'Mike\';”),MySQL能够在name的索引中查找“Mike”值,然后直接转到数据文件中相应的行,准确地返回该行的peopleid(999)。在这个过程中,MySQL只需处理一个行就可以返回结果。如果没有“name”列的索引,MySQL要扫描数据文件中的所有记录,即1000个记录!显然,需要MySQL处理的记录数量越少,则它完成任务的速度就越快。
二、索引的类型
MySQL提供多种索引类型供选择:
- 普通索引
这是最基本的索引类型,而且它没有唯一性之类的限制。普通索引可以通过以下几种方式创建:- 创建索引,例如CREATE INDEX <索引的名字> ON tablename (列的列表);
- 修改表,例如ALTER TABLE tablename ADD INDEX [索引的名字] (列的列表);
- 创建表的时候指定索引,例如CREATE TABLE tablename ( [...], INDEX [索引的名字] (列的列表) );
- 唯一性索引
这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。唯一性索引可以用以下几种方式创建:- 创建索引,例如CREATE UNIQUE INDEX <索引的名字> ON tablename (列的列表);
- 修改表,例如ALTER TABLE tablename ADD UNIQUE [索引的名字] (列的列表);
- 创建表的时候指定索引,例如CREATE TABLE tablename ( [...], UNIQUE [索引的名字] (列的列表) );
- 主键
主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”。如果你曾经用过AUTO_INCREMENT类型的列,你可能已经熟悉主键之类的概念了。主键一般在创建表的时候指定,例如“CREATE TABLE tablename ( [...], PRIMARY KEY (列的列表) ); ”。但是,我们也可以通过修改表的方式加入主键,例如“ALTER TABLE tablename ADD PRIMARY KEY (列的列表); ”。每个表只能有一个主键。 - 全文索引
MySQL从3.23.23版开始支持全文索引和全文检索。在MySQL中,全文索引的索引类型为FULLTEXT。全文索引可以在VARCHAR或者TEXT类型的列上创建。它可以通过CREATE TABLE命令创建,也可以通过ALTER TABLE或CREATE INDEX命令创建。对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建全文索引要比把记录插入带有全文索引的空表更快。本文下面的讨论不再涉及全文索引,要了解更多信息,请参见MySQL documentation。
三、单列索引与多列索引
索引可以是单列索引,也可以是多列索引。下面我们通过具体的例子来说明这两种索引的区别。假设有这样一个people表:
<><>
>这个数据片段中有四个名字为“Mikes”的人(其中两个姓Sullivans,两个姓McConnells),有两个年龄为17岁的人,还有一个名字与众不同的Joe Smith。
这个表的主要用途是根据指定的用户姓、名以及年龄返回相应的peopleid。例如,我们可能需要查找姓名为Mike Sullivan、年龄17岁用户的peopleid(SQL命令为SELECT peopleid FROM people WHERE firstname=\'Mike\' AND lastname=\'Sullivan\' AND age=17;)。由于我们不想让MySQL每次执行查询就去扫描整个表,这里需要考虑运用索引。
首先,我们可以考虑在单个列上创建索引,比如firstname、lastname或者age列。如果我们创建firstname列的索引(ALTER TABLE people ADD INDEX firstname (firstname);),MySQL将通过这个索引迅速把搜索范围限制到那些firstname=\'Mike\'的记录,然后再在这个“中间结果集”上进行其他条件的搜索:它首先排除那些lastname不等于“Sullivan”的记录,然后排除那些age不等于17的记录。当记录满足所有搜索条件之后,MySQL就返回最终的搜索结果。
由于建立了firstname列的索引,与执行表的完全扫描相比,MySQL的效率提高了很多,但我们要求MySQL扫描的记录数量仍旧远远超过了实际所需要的。虽然我们可以删除firstname列上的索引,再创建lastname或者age列的索引,但总地看来,不论在哪个列上创建索引搜索效率仍旧相似。
为了提高搜索效率,我们需要考虑运用多列索引。如果为firstname、lastname和age这三个列创建一个多列索引,MySQL只需一次检索就能够找出正确的结果!下面是创建这个多列索引的SQL命令:
/>
ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age);
由于索引文件以B-树格式保存,MySQL能够立即转到合适的firstname,然后再转到合适的lastname,最后转到合适的age。在没有扫描数据文件任何一个记录的情况下,MySQL就正确地找出了搜索的目标记录!
那么,如果在firstname、lastname、age这三个列上分别创建单列索引,效果是否和创建一个firstname、lastname、age的多列索引一样呢?答案是否定的,两者完全不同。当我们执行查询的时候,MySQL只能使用一个索引。如果你有三个单列的索引,MySQL会试图选择一个限制最严格的索引。但是,即使是限制最严格的单列索引,它的限制能力也肯定远远低于firstname、lastname、age这三个列上的多列索引。
四、最左前缀
多列索引还有另外一个优点,它通过称为最左前缀(Leftmost Prefixing)的概念体现出来。继续考虑前面的例子,现在我们有一个firstname、lastname、age列上的多列索引,我们称这个索引为fname_lname_age。当搜索条件是以下各种列的组合时,MySQL将使用fname_lname_age索引:
- firstname,lastname,age
- firstname,lastname
- firstname
从另一方面理解,它相当于我们创建了(firstname,lastname,age)、(firstname,lastname)以及(firstname)这些列组合上的索引。下面这些查询都能够使用这个fname_lname_age索引:
<><>MySQL文档 /> > <>找到有关该命令的更多说明。下面是一个例子:
>
table type possible_keys key key_len ref rows Extra people ref fname_lname_age fname_lname_age 102 const,const,const 1 Where used 下面我们就来看看这个EXPLAIN分析结果的含义。
- table:这是表的名字。
- type:连接操作的类型。下面是MySQL文档关于ref连接类型的说明:
“对于每一种与另一个表中记录的组合,MySQL将从当前的表读取所有带有匹配索引值的记录。如果连接操作只使用键的最左前缀,或者如果键不是UNIQUE或PRIMARY KEY类型(换句话说,如果连接操作不能根据键值选择出唯一行),则MySQL使用ref连接类型。如果连接操作所用的键只匹配少量的记录,则ref是一种好的连接类型。”
在本例中,由于索引不是UNIQUE类型,ref是我们能够得到的最好连接类型。
如果EXPLAIN显示连接类型是“ALL”,而且你并不想从表里面选择出大多数记录,那么MySQL的操作效率将非常低,因为它要扫描整个表。你可以加入更多的索引来解决这个问题。预知更多信息,请参见MySQL的手册说明。
- possible_keys:
可能可以利用的索引的名字。这里的索引名字是创建索引时指定的索引昵称;如果索引没有昵称,则默认显示的是索引中第一个列的名字(在本例中,它是“firstname”)。默认索引名字的含义往往不是很明显。
- Key:
它显示了MySQL实际使用的索引的名字。如果它为空(或NULL),则MySQL不使用索引。
- key_len:
索引中被使用部分的长度,以字节计。在本例中,key_len是102,其中firstname占50字节,lastname占50字节,age占2字节。如果MySQL只使用索引中的firstname部分,则key_len将是50。
- ref:
它显示的是列的名字(或单词“const”),MySQL将根据这些列来选择行。在本例中,MySQL根据三个常量选择行。
- rows:
MySQL所认为的它在找到正确的结果之前必须扫描的记录数。显然,这里最理想的数字就是1。
- Extra:
这里可能出现许多不同的选项,其中大多数将对查询产生负面影响。在本例中,MySQL只是提醒我们它将用WHERE子句限制搜索结果集。
七、索引的缺点
到目前为止,我们讨论的都是索引的优点。事实上,索引也是有缺点的。
首先,索引要占用磁盘空间。通常情况下,这个问题不是很突出。但是,如果你创建每一种可能列组合的索引,索引文件体积的增长速度将远远超过数据文件。如果你有一个很大的表,索引文件的大小可能达到操作系统允许的最大文件限制。
第二,对于需要写入数据的操作,比如DELETE、UPDATE以及INSERT操作,索引会降低它们的速度。这是因为MySQL不仅要把改动数据写入数据文件,而且它还要把这些改动写入索引文件。
【结束语】在大型数据库中,索引是提高速度的一个关键因素。不管表的结构是多么简单,一次500000行的表扫描操作无论如何不会快。如果你的网站上也有这种大规模的表,那么你确实应该花些时间去分析可以采用哪些索引,并考虑是否可以改写查询以优化应用。要了解更多信息,请参见MySQL manual。另外注意,本文假定你所使用的MySQL是3.23版,部分查询不能在3.22版MySQL上执行。
- 普通索引
-
2005-12-23
大型数据库设计
一个好的数据库产品不等于就有一个好的应用系统,如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能。一般来讲,在一个MIS系统分、设计、测试和试运行阶段,因为数据量较小,设计人员和测试人员往往只注意到功能的实现,而很难注意到性能的薄弱之处,等到系统投入实际运行一段时间后,才发现系统的性能在降低,这时再来考虑提高系统性能则要花费更多的人力物力,而整个系统也不可避免的形成了一个打补丁工程。笔者依据多年来设计和使用数据库的经验,提出以下一些设计准则,供同仁们参考。
命名的规范
不同的数据库产品对对象的命名有不同的要求,因此,数据库中的各种对象的命名、后台程序的代码编写应采用大小写敏感的形式,各种对象命名长度不要超过30个字符,这样便于应用系统适应不同的数据库。
游标(Cursor)的慎用
游标提供了对特定集合中逐行扫描的手段,一般使用游标逐行遍历数据,根据取出的数据不同条件进行不同的操作。尤其对多表和大表定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等特甚至死机,笔者在某市《住房公积金管理系统》进行日终帐户滚积数计息处理时,对一个10万个帐户的游标处理导致程序进入了一个无限期的等特(后经测算需48个小时才能完成)(硬件环境:Alpha/4000 128Mram ,Sco Unix,Sybase 11.0),后根据不同的条件改成用不同的UPDATE语句得以在二十分钟之内完成。
示例如下:
Declare Mycursor cursor for select count_no from COUNT
Open Mycursor
Fetch Mycursor into @vcount_no
While (@@sqlstatus=0)
Begin
If @vcount_no=’’ 条件1
操作1
If @vcount_no=’’ 条件2
操作2
。。。
Fetch Mycursor into @vcount_no
End
。。。
。。。
改为
Update COUNT set 操作1 for 条件1
Update COUNT set 操作2 for 条件2
。。。
。。。
在有些场合,有时也非得使用游标,此时也可考虑将符合条件的数据行转入临时表中,再对临时表定义游标进行操作,可时性能得到明显提高。笔者在某地市〈电信收费系统〉数据库后台程序设计中,对一个表(3万行中符合条件的30多行数据)进行游标操作(硬件环境:PC服务器,PII266 64Mram ,NT4.0 Ms Sqlserver 6.5)。 示例如下:
Create #tmp /* 定义临时表 */
( 字段1
字段2
。。。
)
Insert into #tmp select * from TOTAL where 条件 /* TOTAL中3万行 符合条件只有几十行 */
Declare Mycursor cursor for select * from #tmp
/*对临时表定义游标*/
。。。
索引(Index)的使用原则
创建索引一般有以下两个目的:维护被索引列的唯一性和提供快速访问表中数据的策略。大型数据库有两种索引即簇索引和非簇索引,一个没有簇索引的表是按堆结构存储数据,所有的数据均添加在表的尾部,而建立了簇索引的表,其数据在物理上会按照簇索引键的顺序存储,一个表只允许有一个簇索引,因此,根据B树结构,可以理解添加任何一种索引均能提高按索引列查询的速度,但会降低插入、更新、删除操作的性能,尤其是当填充因子(Fill Factor)较大时。所以对索引较多的表进行频繁的插入、更新、删除操作,建表和索引时因设置较小的填充因子,以便在各数据页中留下较多的自由空间,减少页分割及重新组织的工作。
数据的一致性和完整性
为了保证数据库的一致性和完整性,设计人员往往会设计过多的表间关联(Relation),尽可能的降低数据的冗余。表间关联是一种强制性措施,建立后,对父表(Parent Table)和子表(Child Table)的插入、更新、删除操作均要占用系统的开销,另外,最好不要用Identify 属性字段作为主键与子表关联。如果数据冗余低,数据的完整性容易得到保证,但增加了表间连接查询的操作,为了提高系统的响应时间,合理的数据冗余也是必要的。使用规则(Rule)和约束(Check)来防止系统操作人员误输入造成数据的错误是设计人员的另一种常用手段,但是,不必要的规则和约束也会占用系统的不必要开销,需要注意的是,约束对数据的有效性验证要比规则快。所有这些,设计人员在设计阶段应根据系统操作的类型、频度加以均衡考虑。
事务的陷阱
事务是在一次性完成的一组操作。虽然这些操作是单个的操作,SQL Server能够保证这组操作要么全部都完成,要么一点都不做。正是大型数据库的这一特性,使得数据的完整性得到了极大的保证。
众所周知,SQL Server为每个独立的SQL语句都提供了隐含的事务控制,使得每个DML的数据操作得以完整提交或回滚,但是SQL Server还提供了显式事务控制语句---- BEGIN TRANSACTION 开始一个事务
---- COMMIT TRANSACTION 提交一个事务
---- ROLLBACK TRANSACTION 回滚一个事务
---- 事务可以嵌套,可以通过全局变量@@trancount检索到连接的事务处理嵌套层次。
需要加以特别注意并且极容易使编程人员犯错误的是,每个显示或隐含的事物开始都使得该变量加1,每个事务的提交使该变量减1,每个事务的回滚都会使得该变量置0,而只有当该变量为0时的事务提交(最后一个提交语句时),这时才把物理数据写入磁盘。
数据库性能调整
在计算机硬件配置和网络设计确定的情况下,影响到应用系统性能的因素不外乎为数据库性能和客户端程序设计。而大多数数据库设计员采用两步法进行数据库设计:首先进行逻辑设计,而后进行物理设计。数据库逻辑设计去除了所有冗余数据,提高了数据吞吐速度,保证了数据的完整性,清楚地表达数据元素之间的关系。而对于多表之间的关联查询(尤
其是大数据表)时,其性能将会降低,同时也提高了客 户端程序的编程难度,因此,物理设计需折衷考虑,根据业务规则,确定对关联表的数据量大小、数据项的访问频度,对此类数据表频繁的关联查询应适当提高数据冗余设计。
数据类型的选择
数据类型的合理选择对于数据库的性能和操作具有很大的影响,有关这方面的书籍也有不少的阐述,这里主要介绍几点经验。
Identify字段不要作为表的主键与其它表关联,这将会影响到该表的数据迁移。 Text 和Image字段属指针型数据,主要用来存放二进制大型对象(BLOB)。这类数据的操作相比其它数据类型较慢,因此要避开使用。
日期型字段的优点是有众多的日期函数支持,因此,在日期的大小比较、加减操作上非常简单。但是,在按照日期作为条件的查询操作也要用函数,相比其它数据类型速度上就慢许多,因为用函数作为查询的条件时,服务器无法用先进的性能策略来优化查询而只能进行表扫描遍历每行。
例如:要从DATA_TAB1中(其中有一个名为DATE的日期字段)查询1998年的所有记录。 -
2005-12-20
MySQL集群配置
一、介绍
========
这篇文档旨在介绍如何安装配置基于2台服务器的MySQL集群。并且实现任意一台服务器出现问题或宕机时MySQL依然能够继续运行。
注意!
虽然这是基于2台服务器的MySQL集群,但也必须有额外的第三台服务器作为管理节点,但这台服务器可以在集群启动完成后关闭。同时需要注意的是并不推荐在集群启动完成后关闭作为管理节点的服务器。尽管理论上可以建立基于只有2台服务器的MySQL集群,但是这样的架构,一旦一台服务器宕机之后集群就无法继续正常工作了,这样也就失去了集群的意义了。出于这个原因,就需要有第三台服务器作为管理节点运行。
另外,可能很多朋友都没有3台服务器的实际环境,可以考虑在VMWare或其他虚拟机中进行实验。
下面假设这3台服务的情况:
Server1: mysql1.vmtest.net 192.168.0.1
Server2: mysql2.vmtest.net 192.168.0.2
Server3: mysql3.vmtest.net 192.168.0.3
Servers1和Server2作为实际配置MySQL集群的服务器。对于作为管理节点的Server3则要求较低,只需对Server3的系统进行很小的调整并且无需安装MySQL,Server3可以使用一台配置较低的计算机并且可以在Server3同时运行其他服务。
二、在Server1和Server2上安装MySQL
=================================
从http://www.mysql.com上下载mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
注意:必须是max版本的MySQL,Standard版本不支持集群部署!
以下步骤需要在Server1和Server2上各做一次
# mv mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz /usr/local/
# cd /usr/local/
# groupadd mysql
# useradd -g mysql mysql
# tar -zxvf mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
# rm -f mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
# mv mysql-max-4.1.9-pc-linux-gnu-i686 mysql
# cd mysql
# scripts/mysql_install_db --user=mysql
# chown -R root .
# chown -R mysql data
# chgrp -R mysql .
# cp support-files/mysql.server /etc/rc.d/init.d/mysqld
# chmod +x /etc/rc.d/init.d/mysqld
# chkconfig --add mysqld
此时不要启动MySQL!
三、安装并配置管理节点服务器(Server3)
=====================================
作为管理节点服务器,Server3需要ndb_mgm和ndb_mgmd两个文件:
从http://www.mysql.com上下载mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
# mkdir /usr/src/mysql-mgm
# cd /usr/src/mysql-mgm
# tar -zxvf mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
# rm mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
# cd mysql-max-4.1.9-pc-linux-gnu-i686
# mv bin/ndb_mgm .
# mv bin/ndb_mgmd .
# chmod +x ndb_mg*
# mv ndb_mg* /usr/bin/
# cd
# rm -rf /usr/src/mysql-mgm
现在开始为这台管理节点服务器建立配置文件:
# mkdir /var/lib/mysql-cluster
# cd /var/lib/mysql-cluster
# vi config.ini
在config.ini中添加如下内容:
[NDBD DEFAULT]
NoOfReplicas=2
[MYSQLD DEFAULT]
[NDB_MGMD DEFAULT]
[TCP DEFAULT]
# Managment Server
[NDB_MGMD]
HostName=192.168.0.3 #管理节点服务器Server3的IP地址
# Storage Engines
[NDBD]
HostName=192.168.0.1 #MySQL集群Server1的IP地址
DataDir= /var/lib/mysql-cluster
[NDBD]
HostName=192.168.0.2 #MySQL集群Server2的IP地址
DataDir=/var/lib/mysql-cluster
# 以下2个[MYSQLD]可以填写Server1和Server2的主机名。
# 但为了能够更快的更换集群中的服务器,推荐留空,否则更换服务器后必须对这个配置进行更改。
[MYSQLD]
[MYSQLD]
保存退出后,启动管理节点服务器Server3:
# ndb_mgmd
启动管理节点后应该注意,这只是管理节点服务,并不是管理终端。因而你看不到任何关于启动后的输出信息。
四、配置集群服务器并启动MySQL
=============================
在Server1和Server2中都需要进行如下改动:
# vi /etc/my.cnf
[mysqld]
ndbcluster
ndb-connectstring=192.168.0.3 #Server3的IP地址
[mysql_cluster]
ndb-connectstring=192.168.0.3 #Server3的IP地址
保存退出后,建立数据目录并启动MySQL:
# mkdir /var/lib/mysql-cluster
# cd /var/lib/mysql-cluster
# /usr/local/mysql/bin/ndbd --initial
# /etc/rc.d/init.d/mysqld start
可以把/usr/local/mysql/bin/ndbd加到/etc/rc.local中实现开机启动。
注意:只有在第一次启动ndbd时或者对Server3的config.ini进行改动后才需要使用--initial参数!
五、检查工作状态
================
回到管理节点服务器Server3上,并启动管理终端:
# /usr/bin/ndb_mgm
键入show命令查看当前工作状态:(下面是一个状态输出示例)
[root@mysql3 root]# /usr/bin/ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=2 @192.168.0.1 (Version: 4.1.9, Nodegroup: 0, Master)
id=3 @192.168.0.2 (Version: 4.1.9, Nodegroup: 0)
[ndb_mgmd(MGM)] 1 node(s)
id=1 @192.168.0.3 (Version: 4.1.9)
[mysqld(API)] 2 node(s)
id=4 (Version: 4.1.9)
id=5 (Version: 4.1.9)
ndb_mgm>
如果上面没有问题,现在开始测试MySQL:
注意,这篇文档对于MySQL并没有设置root密码,推荐你自己设置Server1和Server2的MySQL root密码。
在Server1中:
# /usr/local/mysql/bin/mysql -u root -p
> use test;
> CREATE TABLE ctest (i INT) ENGINE=NDBCLUSTER;
> INSERT INTO ctest () VALUES (1);
> SELECT * FROM ctest;
应该可以看到1 row returned信息(返回数值1)。
如果上述正常,则换到Server2上重复上面的测试,观察效果。如果成功,则在Server2中执行INSERT再换回到Server1观察是否工作正常。
如果都没有问题,那么恭喜成功!
六、破坏性测试
==============
将Server1或Server2的网线拔掉,观察另外一台集群服务器工作是否正常(可以使用SELECT查询测试)。测试完毕后,重新插入网线即可。
如果你接触不到物理服务器,也就是说不能拔掉网线,那也可以这样测试:
在Server1或Server2上:
# ps aux | grep ndbd
将会看到所有ndbd进程信息:
root 5578 0.0 0.3 6220 1964 ? S 03:14 0:00 ndbd
root 5579 0.0 20.4 492072 102828 ? R 03:14 0:04 ndbd
root 23532 0.0 0.1 3680 684 pts/1 S 07:59 0:00 grep ndbd
然后杀掉一个ndbd进程以达到破坏MySQL集群服务器的目的:
# kill -9 5578 5579
之后在另一台集群服务器上使用SELECT查询测试。并且在管理节点服务器的管理终端中执行show命令会看到被破坏的那台服务器的状态。
测试完成后,只需要重新启动被破坏服务器的ndbd进程即可:
# ndbd
注意!前面说过了,此时是不用加--inital参数的!
至此,MySQL集群就配置完成了!__________________________________ -
2005-12-20
Linux网络备份MYSQL(精彩)
转自:http://soft.yesky.com/os/lin/461/2164461.shtml
笔者是一个中小Linux网站的管理员,系统构架是:RHEL 4.0 + PHP 4.3 + Mysql 4.03 +Apache 1.23。日均IP访问量在200次,一个典型的Linux小型网站。由于是小型网站,所以没有经费使用磁带机进行系统备份,使用的DVD光盘刻录机+网络硬盘。随着Linux的应用日益广泛,特别是在网络应用方面,有大量的网络服务器使用Linux操作系统。由于Linux的桌面应用和Windows相比还有一定的差距,所以在企业应用中往往是Linux和Windows操作系统共存形成异构网络。在服务器端大多使用Linux和Unix的,PC端使用Windows 9X/2000/XP。
一、 本地备份
使用 mysqldump进行备份非常简单,如果要备份数据库” phpbb_db_backup ”,使用命令:
#mysqldump –u -p phpbb_db_backup > /usr/backups/mysql/ phpbb_db_backup.2005.5.6
还可以使用gzip命令对备份文件进行压缩:
#mysqldump phpbb_db_backup | gzip > /usr/backups/mysql/ phpbb_db_backup.2005.5.6。gz
恢复数据使用命令:
#mysql –u -p phpbb_db_backup
二、 备份数据到DVD盘片
随着MYSQL数据量的增大,使用传统CD—R来备份硬盘并不现实,采用CD—RW分卷制作实在太麻烦、磁带机对于中小企业又过于昂贵。另外各个应用程序的复杂度日与剧增, 处理的数据量也都相当庞大,Linux用户常常遇到的问题就是 : 有什么办法可以经济快捷的对数据做备份与保存。随着DVD刻录机和盘片的价格迅速降低,使用DVD刻录机用来备份Linux操作系统非常明智的。
1、安装
下面以IDE接口的内置刻录设备为例,介绍在Linux环境中使用DVD刻录机。Linux 需要将IDE接口的刻录设备虚拟为SCSI设备才能进行DVD刻录。2.4以上内核Linux发行版本包含了已编译进内核的 SCSI 仿真,所以只要对启动文件作一些小改动;USB或1394(FireWire)接口的外置刻录机就简单多了。
把DVD刻录机设备接入计算机第二个IDE接口(dev/hdc),开启电源。假设系统用Grub启动,用文本编辑器打开/boot/grub/grub.conf,找到以“kernel”开头的一行,在这行内容的未尾加入“hdc=ide-scsi”,例如:“kernel /vmlinuz-2.4.20-8 ro root=LABEL=/ hdc=ide-scsi”。
2、安装刻录软件
DVD+RW-Tools :一个包含有用于刻录DVD和映像的软件工具包,包括:Growisofs和dvd+rw-format。官方站点:http://fy.chalmers.se/~appro/linux/DVD+RW/ ,
CDRDAO :DAO即是Disk-At-Once(实时刻录),是一种在烧录过程中没有音轨间的两秒缓冲的刻录方法。它可以对磁盘的布局和磁道进行完全的控制,这一功能在刻录多来源的盘片相当有帮助。
cdrtools:包含了一套用于CD、DVD刻录的工具。Growisofs在创建映像时会使用这个软件包中的mkisofs工具,并且用户可以使用readcd来从一个现有的DVD上创建ISO映像。此外,Cdrecord应用程序可被用于扫描连接系统上的CD/DVD刻录机,并且可以使用它来将ISO映像刻录到CD—R(W)光盘上。通常大多数Linux版本包括这个软件,也可以下载使用:http://freshmeat.net/redir/cdrec ... epage/cdrecord.html
dvdrecord:命令行下的DVD刻录软件。命令行下的DVD刻录可用于很多种情形,比如当我们通过远程访问主机时,机器上的图形界面无法启动时,或者机器由于某些原因无法启动GUI时。此外,在完成一些备份等自动重复的功能时,也需要使用命令行工具。
以上介绍了一下必须的软件和相关下载网址,安装过程比较简单,这里就不赘述了。
3、命令行下刻录
使用DVD+RW-Tools 进行刻录工作
growisofs是DVD+RW-Tools一个工具,Growlsofs访问其刻录设备使用的是一种不同的方式。它使用/dev下面的Unix路径来连接刻录机。不同的系统和发行版中用于刻录机的路径不尽相同,所以最好的方法是查看发行版中的帮助。在一些系统中,一个名为/dev/dvd的软链接会被设置成指向可用的DVD刻录机,在本文中,使用/dev/dvd来指定刻录机,如果系统中路径设置不同,那么请使用合适的路径将其取代。
(1)格式化可读写DVD光盘
可以使用DVD+RW-Tools工具包中提供的dvd十rw—format命令。它有两种格式化DVD光盘的方式:快速模式、完全模式。快速模式:
#dvd+rw-format -blank /dev/dvd
完全模式:
#dvd+rw-format -blank=full /dev/dvd
(2)将文件存储至DVD刻录盘:
DVD和普通的光盘一样,使用的也是ISO9660文件系统,以及同样的通用扩展(Joliet和RockRidge)。Growlsofs提供了一种简单的将文件或目录存储至DVD刻录盘的方法。先用调用mkisofs工具来创建一个映像,并且无需在将该映像存储至硬盘之前就刻录下来。其基本的命令格式如下:
#growisofs -dvd-compat -Z /dev/dvd -J -R /path/to/home/cao
此命令将/path/to/home/cao目录下的文件制作一个映像并且刻录到的DVD光盘。
二、网络备份
将MYSQL数据放在一台计算机上是不安全的,所以应当把数据备份到局域网中其他计算机中。假设Mysql服务器IP地址是:192.168.1.3。局域网使用Linux的远程计算机IP地址是192.168.1.17;局域网使用Windows的远程计算机IP地址是192.168.1.18。网络拓扑见图1.
1. 通过NFS网络备份
类似于windows的网络共享,UNIX(Linux)系统也有自己的网络共享,那就是NFS(网络文件系统),在linux客户端挂接(mount)NFS磁盘共享之前,必须先配置好NFS服务端。linux系统NFS服务端配置方法如下:
(1)修改 /etc/exports,增加共享目录
/export/home/sunky 192.168.1.17(rw)
/export/home/sunky1 *(rw)
/export/home/sunky2 linux-client(rw)
注:/export/home/目录下的sunky、sunky1、sunky2是准备共享的目录,10.140.133.23、*、linux-client是被允许挂接此共享linux客户机的IP地址或主机名。如果要使用主机名linux-client必须在服务端主机/etc/hosts文件里增加linux-client主机ip定义。格式如下:
192.168.1.17 linux-client
若修改/etc/export文件增加新的共享,应先停止NFS服务,再启动NFS服务方能使新增加的共享起作用。使用命令exportfs -rv也可以达到同样的效果。linux客户端挂接(mount)其他linux系统或UNIX系统的NFS共享。这里我们假设192.168.1.17是NFS服务端的主机IP地址,当然这里也可以使用主机名,但必须在本机/etc/hosts文件里增加服务端ip定义。/export/home/sunky为服务端共享的目录。如此就可以在linux客户端通过/mnt/nfs来访问其它linux系统或UNIX系统以NFS方式共享出来的文件了。
把MYSQL数据备份到使用Linux的远程计算机需要在两端都安装NFS协议(Network File System),远程NFS计算机安装NFS协议后还要修改配置文件:/etc/exports,加入一行:
/usr/backups/mysql/ 192.168.1.17 (rw, no_root_squash)
表示将/usr/backups/mysql/目录共享。这个目录具有远程root用户读写权限。保存NFS配置文件,然后使用命令:
#exportfs -a –r
然后重新启动NFS服务:
#service nfsd start
远程计算机设定后,在MYSQL服务器/mnt 目录下建立一个backup_share目录:
#mkdir /mnt/backup_share
将远程的Linux计算机的/usr/backups/mysql/目录挂载到MYSQL服务器的/mnt/backup_share目录下:
# mount -t nfs 192.168.1.17:/usr/backups/mysql /mnt/backup_share
将目录挂载进来后,只要进入/mnt/backup_share 目录,就等于到了IP地址:192.168.1.7那部NFS 计算机的/usr/backups/mysql 目录中。下面使用mysqldump把“phpbb_db_backup”备份到远程计算机:
# mysqldump phpbb_db_backup > /mnt/backup_share/ phpbb_db_backup.2005-5-6
2. 通过Samba网络备份
Windows网络共享的核心是SMB/CIFS,在linux下要挂接(mount)windows的磁盘共享,就必须安装和使用samba软件包。现在流行的linux发行版绝大多数已经包含了samba软件包,如果安装linux系统时未安装samba请首先安装samba。当然也可以到www.samba.org网站下载samba软件包,现在最新的版本是3.0.10版。然后Windows计算机上建立一个目录(/arc)并且共享,赋予其读写权限。同样在MYSQL服务器/mnt 目录下建立一个backup_share1目录,然后进行挂载:
# mount -t smbfs -o username=cjh, password=XXXX //192.168.1.18/arc /mnt/backup_share
最后使用命令进行备份:
# mysqldump phpbb_db_backup > /mnt/backup_share/ phpbb_db_backup.2005-5-6 -
2005-12-20
MySql管理的一点心得
MySql数据库是中小型网站后台数据库的首选,因为它对非商业应用是免费的.网站开发者可以搭建一个"Linux+Apache+PHP+MySql" 平台,这是一个最省钱的高效平台.在使用MySql进行开发时,MySql自带的文档对于新手来说是份很好的参考资料.本文是我在使用MySql中的小小心得。
当前一般用户的开发环境多是Windows或Linux,用户可以到http://www.mysql.com下载相关版本进行安装,在 windows中MySql以服务形式存在,在使用前应确保此服务已经启动,未启动可用net start mysql命令启动。而Linux中启动时可用“/etc/rc.d/init.d/mysqld start"命令,注意启动者应具有管理员权限。
刚安装好的MySql包含一个含空密码的root帐户和一个匿名帐户,这是很大的安全隐患,对于一些重要的应用我们应将安全性尽可能提高,在这里应把匿名帐户删除、 root帐户设置密码,可用如下命令进行:
use mysql;
delete from User where User="";
update User set Password=PASSWORD('newpassword') where User='root';
如果要对用户所用的登录终端进行限制,可以更新User表中相应用户的Host字段,在进行了以上更改后应重新启动数据库服务,此时登录时可用如下类似命令:
mysql -uroot -p;
mysql -uroot -pnewpassword;
mysql mydb -uroot -p;
mysql mydb -uroot -pnewpassword;
上面命令参数是常用参数的一部分,详细情况可参考文档。此处的mydb是要登录的数据库的名称。
在进行开发和实际应用中,用户不应该只用root用户进行连接数据库,虽然使用root用户进行测试时很方便,但会给系统带来重大安全隐患,也不利于管理技术的提高。我们给一个应用中使用的用户赋予最恰当的数据库权限。如一个只进行数据插入的用户不应赋予其删除数据的权限。MySql的用户管理是通过 User表来实现的,添加新用户常用的方法有两个,一是在User表插入相应的数据行,同时设置相应的权限;二是通过GRANT命令创建具有某种权限的用户。其中GRANT的常用用法如下:
grant all on mydb.* to NewUserName@HostName identified by "password" ;
grant usage on *.* to NewUserName@HostName identified by "password";
grant select,insert,update on mydb.* to NewUserName@HostName identified by "password";
grant update,delete on mydb.TestTable to NewUserName@HostName identified by "password";
若要给此用户赋予他在相应对象上的权限的管理能力,可在GRANT后面添加WITH GRANT OPTION选项。而对于用插入User表添加的用户,Password字段应用PASSWORD 函数进行更新加密,以防不轨之人窃看密码。对于那些已经不用的用户应给予清除,权限过界的用户应及时回收权限,回收权限可以通过更新User表相应字段,也可以使用REVOKE操作。
下面给出本人从其它资料(www.cn-java.com)获得的对常用权限的解释:
全局管理权限:
FILE: 在MySQL服务器上读写文件。
PROCESS: 显示或杀死属于其它用户的服务线程。
RELOAD: 重载访问控制表,刷新日志等。
SHUTDOWN: 关闭MySQL服务。
数据库/数据表/数据列权限:
ALTER: 修改已存在的数据表(例如增加/删除列)和索引。
CREATE: 建立新的数据库或数据表。
DELETE: 删除表的记录。
DROP: 删除数据表或数据库。
INDEX: 建立或删除索引。
INSERT: 增加表的记录。
SELECT: 显示/搜索表的记录。
UPDATE: 修改表中已存在的记录。
特别的权限:
ALL: 允许做任何事(和root一样)。
USAGE: 只允许登录--其它什么也不允许做。
最后给出本人在RedHat9.0下的MySql操作演示:
选用数据库的root用户登录
[weiwen@weiwenlinux]$mysql -uroot -p
Enter password:MyPassword
mysql>create database mydb;
Query OK, 1 row affected (0.02 sec)
mysql>use mydb;
Database changed
mysql>create table TestTable(Id int aut_increment primary key,
UserName varchar(16) not null,
Address varchar(255));
Query OK, 0 rows affected (0.02 sec)
mysql>grant all on mydb.* to test@localhost identified by "test";
Query OK, 0 rows affected (0.01 sec)
mysql>quit
Bye
[weiwen@weiwenlinux]$mysql mydb -utest -ptest
其中test.sql是用vi编辑好的SQL脚本,其内容为:
Insert into TestTable(UserName,Address)values('Tom','shanghai');
Insert into TestTable(UserName,Address)values('John','beijing');
select * from TestTable;
运行已经编辑好的SQL脚本可以用source filename 或 . filename。
以上只是对新手的简单练习,要成为一个数据库好手,当以孜孜不倦地追求知识,不断地思考、尝试、再思考。







