MySQL
# rpm -qa | grep sql
如需卸载系统默认安装的mysql:
# rpm -e --nodeps mysql-3.23.58-1
下载地址为:http://www.mysql.com/downloads/mysql-4.0.html, 打开此网页,下拉网页找到“Linux x86 RPM downloads”项,找到“Server”和“Client programs”项,找到“Server”和“Client programs”项,下载需要的上述两个rpm文件
安装服务器端和安装客户端
# rpm -ivh MySQL-server-5.1.7-0.i386.rpm MySQL-client-5.1.7-0.i386.rpm
# rpm -ivh MySQL-client-5.1.7-0.i386.rpm
MySQL安装完成后启动文件mysql在/etc/init.d目录下,在需要启动时运行下面命令即可。
# /etc/init.d/mysql start
停止:
# /usr/bin/mysqladmin -u root -p shutdown
自动启动
检查mysql是否在自动启动列表中
# /sbin/chkconfig --list
把MySQL添加到你系统的启动服务组里面去
# /sbin/chkconfig - add mysql
把MySQL从启动服务组里面删除。
# /sbin/chkconfig -del mysql
测试是否成功可运行netstat看Mysql端口是否打开,如打开表示服务已经启动,安装成功。Mysql默认的端口是3306。
# netstat -nat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
上面显示可以看出MySQL服务已经启动。
登录MySQL的命令是mysql, mysql的使用语法如下:
# mysql [-u username] [-h host] [-p[password]] [dbname]
username 与 password 分别是 MySQL 的用户名与密码,mysql的初始管理帐号是root,没有密码,注意:这个root用户不是Linux的系统用户。MySQL默认用户是root,由于初始没有密码,第一次进时只需键入mysql即可。
# mysql
增加了密码后的登录格式如下:
# mysql -u root -p
Enter password: (输入密码)
其中-u后跟的是用户名,-p要求输入密码,回车后在输入密码处输入密码。
注意:这个mysql文件在/usr/bin目录下,与后面讲的启动文件/etc/init.d/mysql不是一个文件。
默认目录
数据库目录: /var/lib/mysql/
配置文件: /usr/share/mysql(mysql.server命令及配置文件)
相关命令:/usr/bin(mysqladmin mysqldump等命令)
启动脚本:/etc/rc.d/init.d/(启动脚本文件mysql的目录)
MySQL默认的数据文件存储目录为/var/lib/mysql。假如要把目录移到/home/data下,需要进行下面几步:
1、home目录下建立data目录
2、把MySQL服务进程停掉:
# mysqladmin -u root -p shutdown
3、把/var/lib/mysql整个目录移到/home/data
# mv /var/lib/mysql /home/data/
这样就把MySQL的数据文件移动到了/home/data/mysql下
4、修改my.cnf配置文件
如果/etc/目录下没有my.cnf配置文件,请到/usr/share/mysql/下找到*.cnf文件,拷贝其中一个到/etc/并改名为my.cnf)中。命令如下:
# cp /usr/share/mysql/my-medium.cnf /etc/my.cnf
编辑MySQL的配置文件/etc/my.cnf
为保证MySQL能够正常工作,需要指明mysql.sock文件的产生位置。修改my.cnf:
# The MySQL server
[mysqld]
port = 3306
#socket= /var/lib/mysql/mysql.sock(原内容,为了更稳妥用“#”注释此行)
socket = /home/data/mysql/mysql.sock (加上此行)
5. 修改MySQL启动脚本/etc/rc.d/init.d/mysql
最后,需要修改MySQL启动脚本/etc/rc.d/init.d/mysql:
#datadir=/var/lib/mysql (注释此行)
datadir=/home/data/mysql (加上此行)
6. 重新启动MySQL服务
# /etc/rc.d/init.d/mysql start
MySQL默认没有密码,安装完毕增加密码:
# usr/bin/mysqladmin -u root password 'new-password'
测试是否修改成功,不用密码登录
# mysql
ERROR 1045: Access denied for user: 'root@localhost' (Using password: NO)
显示错误,说明密码已经修改。
用修改后的密码登录
# mysql -u root -p
Enter password: (输入修改后的密码123456)
这是通过mysqladmin命令修改口令,也可通过修改库来更改口令。
# /etc/init.d/mysql stop
# mysqld_safe --user=mysql --skip-grant-tables --skip-networking &
# mysql -u root mysql
mysql> UPDATE user SET Password=PASSWORD('newpassword') where USER='root';
mysql> FLUSH PRIVILEGES;
mysql> quit
# /etc/init.d/mysql restart
# mysql -uroot –p
Enter password: <输入新设的密码newpassword>
mysql>
注意:MySQL中每个命令后都要以分号;结尾。
Hierarchy: database –> tables -> records;
l 显示所有库:
# mysql> show databases;
Mysql刚安装完有两个数据库:mysql和test。Mysql库非常重要,它里面有MySQL的系统信息,我们改密码和新增用户,实际上就是用这个库中的相关表进行操作。
l 建库:
# mysql> create databases db_name;
l 删库:
# mysql>drop database 库名;
l 打开库:
# mysql> use db_name;
l Show tables:
# mysql> use mysql; (打开库,对每个库进行操作就要打开此库)
# mysql> show tables;
l show table structure:
# mysql>describe 表名;
l Create tables:
# mysql> use 库名;
# mysql> create table 表名 (字段设定列表);
例如:在刚创建的aaa库中建立表name,表中有id(序号,自动增长),xm(姓名),xb(性别),csny(出身年月)四个字段
# mysql>use aaa;
# mysql>create table name (id int(3) auto_increment not null primary key, xm char(8),xb char(2),csny date);
可以用describe命令察看刚建立的表结构。
# mysql> describe name;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| id | int(3) | | PRI | NULL | auto_increment |
| xm | char(8) | YES | | NULL | |
| xb | char(2) | YES | | NULL | |
| csny | date | YES | | NULL | |
+-------+---------+------+-----+---------+----------------+
l Delete tables:
# mysql> drop table 表名;
l Show Table Record:
# mysql>select * from 表名;
例如:显示mysql库中user表中的纪录。所有能对MySQL用户操作的用户都在此表中。
# mysql>select * from user;
l Add record
例如:增加几条相关纪录。
# mysql> insert into name values('','张三','男','1971-10-01');
# mysql> insert into name values('','白云','女','1972-05-20');
验证结果:
# mysql> select * from name;
+----+------+------+------------+
| id | xm | xb | csny |
+----+------+------+------------+
| 1 | 张三 | 男 | 1971-10-01 |
| 2 | 白云 | 女 | 1972-05-20 |
+----+------+------+------------+
l modify record
例如:将张三的出生年月改为1971-01-10
# mysql> update name set csny='1971-01-10' where xm='张三';
l delete record
例如:删除张三的纪录。
# mysql> delete from name where xm='张三';
# 格式:grant select on 数据库.* to 用户名@登录主机 identified by "密码"
l 开一个可以在远程任意妄为的用户:
# mysql>grant all privileges on *.* to user_name@'%' identified by 'passwd '
l 开一个本地的用户:
# mysql>grant all privileges on *.* to user_name@'localhost ' identified by 'passwd '
例:
增加一个用户user_1密码为123,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入MySQL,然后键入以下命令:
# mysql> grant select,insert,update,delete on *.* to user_1@"% " Identified by "123";
增加的用户是十分危险的,如果知道了user_1的密码,那么他就可以在网上的任何一台电脑上登录你的MySQL数据库并对你的数据为所欲为了,解决办法同下面的user_2:
增加一个用户user_2密码为123, 让此用户只可以在localhost上登录,并可以对数据库aaa进行查询、插入、修改、删除的操作(localhost指本地主机,即MySQL数据库所在的那台主机),这样用户即使用知道user_2的密码,他也无法从网上直接访问数据库,只能通过 MYSQL主机来操作aaa库。
# mysql>grant select,insert,update,delete on aaa.* to user_2@localhost identified by "123";
用新增的用户如果登录不了MySQL,在登录时用如下命令:
# mysql -u user_1 –p -h 192.168.113.50 (-h后跟的是要登录主机的ip地址)
目前 MySQL 支持的免费备份工具有:
l Mysqldump
l mysqlhotcopy
l SQL 语法备份:BACKUP TABLE或者SELECT INTO OUTFILE
l 备份二进制日志(binlog)
l 直接拷贝数据文件和相关的配置文件
MyISAM 表是保存成文件的形式,因此相对比较容易备份,上面提到的几种方法都可以使用。
Innodb 所有的表都保存在同一个数据文件 ibdata1 中(也可能是多个文件,或者是独立的表空间文件),相对来说比较不好备份,免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump。
mysqldump 是采用SQL级别的备份机制,它将数据表导成 SQL 脚本文件,在不同的 MySQL 版本之间升级时相对比较合适,这也是最常用的备份方法。现在来讲一下 mysqldump 的一些主要参数:
--compatible=name它告诉 mysqldump,导出的数据将和哪种数据库或哪个旧版本的 MySQL 服务器相兼容。值可以为 ansi、mysql323、mysql40、postgresql、oracle、mssql、db2、maxdb、no_key_options、no_tables_options、no_field_options 等,要使用几个值,用逗号将它们隔开。当然了,它并不保证能完全兼容,而是尽量兼容。
--complete-insert,-c导出的数据采用包含字段名的完整 INSERT 方式,也就是把所有的值都写在一行。这么做能提高插入效率,但是可能会受到 max_allowed_packet 参数的影响而导致插入失败。因此,需要谨慎使用该参数,至少我不推荐。
--default-character-set=charset指定导出数据时采用何种字符集,如果数据表不是采用默认的 latin1 字符集的话,那么导出时必须指定该选项,否则再次导入数据后将产生乱码问题。
--disable-keys告诉 mysqldump 在 INSERT 语句的开头和结尾增加 /*!40000 ALTER TABLE table DISABLE KEYS */; 和 /*!40000 ALTER TABLE table ENABLE KEYS */; 语句,这能大大提高插入语句的速度,因为它是在插入完所有数据后才重建索引的。该选项只适合 MyISAM 表。
--extended-insert = true|false默认情况下,mysqldump 开启 --complete-insert 模式,因此不想用它的的话,就使用本选项,设定它的值为 false 即可。
--hex-blob使用十六进制格式导出二进制字符串字段。如果有二进制数据就必须使用本选项。影响到的字段类型有 BINARY、VARBINARY、BLOB。
--lock-all-tables,-x在开始导出之前,提交请求锁定所有数据库中的所有表,以保证数据的一致性。这是一个全局读锁,并且自动关闭 --single-transaction 和 --lock-tables 选项。
--lock-tables它和 --lock-all-tables 类似,不过是锁定当前导出的数据表,而不是一下子锁定全部库下的表。本选项只适用于 MyISAM 表,如果是 Innodb 表可以用 --single-transaction 选项。
--no-create-info,-t只导出数据,而不添加 CREATE TABLE 语句。
--no-data,-d不导出任何数据,只导出数据库表结构。
--opt这只是一个快捷选项,等同于同时添加 --add-drop-tables --add-locking --create-option disable-keys --extended-insert --lock-tables --quick --set-charset 选项。本选项能让 mysqldump 很快的导出数据,并且导出的数据能很快导回。该选项默认开启,但可以用 --skip-opt 禁用。注意,如果运行 mysqldump 没有指定 --quick 或 --opt 选项,则会将整个结果集放在内存中。如果导出大数据库的话可能会出现问题。
--quick,-q该选项在导出大表时很有用,它强制 mysqldump 从服务器查询取得记录直接输出而不是取得所有记录后将它们缓存到内存中。
--routines,-R导出存储过程以及自定义函数。
--single-transaction该选项在导出数据之前提交一个 BEGIN SQL语句,BEGIN 不会阻塞任何应用程序且能保证导出时数据库的一致性状态。它只适用于事务表,例如 InnoDB 和 BDB。本选项和 --lock-tables 选项是互斥的,因为 LOCK TABLES 会使任何挂起的事务隐含提交。要想导出大表的话,应结合使用 --quick 选项。
--triggers同时导出触发器。该选项默认启用,用 --skip-triggers 禁用它。
其他参数详情请参考手册
通常使用以下SQL来备份MyISAM 表:
# /usr/local/mysql/bin/mysqldump –uyejr –pyejr --default-character-set=utf8 --opt --extended-insert=false --triggers -R --hex-blob -x db_name > db_name.sql
使用以下SQL来备份Innodb表:
# /usr/local/mysql/bin/mysqldump -uyejr -pyejr --default-character-set=utf8 --opt --extended-insert=false --triggers -R --hex-blob --single-transaction db_name > db_name.sql
另外,如果想要实现在线备份,还可以使用 --master-data 参数来实现,如下:
# /usr/local/mysql/bin/mysqldump -uyejr -pyejr --default-character-set=utf8 --opt --master-data=1 --single-transaction --flush-logs db_name > db_name.sql
它只是在一开始的瞬间请求锁表,然后就刷新binlog了,而后在导出的文件中加入CHANGE MASTER 语句来指定当前备份的binlog位置,如果要把这个文件恢复到slave里去,就可以采用这种方法来做。
用 mysqldump 备份出来的文件是一个可以直接倒入的 SQL 脚本,有两种方法可以将数据导入。
直接用 mysql 客户端例如:
# /usr/local/mysql/bin/mysql -uyejr -pyejr db_name < db_name.sql
用 SOURCE 语法, 其实这不是标准的 SQL 语法,而是 mysql 客户端提供的功能,例如:
# mysql>SOURCE /tmp/db_name.sql
这里需要指定文件的绝对路径,并且必须是 mysqld 运行用户(例如 nobody)有权限读取的文件。
mysqlhotcopy 是一个 PERL 程序,最初由Tim Bunce编写。它使用 LOCK TABLES、FLUSH TABLES 和 cp 或 scp 来快速备份数据库。
它是备份数据库或单个表的最快的途径,但它只能运行在数据库文件(包括数据表定义文件、数据文件、索引文件)所在的机器上。
mysqlhotcopy 只能用于备份 MyISAM,并且只能运行在类Unix 和 NetWare 系统上。
mysqlhotcopy 支持一次性拷贝多个数据库,同时还支持正则表达。以下是几个例子:
# /usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr db_name /tmp
(把数据库目录 db_name 拷贝到 /tmp 下)
# /usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr db_name_1 ... db_name_n /tmp
# /usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr db_name./regex/ /tmp
更详细的使用方法请查看手册,或者调用下面的命令来查看 mysqlhotcopy 的帮助:
# perldoc /usr/local/mysql/bin/mysqlhotcopy
注意,想要使用 mysqlhotcopy,必须要有 SELECT、RELOAD(要执行 FLUSH TABLES) 权限,并且还必须要能够有读取 datadir/db_name 目录的权限。
mysqlhotcopy 备份出来的是整个数据库目录,使用时可以直接拷贝到 mysqld 指定的 datadir (在这里是 /usr/local/mysql/data/)目录下即可,同时要注意权限的问题,如下例:
root#cp -rf db_name /usr/local/mysql/data/ root#chown -R nobody:nobody /usr/local/mysql/data/
(将 db_name 目录的属主改成 mysqld 运行用户)
BACKUP TABLE 语法其实和 mysqlhotcopy 的工作原理差不多,都是锁表,然后拷贝数据文件。它能实现在线备份,但是效果不理想,因此不推荐使用。
它只拷贝表结构文件和数据文件,不同时拷贝索引文件,因此恢复时比较慢。
例子:
# BACK TABLE tbl_name TO '/tmp/db_name/'
注意,必须要有 FILE 权限才能执行本SQL,并且目录 /tmp/db_name/ 必须能被 mysqld 用户可写,导出的文件不能覆盖已经存在的文件,以避免安全问题。
SELECT INTO OUTFILE 则是把数据导出来成为普通的文本文件,可以自定义字段间隔的方式,方便处理这些数据。
例子:
# SELECT * INTO OUTFILE '/tmp/db_name/tbl_name.txt' FROM tbl_name
注意,必须要有 FILE 权限才能执行本SQL,并且文件 /tmp/db_name/tbl_name.txt 必须能被 mysqld 用户可写,导出的文件不能覆盖已经存在的文件,以避免安全问题。
用 BACKUP TABLE 方法备份出来的文件,可以运行 RESTORE TABLE 语句来恢复数据表。
例子:
# RESTORE TABLE FROM '/tmp/db_name/'
权限要求类似上面所述。
用 SELECT INTO OUTFILE 方法备份出来的文件,可以运行 LOAD DATA INFILE 语句来恢复数据表。
例子:
# LOAD DATA INFILE '/tmp/db_name/tbl_name.txt' INTO TABLE tbl_name
权限要求类似上面所述。倒入数据之前,数据表要已经存在才行。如果担心数据会发生重复,可以增加 REPLACE 关键字来替换已有记录或者用 IGNORE 关键字来忽略他们。
采用 binlog 的方法相对来说更灵活,省心省力,而且还可以支持增量备份。
启用 binlog 时必须要重启 mysqld。
首先,关闭 mysqld,打开 my.cnf,加入以下几行:
# server-id = 1 log-bin = binlog log-bin-index = binlog.index
然后启动 mysqld 就可以了。
运行过程中会产生 binlog.000001 以及 binlog.index
前面的文件是 mysqld 记录所有对数据的更新操作,后面的文件则是所有 binlog 的索引,都不能轻易删除。
关于 binlog 的信息请查看手册。
需要备份时,可以先执行一下 SQL 语句,让 mysqld 终止对当前 binlog 的写入,就可以把文件直接备份,这样的话就能达到增量备份的目的了: FLUSH LOGS;
如果是备份复制系统中的从服务器,还应该备份 master.info 和 relay-log.info 文件。
备份出来的 binlog 文件可以用 MySQL 提供的工具 mysqlbinlog 来查看,如:
/usr/local/mysql/bin/mysqlbinlog /tmp/binlog.000001
该工具允许你显示指定的数据库下的所有 SQL 语句,并且还可以限定时间范围,相当的方便,详细的请查看手册。
恢复时,可以采用类似以下语句来做到:
# /usr/local/mysql/bin/mysqlbinlog /tmp/binlog.000001 | mysql -uyejr -pyejr db_name
把 mysqlbinlog 输出的 SQL 语句直接作为输入来执行它。 如果你有空闲的机器,不妨采用这种方式来备份。
由于作为 slave 的机器性能要求相对不是那么高,因此成本低,用低成本就能实现增量备份而且还能分担一部分数据查询压力,何乐而不为呢?
相较前几种方法,备份数据文件最为直接、快速、方便,缺点是基本上不能实现增量备份。
为了保证数据的一致性,需要在靠背文件前,执行以下 SQL 语句:
# FLUSH TABLES WITH READ LOCK;
也就是把内存中的数据都刷新到磁盘中,同时锁定数据表,以保证拷贝过程中不会有新的数据写入。
这种方法备份出来的数据恢复也很简单,直接拷贝回原来的数据库目录下即可。
注意,对于 Innodb 类型表来说,还需要备份其日志文件,即 ib_logfile* 文件。因为当 Innodb 表损坏时,就可以依靠这些日志文件来恢复。
对于中等级别业务量的系统来说,备份策略可以这么定:
第一次全量备份,每天一次增量备份
每周再做一次全量备份,如此一直重复。
而对于重要的且繁忙的系统来说,则可能需要每天一次全量备份,每小时一次增量备份,甚至更频繁。为了不影响线上业务,实现在线备份,并且能增量备份,最好的办法就是采用主从复制机制(replication),在 slave 机器上做备份。
为保证数据表能安全、稳定、高速使用,需要定期维护数据表。
以下 SQL 语句就很有用:
CHECK TABLE 或 REPAIR TABLE,检查或维护 MyISAM 表
OPTIMIZE TABLE,优化 MyISAM 表
ANALYZE TABLE,分析 MyISAM 表
当然了,上面这些命令起始都可以通过工具 myisamchk 来完成,在这里不作详述。
Innodb 表则可以通过执行以下语句来整理碎片,提高索引速度:
# ALTER TABLE tbl_name ENGINE = Innodb;
这其实是一个 NULL 操作,表面上看什么也不做,实际上重新整理碎片了。
通常使用的 MyISAM 表可以用上面提到的恢复方法来完成。如果是索引坏了,可以用 myisamchk 工具来重建索引。而对于 Innodb 表来说,就没这么直接了,因为它把所有的表都保存在一个表空间了。
不过 Innodb 有一个检查机制叫 模糊检查点,只要保存了日志文件,就能根据日志文件来修复错误。可以在 my.cnf 文件中,增加以下参数,让 mysqld 在启动时自动检查日志文件:
innodb_force_recovery = 4
关于该参数的信息请查看手册。
# mysql > insert into db2.tb2 (field1, field2, ....) (select field1, field2, .... from db1.tb1)
# mysql > insert into ... select distinct * from ( (select * from t1) union (select * from t2) )
union: 联合
intersect: 取公共部分
minus 减, 效率低
使用WHERE从句来选择您需要的记录导出到文件中。要达到这样的目的,可以使用类似于下面的命令:
# mysqldump –p –where="Order_ID > 2000" Meet_A_Geek Orders > Special_Dump.txt
1. 将需要插入数据的表重命名
# ALTER TABLE users RENAME TO test_users;
2. 导入提供数据的表.
# SOURCE users.sql; (users.sql 包含提供数据的表, 此表名为 users)
3. 插入缺失的数据
# INSERT INTO test_users SELECT * FROM users WHERE users.name NOT IN (SELECT name FROM test_users);
(这里说明一下这个是插入的相对表段的内容,也就是说你的字段的数量是一样的,如果不一样就不能用这条了,后边的where只是一个简单的判断你可以自己更改)
# INSERT INTO test_users(filename1,filename2,…….) SELECT filename1,filename2,…FROM users WHERE users.name NOT IN (SELECT name FROM test_users);
4. 删除提供数据的表
# DROP TABLE users;
5. 重命名插完数据的表
# ALTER TABLE test_users RENAME TO users;
例如合并两个结构完全相同的论坛数据库,将a数据库加入到b数据库中。这其中最难的就是怎么解决自动递增的id字段的问题,例如topic表中的id字段。因为id字段通常是主键,是唯一的。a数据库和b数据库可能存在id字段重复的问题。
我们可以用下面的方法解决这个问题: 首先:
a数据库:
# update `a`.`topic` set id=id+1000;
这里的1000只是示例,应该取b数据库的topic表中id字段的最大值,例如最大的id为1000,就应该用id+1000,当然也可以取得更大一些。 这样两个数据库的topic表就不存在id字段重复的问题了。 如果在其他表中调用了id字段,用同样的方法: update `a`.`tablename` set id=id+1000;
后面的任务就很简单了,导出a数据库的topic表,再导入b数据库的topic表,就OK了。
# INSERT INTO `b`.`topic` SELECT * FROM `a`.`topic` ;
Show create table user;
Alter table user drop foreign key fk_card id;