mysql basic operation,mysql总结,对mysql常用语句的详细总结,MySQL学习笔记

mysql> select * from wifi_data where dev_id like "0023-AABBCCCCBBAA" ;

一、显示数据库列表。
show databases;
刚开始时才两个数据库:mysql和test。mysql库很重要它里面有MYSQL的系统信息,咱们改密码和新增用户,实际上就是用这个库进行操做。

二、显示库中的数据表:
use mysql; //打开库,学过FOXBASE的必定不会陌生吧
show tables;

三、显示数据表的结构:
describe 表名;

四、建库:
create database 库名;

五、建表:
use 库名;
create table 表名 (字段设定列表);
以下:
CREATE TABLE `wifi_test` (
 `dev_id` varchar(30) NOT NULL default '' COMMENT '设备ID',
 `timestamp` varchar(50) NOT NULL default '' COMMENT '时间',
 `interval` tinyint(1) NOT NULL default '1' COMMENT '上传间隔',
 PRIMARY KEY  (`dev_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


六、删库和删表:
drop database 库名;
drop table 表名;

七、将表中记录清空:
delete from 表名;

八、显示表中的记录:
select * from 表名;

九、表数据中的增删改查
(所有插入)insert into 表名 valus('','',……,'');
(部分插入)insert into 表名(列x,列y,……,列z) valus('','',……,'');
insert into wifi_test values("1234567890ab","201506161330","300");
insert into wifi_test values("1234567890ad","201506161332",0);
 insert into wifi_test(dev_id,timestamp) values("1234567890ag","201506181405");
 insert into wifi_test(timestamp) values("201506181505");
select * from wifi_test;



10.向表中删除行数据:
delect from 表名;(清空表)
delect from 表名 where [检索条件表达式]
delete from wifi_test where dev_id=1234567890ab;
delete from table_xx where catch_time LIKE '2016-07-14 20:22:%';
 

11.修改,更改表中的数据:
update 表名 set 列名='表达式' [from 另外一表名] where [检索条件表达式];
update wifi_test set interval='300' where dev_id=1234567890ag;
update wifi_test set interval=replace(interval,127,80);
 update wifi_test set timestamp=20150618143333 where dev_id;


update语法
Single-table语法:
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]
    [ORDER BY ...]
    [LIMIT row_count]
Multiple-table语法:
UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET col_name1=expr1 [, col_name2=expr2 ...]
    [WHERE where_definition]

UPDATE语法能够用新值更新原有表行中的各列。SET子句指示要修改哪些列和要给予哪些值。WHERE子句指定应更新哪些行。若是没有WHERE子句,则更新全部的行。若是指定了ORDER BY子句,则按照被指定的顺序对行进行更新。LIMIT子句用于给定一个限值,限制能够被更新的行的数目。

若是您在一个表达式中经过tbl_name访问一列,则UPDATE使用列中的当前值。例如,如下语句把年龄列设置为比当前值多一:
UPDATE persondata SET age=age+1;
UPDATE赋值被从左到右评估。例如,如下语句对年龄列加倍,而后再进行增长:
UPDATE persondata SET age=age*2, age=age+1;
若是您把一列设置为其当前含有的值,则MySQL会注意到这一点,但不会更新。
update表的某些字段为null
update person set number=null,name=null;
若是您把被已定义为NOT NULL的列更新为NULL,则该列被设置到与列类型对应的默认值,而且累加警告数。对于数字类型,默认值为0;对于字符串类型,默认值为空字符串('');对于日期和时间类型,默认值为“zero”值。

多个表的UPDATE操做
UPDATE items,month SET items.price=month.price WHERE items.id=month.id;
以上的例子显示出了使用逗号操做符的内部联合,可是multiple-table UPDATE语句能够使用在SELECT语句中容许的任何类型的联合,好比LEFT JOIN,可是您不能把ORDER BY或LIMIT与multiple-table UPDATE同时使用。



12.查询表中的数据:select          */表字段1,表字段2,……表字段n     from 表名 【where 查询条件】;
mysql> select * from student;
mysql> select * from student where id=1;
mysql> select id,name from student;
mysql> select id,name from student where id in(1,3,4);//in表示集合。php

 

 //看当前使用的是哪一个数据库 ,若是你还没选择任何数据库,结果是NULL。
mysql>select database();
+------------+
| DATABASE() |
+------------+
| menagerie  |
+------------+

//查看有哪些数据库
 mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
+--------------------+

//选择数据库
mysql>use test;  //;号无关紧要,必须单行使用.  

为了找出当前的数据库包含什么表(例如,当你不能肯定一个表的名字),使用这个命令:

//看数据库里有哪些表
mysql>show tables;
+---------------------+
| Tables in menagerie |
+---------------------+
| event               |
| pet                 |
+---------------------+
若是你想要知道一个表的结构,能够使用DESCRIBE命令;它显示表中每一个列的信息:

//看表里有哪些列
mysql> describe pet;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name    | varchar(20) | YES  |     | NULL    |       |
| owner   | varchar(20) | YES  |     | NULL    |       |
| species | varchar(20) | YES  |     | NULL    |       |
| ***     | char(1)     | YES  |     | NULL    |       |
| birth   | date        | YES  |     | NULL    |       |
| death   | date        | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
Field显示列名字,Type是列的数据类型,Null表示列是否能包含NULL值,Key显示列是否被索引而Default指定列的默认值。

若是表有索引,SHOW INDEX FROM tbl_name生成有关索引的信息。

删除数据库.
mysql>drop database test;  





 如先输入mysql,成功启动后输入use mysql,出现以下错误:Access denied for user ''@'localhost' to database 'mysql'
还有,输mysql能够,输mysql -u root就出错了:
Access denied for user 'root'@'localhost' (using password: NO).
The reason is:
是昨日更新ROOT密码时出错
update user set password = '123456' where user ="root" //这样写是错的,密码其实不是123456
应该为update user set password = password ('123456') where user = "root"
具体操做步骤:
关闭mysql:
# service mysqld stop
而后:
# mysqld_safe --skip-grant-tables(该命令完成后,可能终端不会提示输入下一命令,下面命令在新开的终端中实现)
启动mysql:
# service mysqld start
mysql -u root
mysql> use mysql
mysql> UPDATE user SET Password=PASSWORD('xxx') WHERE user='root';
mysql> flush privileges;
mysql>\q




ERROR 1044 (42000): Access denied for user ''@'localhost' to database
 解决 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) 问题
最近新装好的mysql在进入mysql工具时,老是有错误提示:
# mysql -u root -p
Enter password:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
或者
# mysql -u root -p password 'newpassword'
Enter password:
mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: YES)'
如今终于找到解决方法了。原本准备重装的,如今没必要了。
方法操做很简单,以下:
# /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' and host='root' or host='localhost';//把空的用户密码都修改为非空的密码就好了。
mysql> FLUSH PRIVILEGES;
mysql> quit # /etc/init.d/mysqld restart
# mysql -uroot -p
Enter password: <输入新设的密码newpassword>


html

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)前端

此问题是没有开启mysqld服务.mysql




  root 用户的 create_priv 权限是否被设置为N了?


在建立数据库时报错
mysql> create database haha;
ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'haha' mysql>  
解决方案:这是由于在mysql的usr表中,存在用户名为空的帐户,虽然登录时用的是root,可是匿名登录。删除user.user中值为NULL的,或更新NULL为test 1)delete from user where user is NULL
2)update user set user='test' where user is NULL





ERROR 1044 (42000): Access denied for user 'root'@'%' to database
我这里root有三种解析登陆方式分别是:Host: bidevedw\_db、Host: ::一、Host: %
通常状况还有Host:127.0.0.一、Host:localhost个人里面把哪两种删了。
请注意 !
 注意上面每条记录的的红色字体部分Grant_priv: Y
这个表示,以这种方式解析登陆的root用户,是否有grant权限,Y则表示有受权限给其余用户的权限,N表示没有。
这里刚好,就是咱们要找的缘由,由于个人/my.cnf文件里面有skip-name-resolve参数,因此root都是解析到@'%'方式登陆,因而就没有grant_priv权限。

解决方法:
一、在不重启MySQL服务的状况下,只须要在登陆的时候加上-h参数。
例如:(a). /usr/local/mysql/bin/mysql -uroot -p123456 -h::1
         (b)./usr/local/mysql/bin/mysql -uroot -p123456 -h127.0.0.1
二、须要重启MySQL。把skip-name-resolve参数去掉  ---- 还没验证。不过我记得,若是去掉了,日志里面会有大量的警告信息。我是由于那些警告信息,才添加的这个参数。





use testdb;
简单描述表结构,字段类型:
desc tb_content;

查看表生成的DDL,这个命令虽然显示起来不是太容易看, 这个不是问题能够用\G来结尾,使得结果容易阅读;该命令把建立表的DDL显示出来,因而表结构、类型,外键,备注所有显示出来了。我比较喜欢这个命令:输入简单,显示结果全面。
show create table tb_content;

查询表中列的注释信息
select * from information_schema.columns where table_schema = 'testdb';
select * from information_schema.columns where table_schema = 'testdb' and table_name = 'tb_content';

只查询列名和注释
select  column_name, column_comment from information_schema.columns where table_schema ='testdb'  and table_name = 'tb_content' ;

查看当前使用的数据库:
mysql>select database();
mysql>status;










 
修改root密码
mysql> use mysql
Database changed
mysql> update user set password=PASSWORD('123456') where user='root';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)


查看全部用户密码:
SELECT User, Password, Host FROM user;


windows添加防火墙端口:
.须要设置防火墙放开mysql 3306端口的访问,控制面板->windows防火墙->高级设置,打开另外一个界面,
  在该界面中选择入站规则,而后在右边栏选择 新建规则,下一步选择端口,下一步选择TCP/特定本地端口并输入3306,下一步选择容许链接,下一步默认选择,下一步输入你想给的名称好比mysqlport,而后点击完成。
打开防火墙,选择例外选项卡,添加端口
名称:mysqlport
端口号:3306
选中TCP
  设置好后,务必从新启动计算机


iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT
打开防火墙配置文件可查看当前防火墙状况:vi  /etc/sysconfig/iptables
iptables-save
sudo service iptables save
iptables-save, service iptables save 做用同样,只不过iptables-save须要手动指定路径及文件名,而service iptables save的文件为/etc/sysconfig/iptables
注意:增长的开放3306端口的语句必定要在icmp-host-prohibited以前



linux

 

 

 

CREATE TABLE tab2 AS (SELECT * FROM tab1)
这种作法表的存储引擎也会采用服务器默认的存储引擎而不是源表的存储引擎,此种复制方法把表的内容也一块儿复制过来了。正则表达式

CREATE TALBE tab2 ENGINE=MYISAM, CHARSET='UTF8' AS (SELECT * FROM tab1)
能够本身指定存储引擎和字符集,弥补方法一的不足算法

CREATE TABLE tab2 LIKE tab1
使用和tab1表相同的结构来建立一个新表,列名、数据类型、空指和索引也将复制,可是表的内容不会被复制。外键和专用的权限也没有被复制。sql

MySQL复制表结构及数据到新表
CREATE TABLE tab_new SELECT * FROM tab_oldshell

复制旧表的数据到新表(假设两个表结构同样)
INSERT INTO tab1 SELECT * FROM tab2数据库

复制旧表的数据到新表(假设两个表结构不同)
INSERT INTO tab1(字段1, 字段2, ...) SELECT 字段1, 字段2, ... FROM tab2

更改表名
ALTER TABLE employee RENAME TO staff

更改列类型
ALTER TABLE employee MODIFY COLUMN truename VARCHAR(10) NOT NULL DEFAULT ''

更改列名
ALTER TABLE employee CHANGE COLUMN truename employeename VARCHAR(10) NOT NULL DEFAULT ''

添加默认值
ALTER TABLE employee ALTER COLUMN truename SET DEFAULT ''

删除默认值
ALTER TABLE employee ALTER COLUMN truename DEOP DEFAULT


mysql修改表
表的结构以下:

mysql> show create table person;
| person | CREATE TABLE `person` (
`number` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`birthday` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
删除列:

ALTER TABLE person DROP COLUMN birthday;
添加列:

ALTER TABLE person ADD COLUMN birthday datetime;
修改列,把number修改成bigint:

ALTER TABLE person MODIFY number BIGINT NOT NULL;
或者是把number修改成id,类型为bigint:

ALTER TABLE person CHANGE number id BIGINT;

添加主键:

ALTER TABLE person ADD PRIMARY KEY (id);
删除主键:

ALTER TABLE person DROP PRIMARY KEY;
添加惟一索引:

ALTER TABLE person ADD UNIQUE name_unique_index (`name`);
为name这一列建立了惟一索引,索引的名字是name_unique_index.

 

添加普通索引:

ALTER TABLE person ADD INDEX birthday_index (`birthday`);

删除索引:

ALTER TABLE person DROP INDEX birthday_index;
ALTER TABLE person DROP INDEX name_unique_index;

禁用非惟一索引

ALTER TABLE person DISABLE KEYS;
ALTER TABLE...DISABLE KEYS让MySQL中止更新MyISAM表中的非惟一索引。

激活非惟一索引

ALTER TABLE person ENABLE KEYS;
ALTER TABLE ... ENABLE KEYS从新建立丢失的索引。

 

把表默认的字符集和全部字符列(CHAR, VARCHAR, TEXT)改成新的字符集:

ALTER TABLE person CONVERT TO CHARACTER SET utf8;
修改表某一列的编码

ALTER TABLE person CHANGE name name varchar(255) CHARACTER SET utf8;
仅仅改变一个表的默认字符集

ALTER TABLE person DEFAULT CHARACTER SET utf8;
修改表名

RENAME TABLE person TO person_other;
移动表到其余数据库

RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

 


在mysql中咱们对数据表字段的修改命令只要使用alter就能够了,下面我来给你们详细介绍mysql中修改表字段名/字段长度/字段类型等等一些方法介绍,有须要了解的朋友可参考。

先来看看经常使用的方法
MySql的简单语法,经常使用,却不容易记住。固然,这些Sql语法在各数据库中基本通用。下面列出:
1.增长一个字段
alter table user add COLUMN new1 VARCHAR(20) DEFAULT NULL; //增长一个字段,默认为空
alter table user add COLUMN new2 VARCHAR(20) NOT NULL;    //增长一个字段,默认不能为空
2.删除一个字段
alter table user DROP COLUMN new2;                //删除一个字段
3.修改一个字段
alter table user MODIFY new1 VARCHAR(10);            //修改一个字段的类型
alter table user CHANGE COLUMN new1 new4 varchar(512) default "";              //修改一个字段的名称,此时必定要从新指定该字段的类型

//主键
alter table tabelname add new_field_id int(5) unsigned default 0 not null auto_increment ,add primary key (new_field_id);
//增长一个新列
alter table t2 add d timestamp;
alter table infos add ex tinyint not null default ‘0′;
//删除列
alter table t2 drop column c;
//重命名列
alter table t1 change a b integer;
//改变列的类型
alter table t1 change b b bigint not null;
alter table infos change list list tinyint not null default ‘0′;
//重命名表
alter table t1 rename t2;
加索引
mysql> alter table tablename change depno depno int(5) not null;
mysql> alter table tablename add index 索引名 (字段名1[,字段名2 …]);
mysql> alter table tablename add index emp_name (name);
加主关键字的索引
mysql> alter table tablename add primary key(id);
加惟一限制条件的索引
mysql> alter table tablename add unique emp_name2(cardnumber);
删除某个索引
mysql>alter table tablename drop index emp_name;
增长字段:
mysql> ALTER TABLE table_name ADD field_name field_type;
修改原字段名称及类型:
mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type;
删除字段:
mysql> ALTER TABLE table_name DROP field_name;
mysql修改字段长度
alter table 表名 modify column 字段名 类型;
例如
数据库中user表 name字段是varchar(30)
能够用
alter table user modify column name varchar(50) ;

 

 

 

 


mysql更改表结构:添加、删除、修改字段、调整字段顺序
mysqltablenulluserlist
添加字段:

alter table `user_movement_log`
Add column GatewayId int not null default 0 AFTER `Regionid` (在哪一个字段后面添加)

删除字段:

alter table `user_movement_log` drop column Gatewayid

调整字段顺序:

ALTER TABLE `user_movement_log` CHANGE `GatewayId` `GatewayId` int not null default 0 AFTER RegionID

//主键

alter table tabelname add new_field_id int(5) unsigned default 0 not null auto_increment ,add primary key (new_field_id);

//增长一个新列

alter table t2 add d timestamp;
alter table infos add ex tinyint not null default '0';

//删除列

alter table t2 drop column c;

//重命名列

alter table t1 change a b integer;

//改变列的类型

alter table t1 change b b bigint not null;
alter table infos change list list tinyint not null default '0';

//重命名表

alter table t1 rename t2;

加索引

mysql> alter table tablename change depno depno int(5) not null;
mysql> alter table tablename add index 索引名 (字段名1[,字段名2 …]);
mysql> alter table tablename add index emp_name (name);

加主关键字的索引

mysql> alter table tablename add primary key(id);

加惟一限制条件的索引

mysql> alter table tablename add unique emp_name2(cardnumber);

删除某个索引

mysql>alter table tablename drop index emp_name;

修改表:

增长字段:

mysql> ALTER TABLE table_name ADD field_name field_type;

修改原字段名称及类型:

mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type;

删除字段:

mysql> ALTER TABLE table_name DROP field_name;

 

 

 


 

 


MySql表结构修改详解

修改表的语法
=========================
增长列[add 列名]
=========================
①alter table 表名 add 列名 列类型 列参数【加的列在表的最后面】
例:alter table test add username char(20) not null default '';
alter table test add birth date not null default '0000-00-00';

②alter table 表名 add 列名 列类型 列参数 after 某列【把新列加在某列后面】
例:alter table test add gender char(1) not null default '' after username;

③alter table 表名 add 列名 列类型 列参数 first【把新列加在最前面】
例:alter table test add pid int not null default 0 first;

=========================
删除列[drop 列名]
=========================
①alter table 表名 drop 列名
例:alter table test drop pid;

=========================
修改列[modife 列名]
=========================
①alter table 表名 modify 列名 新类型 新参数【修改列类型】
例:alter table test modify gender char(4) not null default '';
②alter table 表名 change 旧列名 新列名 新类型 新参数【修改列名和列类型】
例:alter table test change pid uid int unsigned not null default 0;

=========================
查询列
=========================
①desc 表名【查询全部列】
例: desc test;
mysql> desc department;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| dId | int(11) | NO | PRI | | |
| dName | varchar(32) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+

②show columns from 表名【效果和desc同样】
mysql> show columns from department;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| dId | int(11) | NO | PRI | | |
| dName | varchar(32) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+

③show create table 表名【查看表的建立代码】
mysql> show create table department;
CREATE TABLE `department` (
`dId` int(11) NOT NULL,
`dName` varchar(32) DEFAULT NULL,
PRIMARY KEY (`dId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

 


总结一下对mysql表结构的修改操做,包括对字段及索引的修改操做: 添加字段: alter table `user_movement_log` Add column GatewayId int not null default 0 AFTER `Regionid` (在哪一个字段后面添加) 删除字段: alter table `user_movement_log` drop column Gatewayid 调整字段顺序: ALTER TABLE `user_movement_log` CHANGE `GatewayId` `GatewayId` int not null default 0 AFTER RegionID //主键 alter table tabelname add new_field_id int(5) unsigned default 0 not null auto_increment ,add primary key (new_field_id); //增长一个新列 alter table t2 add newfield timestamp; (简单语法,只指定新添字段newfield 类型为timestamp) alter table infos add newfield tinyint not null default '0'; (同时指定字段null属性、默认值) //删除列 alter table t2 drop column c; (删除列c) //重命名列 alter table t1 change a b integer; (把列a更名为b,注意要指定列类型) //改变列的类型 alter table t1 change b b bigint not null; (把列a更名为b,指定列类型及null属性) alter table infos change list list tinyint not null default '0'; //重命名表 alter table t1 rename t2; 加索引 mysql> alter table tablename change depno depno int(5) not null; mysql> alter table tablename add index 索引名 (字段名1[,字段名2 …]); mysql> alter table tablename add index emp_name (name); 加主关键字的索引 mysql> alter table tablename add primary key(id); 加惟一限制条件的索引 mysql> alter table tablename add unique emp_name2(cardnumber); 删除某个索引 mysql>alter table tablename drop index emp_name; 修改表: 增长字段: mysql> ALTER TABLE table_name ADD field_name field_type; 修改原字段名称及类型: mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type; 删除字段: mysql> ALTER TABLE table_name DROP field_name;


ORDER BY _column1, _column2; /* _column1升序,_column2升序 */
ORDER BY _column1, _column2 DESC; /* _column1升序,_column2降序 */
ORDER BY _column1 DESC, _column2 ; /* _column1降序,_column2升序 */
ORDER BY _column1 DESC, _column2 DESC; /* _column1降序,_column2降序 */
用 DESC 表示按倒序排序(即:从大到小排序)
用 ACS 表示按正序排序(即:从小到大排序)

 

order应该是以汉字的 ASCII 码排序,下面是按照汉字拼音排序
select * from corp_data where Chengshi like "图木舒克" order by convert(name using gbk);


#select count(*) as count from corp_data where Chengshi like "图木舒克";
select * from corp_data where Chengshi like "图木舒克" order by convert(name using gbk);
#delete from corp_data where Chengshi like "图木舒克";
#desc corp_data;
#alter table corp_data modify column hangye varchar(100) ;
#alter table corp_data modify column jianjie varchar(10000) ;

 

 

 

 

 

mysql如何查询最新的5条数据
select * from tb_content where id=(select msx(id) from tb_content) limit 0,5;

jdbcTemplate.execute("CREATE
建数据库不合适,要手动drop database ,再create database.


查总数:
select count(*) as count from tb_content;
select count(id) as count from tb_content;
navicat->分析表->取得表的总数

select * from corp_data where Chengshi like "上海";
select * from corp_data where Shengzhixiashi like "河南";

select name ,count(distinct(url)) from corp_data group by  name;
select Chengshi ,count(distinct(url)) from corp_data group by  Chengshi;
select Chengshi ,count(*) from corp_data group by  Chengshi;
select count(*) from corp_data where Chengshi like "北京";
select * from corp_data where Chengshi like "北京";
select name ,url  from corp_data limit 1;
select *  from corp_data limit 1;

select *  from corp_data limit 10;

select count(*) as count from corp_data limit 10;
select count(distinct(name)) as count from corp_data;

 varchar(N),  这里的N是指字符数,并非字节数.占用的字节数与编码有关
utf-8, 一个汉字3字节 英文字母1字节

CREATE TABLE IF NOT EXISTS corp_url_all_20150909 (id int(11) NOT NULL AUTO_INCREMENT,url varchar(500),PRIMARY KEY (id))
insert into corp_url_all_20150909 select * from corp_url_all;

 

备份:

mysql> create table corp_url_all_20150909 select * from corp_url_all;
Query OK, 3186326 rows affected (1 min 14.19 sec)
Records: 3186326  Duplicates: 0  Warnings: 0
mysql> select count(distinct(url)) as count from corp_url_all_20150909;
+--------+
| count  |
+--------+
| 357399 |
+--------+
1 row in set (11.21 sec)

去重:

create table corp_url_all_single select distinct(url) from corp_url_all_20150909;
select count(distinct(url)) as count from corp_url_all_single;


 

 

 

 

 

基本的SQL语句

2、数据定义语言(DDL)

数据定义语言:Data Definition Language。如CREATE, DROP,ALTER等语句。须要注意的是,数据库中的命令不区分大小写

建数据库,命名为mydb:

CREATE DATABASE mydb; 

注:如若要删除数据库,将“create”改成“drop”便可。

建立一个名为teacher的表:

复制代码
CREATE TABLE teacher( id int primary key auto_increment, name varchar(20), gender char(1), age int(2), birth date,
description varchar(100) );
复制代码
查看表结构:
desc teacher; 

须要注意的是:主键是用来惟一表明一条记录的字段(主键值必须是惟一)

修改表结构(ALTER TABLE语句):(假设表名为test)
  • alter table test add column job varchar(10); --添加表列
  • alter table test rename test1; --修改表名
  • alter table test drop column name; --删除表列
  • alter table test modify address char(10) --修改表列类型(改类型)
  • alter table test change address address1  char(40) --修改表列类型(更名字和类型,和下面的一行效果同样)
  • alter table test change column address address1 varchar(30)--修改表列名(更名字和类型)

自动增加

alter table tab_teacher change id id int auto_increment;

 

增长数据
insert into tab_teacher(name,gender,age,createDate) values('smyh','b',22,now()); 

now()函数能够调出当前系统的时间。

 

修改数据(UPDATE … SET语句):

UPDATE 表名 SET 字段1名=值,字段2名=值,字段3名=值 where 字段名=值; 

注:where后面的部分表示修改的条件。修改时,按照字段一、字段二、字段3的前后顺序修改。

 

删除数据

DELETE FROM 表名; 

 

删除ID为1的记录:

DELETE FROM 表名 where id=1; 

 

4、数据查询语言(DRL):

数据查询语言(Data Retrieval Language --DRL):SELECT语句。

在实际开发中,数据查询语言用的是最多的。注:实际开发中,要避免使用通配符"*"(通配符表明全部字段),由于系统要先解析出全部的字段名,将其还原为真实的名字,而后再进行操做。若是记录数据库内容特别多,会影响效率。

查询全部信息:

select id,name,gender,age,job,createDate from tab_teacher; 

 

在没有表被引用的状况下,容许指定DUAL做为一个假的表名:

DUAL是虚拟表。也就是说,表中没有这个数据,可是要执意使用sql语句,系统就会用这个虚拟表来知足你。举例效果以下:

查询ID为2的老师信息:

select * from tab_teacher where id=2; 

 

查询职业为空的老师信息:

select * from tab_teacher where job is null;#字段为空用“job is null”来表示,而不是“job=null”。

 

查询ID为2的老师的姓名和性别:

select name,gender from tab_teacher where id=2; 

 

查询性别为女和指定日期的老师信息:

select $ from tab_teacher where gender='w' and ceateDate='2014-10-14'; #而且用“and”,或用“or”。

 

查询性别为男或者ID小于2的老师:

select * from tab_teacher where gender='m' or id<2; 

 

查询姓名的最后一个字符为“e”的老师:(关键字:like '%+指定字符')

select * from tab_teacher where name like '%e'; 

 

查询姓名以指定字符开头的老师:

select * from tab_teacher where name like 's%'; 

 

查询姓名中包含“m”的老师:

select * from tab_teacher where name like '%m%'; 

 

查询全部老师信息,并按日期降序或者升序排列:ORDER BY 字段,+默认为升序:ASC/降序:DESC

  • 升序:
select * from tab_teacher order by createDate; #最后一个单词ASC可写可不写,由于默认为升序

 

  • 降序:
select * from tab_teacher order by createDate desc; 

 

多个排序条件:(当第一个条件相同时,按照第二个条件排序)

例如:上面图片的排序中,是按照日期降序排序的,可是id为2和id为3的日期相同,这两条记录按照默认顺序排序。

举例:如今排序的第一条件为:日期降序,第二条件为:年龄降序。多个排序条件用逗号隔开。命令为:

select * from tab_teacher order by createDate desc,age desc;

 

按性别分组查询男女老师的人数(GROUP BY ):

select gender,count(gender) from tab_teacher group by gender;

上面的命令表示,查找gender这个字段;并计算gender有多少个(count(gender));而后按照gender里的内容将个数进行分组(group by gender)。

问题:我以为应该是先分组,再查询性别,再数性别的个数。

注:这里面用到了count()这个内置的函数。关于count()这个聚合函数,将在下一篇文章中讲到。

正确的效果和错误的效果以下:

按性别分组,查询出女老师人数的总数:

select gender,count(gender) from tab_teacher group by gender having gender='m';

这里在上一个命令的基础上,增长了一个关键字:having。having关键字专门用来在分组以后添加的条件。意思是:先求总数,而后进行分组,而后再从分组里找到字段等于“m”的个数。注:不能用where做为关键字,由于where是加在分组以前的条件。

显示效果以下:

注:这种写法操做繁琐,效率较低,having语句尽可能少用,能够用其余语句代替,例如:

select gender,count(gender) from tab_teacher where gender='m';

效果是同样的。

查询表的总记录数:

  • 方式一:(不推荐)
select count(*) from tab_teacher;
  • 方式二:(使用主键的方式查询)
select count(id) from tab_teacher;

方式一将空记录也包含进来了。因此采用方式二,由于主键惟一,且不能为空,此时id总数则表明总记录数。

别名的用法:

  • 使用别名查询表的总记录数:
select count(id) as counts from tab_teacher; 

不用别名和用别名的效果对好比下:(命令中的"as"能够省略)

  • 使用别名来代替表的名字:

举例:将表的名字起为t。

select t.name,t.age from tab_teacher t;

当表名比较长,或者同时有多个表存在时,用别名就显得很是方便了。

查询老师记录的前三条(从0位置开始找出3条):(很是有用)

select * from tab_teacher limit 0,3;

命令解释:limit后面有两个参数:第一个参数是起始位置,第二个参数是偏移量。声明:第一条记录的id无论为多少,索引位置都是0。

注:这种分页查询方式很是有用,例如使用百度搜索时,告诉你总记录数,可是会分页显示。

 

5、事务控制语言(TCL):

事务控制语言:Transaction Control Language--TCL。如COMMIT,ROLLBACK语句。

一、事务:

事务(Transaction)的概念:事务(Transaction)是访问并可能更新数据库中各类数据项的一个程序执行单元(unit)。在关系数据库中,一个事务能够是一条SQL语句,一组SQL语句或整个程序。

事务的属性:原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持续性(durability)。这四个属性一般称为ACID特性。

事务的特色:事务就是对数据库的多步操做,要么一块儿成功,要么一块儿失败。

总结:事务就是能够把多步操做当作一个总体,这个总体要么一块儿成功,要么一块儿失败。

二、事务的提交和回滚命令:

设置默认事务提交方式:(默认为true)

  • 设置事务提交方式为“手动提交”:
set autocommit = false;
  • 设置事务提交方式为自动提交”:
set autocommit = true;

手动提交事务:

commit;

回滚事务:

rollback;

 

注:只要还没手动commit提交,一旦回滚,以前的修改操做都将清零。

注:commit命令和rollback命令只有在提交方式为“手动提交”时,才能够用。

三、保存还原点的命令:

当数据未commit以前,增删改查的操做都是暂时保存在内存之中的,当咱们修改操做进行到某一步时,能够给这一步设置一个还原点,方便之后回滚到此还原点(相似于PS当中的快照)。

保存还原点:

savepoint name_point;

回滚到指定还原点:

rollback to name_point;

 

 

 

 


 9、MySQL的一些函数:
  一、字符串连接——CONCAT()
    >SELECT CONCAT(name,'=>',score) FROM tb_name

  二、数学函数:
    AVG、SUM、MAX、MIN、COUNT;

  三、文本处理函数:
    TRIM、LOCATE、UPPER、LOWER、SUBSTRING

  四、运算符:
    +、-、*、\

  五、时间函数:
    DATE()、CURTIME()、DAY()、YEAR()、NOW().....

 10、分组查询:
   一、分组查询能够按照指定的列进行分组:
    >SELECT COUNT(*) FROM tb_name GROUP BY score HAVING COUNT(*)>1;
  二、条件使用Having;
  三、ORDER BY 排序:
    ORDER BY DESC|ASC    =>按数据的降序和升序排列

11、UNION规则——能够执行两个语句(能够去除重复行)
 12、全文检索——MATCH和AGAINST
  一、SELECT MATCH(note_text)AGAINST('PICASO') FROM tb_name;
  二、InnoDB引擎不支持全文检索,MyISAM能够;

 十3、视图

  一、建立视图

    >CREATE VIEW name AS SELECT * FROM tb_name WHERE ~~ ORDER BY ~~;

  二、视图的特殊做用:

      a、简化表之间的联结(把联结写在select中);

      b、从新格式化输出检索的数据(TRIM,CONCAT等函数);

      c、过滤不想要的数据(select部分)

      d、使用视图计算字段值,如汇总这样的值。

 十4、使用存储过程:

  我的理解,存储过程就是一个自定义函数,有局部变量参数,可传入参数,能够返回值,不过这语法够呆滞的~~~

  一、建立存储过程:

    >CREATE PROCEDURE pro(

    >IN num INT,OUT total INT)

    >BEGIN

    >SELECT SUM(score) INTO total FROM tb_name WHERE id=num;

    >END;

   ***这里的  IN (传递一个值给存储过程),OUT(从存储过程传出一个值),INOUT(对存储过程传入、传出),INTO(保存变量)

  二、调用存储过程:

    >CALL pro(13,@total)      //这里的存储过程两个变量,一个是IN一个是OUT,这里的OUT也是须要写上的,不写会出错

    >SELECT @total         //这里就能够看到结果了;

  三、存储过程的其余操做:

    >SHOW PROCEDURE STATUS;      //显示当期的存储过程

    >DROP PROCEDURE pro;         //删除指定存储过程

十5、使用游标:

  对这个理解不是很懂,朋友多多指点哦~~~

   一、游标的操做

    >CREATE PROCEDURE pro()

    >BEGIN

    >DECLARE ordername CURSOR FOR

    >SELECT order_num FROM orders;

    >END;

    

    >OPEN ordername;    //打开游标

 

    >CLOSE ordername;    //关闭游标

十6、触发器:

  触发器是指在进行某项指定操做时,触发触发器内指定的操做;

  一、支持触发器的语句有DELETE、INSERT、UPDATE,其余均不支持

  二、建立触发器:

    >CREATE TRIGGER trig AFTER INSERT ON ORDERS FOR EACH ROW SELECT NEW.orser_name;

    >INSERT语句,触发语句,返回一个值

  三、删除触发器

    >DROP TRIGGER trig;

十7、语法整理:

  一、ALTER TABLE(修改表)

    ALTER TABLE table_name

    (  ADD    column  datatype    [ NULL | NOT NULL ]  [ CONSTRAINTS ]

       CHANGE  column   datatype   COLUMNS  [ NULL | NOT NULL ]   [ CONSTRAINTS ]

       DROP    column,

       。。。。

    )

  二、COMMIT(处理事务)

    >COMMIT;

   三、CREATE INDEX(在一个或多个列上建立索引)

    CREATE INDEX index_name ON tb_name (column [ ASC | DESC ] , .......);

   四、CREATE PROCEDURE (建立存储过程)

    CREATE PROCEDURE pro([ parameters ])

    BEGIN

    ........

    END

   五、CREATE TABLE(建立表)

    CREATE TABLE tb_name(

    column_name  datetype  [ NULL | NOT NULL ]   [ condtraints]   ,

    column_name  datetype  [ NULL | NOT NULL ]   [ condtraints]   ,

    .......

    PRIMARY KEY( column_name )

    )ENGINE=[  InnoDB | MyiSAM ]DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

   六、CREATE USER(建立用户)

    CREATE USER user_name [ @hostname ] [ IDENTIFIED BY [ PASSWORD ] 'pass_word' ];

   七、CREATE VIEW (在一个或多个表上建立视图)

    CREATE [ OR REPLACE ] VIEW view_name AS SELECT。。。。。。

   八、DELETE (从表中删除一行或多行)

    DELETE FROM table_name [WHERE ......]

   九、DROP(永久删除数据库及对象,如视图、索引等)

    DROP DATEBASE | INDEX | PROCEDURE | TABLE | TRIGGER | USER | VIEW  name

   十、INSERT (给表添加行)

    INSERT INTO tb_name [ ( columns,...... ) ]  VALUES(value1,............);

    使用SELECT值插入:

    INSERT INTO tb_name [ ( columns,...... ) ]

    SELECT columns , .......   FROM tb_name [ WHERE ...... ] ;

   十一、ROLLBACK(撤销一个事务处理块)

    ROLLBACK [  TO  savapointname  ];

   十二、SAVEPOINT(为ROLLBACK设置保留点)

    SAVEPOINT sp1;

   1三、SELECT (检索数据,显示信息)

    SELECT column_name,.....FROM tb_name  [ WHERE ]   [ UNION ]    [ RROUP BY ]   [ HAVING ]   [ ORDER BY ]

   1四、START TRANSACTION (一个新的事务处理块的开始)

    START TRANSACTION

   1五、UPDATE(更新一个表中的一行或多行)

    UPDATE tb_name SET column=value,......[ where ]

 


其它mysql基本操做:
http://www.cnblogs.com/RanNing/archive/2012/11/17/2870484.html





几个最经常使用的api函数
mysql_affected_rows()     返回被最新的UPDATE, DELETE或INSERT查询影响的行数。
mysql_close()     关闭一个服务器链接。
mysql_errno()     返回最近被调用的MySQL函数的出错编号。
mysql_error()     返回最近被调用的MySQL函数的出错消息。
mysql_fetch_row()     从结果集合中取得下一行。
mysql_field_count()     返回最近查询的结果列的数量。
mysql_init()     得到或初始化一个MYSQL结构。
mysql_insert_id()     返回有前一个查询为一个AUTO_INCREMENT列生成的ID。
mysql_num_rows()     返回一个结果集合中的行的数量。
mysql_query()     执行指定为一个空结尾的字符串的SQL查询。
mysql_real_connect()     链接一个MySQL服务器。
mysql_real_query()     执行指定为带计数的字符串的SQL查询。





mysql经常使用字符串操做函数大全,以及实例
http://www.cnblogs.com/xiangxiaodong/archive/2011/02/21/1959589.html





CREATE TABLE tab2 AS (SELECT * FROM tab1)
这种作法表的存储引擎也会采用服务器默认的存储引擎而不是源表的存储引擎,此种复制方法把表的内容也一块儿复制过来了。

CREATE TALBE tab2 ENGINE=MYISAM, CHARSET='UTF8' AS (SELECT * FROM tab1)
能够本身指定存储引擎和字符集,弥补方法一的不足

CREATE TABLE tab2 LIKE tab1
使用和tab1表相同的结构来建立一个新表,列名、数据类型、空指和索引也将复制,可是表的内容不会被复制。外键和专用的权限也没有被复制。

MySQL复制表结构及数据到新表
CREATE TABLE tab_new SELECT * FROM tab_old

复制旧表的数据到新表(假设两个表结构同样)
INSERT INTO tab1 SELECT * FROM tab2

复制旧表的数据到新表(假设两个表结构不同)
INSERT INTO tab1(字段1, 字段2, ...) SELECT 字段1, 字段2, ... FROM tab2

更改表名
ALTER TABLE employee RENAME TO staff

更改列类型
ALTER TABLE employee MODIFY COLUMN truename VARCHAR(10) NOT NULL DEFAULT ''

更改列名
ALTER TABLE employee CHANGE COLUMN truename employeename VARCHAR(10) NOT NULL DEFAULT ''

添加默认值
ALTER TABLE employee ALTER COLUMN truename SET DEFAULT ''

删除默认值
ALTER TABLE employee ALTER COLUMN truename DEOP DEFAULT


mysql修改表
表的结构以下:

mysql> show create table person;
| person | CREATE TABLE `person` (
`number` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`birthday` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
删除列:

ALTER TABLE person DROP COLUMN birthday; 
添加列:

ALTER TABLE person ADD COLUMN birthday datetime;
修改列,把number修改成bigint:

ALTER TABLE person MODIFY number BIGINT NOT NULL;
或者是把number修改成id,类型为bigint:

ALTER TABLE person CHANGE number id BIGINT;

添加主键:

ALTER TABLE person ADD PRIMARY KEY (id);
删除主键:

ALTER TABLE person DROP PRIMARY KEY;
添加惟一索引:

ALTER TABLE person ADD UNIQUE name_unique_index (`name`);
为name这一列建立了惟一索引,索引的名字是name_unique_index.

 

添加普通索引:

ALTER TABLE person ADD INDEX birthday_index (`birthday`);

删除索引:

ALTER TABLE person DROP INDEX birthday_index;
ALTER TABLE person DROP INDEX name_unique_index;

禁用非惟一索引

ALTER TABLE person DISABLE KEYS;
ALTER TABLE...DISABLE KEYS让MySQL中止更新MyISAM表中的非惟一索引。

激活非惟一索引

ALTER TABLE person ENABLE KEYS;
ALTER TABLE ... ENABLE KEYS从新建立丢失的索引。

 

把表默认的字符集和全部字符列(CHAR, VARCHAR, TEXT)改成新的字符集:

ALTER TABLE person CONVERT TO CHARACTER SET utf8;
修改表某一列的编码

ALTER TABLE person CHANGE name name varchar(255) CHARACTER SET utf8;
仅仅改变一个表的默认字符集

ALTER TABLE person DEFAULT CHARACTER SET utf8;
修改表名

RENAME TABLE person TO person_other;
移动表到其余数据库

RENAME TABLE current_db.tbl_name TO other_db.tbl_name;

 


在mysql中咱们对数据表字段的修改命令只要使用alter就能够了,下面我来给你们详细介绍mysql中修改表字段名/字段长度/字段类型等等一些方法介绍,有须要了解的朋友可参考。

先来看看经常使用的方法
MySql的简单语法,经常使用,却不容易记住。固然,这些Sql语法在各数据库中基本通用。下面列出:
1.增长一个字段
alter table user add COLUMN new1 VARCHAR(20) DEFAULT NULL; //增长一个字段,默认为空
alter table user add COLUMN new2 VARCHAR(20) NOT NULL;    //增长一个字段,默认不能为空
2.删除一个字段
alter table user DROP COLUMN new2;                //删除一个字段
3.修改一个字段
alter table user MODIFY new1 VARCHAR(10);            //修改一个字段的类型
alter table user CHANGE new1 new4 int;              //修改一个字段的名称,此时必定要从新

//主键
alter table tabelname add new_field_id int(5) unsigned default 0 not null auto_increment ,add primary key (new_field_id);
//增长一个新列
alter table t2 add d timestamp;
alter table infos add ex tinyint not null default ‘0′;
//删除列
alter table t2 drop column c;
//重命名列
alter table t1 change a b integer;
//改变列的类型
alter table t1 change b b bigint not null;
alter table infos change list list tinyint not null default ‘0′;
//重命名表
alter table t1 rename t2;
加索引
mysql> alter table tablename change depno depno int(5) not null;
mysql> alter table tablename add index 索引名 (字段名1[,字段名2 …]);
mysql> alter table tablename add index emp_name (name);
加主关键字的索引
mysql> alter table tablename add primary key(id);
加惟一限制条件的索引
mysql> alter table tablename add unique emp_name2(cardnumber);
删除某个索引
mysql>alter table tablename drop index emp_name;
增长字段:
mysql> ALTER TABLE table_name ADD field_name field_type;
修改原字段名称及类型:
mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type;
删除字段:
mysql> ALTER TABLE table_name DROP field_name;
mysql修改字段长度
alter table 表名 modify column 字段名 类型;
例如
数据库中user表 name字段是varchar(30)
能够用
alter table user modify column name varchar(50) ;

 

 

 

 


mysql更改表结构:添加、删除、修改字段、调整字段顺序
mysqltablenulluserlist
添加字段:

alter table `user_movement_log`
Add column GatewayId int not null default 0 AFTER `Regionid` (在哪一个字段后面添加)

删除字段:

alter table `user_movement_log` drop column Gatewayid

调整字段顺序:

ALTER TABLE `user_movement_log` CHANGE `GatewayId` `GatewayId` int not null default 0 AFTER RegionID

//主键

alter table tabelname add new_field_id int(5) unsigned default 0 not null auto_increment ,add primary key (new_field_id);

//增长一个新列

alter table t2 add d timestamp;
alter table infos add ex tinyint not null default '0';

//删除列

alter table t2 drop column c;

//重命名列

alter table t1 change a b integer;

//改变列的类型

alter table t1 change b b bigint not null;
alter table infos change list list tinyint not null default '0';

//重命名表

alter table t1 rename t2;

加索引

mysql> alter table tablename change depno depno int(5) not null;
mysql> alter table tablename add index 索引名 (字段名1[,字段名2 …]);
mysql> alter table tablename add index emp_name (name);

加主关键字的索引

mysql> alter table tablename add primary key(id);

加惟一限制条件的索引

mysql> alter table tablename add unique emp_name2(cardnumber);

删除某个索引

mysql>alter table tablename drop index emp_name;

修改表:

增长字段:

mysql> ALTER TABLE table_name ADD field_name field_type;

修改原字段名称及类型:

mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type;

删除字段:

mysql> ALTER TABLE table_name DROP field_name;

 

 

 

 

 

 


MySql表结构修改详解

修改表的语法
=========================
增长列[add 列名]
=========================
①alter table 表名 add 列名 列类型 列参数【加的列在表的最后面】
例:alter table test add username char(20) not null default '';
alter table test add birth date not null default '0000-00-00';

②alter table 表名 add 列名 列类型 列参数 after 某列【把新列加在某列后面】
例:alter table test add gender char(1) not null default '' after username;

③alter table 表名 add 列名 列类型 列参数 first【把新列加在最前面】
例:alter table test add pid int not null default 0 first;

=========================
删除列[drop 列名]
=========================
①alter table 表名 drop 列名
例:alter table test drop pid;

=========================
修改列[modife 列名]
=========================
①alter table 表名 modify 列名 新类型 新参数【修改列类型】
例:alter table test modify gender char(4) not null default '';
②alter table 表名 change 旧列名 新列名 新类型 新参数【修改列名和列类型】
例:alter table test change pid uid int unsigned not null default 0;

=========================
查询列
=========================
①desc 表名【查询全部列】
例: desc test;
mysql> desc department;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| dId | int(11) | NO | PRI | | |
| dName | varchar(32) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+

②show columns from 表名【效果和desc同样】
mysql> show columns from department;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| dId | int(11) | NO | PRI | | |
| dName | varchar(32) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+

③show create table 表名【查看表的建立代码】
mysql> show create table department;
CREATE TABLE `department` (
`dId` int(11) NOT NULL,
`dName` varchar(32) DEFAULT NULL,
PRIMARY KEY (`dId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

 


总结一下对mysql表结构的修改操做,包括对字段及索引的修改操做: 添加字段: alter table `user_movement_log` Add column GatewayId int not null default 0 AFTER `Regionid` (在哪一个字段后面添加) 删除字段: alter table `user_movement_log` drop column Gatewayid 调整字段顺序: ALTER TABLE `user_movement_log` CHANGE `GatewayId` `GatewayId` int not null default 0 AFTER RegionID //主键 alter table tabelname add new_field_id int(5) unsigned default 0 not null auto_increment ,add primary key (new_field_id); //增长一个新列 alter table t2 add newfield timestamp; (简单语法,只指定新添字段newfield 类型为timestamp) alter table infos add newfield tinyint not null default '0'; (同时指定字段null属性、默认值) //删除列 alter table t2 drop column c; (删除列c) //重命名列 alter table t1 change a b integer; (把列a更名为b,注意要指定列类型) //改变列的类型 alter table t1 change b b bigint not null; (把列a更名为b,指定列类型及null属性) alter table infos change list list tinyint not null default '0'; //重命名表 alter table t1 rename t2; 加索引 mysql> alter table tablename change depno depno int(5) not null; mysql> alter table tablename add index 索引名 (字段名1[,字段名2 …]); mysql> alter table tablename add index emp_name (name); 加主关键字的索引 mysql> alter table tablename add primary key(id); 加惟一限制条件的索引 mysql> alter table tablename add unique emp_name2(cardnumber); 删除某个索引 mysql>alter table tablename drop index emp_name; 修改表: 增长字段: mysql> ALTER TABLE table_name ADD field_name field_type; 修改原字段名称及类型: mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type; 删除字段: mysql> ALTER TABLE table_name DROP field_name;

 

ORDER BY _column1, _column2; /* _column1升序,_column2升序 */ 
ORDER BY _column1, _column2 DESC; /* _column1升序,_column2降序 */ 
ORDER BY _column1 DESC, _column2 ; /* _column1降序,_column2升序 */ 
ORDER BY _column1 DESC, _column2 DESC; /* _column1降序,_column2降序 */ 
用 DESC 表示按倒序排序(即:从大到小排序)
用 ACS 表示按正序排序(即:从小到大排序)

 

order应该是以汉字的 ASCII 码排序,下面是按照汉字拼音排序
select * from corp_data where Chengshi like "图木舒克" order by convert(name using gbk);


#select count(*) as count from corp_data where Chengshi like "图木舒克";
select * from corp_data where Chengshi like "图木舒克" order by convert(name using gbk);
#delete from corp_data where Chengshi like "图木舒克";
#desc corp_data;
#alter table corp_data modify column hangye varchar(100) ;
#alter table corp_data modify column jianjie varchar(10000) ;

 

 

 

 

 

mysql如何查询最新的5条数据
select * from tb_content where id=(select msx(id) from tb_content) limit 0,5;

jdbcTemplate.execute("CREATE
建数据库不合适,要手动drop database ,再create database.


查总数:
select count(*) as count from tb_content;
select count(id) as count from tb_content;
navicat->分析表->取得表的总数

select * from corp_data where Chengshi like "上海";
select * from corp_data where Shengzhixiashi like "河南";

select name ,count(distinct(url)) from corp_data group by  name;
select Chengshi ,count(distinct(url)) from corp_data group by  Chengshi;
select Chengshi ,count(*) from corp_data group by  Chengshi;
select count(*) from corp_data where Chengshi like "北京";
select * from corp_data where Chengshi like "北京";
select name ,url  from corp_data limit 1;
select *  from corp_data limit 1;

select *  from corp_data limit 10;

select count(*) as count from corp_data limit 10;
select count(distinct(name)) as count from corp_data;

 varchar(N),  这里的N是指字符数,并非字节数.占用的字节数与编码有关
utf-8, 一个汉字3字节 英文字母1字节 

 

 


mysql编码最好使用utf-8,导出导入不用考滤编码。
GB2312是GBK的子集,GBK是GB18030的子集,是国标。utf-8为国际标准,特殊中文时使用gb18030。














 

 

 

下面总结的知识点全是常常用的,全都是干货,好好收藏吧。

/* 启动mysql */
net start mysql

/* 链接与断开服务器 */
mysql -h 地址 -p 端口 -u 用户名 -p 密码

/* 跳过权限验证登陆mysql */
mysqld --skip-grant-tables
-- 修改root密码
密码加密函数password()
update mysql.user set password=password('root');

show processlist -- 显示哪些线程正在运行
show variables --

/* 数据库操做 */ ------------------
-- 查看当前数据库
select database();
-- 显示当前时间、用户名、数据库版本
select now(), user(), version();
-- 建立库
create database[ if not exists] 数据库名 数据库选项
数据库选项:
character set charset_name
collate collation_name
-- 查看已有库
show databases[ like 'pattern']
-- 查看当前库信息
show create database 数据库名
-- 修改库的选项信息
alter database 库名 选项信息
-- 删除库
drop database[ if exists] 数据库名
同时删除该数据库相关的目录及其目录内容

/* 表的操做 */ ------------------
-- 建立表
create [temporary] table[ if not exists] [库名.]表名 ( 表的结构定义 )[ 表选项]
每一个字段必须有数据类型
最后一个字段后不能有逗号
temporary 临时表,会话结束时表自动消失
对于字段的定义:
字段名 数据类型 [not null | null] [default default_value] [auto_increment] [unique [key] | [primary] key] [comment 'string']
-- 表选项
-- 字符集
charset = charset_name
若是表没有设定,则使用数据库字符集
-- 存储引擎
engine = engine_name 
表在管理数据时采用的不一样的数据结构,结构不一样会致使处理方式、提供的特性操做等不一样
常见的引擎:innodb myisam memory/heap bdb merge example csv maxdb archive
不一样的引擎在保存表的结构和数据时采用不一样的方式
myisam表文件含义:.frm表定义,.myd表数据,.myi表索引
innodb表文件含义:.frm表定义,表空间数据和日志文件
show engines -- 显示存储引擎的状态信息
show engine 引擎名 {logs|status} -- 显示存储引擎的日志或状态信息
-- 数据文件目录
data directory = '目录'
-- 索引文件目录
index directory = '目录'
-- 表注释
comment = 'string'
-- 分区选项
partition by ... (详细见手册)
-- 查看全部表
show tables[ like 'pattern']
show tables from 表名
-- 查看表机构
show create table 表名 (信息更详细)
desc 表名 / describe 表名 / explain 表名 / show columns from 表名 [like 'pattern']
show table status [from db_name] [like 'pattern']
-- 修改表
-- 修改表自己的选项
alter table 表名 表的选项
eg: alter table 表名 engine=myisam;
-- 对表进行重命名
rename table 原表名 to 新表名
rename table 原表名 to 库名.表名 (可将表移动到另外一个数据库)
-- rename能够交换两个表名
-- 修改表的字段机构
alter table 表名 操做名
-- 操做名
add[ column] 字段名 -- 增长字段
after 字段名 -- 表示增长在该字段名后面
first -- 表示增长在第一个
add primary key(字段名) -- 建立主键
add unique [索引名] (字段名)-- 建立惟一索引
add index [索引名] (字段名) -- 建立普通索引
add 
drop[ column] 字段名 -- 删除字段
modify[ column] 字段名 字段属性 -- 支持对字段属性进行修改,不能修改字段名(全部原有属性也需写上)
change[ column] 原字段名 新字段名 字段属性 -- 支持对字段名修改
drop primary key -- 删除主键(删除主键前需删除其auto_increment属性)
drop index 索引名 -- 删除索引
drop foreign key 外键 -- 删除外键

-- 删除表
drop table[ if exists] 表名 ...
-- 清空表数据
truncate [table] 表名
-- 复制表结构
create table 表名 like 要复制的表名
-- 复制表结构和数据
create table 表名 [as] select * from 要复制的表名
-- 检查表是否有错误
check table tbl_name [, tbl_name] ... [option] ...
-- 优化表
optimize [local | no_write_to_binlog] table tbl_name [, tbl_name] ...
-- 修复表
repair [local | no_write_to_binlog] table tbl_name [, tbl_name] ... [quick] [extended] [use_frm]
-- 分析表
analyze [local | no_write_to_binlog] table tbl_name [, tbl_name] ...

 

/* 数据操做 */ ------------------
-- 增
insert [into] 表名 [(字段列表)] values (值列表)[, (值列表), ...]
-- 若是要插入的值列表包含全部字段而且顺序一致,则能够省略字段列表。
-- 可同时插入多条数据记录!
replace 与 insert 彻底同样,可互换。
insert [into] 表名 set 字段名=值[, 字段名=值, ...]
-- 查
select 字段列表 from 表名[ 其余子句]
-- 可来自多个表的多个字段
-- 其余子句能够不使用
-- 字段列表能够用*代替,表示全部字段
-- 删
delete from 表名[ 删除条件子句]
没有条件子句,则会删除所有
-- 改
update 表名 set 字段名=新值[, 字段名=新值] [更新条件]

/* 字符集编码 */ ------------------
-- mysql、数据库、表、字段都可设置编码
-- 数据编码与客户端编码不需一致
show variables like 'character_set_%' -- 查看全部字符集编码项
character_set_client 客户端向服务器发送数据时使用的编码
character_set_results 服务器端将结果返回给客户端所使用的编码
character_set_connection 链接层编码
set 变量名 = 变量值
set character_set_client = gbk;
set character_set_results = gbk;
set character_set_connection = gbk;
set names gbk; -- 至关于完成以上三个设置
-- 校对集
校对集用以排序
show character set [like 'pattern']/show charset [like 'pattern'] 查看全部字符集
show collation [like 'pattern'] 查看全部校对集
charset 字符集编码 设置字符集编码
collate 校对集编码 设置校对集编码

/* 数据类型(列类型) */ ------------------
1. 数值类型
-- a. 整型 ----------
类型 字节 范围(有符号位)
tinyint 1字节 -128 ~ 127 无符号位:0 ~ 255
smallint 2字节 -32768 ~ 32767
mediumint 3字节 -8388608 ~ 8388607
int 4字节
bigint 8字节

int(m) m表示总位数
- 默认存在符号位,unsigned 属性修改
- 显示宽度,若是某个数不够定义字段时设置的位数,则前面以0补填,zerofill 属性修改
例:int(5) 插入一个数'123',补填后为'00123'
- 在知足要求的状况下,越小越好。
- 1表示bool值真,0表示bool值假。mysql没有布尔类型,经过整型0和1表示。经常使用tinyint(1)表示布尔型。

-- b. 浮点型 ----------
类型 字节 范围
float(单精度) 4字节
double(双精度) 8字节
浮点型既支持符号位 unsigned 属性,也支持显示宽度 zerofill 属性。
不一样于整型,先后均会补填0.
定义浮点型时,需指定总位数和小数位数。
float(m, d) double(m, d)
m表示总位数,d表示小数位数。
m和d的大小会决定浮点数的范围。不一样于整型的固定范围。
m既表示总位数(不包括小数点和正负号),也表示显示宽度(全部显示符号均包括)。
支持科学计数法表示。
浮点数表示近似值。

-- c. 定点数 ----------
decimal -- 可变长度
decimal(m, d) m也表示总位数,d表示小数位数。
保存一个精确的数值,不会发生数据的改变,不一样于浮点数的四舍五入。
将浮点数转换为字符串来保存,每9位数字保存为4个字节。

2. 字符串类型
-- a. char, varchar ----------
char 定长字符串,速度快,但浪费空间
varchar 变长字符串,速度慢,但节省空间
m表示能存储的最大长度,此长度是字符数,非字节数。
不一样的编码,所占用的空间不一样。
char,最多255个字符,与编码无关。
varchar,最多65535字符,与编码有关。
一条有效记录最大不能超过65535个字节。
utf8 最大为21844个字符,gbk 最大为32766个字符,latin1 最大为65532个字符
varchar 是变长的,须要利用存储空间保存 varchar 的长度,若是数据小于255个字节,则采用一个字节来保存长度,反之须要两个字节来保存。
varchar 的最大有效长度由最大行大小和使用的字符集肯定。
最大有效长度是65532字节,由于在varchar存字符串时,第一个字节是空的,不存在任何数据,而后还需两个字节来存放字符串的长度,因此有效长度是64432-1-2=65532字节。
例:若一个表定义为 create table tb(c1 int, c2 char(30), c3 varchar(n)) charset=utf8; 问n的最大值是多少? 答:(65535-1-2-4-30*3)/3

-- b. blob, text ----------
blob 二进制字符串(字节字符串)
tinyblob, blob, mediumblob, longblob
text 非二进制字符串(字符字符串)
tinytext, text, mediumtext, longtext
text 在定义时,不须要定义长度,也不会计算总长度。
text 类型在定义时,不可给default值

-- c. binary, varbinary ----------
相似于char和varchar,用于保存二进制字符串,也就是保存字节字符串而非字符字符串。
char, varchar, text 对应 binary, varbinary, blob.

3. 日期时间类型
通常用整型保存时间戳,由于php能够很方便的将时间戳进行格式化。
datetime 8字节 日期及时间 1000-01-01 00:00:00 到 9999-12-31 23:59:59
date 3字节 日期 1000-01-01 到 9999-12-31
timestamp 4字节 时间戳 19700101000000 到 2038-01-19 03:14:07
time 3字节 时间 -838:59:59 到 838:59:59
year 1字节 年份 1901 - 2155

datetime “yyyy-mm-dd hh:mm:ss”
timestamp “yy-mm-dd hh:mm:ss”
“yyyymmddhhmmss”
“yymmddhhmmss”
yyyymmddhhmmss
yymmddhhmmss
date “yyyy-mm-dd”
“yy-mm-dd”
“yyyymmdd”
“yymmdd”
yyyymmdd
yymmdd
time “hh:mm:ss”
“hhmmss”
hhmmss
year “yyyy”
“yy”
yyyy
yy

4. 枚举和集合
-- 枚举(enum) ----------
enum(val1, val2, val3...)
在已知的值中进行单选。最大数量为65535.
枚举值在保存时,以2个字节的整型(smallint)保存。每一个枚举值,按保存的位置顺序,从1开始逐一递增。
表现为字符串类型,存储倒是整型。
null值的索引是null。
空字符串错误值的索引值是0。

-- 集合(set) ----------
set(val1, val2, val3...)
create table tab ( gender set('男', '女', '无') );
insert into tab values ('男, 女');
最多能够有64个不一样的成员。以bigint存储,共8个字节。采起位运算的形式。
当建立表时,set成员值的尾部空格将自动被删除。

/* 选择类型 */
-- php角度
1. 功能知足
2. 存储空间尽可能小,处理效率更高
3. 考虑兼容问题

-- ip存储 ----------
1. 只需存储,可用字符串
2. 若是需计算,查找等,可存储为4个字节的无符号int,即unsigned
1) php函数转换
ip2long可转换为整型,但会出现携带符号问题。需格式化为无符号的整型。
利用sprintf函数格式化字符串
sprintf("%u", ip2long('192.168.3.134'));
而后用long2ip将整型转回ip字符串
2) mysql函数转换(无符号整型,unsigned)
inet_aton('127.0.0.1') 将ip转为整型
inet_ntoa(2130706433) 将整型转为ip

 

/* 列属性(列约束) */ ------------------
1. 主键
- 能惟一标识记录的字段,能够做为主键。
- 一个表只能有一个主键。
- 主键具备惟一性。
- 声明字段时,用 primary key 标识。
也能够在字段列表以后声明
例:create table tab ( id int, stu varchar(10), primary key (id));
- 主键字段的值不能为null。
- 主键能够由多个字段共同组成。此时须要在字段列表后声明的方法。
例:create table tab ( id int, stu varchar(10), age int, primary key (stu, age));

2. unique 惟一索引(惟一约束)
使得某字段的值也不能重复。

3. null 约束
null不是数据类型,是列的一个属性。
表示当前列是否能够为null,表示什么都没有。
null, 容许为空。默认。
not null, 不容许为空。
insert into tab values (null, 'val');
-- 此时表示将第一个字段的值设为null, 取决于该字段是否容许为null

4. default 默认值属性
当前字段的默认值。
insert into tab values (default, 'val'); -- 此时表示强制使用默认值。
create table tab ( add_time timestamp default current_timestamp );
-- 表示将当前时间的时间戳设为默认值。
current_date, current_time

5. auto_increment 自动增加约束
自动增加必须为索引(主键或unique)
只能存在一个字段为自动增加。
默认为1开始自动增加。能够经过表属性 auto_increment = x进行设置,或 alter table tbl auto_increment = x;

6. comment 注释
例:create table tab ( id int ) comment '注释内容';

7. foreign key 外键约束
用于限制主表与从表数据完整性。
alter table t1 add constraint `t1_t2_fk` foreign key (t1_id) references t2(id);
-- 将表t1的t1_id外键关联到表t2的id字段。
-- 每一个外键都有一个名字,能够经过 constraint 指定

存在外键的表,称之为从表(子表),外键指向的表,称之为主表(父表)。

做用:保持数据一致性,完整性,主要目的是控制存储在外键表(从表)中的数据。

mysql中,能够对innodb引擎使用外键约束:
语法:
foreign key (外键字段) references 主表名 (关联字段) [主表记录删除时的动做] [主表记录更新时的动做]
此时须要检测一个从表的外键须要约束为主表的已存在的值。外键在没有关联的状况下,能够设置为null.前提是该外键列,没有not null。

能够不指定主表记录更改或更新时的动做,那么此时主表的操做被拒绝。
若是指定了 on update 或 on delete:在删除或更新时,有以下几个操做能够选择:
1. cascade,级联操做。主表数据被更新(主键值更新),从表也被更新(外键值更新)。主表记录被删除,从表相关记录也被删除。
2. set null,设置为null。主表数据被更新(主键值更新),从表的外键被设置为null。主表记录被删除,从表相关记录外键被设置成null。但注意,要求该外键列,没有not null属性约束。
3. restrict,拒绝父表删除和更新。

注意,外键只被innodb存储引擎所支持。其余引擎是不支持的。


/* 建表规范 */ ------------------
-- normal format, nf
- 每一个表保存一个实体信息
- 每一个具备一个id字段做为主键
- id主键 + 原子表
-- 1nf, 第一范式
字段不能再分,就知足第一范式。
-- 2nf, 第二范式
知足第一范式的前提下,不能出现部分依赖。
消除符合主键就能够避免部分依赖。增长单列关键字。
-- 3nf, 第三范式
知足第二范式的前提下,不能出现传递依赖。
某个字段依赖于主键,而有其余字段依赖于该字段。这就是传递依赖。
将一个实体信息的数据放在一个表内实现。


/* select */ ------------------

select [all|distinct] select_expr from -> where -> group by [合计函数] -> having -> order by -> limit

a. select_expr
-- 能够用 * 表示全部字段。
select * from tb;
-- 能够使用表达式(计算公式、函数调用、字段也是个表达式)
select stu, 29+25, now() from tb;
-- 能够为每一个列使用别名。适用于简化列标识,避免多个列标识符重复。
- 使用 as 关键字,也可省略 as.
select stu+10 as add10 from tb;

b. from 子句
用于标识查询来源。
-- 能够为表起别名。使用as关键字。
select * from tb1 as tt, tb2 as bb;
-- from子句后,能够同时出现多个表。
-- 多个表会横向叠加到一块儿,而数据会造成一个笛卡尔积。
select * from tb1, tb2;

c. where 子句
-- 从from得到的数据源中进行筛选。
-- 整型1表示真,0表示假。
-- 表达式由运算符和运算数组成。
-- 运算数:变量(字段)、值、函数返回值
-- 运算符:
=, <=>, <>, !=, <=, <, >=, >, !, &&, ||, 
in (not) null, (not) like, (not) in, (not) between and, is (not), and, or, not, xor
is/is not 加上ture/false/unknown,检验某个值的真假
<=>与<>功能相同,<=>可用于null比较

d. group by 子句, 分组子句
group by 字段/别名 [排序方式]
分组后会进行排序。升序:asc,降序:desc

如下[合计函数]需配合 group by 使用:
count 返回不一样的非null值数目 count(*)、count(字段)
sum 求和
max 求最大值
min 求最小值
avg 求平均值
group_concat 返回带有来自一个组的链接的非null值的字符串结果。组内字符串链接。

e. having 子句,条件子句
与 where 功能、用法相同,执行时机不一样。
where 在开始时执行检测数据,对原数据进行过滤。
having 对筛选出的结果再次进行过滤。
having 字段必须是查询出来的,where 字段必须是数据表存在的。
where 不能够使用字段的别名,having 能够。由于执行where代码时,可能还没有肯定列值。
where 不能够使用合计函数。通常需用合计函数才会用 having
sql标准要求having必须引用group by子句中的列或用于合计函数中的列。

f. order by 子句,排序子句
order by 排序字段/别名 排序方式 [,排序字段/别名 排序方式]...
升序:asc,降序:desc
支持多个字段的排序。

g. limit 子句,限制结果数量子句
仅对处理好的结果进行数量限制。将处理好的结果的看做是一个集合,按照记录出现的顺序,索引从0开始。
limit 起始位置, 获取条数
省略第一个参数,表示从索引0开始。limit 获取条数

h. distinct, all 选项
distinct 去除重复记录
默认为 all, 所有记录


/* union */ ------------------
将多个select查询的结果组合成一个结果集合。
select ... union [all|distinct] select ...
默认 distinct 方式,即全部返回的行都是惟一的
建议,对每一个select查询加上小括号包裹。
order by 排序时,需加上 limit 进行结合。
须要各select查询的字段数量同样。
每一个select查询的字段列表(数量、类型)应一致,由于结果中的字段名以第一条select语句为准。


/* 子查询 */ ------------------
- 子查询需用括号包裹。
-- from型
from后要求是一个表,必须给子查询结果取个别名。
- 简化每一个查询内的条件。
- from型需将结果生成一个临时表格,可用以原表的锁定的释放。
- 子查询返回一个表,表型子查询。
select * from (select * from tb where id>0) as subfrom where id>1;
-- where型
- 子查询返回一个值,标量子查询。
- 不须要给子查询取别名。
- where子查询内的表,不能直接用以更新。
select * from tb where money = (select max(money) from tb);
-- 列子查询
若是子查询结果返回的是一列。
使用 in 或 not in 完成查询
exists 和 not exists 条件
若是子查询返回数据,则返回1或0。经常使用于判断条件。
select column1 from t1 where exists (select * from t2);
-- 行子查询
查询条件是一个行。
select * from t1 where (id, gender) in (select id, gender from t2);
行构造符:(col1, col2, ...) 或 row(col1, col2, ...)
行构造符一般用于与对能返回两个或两个以上列的子查询进行比较。

-- 特殊运算符
!= all() 至关于 not in
= some() 至关于 in。any 是 some 的别名
!= some() 不等同于 not in,不等于其中某一个。
all, some 能够配合其余运算符一块儿使用。


/* 链接查询(join) */ ------------------
将多个表的字段进行链接,能够指定链接条件。
-- 内链接(inner join)
- 默认就是内链接,可省略inner。
- 只有数据存在时才能发送链接。即链接结果不能出现空行。
on 表示链接条件。其条件表达式与where相似。也能够省略条件(表示条件永远为真)
也可用where表示链接条件。
还有 using, 但需字段名相同。 using(字段名)

-- 交叉链接 cross join
即,没有条件的内链接。
select * from tb1 cross join tb2;
-- 外链接(outer join)
- 若是数据不存在,也会出如今链接结果中。
-- 左外链接 left join
若是数据不存在,左表记录会出现,而右表为null填充
-- 右外链接 right join
若是数据不存在,右表记录会出现,而左表为null填充
-- 天然链接(natural join)
自动判断链接条件完成链接。
至关于省略了using,会自动查找相同字段名。
natural join
natural left join
natural right join

select info.id, info.name, info.stu_num, extra_info.hobby, extra_info.sex from info, extra_info where info.stu_num = extra_info.stu_id;

/* 导入导出 */ ------------------
select * into outfile 文件地址 [控制格式] from 表名; -- 导出表数据
load data [local] infile 文件地址 [replace|ignore] into table 表名 [控制格式]; -- 导入数据
生成的数据默认的分隔符是制表符
local未指定,则数据文件必须在服务器上
replace 和 ignore 关键词控制对现有的惟一键记录的重复的处理
-- 控制格式
fields 控制字段格式
默认:fields terminated by '\t' enclosed by '' escaped by '\\'
terminated by 'string' -- 终止
enclosed by 'char' -- 包裹
escaped by 'char' -- 转义
-- 示例:
select a,b,a+b into outfile '/tmp/result.text'
fields terminated by ',' optionally enclosed by '"'
lines terminated by '\n'
from test_table;
lines 控制行格式
默认:lines terminated by '\n'
terminated by 'string' -- 终止

/* insert */ ------------------
select语句得到的数据能够用insert插入。

能够省略对列的指定,要求 values () 括号内,提供给了按照列顺序出现的全部字段的值。
或者使用set语法。
insert into tbl_name set field=value,...;

能够一次性使用多个值,采用(), (), ();的形式。
insert into tbl_name values (), (), ();

能够在列值指定时,使用表达式。
insert into tbl_name values (field_value, 10+10, now());
能够使用一个特殊值 default,表示该列使用默认值。
insert into tbl_name values (field_value, default);

能够经过一个查询的结果,做为须要插入的值。
insert into tbl_name select ...;

能够指定在插入的值出现主键(或惟一索引)冲突时,更新其余非主键列的信息。
insert into tbl_name values/set/select on duplicate key update 字段=值, …;

/* delete */ ------------------
delete from tbl_name [where where_definition] [order by ...] [limit row_count]

按照条件删除

指定删除的最多记录数。limit

能够经过排序条件删除。order by + limit

支持多表删除,使用相似链接语法。
delete from 须要删除数据多表1,表2 using 表链接操做 条件。

/* truncate */ ------------------
truncate [table] tbl_name
清空数据
删除重建表

区别:
1,truncate 是删除表再建立,delete 是逐条删除
2,truncate 重置auto_increment的值。而delete不会
3,truncate 不知道删除了几条,而delete知道。
4,当被用于带分区的表时,truncate 会保留分区


/* 备份与还原 */ ------------------
备份,将数据的结构与表内数据保存起来。
利用 mysqldump 指令完成。

-- 导出
1. 导出一张表
  mysqldump -u用户名 -p密码 库名 表名 > 文件名(d:/a.sql)
2. 导出多张表
  mysqldump -u用户名 -p密码 库名 表1 表2 表3 > 文件名(d:/a.sql)
3. 导出全部表
  mysqldump -u用户名 -p密码 库名 > 文件名(d:/a.sql)
4. 导出一个库 
  mysqldump -u用户名 -p密码 -b 库名 > 文件名(d:/a.sql)

能够-w携带备份条件

-- 导入
1. 在登陆mysql的状况下:
  source 备份文件
2. 在不登陆的状况下
  mysql -u用户名 -p密码 库名 < 备份文件


/* 视图 */ ------------------
什么是视图:
视图是一个虚拟表,其内容由查询定义。同真实的表同样,视图包含一系列带有名称的列和行数据。可是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,而且在引用视图时动态生成。
视图具备表结构文件,但不存在数据文件。
对其中所引用的基础表来讲,视图的做用相似于筛选。定义视图的筛选能够来自当前或其它数据库的一个或多个表,或者其它视图。经过视图进行查询没有任何限制,经过它们进行数据修改时的限制也不多。
视图是存储在数据库中的查询的sql语句,它主要出于两种缘由:安全缘由,视图能够隐藏一些数据,如:社会保险基金表,能够用视图只显示姓名,地址,而不显示社会保险号和工资数等,另外一缘由是可以使复杂的查询易于理解和使用。

-- 建立视图
create [or replace] [algorithm = {undefined | merge | temptable}] view view_name [(column_list)] as select_statement
- 视图名必须惟一,同时不能与表重名。
- 视图能够使用select语句查询到的列名,也能够本身指定相应的列名。
- 能够指定视图执行的算法,经过algorithm指定。
- column_list若是存在,则数目必须等于select语句检索的列数

-- 查看结构
show create view view_name

-- 删除视图
- 删除视图后,数据依然存在。
- 可同时删除多个视图。
drop view [if exists] view_name ...

-- 修改视图结构
- 通常不修改视图,由于不是全部的更新视图都会映射到表上。
alter view view_name [(column_list)] as select_statement

-- 视图做用
1. 简化业务逻辑
2. 对客户端隐藏真实的表结构

-- 视图算法(algorithm)
merge 合并
将视图的查询语句,与外部查询须要先合并再执行!
temptable 临时表
将视图执行完毕后,造成临时表,再作外层查询!
undefined 未定义(默认),指的是mysql自主去选择相应的算法。

 

/* 事务(transaction) */ ------------------
事务是指逻辑上的一组操做,组成这组操做的各个单元,要不全成功要不全失败。 
- 支持连续sql的集体成功或集体撤销。
- 事务是数据库在数据晚自习方面的一个功能。
- 须要利用 innodb 或 bdb 存储引擎,对自动提交的特性支持完成。
- innodb被称为事务安全型引擎。

-- 事务开启
start transaction; 或者 begin;
开启事务后,全部被执行的sql语句均被认做当前事务内的sql语句。
-- 事务提交
commit;
-- 事务回滚
rollback;
若是部分操做发生问题,映射到事务开启前。

-- 事务的特性
1. 原子性(atomicity)
事务是一个不可分割的工做单位,事务中的操做要么都发生,要么都不发生。
2. 一致性(consistency)
事务先后数据的完整性必须保持一致。
- 事务开始和结束时,外部数据一致
- 在整个事务过程当中,操做是连续的
3. 隔离性(isolation)
多个用户并发访问数据库时,一个用户的事务不能被其它用户的事物所干扰,多个并发事务之间的数据要相互隔离。
4. 持久性(durability)
一个事务一旦被提交,它对数据库中的数据改变就是永久性的。

-- 事务的实现
1. 要求是事务支持的表类型
2. 执行一组相关的操做前开启事务
3. 整组操做完成后,都成功,则提交;若是存在失败,选择回滚,则会回到事务开始的备份点。

-- 事务的原理
利用innodb的自动提交(autocommit)特性完成。
普通的mysql执行语句后,当前的数据提交操做都可被其余客户端可见。
而事务是暂时关闭“自动提交”机制,须要commit提交持久化数据操做。

-- 注意
1. 数据定义语言(ddl)语句不能被回滚,好比建立或取消数据库的语句,和建立、取消或更改表或存储的子程序的语句。
2. 事务不能被嵌套

-- 保存点
savepoint 保存点名称 -- 设置一个事务保存点
rollback to savepoint 保存点名称 -- 回滚到保存点
release savepoint 保存点名称 -- 删除保存点

-- innodb自动提交特性设置
set autocommit = 0|1; 0表示关闭自动提交,1表示开启自动提交。
- 若是关闭了,那普通操做的结果对其余客户端也不可见,须要commit提交后才能持久化数据操做。
- 也能够关闭自动提交来开启事务。但与start transaction不一样的是,
set autocommit是永久改变服务器的设置,直到下次再次修改该设置。(针对当前链接)
而start transaction记录开启前的状态,而一旦事务提交或回滚后就须要再次开启事务。(针对当前事务)


/* 锁表 */
表锁定只用于防止其它客户端进行不正当地读取和写入
myisam 支持表锁,innodb 支持行锁
-- 锁定
lock tables tbl_name [as alias]
-- 解锁
unlock tables


/* 触发器 */ ------------------
触发程序是与表有关的命名数据库对象,当该表出现特定事件时,将激活该对象
监听:记录的增长、修改、删除。

-- 建立触发器
create trigger trigger_name trigger_time trigger_event on tbl_name for each row trigger_stmt
参数:
trigger_time是触发程序的动做时间。它能够是 before 或 after,以指明触发程序是在激活它的语句以前或以后触发。
trigger_event指明了激活触发程序的语句的类型
insert:将新行插入表时激活触发程序
update:更改某一行时激活触发程序
delete:从表中删除某一行时激活触发程序
tbl_name:监听的表,必须是永久性的表,不能将触发程序与temporary表或视图关联起来。
trigger_stmt:当触发程序激活时执行的语句。执行多个语句,可以使用begin...end复合语句结构

-- 删除
drop trigger [schema_name.]trigger_name

能够使用old和new代替旧的和新的数据
更新操做,更新前是old,更新后是new.
删除操做,只有old.
增长操做,只有new.

-- 注意
1. 对于具备相同触发程序动做时间和事件的给定表,不能有两个触发程序。


-- 字符链接函数
concat(str1[, str2,...])

-- 分支语句
if 条件 then
执行语句
elseif 条件 then
执行语句
else
执行语句
end if;

-- 修改最外层语句结束符
delimiter 自定义结束符号
sql语句
自定义结束符号

delimiter ; -- 修改回原来的分号

-- 语句块包裹
begin
语句块
end

-- 特殊的执行
1. 只要添加记录,就会触发程序。
2. insert into on duplicate key update 语法会触发:
若是没有重复记录,会触发 before insert, after insert;
若是有重复记录并更新,会触发 before insert, before update, after update;
若是有重复记录可是没有发生更新,则触发 before insert, before update
3. replace 语法 若是有记录,则执行 before insert, before delete, after delete, after insert


/* sql编程 */ ------------------

--// 局部变量 ----------
-- 变量声明
declare var_name[,...] type [default value] 
这个语句被用来声明局部变量。要给变量提供一个默认值,请包含一个default子句。值能够被指定为一个表达式,不须要为一个常数。若是没有default子句,初始值为null。

-- 赋值
使用 set 和 select into 语句为变量赋值。

- 注意:在函数内是能够使用全局变量(用户自定义的变量)


--// 全局变量 ----------
-- 定义、赋值
set 语句能够定义并为变量赋值。
set @var = value;
也能够使用select into语句为变量初始化并赋值。这样要求select语句只能返回一行,可是能够是多个字段,就意味着同时为多个变量进行赋值,变量的数量须要与查询的列数一致。
还能够把赋值语句看做一个表达式,经过select执行完成。此时为了不=被看成关系运算符看待,使用:=代替。(set语句能够使用= 和 :=)。
select @var:=20;
select @v1:=id, @v2=name from t1 limit 1;
select * from tbl_name where @var:=30;

select into 能够将表中查询得到的数据赋给变量。
-| select max(height) into @max_height from tb;

-- 自定义变量名
为了不select语句中,用户自定义的变量与系统标识符(一般是字段名)冲突,用户自定义变量在变量名前使用@做为开始符号。
@var=10;

- 变量被定义后,在整个会话周期都有效(登陆到退出)


--// 控制结构 ----------
-- if语句
if search_condition then 
statement_list 
[elseif search_condition then
statement_list]
...
[else
statement_list]
end if;

-- case语句
case value when [compare-value] then result
[when [compare-value] then result ...]
[else result]
end


-- while循环
[begin_label:] while search_condition do
statement_list
end while [end_label];

- 若是须要在循环内提早终止 while循环,则须要使用标签;标签须要成对出现。

-- 退出循环
退出整个循环 leave
退出当前循环 iterate
经过退出的标签决定退出哪一个循环


--// 内置函数 ----------
-- 数值函数
abs(x) -- 绝对值 abs(-10.9) = 10
format(x, d) -- 格式化千分位数值 format(1234567.456, 2) = 1,234,567.46
ceil(x) -- 向上取整 ceil(10.1) = 11
floor(x) -- 向下取整 floor (10.1) = 10
round(x) -- 四舍五入去整
mod(m, n) -- m%n m mod n 求余 10%3=1
pi() -- 得到圆周率
pow(m, n) -- m^n
sqrt(x) -- 算术平方根
rand() -- 随机数
truncate(x, d) -- 截取d位小数

-- 时间日期函数
now(), current_timestamp(); -- 当前日期时间
current_date(); -- 当前日期
current_time(); -- 当前时间
date('yyyy-mm-dd hh:ii:ss'); -- 获取日期部分
time('yyyy-mm-dd hh:ii:ss'); -- 获取时间部分
date_format('yyyy-mm-dd hh:ii:ss', '%d %y %a %d %m %b %j'); -- 格式化时间
unix_timestamp(); -- 得到unix时间戳
from_unixtime(); -- 从时间戳得到时间

-- 字符串函数
length(string) -- string长度,字节
char_length(string) -- string的字符个数
substring(str, position [,length]) -- 从str的position开始,取length个字符
replace(str ,search_str ,replace_str) -- 在str中用replace_str替换search_str
instr(string ,substring) -- 返回substring首次在string中出现的位置
concat(string [,...]) -- 链接字串
charset(str) -- 返回字串字符集
lcase(string) -- 转换成小写
left(string, length) -- 从string2中的左边起取length个字符
load_file(file_name) -- 从文件读取内容
locate(substring, string [,start_position]) -- 同instr,但可指定开始位置
lpad(string, length, pad) -- 重复用pad加在string开头,直到字串长度为length
ltrim(string) -- 去除前端空格
repeat(string, count) -- 重复count次
rpad(string, length, pad) --在str后用pad补充,直到长度为length
rtrim(string) -- 去除后端空格
strcmp(string1 ,string2) -- 逐字符比较两字串大小

-- 流程函数
case when [condition] then result [when [condition] then result ...] [else result] end 多分支
if(expr1,expr2,expr3) 双分支。

-- 聚合函数
count()
sum();
max();
min();
avg();
group_concat()

-- 其余经常使用函数
md5();
default();


--// 存储函数,自定义函数 ----------
-- 新建
create function function_name (参数列表) returns 返回值类型
函数体

- 函数名,应该合法的标识符,而且不该该与已有的关键字冲突。
- 一个函数应该属于某个数据库,能够使用db_name.funciton_name的形式执行当前函数所属数据库,不然为当前数据库。
- 参数部分,由"参数名"和"参数类型"组成。多个参数用逗号隔开。
- 函数体由多条可用的mysql语句,流程控制,变量声明等语句构成。
- 多条语句应该使用 begin...end 语句块包含。
- 必定要有 return 返回值语句。

-- 删除
drop function [if exists] function_name;

-- 查看
show function status like 'partten'
show create function function_name;

-- 修改
alter function function_name 函数选项


--// 存储过程,自定义功能 ----------
-- 定义
存储存储过程 是一段代码(过程),存储在数据库中的sql组成。
一个存储过程一般用于完成一段业务逻辑,例如报名,交班费,订单入库等。
而一个函数一般专一与某个功能,视为其余程序服务的,须要在其余语句中调用函数才能够,而存储过程不能被其余调用,是本身执行 经过call执行。

-- 建立
create procedure sp_name (参数列表)
过程体

参数列表:不一样于函数的参数列表,须要指明参数类型
in,表示输入型
out,表示输出型
inout,表示混合型

注意,没有返回值。


/* 存储过程 */ ------------------
存储过程是一段可执行性代码的集合。相比函数,更偏向于业务逻辑。
调用:call 过程名
-- 注意
- 没有返回值。
- 只能单独调用,不可夹杂在其余语句中

-- 参数
in|out|inout 参数名 数据类型
in 输入:在调用过程当中,将数据输入到过程体内部的参数
out 输出:在调用过程当中,将过程体处理完的结果返回到客户端
inout 输入输出:既可输入,也可输出

-- 语法
create procedure 过程名 (参数列表)
begin
过程体
end

 

/* 表维护 */
-- 分析和存储表的关键字分布
analyze [local | no_write_to_binlog] table 表名 ...
-- 检查一个或多个表是否有错误
check table tbl_name [, tbl_name] ... [option] ...
option = {quick | fast | medium | extended | changed}
-- 整理数据文件的碎片
optimize [local | no_write_to_binlog] table tbl_name [, tbl_name] ...


/* 杂项 */ ------------------
1. 可用反引号(`)为标识符(库名、表名、字段名、索引、别名)包裹,以免与关键字重名!中文也能够做为标识符!
2. 每一个库目录存在一个保存当前数据库的选项文件db.opt。
3. 注释:
单行注释 # 注释内容
多行注释 /* 注释内容 */
单行注释 -- 注释内容 (标准sql注释风格,要求双破折号后加一空格符(空格、tab、换行等))
4. 模式通配符:
_ 任意单个字符
% 任意多个字符,甚至包括零字符
单引号须要进行转义 \'
5. cmd命令行内的语句结束符能够为 ";", "\g", "\g",仅影响显示结果。其余地方仍是用分号结束。delimiter 可修改当前对话的语句结束符。
6. sql对大小写不敏感
7. 清除已有语句:\c

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

MySQL学习笔记

Chapter 1. MySQL数据库的数据

 
 

MySQL数据库是由数据组成的,为了能方便管理和使用这些数据,咱们把这些数据进行分类,造成各类数据类型,有数据值的类型,有表中数据列的类型,有数据表的类型。理解MySQL的这些数据类型能使咱们更好地使用MySQL数据库。下面对各类数据类型进行简单的介绍。

1.1. 数据值类型(data type)

 

对MySQL中数据值的分类,有数值型、字符型、日期型和空值等,这和通常的编程语言的分类差很少。

1.1.1. 数值

 

MySQL中的数值分整型和浮点型两种。MySQL支持科学记数法。整型能够是十进制,也但是十六进制数。

1.1.2. 字符串

 

MySQL支持以单或双引号包围的字符序列。如“MySQL tutorial”、‘Mysql Database’。

MySQL能识别字符串中的转义序列,转义序列用反斜杠(\)表示。下面是一个转义序列列表。

Table 1.1. 转义序列

转义序列 含义
\0 NUL(ASCII的0值)
\' 单引号
\" 双引号
\b 后退符
\n 换行符
\r 回车符
\t 制表符
\\ 反斜杠
\Z Ctrl+Z

若是字符串自己包含有单双引号,则用如下三种方法中的一种来表示:

  • 字符串的引号和字符串两端的引号双同,则双写该引号。如:'mysql''s test'。

  • 用与字符串的引号不一样的引号把字符串引发来,如:"mysql's test"。

  • 用反斜杠转义引号,如:"mysql\' test",'mysql\' test'。这样就不用理会字符串两端的是单引号仍是双引号了。

字符串可由一个十六进制数表示,如0x61表示字符"a"。由MySQL 4.0开始,字符串值也可用ANSI SQL表示法X'val'来表示。如X'61'表示字符"a"。

从MySQL 4.1开始,能够为字符串值专门指定一个字符集。

1.1.3. 日期和时间

 

MySQL默认按“年-月-日”的顺序显示日期。

1.2. 列类型(column type)

 

MySQL数据库的表是一个二维表,由一个或多个数据列构成。每一个数据列都有它的特定类型,该类型决定了MySQL如何看待该列数据,咱们能够把整型数值存放到字符类型的列中,MySQL则会把它当作字符串来处理。MySQL中的列类型有三种:数值类、字符串类和日期/时间类。从大类来看列类型和数值类型同样,都是只有三种。但每种列类型都还可细分。下面对各类列类型进行详细介绍。

1.2.1. 数值类的数据列类型

 

数值型的列类型包括整型和浮点型两大类。

Table 1.2. 数值类数据列类型

数据列类型 存储空间 描述
TINYINT 1字节 很是小的正整数,带符号:-128~127,不带符号:0~255
SMALLINT 2字节 小整数,带符号:-32768~32767,不带符号:0~65535
MEDIUMINT 3字节 中等大小的整数,带符号:-8388608~8388607,不带符号:0~16777215
INT 4字节 标准整数,带符号:-2147483648~2147483647,不带符号:0~4294967295
BIGINT 8字节 大整数,带符号:-9223372036854775808~9233372036854775807,不带符号:0~18446744073709551615
FLOAT 4字节 单精度浮点数,最小非零值:+-1.175494351E-38,最大非零值:+-3.402823466E+38
DOUBLE 8字节 双精度浮点数,最小非零值:+-2.2250738585072014E-308,最大非零值:+-1.7976931348623157E+308
DECIMAL M+2字节 以字符串形式表示的浮点数,它的取值范围可变,由M和D的值决定。

1.2.1.1. 整型数据列类型

 

MySQL有五种整型数据列类型,即TINYINT,SMALLINT,MEDIUMINT,INT和BIGINT。它们之间的区别是取值范围不一样,存储空间也各不相同。在整型数据列后加上UNSIGNED属性能够禁止负数,取值从0开始。

声明整型数据列时,咱们能够为它指定个显示宽度M(1~255),如INT(5),指定显示宽度为5个字符,若是没有给它指定显示宽度,MySQL会为它指定一个默认值。显示宽度只用于显示,并不能限制取值范围和占用空间,如:INT(3)会占用4个字节的存储空间,而且容许的最大值也不会是999,而是INT整型所容许的最大值。

1.2.1.2. 浮点型数据列类型

 

MySQL有三种浮点型数据列类型,分别是:FLOAT,DOUBLE和DECIMAL。浮点类数据类型有一个最大可表示值和一个最小非零可表示值,最小非零可表示值决定了该类型的精确度。

MySQL 4.0.2版以后,FLOAT和DOUBLE均可以指定UNSIGNED属性。当指定该属性时,取值范围不平移到正数区间,而只是简单地把浮点类型的负数部份去掉。

浮点类型也有M(1~255)和D(1~30,且不能大于M-2)。分别表示显示宽度和小数位数。M和D在FLOAT和DOUBLE中是可选的,默认,当MySQL版本大于3.23.6时,FLOAT和DOUBLE类型将被保存为硬件所支持的最大精度。DECIMAL的M和D值在MySQL3.23.6后可选,默认D值为0,M值为10。

1.2.1.3. 如何选择数值类数据列类型?

 

为了节省存储空间和提升数据库处理效率,咱们应根据应用数据的取值范围来选择一个最适合的数据列类型。若是把一个超出数据列取值范围的数存入该列,则MySQL就会截短该值,如:咱们把99999存入SMALLINT(3)数据列里,由于SMALLINT(3)的取值范围是-32768~32767,因此就会被截短成32767存储。显示宽度3不会影响数值的存储。只影响显示。

对于浮点数据列,存入的数值会被该列定义的小数位进行四舍五入。如把一个1.234存入FLOAT(6.1)数据列中,结果是1.2。

DECIMAL与FLOAT和DOUBLE的区别是:DECIMAL类型的值是以字符串的形式被储存起来的,它的小数位数是固定的。它的优势是,不会象FLOAT和DOUBLE类型数据列那样进行四舍五入而产生偏差,因此很适合用于财务计算;而它的缺点是:因为它的存储格式不一样,CPU不能对它进行直接运算,从而影响运算效率。DECIMAL(M,D)总共要占用M+2个字节。

1.2.1.4. 数值类数据列的属性

 
  • ZEROFILL属性适用于全部数值类数据列类型,做用是,若是数值的宽度小于定义的显示宽度,则在数值前填充0。

  • UNSIGNED属性不容许数据列出现负数。

  • AUTO_INCREMENT属性可生成独一无二的数字序列。只对整数类的数据列有效。

  • NULL和NOT NULL属性设置数据列是否可为空。

  • DEFAULT属性可为数据列指定默认值。

1.2.2. 字符串类数据列类型

 

字符串能够用来表示任何一种值,因此它是最基本的类型之一。咱们能够用字符串类型来存储图象或声音之类的二进制数据,也可存储用gzip压缩的数据。下表介绍了各类字符串类型:

Table 1.3. 字符串类数据列类型

类型 最大长度 占用存储空间
CHAR[(M)] M字节 M字节
VARCHAR[(M)] M字节 L+1字节
TINYBLOD,TINYTEXT 2^8-1字节 L+1字节
BLOB,TEXT 2^16-1字节 L+2
MEDIUMBLOB,MEDIUMTEXT 2^24-1字节 L+3
LONGBLOB,LONGTEXT 2^32-1字节 L+4
ENUM('value1','value2',...) 65535个成员 1或2字节
SET('value1','value2',...) 64个成员 1,2,3,4或8字节

L+一、L+2是表示数据列是可变长度的,它占用的空间会根据数据行的增减面则改变。数据行的总长度取决于存放在这些数据列里的数据值的长度。L+1或L+2里多出来的字节是用来保存数据值的长度的。在对长度可变的数据进行处理时,MySQL要把数据内容和数据长度都保存起来。

若是把超出字符串最大长度的数据放到字符类数据列中,MySQL会自动进行截短处理。

ENUM和SET类型的数据列定义里有一个列表,列表里的元素就是该数据列的合法取值。若是试图把一个没有在列表里的值放到数据列里,它会被转换为空字符串(“”)。

字符串类型的值被保存为一组连续的字节序列,并会根据它们容纳的是二进制字符串仍是非二进制字符而被区别对待为字节或者字符:

  • 二进制字符串被视为一个连续的字节序列,与字符集无关。MySQL把BLOB数据列和带BINARY属性的CHAR和VARCHAR数据列里的数据看成二进制值。

  • 非二进制字符串被视为一个连续排列的字符序列。与字符集有关。MySQL把TEXT列与不带BINARY属性的CHAR和VARCHAR数据列里的数据看成二进制值对待。

在MySQL4.1之后的版本中,不一样的数据列能够使用不一样的字符集。在MySQL4.1版本之前,MySQL用服务器的字符集做为默认字符集。

非二进制字符串,即咱们一般所说的字符串,是按字符在字符集中前后次序进行比较和排序的。而二进制字符串由于与字符集无关,因此不以字符顺序排序,而是以字节的二进制值做为比较和排序的依据。下面介绍两种字符串的比较方式:

  • 二进制字符串的比较方式是一个字节一个字节进行的,比较的依据是两个字节的二进制值。也就是说它是区分大小写的,由于同一个字母的大小写的数值编码是不同的。

  • 非二进制字符串的比较方式是一个字符一个字符进行的,比较的依据是两个字符在字符集中的前后顺序。在大多数字符集中,同一个字母的大小写每每有着相同的前后顺序,因此它不区分大小写。

二进制字符串与字符集无关,因此不管按字符计算仍是按字节计算,二进制字符串的长度都是同样的。因此VARCHAR(20)并不表示它最多能容纳20个字符,而是表示它最多只能容纳能够用20个字节表示出来的字符。对于单字节字符集,每一个字符只占用一个字节,因此这二者的长度是同样的,但对于多字节字符集,它能容纳的字符个数确定少于20个。

1.2.2.1. CHAR和VARCHAR

 

CHAR和VARCHAR是最经常使用的两种字符串类型,它们之间的区别是:

  • CHAR是固定长度的,每一个值占用相同的字节,不够的位数MySQL会在它的右边用空格字符补足。

  • VARCHAR是一种可变长度的类型,每一个值占用其恰好的字节数再加上一个用来记录其长度的字节即L+1字节。

CHAR(0)和VARCHAR(0)都是合法的。VARCHAR(0)是从MySQL4.0.2版开始的。它们的做用是做为占位符或用来表示各类on/off开关值。

如何选择CHAR和VARCHAR,这里给出两个原则:

  • 若是数据都有相同的长度,选用VARCHAR会多占用空间,由于有一位用来存储其长度。若是数据长短不一,选用VARCHAR能节省存储空间。而CHAR不论字符长短都需占用相同的空间,即便是空值也不例外。

  • 若是长度出入不大,并且是使用MyISAM或ISAM类型的表,则用CHAR会比VARCHAR好,由于MyISAM和ISAM类型的表对处理固定长度的行的效率高。

[Note]  
在一个数据表里,只要有一个数据列的长度是可变的,则全部数据列的长度将是可变的。MySQL会进行自动地转换。一个例外,CHAR长度小于4的不会进行自动转换,由于MySQL会认为这样作不必,节省不了多少空间。反而MySQL会把大量长度小的VARCHAR转换成CHAR,以减小空间占用量。

1.2.2.2. BLOB和TEXT

 

BLOB是二进制字符串,TEXT是非二进制字符串。二者均可存放大容量的信息。

有关BLOB和TEXT索引的创建:

  • BDB表类型和MySQL3.23.2以上版本的MyISAM表类型容许在BLOB和TEXT数据列上创建索引。

  • ISAM、HEAP和InnoDB表不支持大对象列的索引。

使用BLOB和TEXT应注意的问题:

  • 因为这两个列类型所存储的数据量大,因此删除和修改操做容易在数据表里产生大量的碎片,需按期运行OPTIMIZE TABLE以减小碎片和提升性能。

  • 若是使用的值很是巨大,就需对服务器进行相应的优化调整,增长max_allowed_packet参数的值。对那些可会用到变些巨大数据的客户程序,也需加大它们的数据包大小。

1.2.2.3. ENUM和SET

 

ENUM和SET都是比较特殊的字符串数据列类型,它们的取值范围是一个预先定义好的列表。ENUM或SET数据列的取值只能从这个列表中进行选择。ENUM和SET的主要区别是:

  • ENUM只能取单值,它的数据列表是一个枚举集合。它的合法取值列表最多容许有65535个成员。例如:ENUM("N","Y")表示,该数据列的取值要么是"Y",要么就是"N"。

  • SET可取多值。它的合法取值列表最多容许有64个成员。空字符串也是一个合法的SET值。

ENUM和SET的值是以字符串形式出现的,但在内部,MySQL以数值的形式存储它们。

  • ENUM的合法取值列表中的字符串被按声明定义的顺序被编号,从1开始。

  • SET的编号不是按顺序进行编号的,SET中每个合法取值都对应着SET值里的一个位。第一个合法取值对应0位,第二个合法取值对应1位,以此类推,若是数值形式的SET值等于0,则说明它是一个空字符串,若是某个合法的取值出如今SET数据列里,与之对应的位就会被置位;若是某个合法的取值没有出如今SET数据列里,与之对应的位就会被清零。正由于SET值与位有这样的对应关系,因此SET数据列的多个合法取值才能同时出现并构成SET值。

1.2.2.4. 字符串类型数据列的字符集属性

 

在MySQL 4.1之前的版本,字符串数据列的字符集由服务器的字符决定,MySQL 4.1版之后的版本可对每一个字符串数据列指定不一样的字符串。若是按默认方式设置,可按数据列、数据表、数据库、服务器的顺序关联字符串的字符集,直到找一个明肯定义的字符集。

1.2.3. 日期,时间型数据列类型

 

MySQL的日期时间类型有:DATE,DATETIME,TIME,TIMESTAMP和YEAR,下表是这些类型的取值范围和存储空间要求:

Table 1.4. 日期,时间类型列

类型 取值范围 存储空间 零值表示法
DATE 1000-01-01~9999-12-31 3字节(MySQL3.23版之前是4字节 ) 0000-00-00
TIME -838:59:59~838:59:59 3字节 00:00:00
DATETIME 1000-01-01 00:00:00~9999-12-31 23:59:59 8字节 0000-00-00 00:00:00
TIMESTAMP 19700101000000~2037年的某个时刻 4字节 00000000000000
YEAR YEAR(4):1901~2155 YEAR(2):1970~2069 1字节 0000
[Note]  
MySQL老是把日期和日期里的年份放在最前面,按年月日的顺序显示。

1.2.3.1. DATE、TIME、DATATIME数据列类型

 

DATE、TIME和DATATIME类型分别存放日期值、时间值、日期和时间值的组合。它们的格式分别是“CCYY-MM-DD”、“hh:mm:ss”、“CCYY-MM-DD hh:mm:ss”。

DATATIME里的时间值和TIME值是有区别的,DATATIME里的时间值表明的是几点几分,TIME值表明的是所花费的时间。当向TIME数据列插值时,需用时间的完整写法,如12分30秒要写成“00:12:30”。

1.2.3.2. TIMESTAMP数据列类型

 

TIMESTAMP数据列的格式是CCYYMMDDhhmmss,取值范围从19700101000000开始,即1970年1月1号,最大到2037年。它的特色是能把数据行的建立或修改时间记录下来:

  • 若是把一个NULL值插入TIMESTAMP列,这个数据列就将自动取值为当前的日期和时间。

  • 在建立和修改数据行时,若是没有明确对TIMESTAMP数据列进行赋值,则它就会自动取值为当前的日期和时间。若是行中有多个TIMESTAMP列,只有第一个会自动取值。

  • 若是对TIMESTAMP设置一个肯定的日期和时间值,则会使TIMESTAMP的自动取值功能失效。

TIMESTAMP默认的列宽是14,可指定列宽,以改变显示效果。但不论你指定的列宽如何,MySQL都是以4字节来存储TIMESTAMP值,也老是以14位精度来计算。

若是须要把建立时间和最近一次修改时间同时记录下来,能够用两个时间戳来记录,一个记录建立时间,一个记录修改时间。不过需记住两件事,一是要把记录修改时间的TIMESTAMP数据列放在最前面,这样才会自动取值;二是建立一条新记录时,要用now()函数来初始化建立时间TIMESTAMP数据列,这样,该TIMESTAMP数据列就不会再变化。

1.2.3.3. YEAR

 

YEAR是一种单字节的数据列类型,YEAR(4)的取值范围是1901~2155,YEAR(2)的取值范围是1970~2069,但只显示最后两位数。MySQL能自动把两位数字年份转换成四位数字的年份,如97和14分被转换成1997和2014。转换规则是这样的:

  • 年份值00~69将被转换成2000~2069;

  • 年份值70~99将被转换成1970~1999。

[Note]  
00被转换成0000,而不是2000。由于数值00也就是0,而0值是YEAR的一个合法取值。

1.3. 惟一编号

 

在数据库应用,咱们常常要用到惟一编号,以标识记录。在MySQL中可经过数据列的AUTO_INCREMENT属性来自动生成。MySQL支持多种数据表,每种数据表的自增属性都有差别,这里将介绍各类数据表里的数据列自增属性。

  • ISAM表

    • 若是把一个NULL插入到一个AUTO_INCREMENT数据列里去,MySQL将自动生成下一个序列编号。编号从1开始,并1为基数递增。

    • 把0插入AUTO_INCREMENT数据列的效果与插入NULL值同样。但不建议这样作,仍是以插入NULL值为好。

    • 当插入记录时,没有为AUTO_INCREMENT明确指定值,则等同插入NULL值。

    • 当插入记录时,若是为AUTO_INCREMENT数据列明确指定了一个数值,则会出现两种状况,状况一,若是插入的值与已有的编号重复,则会出现出错信息,由于AUTO_INCREMENT数据列的值必须是惟一的;状况二,若是插入的值大于已编号的值,则会把该插入到数据列中,并使在下一个编号将从这个新值开始递增。也就是说,能够跳过一些编号。

    • 若是自增序列的最大值被删除了,则在插入新记录时,该值被重用。

    • 若是用UPDATE命令更新自增列,若是列值与已有的值重复,则会出错。若是大于已有值,则下一个编号从该值开始递增。

    • 若是用replace命令基于AUTO_INCREMENT数据列里的值来修改数据表里的现有记录,即AUTO_INCREMENT数据列出如今了replace命令的where子句里,相应的AUTO_INCREMENT值将不会发生变化。但若是replace命令是经过其它的PRIMARY KEY OR UNIQUE索引来修改现有记录的(即AUTO_INCREMENT数据列没有出如今replace命令的where子句中),相应的AUTO_INCREMENT值--若是设置其为NULL(如没有对它赋值)的话--就会发生变化。

    • last_insert_id()函数可得到自增列自动生成的最后一个编号。但该函数只与服务器的本次会话过程当中生成的值有关。若是在与服务器的本次会话中还没有生成AUTO_INCREMENT值,则该函数返回0。

    其它数据表的自动编号机制都以ISAM表中的机制为基础。

  • MyISAM数据表

    • 删除最大编号的记录后,该编号不可重用。

    • 可在建表时可用“AUTO_INCREMENT=n”选项来指定一个自增的初始值。

    • 可用alter table table_name AUTO_INCREMENT=n命令来重设自增的起始值。

    • 可以使用复合索引在同一个数据表里建立多个相互独立的自增序列,具体作法是这样的:为数据表建立一个由多个数据列组成的PRIMARY KEY OR UNIQUE索引,并把AUTO_INCREMENT数据列包括在这个索引里做为它的最后一个数据列。这样,这个复合索引里,前面的那些数据列每构成一种独一无二的组合,最末尾的AUTO_INCREMENT数据列就会生成一个与该组合相对应的序列编号。

  • HEAP数据表

    • HEAP数据表从MySQL4.1开始才容许使用自增列。

    • 自增值可经过CREATE TABLE语句的 AUTO_INCREMENT=n选项来设置。

    • 可经过ALTER TABLE语句的AUTO_INCREMENT=n选项来修改自增始初值。

    • 编号不可重用。

    • HEAP数据表不支持在一个数据表中使用复合索引来生成多个互不干扰的序列编号。

  • BDB数据表

    • 不可经过CREATE TABLE OR ALTER TABLE的AUTO_INCREMENT=n选项来改变自增初始值。

    • 可重用编号。

    • 支持在一个数据表里使用复合索引来生成多个互不干扰的序列编号。

  • InnDB数据表

    • 不可经过CREATE TABLE OR ALTER TABLE的AUTO_INCREMENT=n选项来改变自增初始值。

    • 不可重用编号。

    • 不支持在一个数据表里使用复合索引来生成多个互不干扰的序列编号。

在使用AUTO_INCREMENT时,应注意如下几点:

  • AUTO_INCREMENT是数据列的一种属性,只适用于整数类型数据列。

  • 设置AUTO_INCREMENT属性的数据列应该是一个正数序列,因此应该把该数据列声明为UNSIGNED,这样序列的编号个可增长一倍。

  • AUTO_INCREMENT数据列必须有惟一索引,以免序号重复。

  • AUTO_INCREMENT数据列必须具有NOT NULL属性。

  • AUTO_INCREMENT数据列序号的最大值受该列的数据类型约束,如TINYINT数据列的最大编号是127,如加上UNSIGNED,则最大为255。一旦达到上限,AUTO_INCREMENT就会失效。

  • 当进行全表删除时,AUTO_INCREMENT会从1从新开始编号。全表删除的意思是发出如下两条语句时:

    delete from table_name;
    or
    truncate table table_name
    

    这是由于进行全表操做时,MySQL实际是作了这样的优化操做:先把数据表里的全部数据和索引删除,而后重建数据表。若是想删除全部的数据行又想保留序列编号信息,可这样用一个带where的delete命令以抑制MySQL的优化:

    delete from table_name where 1;
    

    这将迫使MySQL为每一个删除的数据行都作一次条件表达式的求值操做。

  • 强制MySQL不复用已经使用过的序列值的方法是:另外建立一个专门用来生成AUTO_INCREMENT序列的数据表,并作到永远不去删除该表的记录。当须要在主数据表里插入一条记录时,先在那个专门生成序号的表中插入一个NULL值以产生一个编号,而后,在往主数据表里插入数据时,利用LAST_INSERT_ID()函数取得这个编号,并把它赋值给主表的存放序列的数据列。如:

    insert into id set id = NULL;
    insert into main set main_id = LAST_INSERT_ID();
    
  • 可用alter命令给一个数据表增长一个具备AUTO_INCREMENT属性的数据列。MySQL会自动生成全部的编号。

  • 要从新排列现有的序列编号,最简单的方法是先删除该列,再重建该,MySQL会从新生连续的编号序列。

  • 在不用AUTO_INCREMENT的状况下生成序列,可利用带参数的LAST_INSERT_ID()函数。若是用一个带参数的LAST_INSERT_ID(expr)去插入或修改一个数据列,紧接着又调用不带参数的LAST_INSERT_ID()函数,则第二次函数调用返回的就是expr的值。下面演示该方法的具体操做:

    先建立一个只有一个数据行的数据表:
    create table seq_table (id int unsigned not null);
    insert into seq_table values (0);
    接着用如下操做检索出序列号:
    update seq_table set seq = LAST_INSERT_ID( seq + 1 );
    select LAST_INSERT_ID();
    经过修改seq+1中的常数值,可生成不一样步长的序列,如seq+10可生成步长为10的序列。
    

    该方法可用于计数器,在数据表中插入多行以记录不一样的计数值。再配合LAST_INSERT_ID()函数的返回值生成不一样内容的计数值。这种方法的优势是不用事务或LOCK,UNLOCK表就可生成惟一的序列编号。不会影响其它客户程序的正常表操做。

1.4. 字符集支持

 

MySQL4.1之前版本服务器只能使用单一字符集,从MySQL4.1版本开始,不只服务器可以使用多种字符集,并且在服务器、数据库、数据表、数据列以及字符串常数多个级别上设置不一样的字符集。

1.4.1. MySQL4.1之前版本

 

MySQL4.1之前版本的字符集由服务器默认指定,默认值是编译系统时指定的字符集,该字符集也可经过在启动服务器时指定--default-character-set来修改。这种修改会对数据表的索引形成影响,由于索引的顺序是和字符集有关的,修改字符集会使这个已排序的顺序产生错误。要解决该问题,咱们要用修改后的字符集的排序顺序重建表的索引。重建索引有如下几种方法:

  • 用mysqldump导出数据,再清除表里的内容,最后用导出文件从新导入。数据表的索引将在导入数时重建。该方法适用于全部数据表类型。

  • 删除索引,而后重建。用alter table命令或drop index和create index命令来完成。该方法也适用于全部数据表类型。但该方法须要咱们了解重建索引的精肯定义。

  • MyISAM数据表的索引能够用myisamchk程序的--recover和--quick选项加上一个用来设定新字符集的--set-character-set选项进行重建。还能够用mysqlcheck程序的--repair和--quick选项或者一个带QUICK选项的REPLACE TABLE语句来重建索引,这种方式较方便。

1.4.2. MySQL4.1之后版本

 

MySQL4.1之后的版本对字符集的支持好了不少,具备如下新增功能:

  • 支持服务器同时使用多种字符集。

  • 容许在服务器,数据库,数据表,数据列等多级别上设置不一样的字符集。

    • 服务器的默认字符集在编译时选定,但可在启动服务器时用--default-character-set选项来更改。

    • 用ALTER DATABASE db_name DEFAULT CHARACTER SET charset来设置数据库字符集。 若是只有default参数,则使用服务器的字符集。

    • 用CREATE TABLE table_name(...) CHARACTER SET = charset设置数据表字符集。若是charset为default,则使用数据表所在数据库的字符集做为数据表的字符集。

    • 在数据列中,可用CHARACTER SET charset属性来设置数据列的字符集。charset不能是default,若是没有该属性,则默认使用数据表的字符集。容许设置字符集的数据列有char,varchar(不带binary属性)及TEXT类型。

    • 用_charset str转换字符串常数的字符集。如:_utf8 'mysql',_latinl 'oracle'。该方法只适用于括在引号内的字符串,其它十六进制常数 、字符串表达式等可用CONVERT()函数进行转换,如:SELECT CONVERT( str USING charset)。

  • 经过MySQL提供的函数可进行字符集转换和查询。

  • 新增的COLLATE操做符使咱们可按某一种字符集的排序顺序来处理另外一种字符集的数据。如:SELECT a from t ORDER BY a COLLATE utf-8;

  • 用SHOW CHARACTER SET命令可显示服务器支持的字符集列表。

  • 当服务器转换到另外一种字符集时,会自动对索引进行从新排序。

  • 经过UTF-8和UCS2字符集提供了Unicode支持。

MySQL如今还不支持:1,在同一个字符串里混用不一样字符集的字符;2,在同一个数据列里混用不一样的字符集。

1.4.3. 各级字符集的查询方法

 
  • 服务器级

    SHOW CHARACTER SET;可查出可供使用的全部字符集。
    SHOW VARIABLES LIKE 'character_set';可查出服务器的默认字符集。
    
  • 可查出数据库级的字符集。

    SHOW CREATE DATABASE db_name;
    
  • 两条命令可查出数据表的字符集。

    SHOW CREATE TABLE table_name;
    SHOW TABLE STATUS LIKE 'table_name'
    
  • 如下几命令可查出数据列的字符集:

    DESCRIBE table_name;
    SHOW COLUMNS FROM table_name;
    SHOW CREATE TABLE table_name;
    
  • 用CHARSET()函数可肯定特定字符串,字符串表达式或数据列值相关联的字符串的字符集。如:SELECT CHARSET(str)。

1.4.4. Unicode支持

 

MySQL提供两种字符集来支持Unicode。一个是UTF-8,一种可变长的编码格式,需用1至4个字节来表示一个字符;另外一个是UCS2,该字符集中的每一个字符须要用两个字节来表示。

1.5. 如何选择数据列类型?

 

选择正确的数据列类型能大大提升数据库的性能和使数据库具备高扩展性。在选择数据列类型时,请从如下几个方面考虑:

  • 存放到数据列中的数据类型。

  • 数据值的取值范围。

  • 考虑性能和处理效率。

    • 数值操做比字符操做快。

    • 小类型的处理速度比大类型快。

    • 不一样数据表中固定长度类型和可变长度类型的处理效率是不一样的。

      可变长度类型在通过删除和修改操做后容易产生碎片,下降系统性能,需按期运行OPTIMIZE TABLE命令以优化数据表。

      固定长度类型因为有固定的长度,因此容易肯定每条记录的起始点,可加快数据表的修复速度。

      在MyISAM和ISAM表中使用固定长度类型数据列有助改善数据库性能。

      在InnoDB表中,固定长度和可变长度数据列类型都以相同方式存储,因此固定长度数据列类型并无性能优点,反而因为可度长度数据列类型因为占用存储空间较少,因此处理速度会快些。

    • 可索引类型能加快数据的查询速度。

    • 明确指定数据列的NOT NULL属性可以使MySQL在检索过程当中不用去判断数据列是不是NULL,因此可加快处理速度。

  • 数据如何进行比较,是否区分大小写。

  • 是否要在数据列上创建索引。

1.6. 表达式操做符

 

Table 1.5. 算术操做符

操做符 语法 含义
+ a + b 相加
- a - b 相减
- - a 求负
* a * b 乘法
/ a / b 除法
% a % b 求余

Table 1.6. 逻辑操做符

操做符 语法 含义
AND 或 && a AND b 或 a && b 逻辑与,若两个操做数同时为真,则为真
OR 或 || a OR b 或 a || b 逻辑或,只要有一个操做数为真,则为真
XOR a XOR b 逻辑异或,如有且仅有一个操做数为真,则为真
NOT 或 ! NOT a 或 !a 逻辑非,若操做数为假,则为真

Table 1.7. 位操做符

操做符 语法 含义
& a & b 按位与,若操做数同位同为1,则该位为1
| a | b 按位或,若操做数同位有一位为1,则该位为1
^ a ^ b 按拉异或,若操做数同一位分别为1和0,则该位为1
<< a << b 把a中的各个位左移b个位置
>> a >> b 把a中的各个位右移b个位置

Table 1.8. 比较操做符

操做符 语法 含义
= a = b 若两个操做数相等,则为真
<=> a <=> b 若两个操做数相等,则为真,可用于NULL值比较
!= 或 <> a != b 或 a <> b 若两个操用数不等,则为真
< a < b 若a小于b,则为真
<= a <= b 若a小于或等于b,则为真
> a > b 若a大于b,则为真
>= a > b 若a大于或等于b,则为真
IN a IN (b1,b2,...) 若a等于b1,b2,...中的某一个,则为真
BETWEEN a BETWEEN b AND c 若a在b和c之间(包括b和c),则为真
NOT BETWEEN a NOT BETWEEN b AND c 若a不在b和c之间(包括b和c),则为真
LIKE a LIKE b SQL模式匹配,若a匹配b,则为真
NOT LIKE a NOT LIKE b SQL模式匹配,若a不匹配b,则为真
REGEXP a REGEXP b 正则表达式匹配,若a匹配b,则为真
NOT REGEXP a NOT REGEXP b 正则表达式匹配,若a不匹配b,则为真
IS NULL a IS NULL 若a为NULL,则为真
IS NOT NULL a IS NOT NULL 若a不为NULL,则为真
[Note]  
LIKE模式匹配中的“%”匹配任意个字符,“_”匹配一个字符。匹配不区分大小写字符。

Table 1.9. 操做符优先级(由高至低排列)

操做符
BINARY,COLLATE
NOT、!
^
XOR
-(一元求负操做符)、~(一元取反操做符)
*、/、%
+、-
<<、>>
&
|
<、<=、=、<=>、!=、<>、>=、>、IN、IS、LIKE、REGEXP、RLIKE
BETWEEN、CASE、WHEN、THEN、ELSE
AND、&&
OR、||
:=

1.7. 类型转换

 

在MySQL的表达式中,若是某个数据值的类型与上下文所要求的类型不相符,MySQL则会根据将要进行的操做自动地对数据值进行类型转换。如:

1 + '2'      会转换成1 + 2 = 3
1+ 'abc'     会转换成1 + 0 = 1 因为abc不能转换成任何的值,因此默认为0

MySQL会根据表达式上下文的要求,把字符串和数值自动转换为日期和时间值

对于超范围或非法的值,MySQL也会进行转换,但转换出来的结果是错误的。出现该状况时,MySQL会提示警告信息,咱们可捕获该信息以进行相应的处理。

Chapter 2. 查询优化

 

数据库是数据的集合,与数学的集合论有密不可分的关系。

为提升查询速度,咱们能够:

  • 对数据表添加索引,以加快搜索速度;

  • 经过编程技巧最大限度地利用索引;

  • 优化查询语句,以使服务器最快响应多客户的请求。

  • 研究硬件处理过程,减小物理约束。

2.1. 索引

 

索引技术是关系数据查询中最重要的技术。若是要加提高数据库的性能,索引优化是首先应该考虑的。由于它能使咱们的数据库获得最大性能方面的提高。

索引的优势:

  • 没有索引的表是没有排序的数据集合,若是要查询数据需进行全表扫描。有索引的表是一个在索引列上排序了数据表,可经过索引快速定位记录。在MyISAM和ISAM数据表中,数据行保存在数据文件中,索引保存在索引文件中。BDB与InnoDB数据表把数据与索引放在同一个文件中。

  • 在多表关联查询中,索引的做用就更大。若是没有索引,在最坏的状况下,全表扫描的次数多是各表数据行的组合个数,多是一个天文数字。这样的查询是破坏性的,可能会形成数据库瘫痪。

  • 对于使用了MIN()或是MAX()函数的查询,若是相关的数据列上有索引,MySQL能直接找到该最大、最小值的行,根本不用一个一个地去检查数据行。

  • 索引加快ORDER BY 和 GROUP BY子句的操做。

  • 当在数值型数据列上查询数据,而该列有索引,索引能使MySQL根本不用去读取数据行,直接从索引取值。

索引的缺点:

  • 索引需占用磁盘空间。

  • 索引会减慢在索引数据列上的插入、删除和修改操做。

索引列的选择

  • 索引应该建立在搜索、排序、分组等操做所涉及的数据列上。也就是说,在where子句,关联检索中的from子句、order by或group by子句中出现过的数据列最适合用来建立索引。

  • 尽可能使用惟一索引,它能使索引起挥最好的效能。

  • 尽可能用比较短的值进行索引。当对字符串进行索引时,应该指定一个前缀长度,好比对字符串的前10位或20位的字符进行排序,而不用把整个字符串几十个字符用来索引排序。这样能减小磁盘I/O,提升处理速度。最重要的一点是,键值越短,索引缓冲区里容纳的键值也就越多,而MySQL同时保存在内存里的索引越多,索引缓冲区的命中率也就越高。固然,只对数据列第一个字符进行索引是没什么意义的。

  • 充分利用最左前缀。所谓最左前缀也就是在复合索引中最边的索引列。如复合索引(a,b,c) ,其中a就是最左前缀。它是使用率最高的索引,需认真选择。

  • 不要建太多索引,索引是会消耗系统资源的,要适可而止。

  • 索引主要用于<、<=、=、>=、>、BETWEEN等的比较操做中,因此索引应该创建在与这样操做相关的数据列上。

  • 利用慢查询日志来找出性能差的查询,经过mysqldumpslow可查看该日志。针对性能差的查询可利用索引来加快查询速度。

2.2. 查询优化程序

 

当咱们发一条查询命令时,MySQL分对它进行分析,以优化查询。把explain语名放到查询前面可显示查询的执行路线,对优化查询提供有用的信息。如下几个原则可帮助系统挑选和使用索引:

  • 尽可能对同类型的数据列进行比较。如:VARCHAR(5)和VARCHAR(5)是同类型的,CHAR(5)和VARCHAR(5)是不一样类型的。

  • 尽可能让索引的数据列在比较表达式中单独出现,不要把它包含在函数或复杂表达式。不然索引会不起做用。

  • 尽可能不要在LIKE模式的开头使用通配符。如:%string%。

  • 对于MyISAM和BDB数据表,用ANALYZE TABLE语句让服务器对索引键值的分布进行分析,为优化程序提供更有价值的信息。另外一个方法是用myisamchk --analyze(适用于MyISAM表)或isamchk --analyze(适用于ISAM表)命令。

  • 用EXPLAIN语句来分析查询语句的执行效率。检查查询所使用的索引是否是可以迅速地排除不符合条件的数据行,若是不是,能够试着用STRAIGHT_JOIN强制各有关数据表按指定顺序进行关联。

  • 尝试查询的不一样写法,比较运行状况。

  • 不要滥用MySQL的类型自动转换功能。自动转换会减慢查询的速度并会使有关的索引失效。

2.3. 数据列类型与查询效率

 

选用适当的数据列类型有助于提升查询命令的执行速度,下面是几点关于如何选择合适数据列类型的建议:

  • 尽可能选用尺寸较小的数据列。这样能节约磁盘空间和加快查询速度。若是较短的数据列上建有索引,则索引的处理速度会进一步提升。

  • 针对数据列类型,尽可能选择最适用的数据表类型。如固定长度数据列在MyISAM或ISAM数据表中的速度是最快的,因此在这样数据表中尽可能使用char类型而不是varchar类型来保存字符串数据。对于InnoDB数据表类型,因为varchar类型可有效减小占用空间,从而减小磁盘I/O,因此使用varchar类型是有利的。对于BDB类型数据表,使用定长和不定长列类型的区别就不大,可任选一种。

  • 尽可能把数据列声明为NOT NULL,以节约存储空间和加快处理速度。

  • 对于取值范围有限的数据列,考虑使用ENUM数据列类型。ENUM数据列类型在MySQL中的处理速度是很快。

  • 使用PROCEDURE ANALYSE()语句来分析数据表,它会对数据列的声明提出建议,咱们可根据建议进行修改。

    select * from table_name PROCEDURE ANALYSE();
    select * from table_name PROCEDURE ANALYSE(16,256);    #(16,256)含义是:若是某列的不一样取值在16个以上或长度超过256字节,就不提出使用ENUM的建议。
    
  • 用OPTIMIZE TABLE语句对容易出现碎片的数据表进行整理。包含可变长数据列的数据表都会产生碎片,从而占用多余的磁盘空间和影响查询速度。因此要按期运行OPTIMIZE TABLE语句以防止数据表查询性能下降。但该语句只对MyISAM数据表有效。对各类数据表通用的碎片整理方法是这样的:先用工具程序mysqldump导出数据表,再删除数据表后重建,如:

    $ mysqldump --opt db_name table_name > dump.sql
    $ mysql db_name < dump.sql
    
  • 把非结构化和变化大的数据放在BLOB数据列里,按期用OPTIMIZE TABLE命令优化。

  • 人为地给数据表增长一个数据列,以充当索引。作法是这样的,先根据数据表里的其它数据列计算出一个散列值,并保存在一个数据列里,而后经过搜索散列值来检索数据行。注意,该技巧只适用于精确匹配型查询。散列值在大于,小于等的操做中不起做用。散列值能够MD5()(适用于3.23及以上版本),SHA1()(适用于4.0.1及以上版本),CRC32()(适用于4.1及以上版本)等函数生成。使用散列值支检索BLOB和TEXT值的作法比直接检索BLOB和TEXT自己的作法快。

  • 尽可能避免对大尺寸的BLOB值进行检索。若是要检索都应该经过它的上面提到散列值先进行筛选。而不该该盲目地在网络中传送大量BLOB值。

  • 若是把BLOB值剥离到另一个数据表里去,可实现数据表中其它数据列转变成固定长度数据列的话。就便可减小数据表碎片,又可以使在原始表中的select *查询不会把大尺寸的BLOB值没必要要地经过网络传送。

2.4. 有效地加载数据

 

有时咱们需大量地把数据加载到数据表,采用批量加载的方式比一个一个记录加载效率高,由于MySQL不用每加载一条记录就刷新一次索引。下面介绍几个有助于加快数据加载的操做:

  • 使用LOAD DATA语句要比INSERT语句的加载速度快。

  • LOAD DATA比LOAD DATA LOCAL语句的效率高。前者可由服务器直接从本地磁盘读取加载数据,后者需由客户程序去读取文件并经过网络传送到服务器。

  • 若是必定要用INSERT语句,应尽可能在一条语句中插入多个数据行。

  • 若是必须使用多条INSERT语句,则应尽可能把它们集中在一块儿放到一个事务中进行处理,而不是在自动提交模式下执行它们:如:

    BEGIN;
    INSERT INTO table_name values (...);
    INSERT INTO table_name values (...);
    INSERT INTO table_name values (...);
    ...
    COMMIT;
    

    对于不支持事务的表,应对表进行写锁定,而后在表锁按期间对表进行INSERT操做,如:

    LOCK TABLES table_name WRITE;
    INSERT INTO table_name ...;
    INSERT INTO table_name ...;
    INSERT INTO table_name ...;
    ...
    UNLOCK TABLES;
    
  • 利用客户/服务器通讯协议中的压缩功能以减小网络传输的数据量。但该压缩会消耗大量的系统资源,因此当心使用。

  • 尽可能让MySQL插入默认值。不要在INSERT中写太多值,以减小网络传输量和服务器端的语法分析时间。

  • 对于MyISAM和ISAM数据表,若是需加载大量数据,应先创建一个没索引的表,加载数据后再建立索引。该方法不适用于InnoDB或BDB数据表。

禁用和从新激活索引的方法有两种:

  • 使用ALTER TABLE语句的DISABLE KEYS和ENABLE KEYS命令,如:

    ALTER TABLE table_name DISABLE KEYS;
    ALTER TABLE table_name ENABLE KEYS;
    
  • 使用myisamchk或isamchk工具。如:

    $ myisamchk --keys-used=0 table_name                   #禁止
    $ myisamchk --recover --quick --key-used=n table_name  #激活
    n是用来代表须要激活索引的位掩码,第0位对应第一个索引,若是有三个索引,n值就是7(二进制111)。索引编号能够下命令肯定:
    $ myisamchk --description table_name
    

     

2.5. 调度和锁定

 

在不少客户一块儿查询数据表时,若是使客户能最快地查询到数据就是调度和锁定作的工做了。在MySQL中,咱们把select操做叫作读,把对数据表修改增长的操做(INSERT,UPDATE,REPLACE...)叫作写。MySQL的基本调度策略能够概括为如下两条:

  • 写入请求将按它们到达服务器的顺序进行处理;

  • 写操做的优先级要高于读操做。

MyISAM和ISAM数据表的调度策略是在数据表锁的帮助下实现的,在客户程序要访问数据表以前,需得到相应的锁,在完成对数据表的操做后,再释放该锁。锁的管理一般由服务器管理,也可人为地用LOCK TABLES和UNLOCK TABLES命令来申请和释放锁。写操做时,须要申请一个独占性的锁,也就是说在写操做其间,该表只能由写操做的客户使用。读操做时,客户必须申请一个容许其余客户对数据表进行写操做的锁,以确保客户在读的过程当中数据表不会发生改变。但读操做锁不是独占的,可有多个读操做同时做用于同一个数据表。

经过一些修饰符可影响调度策略,如LOW_PRIORITY(用于DELETE,INSERT,LOAD DATA,REPLACE,UPDATE语句)、HIGH_PRIORITY(用于SELECT语句)、DELAYED(用于INSERT和REPLACE语句)。它们的做用是这样的:

  • LOW_PRIORITY会使写操做的优先级下降到读操做如下,也就是说读操做会阻塞该级别的写操做,SELECT的HIGH_PRIORITY有相似的做用。

  • INSERT语句中的DELAYED修饰会使插入操做被放入一个“延迟插入”队列。并返回状态信息给客户,使客户程序可在新数据行还没插入到数据表以前继续执行后面的操做。若是一直有客户读该数据表,新数据行会一直待在队列中,直到数据表没有读操做时,服务器才会把队列中的数据行真正插入到数据表中。该语句可用在如下场合,在一个有冗长查询的数据表中插入数据,而你又不想被阻塞,你就可发出INSERT DELAYED语句,把插入操做放入服务器“延迟插入”队列,你无需等待就立刻可进行接下来的操做。

  • 当一个数据表里从未进行过删除操做或刚刚对它进行过碎片整理的状况下,用INSERT语句插入的数据行只会被添加到数据表的末尾,而不会插入到数据表的中间位置。这样,对于MyISAM表,MySQL容许在有其它客户正在读操做的时间进行写操做。咱们称之这并发插入。要使用该技巧,需注意如下两个问题:

    • 不要在INSERT语句中使用LOW_PRIORITY修饰符。

    • 读操做应用LOCK TABLES ... READ LOCAL而不是用LOCK TABLES ... READ语句来进行数据表读锁定。LOCAL关键字只对数据表中已存在行进行锁定,不会阻塞把新行添加到数据表末尾。

BDB数据表使用页面级操做锁,InnoDB数据表使用数据行级操做锁。因此这两种表的并发性比MyISAM和ISAM数据表这种表级锁的并发性会好不少。其中InnoDB的并发性最好。综上所述,咱们可得出如下结论:

  • MyISAM和ISAM数据表的检索速度最快,但若是在检索和修改操做较多的场合,会出锁竞争的问题,形成等待时间延长。

  • BDB和InnoDB数据表能在有大量修改操做的环境下提供很好的并发性,从而提供更好的性能。

  • MyISAM和ISAM数据表因为进行表级锁定,因此不会出现死锁现象,BDB和InnoDB数据表则存在死锁的可能性。

2.6. 服务器优化

 

优化原则:

  • 内存里的数据要比磁盘上的数据访问起来快;

  • 站数据尽量长时间地留在内存里能减小磁盘读写活动的工做量;

  • 让索引信息留在内存里要比让数据记录的内容留在内存里更重要。

针对以上几个原则,咱们应该调整服务器:

  • 增长服务器的缓存区容量,以便数据在内存在停留的时间长一点,以减小磁盘I/0。下面介绍几个重要的缓冲区:

    • 数据表缓冲区存放着与打开的数据表相的信息,它的大小可由服务器参数“table_cache”设置。Opened_tables参数记录服务器进行过多少次数据表打开操做,若是该值变化很大,就多是数据表缓冲区已满,需把一些不经常使用的表移出缓冲区,以腾出空打开新的数据表。可用如下命令查看Opened_tables的值:

      SHOW STATUS LIKE 'Opened_tables';
      
    • 在MyISAM和ISAM数据表中,索引被缓存在“key buffer”里,它的大小由服务器参数“key_buffer_size”来控制。系统默认的大小是8M,若是内存充足的话可适当扩大该值,以使更多索引块缓存在该区里,以加快索引的速度。

    • InnoDB和BDB数据表也各有一个缓冲区,分别叫innodb_buffer_pool_size和bdb_cache_size。InnoDB还有一个日志缓冲区叫innodb_log_buffer_size。

    • 自4.0.1开始,MySQL多了一个缓冲区,叫查询缓冲区,主要用来存放重复执行的查询文本和结果,当再次遇到相同的查询,服务器会直接从缓冲区中返回结果。该功能是内建的功能,如不想支持该功能,可在编译服务器时用configure脚本的--without-query-cache选项去掉该功能。

      查询缓冲区由三个服务器参数控制,分别是:

      一、query_cache_size    
      控制缓冲区的大小,若是该值为0,则禁用查询缓冲功能。设置方法是在选项文件中设置:
      [mysqld]
      set-variable = query_cache_size = 16M     
      这样就设置了一个16M的查询缓冲区
      
      二、query_cache_limit
      缓冲结果集的最大容量(以字节为单位),若是查询的结果集大于该值,则不缓冲该值。
      
      三、query_cache_type
      缓冲区的操做模式。
      0表示不进行缓冲;
      1表示除SELECT SQL_NO_CACHE开头的查询外,其他的都缓冲;
      2表示只对以SELECT SQL_ON_CACHE开头的查询进行缓冲。
      

      默认状况下,按服务器的设置进行缓冲,但客户端也可经过命令改变服务器设置。客户端可直接用SELECT SQL_NO_CACHE和SELECT SQL_CACHE命令来要求服务器缓冲或不缓冲查询结果。若是不想每条查询都写参数,咱们也可在客户端用SET SQL_QUERY_CACHE_TYPE = val;来改变服务器的查询缓冲行为。val可取值0,1,2或OFF,ON,或DEMAND。

  • 禁用用不着的数据表处理程序。如服务器是从源码建立,就可完全禁用ISAM,InnoDB和BDB数据表。

  • 权限表里的权限关系应尽量简单,固然了,是要在保证安全的前提下。

  • 在从源码建立服务器时,尽可能使用静态库而不是共享库来完成其配置工做。静态库的执行速度更快,但若是要加载用户定义函数(UDF)的话,就不能使用静态库,由于UDF机制必须依赖动态库才能实现。

2.7. 硬件优化

 

为了提升数据运行速度,升级硬件是最直接的解决方案。针对数据库应用的特色,在升级硬件时应考虑如下内容:

  • 对于数据库服务器,内存是最重要的一个影响性能因素。经过加大内存,数据库服务器可把更多的数据保存在缓冲区,可大大减小磁盘I/O,从而提高数据库的总体性能。

  • 配置高速磁盘系统,以减小读盘的等待时间,提升响应速度。

  • 合理分布磁盘I/O,应把磁盘I/O分散在多个设备上,以减小资源竞争,提升并行操做能力。

  • 配置多处理器,MySQL是多线程的数据库,多处理器可同时执行多个线程。

Chapter 3. 数据库管理

 

数据库是一个复杂而又关键的系统,为确保系统安全、高效运行,需熟悉数据库内部的运做机制,掌握各类维护工具,并作好平常的管理工做。下面列举几项主要工做职责:

  • 服务器的关闭和启动;

  • 管理用户账号;

  • 管理日志文件;

  • 数据库备份恢复;

  • 数据库优化;

  • 确保数据库数据安全;

  • 数据库软件升级。

3.1. 数据目录

 

数据目录是用来存放数据表和相关信息的地方,是数据库的核心。在MySQL中的数据目录根据不一样平台的有一些差别:

  • 在UNIX/Linux系统上,若是用源码编译安装,数据目录的位置默认是在/usr/local/mysql/var中;

  • 在UNIX/Linux系统上,若是用二进制发行版安装,数据目录的位置默认是在/usr/local/mysql/data中;

  • 在WINDOWS系统上,数据目录的位置默认是在c:/mysql/data中;

[Note]  
在服务器启动时,可用--datadir=dir_name来指定数据目录,也可把它写到配置文件中。

咱们还可用命令向服务器查询数据目录的位置,数据目录的变量名是datadir,如:

  • % mysqladmin variables

    若是在一台机器上同时运行多个服务器,则可根据端口的不时来查询每一个服务器的数据目录,如:

    % mysqladmin --host=127.0.0.1 --port=port_number variables

    若是--host是localhost,系统则会用一个UNIX套接字去链接数据库服务器,这时要使用--socket选项,因此查询语句变成:

    % mysqladmin --host=localhost --socket=/path/to/socket variables
  • mysql> SHOW VARIABLES LIKE 'datadir';
  • 在windows NT平台上能够使用“.”做为一条命名管道链接的主机名,用--socket选项给出命名管道的名字,如:

    c:\ mysqladmin --host=. --socket=pipe_name variables
  • 配置文件的中[mysqld]段中的datadir=/path/to/datadir设置也可查询到数据目录。

  • 在mysqld程序的帮助信息里也有程序编译时默认的数据目录信息,可用如下命令显示:

    % mysqld --help

数据目录是存放数据文件的地方,每一个数据库对应目录的不一样文件。InnoDB数据表因为用表空间来管理数据库,因此就没这种对应关系。但也是保存在数据目录中的,在数据目录除保存数据库文件外,还可能会保存如下几类文件:

  • 服务器的配置文件,my.cnf;

  • 服务器的进程ID(PID)文件;

  • 服务器的日志文件和状态文件,这些文件对管理数据库有重要的价值;

  • DES密钥文件或服务器的SSL证书与密钥文件。

数据目录中的全部数据库所有由服务器(mysqld)来管理,客户端不直接操做数据。服务器是客户使用数据的惟一通道。

在MySQL中,每一个数据库其实就是在数据目录下一个子目录,show databases命令至关于列出数据目录中的目录清单。create database db_name命令会在数据目录下新建一个db_name的目录,以存放数据库的数据文件。因此咱们也可下面的shell命令方式来创建一个空数据库:

% cd datadir
% mkdir db_name
% chmod u=rwx,go-rwx db_name

同理,删除数据库drop database db_name也就是删除数据目录中一个名为db_name的目录及目录中的数据表文件。咱们也可用shell这进行操做:

% cd datadir
% rm -rf db_name
[Note]  
比较shell方式与drop database方式,drop database db_name命令不能删除db_name目录中建立的其它非数据表文件;因为InnoDB是表空间来管理数据表,因此不能用rm或del命令删除InnoDB的数据表。

3.2. MySQL数据表在系统中表现形式

 

MySQL数据表类型有:ISAM、MyISAM、MERGE、BDB、InnoDB和HEAP。每种数据表在文件系统中都有不一样的表示方式,有一个共同点就是每种数据表至少有一个存放数据表结构定义的.frm文件。下面介绍每种数据表文件:

  • ISAM数据表是最原始的数据表,有三个文件,分别是:

    .frm,存放数据表的结构定义;

    .ISD,数据文件,存放数据表中的各个数据行的内空;

    .ISM,索引文件,存放数据表的全部索引信息。

  • MyISAM数据表是ISAM数据表的继承者,也有三个文件,分别是:

    .frm,结构定义文件;

    .MYD,数据文件;

    .MYI,索引文件。

  • MERGE数据表是一个逻辑结构,表明一组结构彻底相同的MyISAM数据表构成的集合。它在文件系统中有二个文件,分别是:

    .frm,结构定义文件;

    .MRG,构成MERGE表的MyISAM数据表清单,每一个MyISAM数据表名占一行。也就是说可经过改变该表的内容来改变MERGE数据表的结构。修改前请先刷新缓存(flush tables),但不建议这样修改MERGE数据表。

  • BDB数据表用两个文件来表示,分别是:

    .frm,结构定义文件;

    .db,数据表数据和索引文件

  • InnoDB因为采用表空间的概念来管理数据表,因此它只有一个与数据表对应.frm文件,同一目录下的其它文件表示为表空间,存储数据表的数据和索引。

  • HEAP数据表是一个存在于内存中的表,因此它的数据和索引都存在于内存中,文件系统中只有一个.frm文件,以定义结构。

了解MySQL数据表在文件系统中表现形式后,咱们可知道,建立、修改或删除数据表,其实就是对这些文件进行操做。例如一些数据表(除InnoDB和HEAP数据表外),咱们可直接在文件系统中删除相应的文件来删除数据表。

% cd datadir
% rm -f mydb/mydb.*

以上命令可删除mydb数据库中的mydb数据表。

3.3. 数据表最大尺寸限制

 

在MySQL中影响数据表尺寸的因素有不少,下面分别进行介绍:

  • MySQL数据表类型的不一样对数据表尺寸的限制:

    • ISAM数据表中单个.ISD和.ISM文件的最大尺寸为4G;

    • MyISAM数据表中单个.MYD和.MYI文件的默认最大尺寸也是4G,但可在建立数据表时用AVG_ROW_LENGTH和MAX_ROWS选项把这个最值扩大到800万TB。

    • MERGE数据表的最大尺寸是它的各组成MyISAM数据表的最大尺寸之和。

    • BDB数据表的尺寸受限于BDB处理程序所容许的.db文件的最大尺寸。这个最大尺寸随着数据表页面尺寸(编译时肯定)而变化,但即便是最小的页面尺寸(512字节),.db文件的最大尺寸也可达2TB。

    • InnoDB数据表的表空间的最大尺寸是40亿个页面,默认的页面尺寸是16K,该值可在8K到64K之间,在编译时肯定。InnoDB数据表的最大尺寸也就是表空间的最大尺寸。

  • 操做系统对文件的尺寸限制,通常文件系统都对单个文件不得超过2G的限制。该约束会对数据库文件形成限制。InnoDB数据表可经过利用未格式化硬盘做为表空间来绕过该限制。

  • 对于数据和索引分开两个文件存放的数据表,其中任何一个文件达到操做系统文件的最大限制,数据库表也就达到最大尺寸。

  • 包含AUTO_INCREMENT数据列的表受到该数据列类型最大上限值的限制。

  • 因为InnoDB数据表用表空间来管理,一个表空间可同时空纳多个数据表,因此数据表的最大尺寸受系统文件和同一表空间中数据表空间的约束。

3.4. 状态文件和日志文件

 

在MySQL数据目录中还包含着许多状态文件和日志文件,这些文件的文件名都是以主机名加上相关后缀来命名的。下面是这些文件的一个说明列表:

Table 3.1. 状态文件和日志文件

文件类型 默认名 文件内容
进程ID文件 hostname.pid MySQL服务器进程的ID
常规查询日志 hostname.log 链接/断开链接事件和查询信息
慢查询日志 hostname-slow.log 记录查询时间很长的命令信息
变动日志 hostname.nnn 建立或修改数据表结构和内容的查询命令信息
二进制变动日志 hostname-bin.nnn 建立或修改数据表结构和内容的查询命令的二进制表示法
二进制变动日志的索引文件 hostname-bin.index 使用中的“二进制变动日志”列表
错误日志 hostname.err 记录“启动/关闭”事件和异常状况

变动日志和二进制变动日志主要用于MySQL数据库服务器的崩溃恢复中,因为变动日志记录了数据库的全部变动操做,因此能够进行事件重放。具体操做请参考相关数据库备份恢复章节。对于变动日志,咱们可用--log-long-format选项来让它以扩展方式记录有关事件。扩展方式可记录谁发出查询和何时发出查询的信息。可以使咱们更好地掌握客户端的操做状况。日志记录着查询命令的全部操做,里面可能会有一些敏感信息。因此咱们要确保日志文件的安全。

3.5. 调整MySQL数据目录位置

 

MySQL数据库的数据目录位置,包括目录里的各类文件的位置)可根据实际状况进行调整。调整的方法有两种,一种是使用符号连接;一种用服务器启动选项。下面一个列表说明了数据目录及目录中文件各自适宜采用的方法:

Table 3.2. MySQL数据目录及目录中文件位置的调整方法

调整对象 适用方法
整个数据目录 启动选项和符号连接
数据库目录 符号连接
数据表 符号连接
InnoDB数据表空间 启动选项
PID文件 启动选项
日志文件 启动选项

下面是各类调整方法的具体操做过程:

  • 在调整MySQL的数据目录时,要先中止服务器,再把数据目录移动到新的位置。接着,咱们可选择在原来目录下建立一个符号连接指向新的位置,或者用启动选择--datadir指向新的数据目录。推荐用建立符号连接的方法,由于若是那个数据目录中有my.cnf文件,相应的服务器还能找到它。

  • 数据库只能存在于MySQL数据目录中,因此只能使用符号连接的方法调整它的位置。在Linux系统的操做步骤如:

    1. 关闭服务器;

    2. 把数据库目录拷贝到新的位置;

    3. 删除原来的数据库目录;

    4. 在原来的MySQL数据目录中建立一个同名符号连接指向新的位置;

    5. 从新启动服务器。

    在windows下的操做方法不些不一样,操做方法以下:

    1. 关闭服务器;

    2. 把数据库目录移动新的位置;

    3. 删除原来的数据库目录;

    4. 在原来数据目录下建一个同名的.sym文件,在文件中输入数据库新目录的全路径,如c:\mysql\newdir\mydb。这个文件就至关于Linux下的符号连接;

    5. 重启服务器。

      [Note]  
      为了支持符号连接功能,必须用--use-symbolic-links选项启动服务器;或在选项文件的[mysqld]节中添加use-symbolic-links选项。
      [Note]  
      MySQL必须是3.23.16以上版本且是max服务器(mysqld-max或mysqld-max-nt)。
  • 要移动数据表,必须知足如下全部条件才行:

    • MySQL的版本必须是4.0或以上的版本;

    • 操做系统必须有一个可用的realpath()调用;

    • 移动的数据表必须是MyISAM类型的数据表。

    在知足以上全部条件后,咱们就可把.MYD数据文件和MYI索引文件移到新位置,再在原来位置建立两个同名符号连接指定新的位置。注意,.frm定义文件仍需留在原来的数据库目录中。

    如以上条件不能所有知足,最好不要移动数据表文件。不然一旦你运行ALTER TABLE、OPTIMIZE TABLE、REPAIR TABLE语句对移动过的数据表进行优化或修改,这样数据表就会回到原来的位置,使移动操做失效。由于这些命令的执行过程是这样的:它会先在数据目录中建立一个临时数据表并对这个临时数据表进行优化或修改,而后删除原来的数据表(这里是你为了移动数据表而建立的一个符号连接),再把临时数据表改名为原来的数据表名称。这样一来,你移走的数据表就和这个数据库彻底没有关系了。基于如下的不稳定因素,如无特殊必要,不建议移动数据表。

  • InnoDB表空间是经过在选项文件中使用innodb_data_home_dir和innodb_data_file_path选项列出InnoDB表空间组成文件清单的方法来配置的,因此咱们可经过修改这些选项来从新安置InnoDB表空间的组成文件。步骤以下:

    • 关闭服务器;

    • 移动组成表空间的文件;

    • 修改选项文件,指出组成表空间的文件的新位置;

    • 重启服务器。

  • 状态文件和日志文件的位置可经过选项文件或启动服务器时指定。

Chapter 4. MySQL数据库平常管理

 

为了确保数据库平稳可靠运行,咱们需进行维护和管理,这是每一位数据库管理员的职责。下面分几个专题分别介绍。

4.1. 数据库安全管理

 

MySQL数据库经过用户和密码来控制用户对数据库的访问,当咱们新安装了一个数据库服务器时,MySQL的权限表设置是很不安全,它默认容许任何人不须要密码就可访问数据库。因此咱们安装好服务器后第一件须要作的就是设置用户密码。

在MySQL中的mysql数据库的user数据表中存有用户的账号信息,在初始状态下已存在root和一些匿名用户,且全部用户都没有设置密码。该数据表的这些用户信息是经过一个mysql_install_db脚本安装的。该表的主要列有:

  • User,链接数据库的用户名。

  • Host,容许链接到数据库服务器的主机名,“%”通配符表明全部主机。

  • Password,链接密码,已加密。

  • 其它权限列,以“Y”或“N”标识是否有效。

在这种状态下的数据库是极不安全的,咱们可用如下命令轻易地访问数据库:

% mysql -h localhost -u root     #经过本地主机,root用户访问,不须要密码验证
% mysql -h localhost             #经过本地主机,匿名用户访问,不须要密码验证

设置MySQL用户账号密码的方法有三种:

  • 使用mysqladmin程序:

    % mysqladmin -h localhost -u root password "password"   #设置在本地以root身分登陆的密码
    % mysqladmin -h remote -u root password "password"      #设置远程主机以root身分登陆的密码
    

    在初始设置时,这两条语句都要运行,以确保数据库本地访问和网络访问的安全。

  • 经过set password这条SQL语句设置:

    mysql> set password for 'root'@'localhost' = password('password');
    mysql> set password for 'root'@'remote' = password('password');
    
  • 直接修改user权限表:

    mysql> use mysql;
    mysql> update user set password=password('password') where user='root';
    mysql> flush privileges;                            #重载权限表,使修改立刻生效
    

    MySQL使用驻留在内存中的权限表拷贝来进行访问控制,当使用mysqladmin和set password设置密码,MySQL会监察到权限表已被修改,它自动重载该表。而用update的方式,MySQL就监察不到变化,需手动用flush privileges命令刷新内存中的权限表,以使它立刻生效。

为root用户设置密码后,若是需以root身份链接数据库,就需验证密码。咱们可用如下语句链接数据库:

% mysql -u root -p
Enter password:                         #输入root的密码

在user表中,user列为空的为匿名用户。它也是没有密码的,咱们需为它们设置一个密码,或干脆把它们删除。在windows系统上的本地匿名用户账号和root用户有着一样的权限,这是一个很大的安全漏洞。应该把它删除或把权限削弱。

4.2. 服务器的启动和关闭

 

在Linux和windows平台下MySQL服务器的启动方式有很大不一样,这里将分开介绍:

  • Linux平台:

    Linux平台下,每个进程都需由一个用户来运行,MySQL最好不要以root用户来运行。咱们可建立一个mysql用户和mysql组,MySQL服务器程序目录和数据目录由这个用户和组所拥有,其它用户没有任何权限。以mysql用户来运行MySQL服务器。

    % mysqld --user=mysql     #即便以root用户执行该命令,MySQL数据库仍是会与mysql用户ID关联。
    

    为了使服务器在系统启动时自动以mysql用户运行,需配置my.cnf配置文件 ,把user=mysql包含在[mysqld]段中。

    关闭服务器可用% mysql.server stop或% mysqladmin -u root -p shutdown

  • windows平台:

    手动方式:直接运行c:\mysqld命令。

    做为服务方式:运行c:\mysqld-nt --install命令,把mysqld-nt安装为windows的服务,此后,每当windows启动时,它就会自动运行。mysqld-nt是一个支持命名管道的MySQL服务器。运行c:\mysqld-nt --remove可把服务删除。手动启动关闭服务的方法是运行c:\net start mysql和c:\net stop mysql命令。

4.3. 链接故障恢复

 

当因为误删mysql套接字时(/tmp/mysql.sock),咱们就不能经过套接字链接服务器。这时咱们可经过tcp/ip来链接服务器,要创建一个tcp/ip链接,需用127.0.0.1代替locahost做为-h参数的值来链接服务器。如:

% mysqladmin -h 127.0.0.1 -u root -p shutdown       #关闭服务器再重启会重建套接字

当咱们由于忘记root用户密码而不能链接服务器时,重设置密码的步骤如:

  • 用 % kill -TERM PID关闭服务器,用-TERM信息可以使服务器在关闭前把内存中的数据写入磁盘。若是服务器没有响应,咱们可用% kill -9 PID来强制删除进程,但不建议这样作。这时内存中的数据不会写入磁盘,形成数据不完整。若是你是用mysql_safe脚本启动MySQL服务器的,这个脚本会监控服务器的运行状况并在它被终止时重启服务器,因此如需关闭服务器,要先终止该进程,而后再真正终止mysqld进程。

  • 接着用--skip_grant-tables启动服务器。这时MySQL服务器将不使用权限表对链接操做进行验证。你就可在不提供root密码的状况下链接上服务器,并得到root的权限。这样你就可用上面介绍的修改密码的方法重设root用户的密码。注意:链接上服务器后,要立刻执行flush privileges命令,使权限表读入内存并生效,以阻止其余的链接。该语句还从新激活grant语句,在MySQL服务器不使用权限表时,grant语句被禁用。

  • 修改完root用户密码后,咱们就可关闭服务器并重启使全部配置正常运做。

4.5. 日志文件管理

 

有关MySQL的日志文件前面章节已简要讨论过了,主要有四种日志文件,分别是常规查询日志、慢查询日志、变动查询日志和二进制变动日志。这些日志文件的建立需在启动服务器时用选项指定。

Table 4.3. 日志启动选项

启动选项 激活日志
--log[=file_name] 常规日志文件
--log-bin[=file_name] 二进制变动日志文件
--log-bin-index=file_name 二进制变动日志文件索引文件
--log-update[=file_name] 变动日志文件
--log-slow-queries[=file_name] 慢查询日志文件
--log-isam[=file_name] ISAM/MyISAM日志文件
--log-long-format 设置慢查询日志和变动日志的格式

BDB和InnoDB数据表的日志文件会自动建立不用指定选项。但可用如下选项指时日志文件的存放路径。

Table 4.4. BDB和InnoDB数据表日志选项

启动选项 用途
--bdb-logdir=dir_name 存放BDB日志文件的位置
--innodb-log_arch_dir=dir_name 存放InnoDB日志文件的归档目录
--innodb_log_group_home_dir=dir_name 存放InnoDB日志文件的位置

MySQL日志文件选项可在mysqld和mysqld_safe脚本中使用,也可在选项文件my.cnf的[mysqld]中使用。推荐在选项文件中使用,由于每次启动服务器的日志选项基本上都是一致的。

日志的刷新可用mysqladmin flush-logs命令或flush logs语句实现。另外,对MySQL服务器发送一条SIGHUP信号也会刷新日志。错误日志和DBD/InnoDB日志不能用以上方法刷新。

错误日志记录MySQL数据库系统的论断和出错信息,由mysqld_safe脚本建立,文件名默认为hostname.err,也可经过--err-log或选项文件的err-log语句指定另外的名字。若是直接用mysqld程序启动服务器,错误信息会直接输出到输出设备,也就是屏幕。但咱们可用重定向方法把错误信息输出到其它地方,如把错误信息输出到/var/log/mysql.err文件中,能够执行如下语句:

% mysqld > /var/log/mysql.err 2>&1 &

在windows平台下,MySQL服务器默认把诊断信息写到数据目录的mysql.err文件中,而且不容许另外指定错误日志文件名。如在启动MySQL服务器时给出了--console选项,则MySQL会把诊断信息输出到控制台窗口而不建立错误日志。但如MySQL是做为一个服务运行,则--console选项不起做用。

4.5.1. 日志失效处理

 

在服务器正常运行中,会产生大量的日志文件。咱们要对这些日志文件进行失效管理,以节省磁盘空间和方便查询。进行日志失效处理的方式主要有如下几种:

  • 日志轮转。该方法适用于常规查询日志和慢查询日志这些文件名固定的日志文件,在日志轮转时,应进行日志刷新操做(mysqladmin flush-logs命令或flush logs语句),以确保缓存在内存中的日志信息写入磁盘;

    日志轮转的操做过程是这样的:第一次轮转时,把log改名为log.1,而后服务器再建立一个新的log文件,在第二轮转时,再把log.1改名为log.2,把log改名为log.1,而后服务器再建立一个新的log文件。如此循环,建立一系列的日志文件。当到达日志轮转失效位置时,下次轮转就再也不对它进行改名,直接把最后一个日志文件覆盖掉。例如:若是天天进行一第二天志轮转并想保留最后7天的日志文件,就须要保留log.1--log.7共七个日志文件,等下次轮转时,用log.6覆盖原来的log.7成新的log.7,原来的log.7就天然失效。下面是一个失效处理的shell脚本,以供参考:

    #!/bin/sh
    # shell script ---  rotate_log.sh
    
    if [ $# -ne 1 ]; then
       echo "Usage: $0 logname" 1>&2
       exit 1
    if
    
    logfile=$1
    
    mv $logfile.6 $logfile.7
    mv $logfile.5 $logfile.6
    mv $logfile.4 $logfile.5
    mv $logfile.3 $logfile.4
    mv $logfile.2 $logfile.3
    mv $logfile.1 $logfile.2
    mv $logfile $logfile.1
    mysqladmin -u flush -pflushpass flush-logs     #执行mysqladmin flush-logs会打开一个日志文件----从新生成一个新的日志文件
    

    该脚本以日志文件名为参数,执行方法以下:

    % rotate_log.sh /usr/local/mysql/data/log
    

    注意,脚本中的mysqladmin命令是带有-u和-p参数的,由于咱们进行日志刷新时需链接服务器。为确保安全,咱们创建一个flush用户,密码为flushpass。该用户只有日志刷新的权限(reload权限)。建立该用户的语句以下:

    GRANT RELOAD ON *.* TO 'flush'@'localhost' IDENTIFIED BY 'fulshpass';
    

    设置好后,咱们就可利用系统的自动处理机制按期运行该脚本以生成轮转日志。在Linux系统上的MySQL发行版中带有一个用来安装mysql-log-rotate日志轮转脚本的logrotate工具,如用RPM安装,则在/usr/share/mysql目录,如用二进制方式安装,则在MySQL安装目录的support-files目录,如用源码安装,则在安装目录的share/mysql目录中。

    在windows平台下,不能在线改名,需停掉服务器,再进行。下面是一个进行日志改名的批处理文件:

    @echo off
    REM script name : rotate_log.bat
    
    if not "%1" == "" goto ROTATE
    
       @echo Usage: rotate_log logname
       goto DONE
    
    :ROTATE
    set logfile=%1
    erase %logfile%.7
    rename %logfile%.6 %logfile%.7
    rename %logfile%.5 %logfile%.6
    rename %logfile%.4 %logfile%.5
    rename %logfile%.3 %logfile%.4
    rename %logfile%.2 %logfile%.3
    rename %logfile%.1 %logfile%.2
    rename %logfile% %logfile%.1
    :DONE
    

    该脚本的执行方法以下:

    c:\rotate_log c:\mysql\data\log
    
  • 以时间为依据对日志进行失效处理。该方法将按期删除超过给定时间的日志文件,适用于变动日志和二进制日志等文件名用数字编号标识的日志文件。下面是一个用Perl写成的处理脚本:

    #!/usr/bin/perl -w
    
    # script name: expire_log.pl
    # Usage: expire_log.pl logfile ...
    
    use strict
    die "Usage: $0 logfile ...\n" if @ARGV == 0;
    my $max_allowed_age = 7;      #max allowed age in days
    foreach my $file (@ARGV)      #chack each argument
    {
       unlink ($file) if -e $file && -M $file >= $max_allowed_age;
    }
    exit(0);
    

    该脚本需提供一个将被轮转的日志文件名做为参数,如:

    % expire_log.pl /usr/local/mysql/data/log.[0-9]*
    
    [Note]  
    在给脚本参数时请当心,如给出*为参数,则会删除目录中全部更新时间大于7天的文件。
  • 镜像机制。把日志文件镜像到全部的从服务器上。要使用镜像机制,你必须知道主服务器有多少个从服务器,哪些正在运行,并需依次链接每个从服务器并发出show slave status语句以肯定它正处理主服务器的哪一个二进制日志文件(语句输出列表的Master_Log_File项),只有全部的从服务器都不会用到的日志文件才能删除。删除方法是在主服务器上发出如下语句:

    mysql> PURGE MASTER LOGS TO 'last_log.xx';
    

    上面语句中的last_log.xx是全部从服务器已处理的最小编号日志文件。

4.6. MySQL服务器的一些优化配置

 
  • 服务器的监听端口设置

    • TCP/IP端口3306是MySQL服务器默认的网络监听端口,如用--skip-networking选项启动服务器,则不监听TCP/IP端口。可用--port端口另行指定一个监听端口。如服务器主机有多个IP,还可用--bind-address选项对服务器在监听客户链接时使用的IP地址进行设定。

    • 在UNIX系统上,MySQL可在一个UNIX域套接字文件上监听有无本地客户在试图以localhost为主机名进行链接。默认的套接字文件是/tmp/mysql.sock,可用--socket选项指定另一个套接字文件。

    • 在基于NT的Windows平台上,有-nt的MySQL服务器都支持命名管道。默认的命名管道是MySql,可用--socket选项另行指定。

  • 启用或禁用LOAD DATA语句的LOCAL能力

    • 可在MySQL服务器编译时,用configure脚本的--enable-local-infile或--disable-local-infile选项把LOAD DATA语句的LOCAL能力设置为启用或禁用;

    • 在MySQL服务器启动是,能够用--local-infile或--disable-local-infile选项来启用或禁用服务器的LOCAL能力(在MySQL 4.0.2以前的版本里,要用--local-infile=0来禁用它)。

    若是在服务器端禁用了LOCAL的能力,则客户端就不能使用该功能;如服务器启用了LOCAL的能力,客户端默认也是禁止使用的,但可用mysql程序的--local-infile选项启用它。

  • 国际化和本地化,国际化是指软件可以在世界多个国家地区使用,而本地化则是指可从国际化软件中选择一套适合本地区的语言和习惯的设置来使用。在MySQL中的国际化和本地化设置有如下几方面内容:

    • 时区,若是时区设置不对,则服务器显示的时间将会和当地时间有冲突。设置方法可经过mysqld_safe脚本的--timezone选项来设置,但最好仍是在选项文件里设置,如:

      [mysqld_safe]
      timezone=US/Central
      
    • 配置显示信息的语言,MySQL能用多种语言来显示诊断信息与出错信息,默认是英语。查看share/mysql目录下有几个以语言名称做为目录名的目录就可知道有哪些语言可供选择。可用--language启动选项来指定语言,如--language=/usr/local/mysql/share/mysql/french。

    • 配置服务器的字符集,MySQL支持多种字符集,可在share/mysql/charsets目录下查询支持的字符集,也可用show variables like 'character_sets'来显示支持的字符集清单。MySQL把latin1做为默认的字符集。可在编译时用--with-charset指定另一个字符集为默认字符集。如要增长另外的字符集支持,可用--with-extra-charasets选项进行添加。如:

      % ./configure --with-extra-charsets=latin1,gb2312,big5
      

      --with-extra-charsets有两个特殊的选项,一个是all,表明全部可用字符集;一个是complex,表明全部的复杂字符集(包括多字节字符集和有特殊排序规则的字符集)。

      服务器启动时,使用默认字符集,如需指定另外的字符集,需用--default-character-set选项指明。

      在MySQL 4.1之前,若是在建立好数据表后改变服务器的默认字符集,就需对索引从新排序才能保证索引键值可以正确反映出数据表记录在新字符集下的排列顺序。从新排序的操做命令以下:

      % myisamchk --recover --quick --set-character-set=gb2312       #在执行该语句需关闭服务器,适用于MyISAM数据表
      也可用:
      % mysqlcheck --repair --quick                                  #不需关闭服务器,适用于各类数据表
      或者用:
      mysql> REPLACE TABLE ... QUICK;
      

      在客户端,可用--default-character-set选项指定客户程序使用的字符集。--character-sets-dir选项可指出字符集文件的安装目录。

  • 升级数据表到4.1,支持多字符集数据表。步骤以下:

    1. 用mysqldump程序备份数据库:

      % mysqldump -p -u root --all-databases --opt > dumpfile.sql
      --all-databases选项的做用是转储全部数据库;
      --opt选项的做用是对转储文件进行优化。
      
    2. 关闭服务器,升级MySQL服务器软件到4.1版。

    3. 用备份文件从新加载数据表:

      % mysql -p -u root < dumpfile.sql
      

    这样,字符集信息就被分配到每个数据列中,此后,即便服务器改变了默认的字符集,各数据列的字符集也不会改变。当之后修改某个数据列的字符集时,服务器会自动重索引,以反映最新变化。

  • 配置InnoDB表空间。InnoDB表空间在逻辑上是一个链接的存储区域,但其实是由一个或多个磁盘文件组成。这些文件能够是普通的文件,也能够是一个未格式化的原始硬盘分区。InnoDB表空间经过一系列的配置选项来设置,其中最重要的有如下两个:

    为确保服务器每次启动时都能调用一样的选项,InnoDB的选项最好存放到选文件中。下面是一个例子:

    innodb_data_home_dir = 
    innodb_data_file_path=/usr/loca/mysql/data/idbdata1:10M:autoextend:max:100M
    说明:
    InnoDB表空间文件默认存放到了MySQL的数据目录中,名字叫idbdata1;
    文件长度为10M;
    可自动扩展,以8M为步长扩展,若有多个数据文件,只容许最后一个文件可自动扩展;
    规定了最大的可扩展尺寸为100M。
    
    • innodb_data_home_dir,设置InnoDB表空间各组成文件的父目录,若是没有指出,则默认是MySQL的数据目录。

    • innodb_data_file_path,描述InnoDB主目录中各有关文件,包括文件名,文件长度和一些选项。各文件以分号分隔,各组成文件长度至少为10M。

    把选项写入选项文件后,启动服务器就可自动建立和初始化InnoDB表空间。

    利用原始磁盘分区做为InnoDB表空间可建立一个很是大的表空间,不受操做系统单文件最大容量的限制。而且能有效减小磁盘碎片的产生。要使用原始磁盘分区,需做以下配置:

    • 首先,要进行初始化,在选项文件的[mysqld]中配置:

      innodb_data_home_dir=
      innodb_data_file_path=/dev/hda1:10Gnewraw     #初始化/dev/hda1这个10G容量的分区
      

      启动服务器,服务器会对这个10G的分区进行初始化。

    • 接着,关闭服务器,修改配置文件,把newraw改成raw,如:

      innodb_data_home_dir=
      innodb_data_file_path=/dev/hda1:10Graw
      

    从新启动服务器,MySQL就会以读/写方式使用该表空间了。在windows平台上配置InnoDB表空间时,windows路径名中的反斜杠能够写成单个的斜线字符(/)。也可写成两个反斜杠(\\)。如:

    innodb_data_home_dir=
    innodb_data_file_path=c:/mysql/data/ibdata1:10M;d:/ibdata2:20M
    

    默认状况下,InnoDB的日志文件会存储在MySQL的数据目录,文件名以ib开头。一旦完成InnoDB表空间的初始化,就不能改变组成文件的大小,但可经过添加数据文件或设置自动扩展来增长表空间容量。如需经过增长文件的方法扩大表空间的容量,可按如下步骤进行:

    1. 关闭正在运行的MySQL服务器

    2. 若是InnoDB表空间的最后一个组成文件是可自扩展的,就要先把它改变成一个固定长度文件才能把另外一个文件添加到它后面。方法是先计算出该文件的近似大小,从新设置,如:

      innodb_data_file_path=ibdata1:100M:autoextend
      改为:
      innodb_data_file_path=ibdata1:150M
      
    3. 把新的组成文件添加到文件清单的末尾,该文件能够是普通文件,也能够是一个原始硬盘分区。

    4. 重启服务器。

    还有一种方法从新配置InnoDB表空间,就是先备份,再从新配置,最后从新加载备份。具体步骤以下:

    1. 使用mysqldump备份整个InnoDB数据库;

    2. 关闭服务器,删除全部InnoDB表空间、InnoDB日志文件 及InnoDB数据表的.frm文件;

    3. 从新配置InnoDB表空间;

    4. 配置完成后,用备份文件重载数据,生成新的InnoDB数据表。

4.7. 优化服务器

 

MySQL服务器为咱们提供了丰富的参数,以调整服务器知足不一样环境的要求。下面分别讨论一下这些参数:

  • 服务器参数变量的设置。MySQL服务器参数可在服务器启动时设置,在MySQL4.0.3及之后的版本中,有些参数也容许在线设置。在MySQL4.0.2及之后的版本里,能够把一个变量名视为一个选项名来设置。如数据表缓冲区的尺寸由服务器参数talbe_cache来设置。若是需把它设置为128,则能够在命令行里增长

    --table_cache=128
    

    也可在选项文件中设置:

    [mysqld]
    table_cache=128       
    

    在命令行选项中'_'可写'-',变成:

    --table-cache=128     #这种写法更像一个标准选项
    

    还有一种是使用--set-variable或-O选项,如:

    --set-variable=table_cache=128
    or
    -O table_cache=128
    在选项文件中可写成:
    [mysqld]
    set-variable=table_cache=128
    

    服务器参数分为全局级和会话级两个级别。全局级参数将影响整个服务器,会话级参数则只影响某给定客户链接上的工做。若是某个变量同时存在于两个级别,则服务器在客户创建链接时用全局变量的值去初始化相应的会话级参数,一旦客户链接创建起来后,对全局参数所做的修改不会影响到相应的会话级参数当前值。设置全局参数和会话级参数的语句:

    全局级:
    mysql> SET GLOBAL variable = value;
    mysql> SET @@GLOBAL.variable = value;
    会话级:
    mysql> SET SESSION variable = value;
    mysql> SET @@SESSION.variable = value;
    默认不带级别限定符的SET语句修改的参数属会话级,如:
    mysql> SET variable = value;
    mysql> SET @@variable = value;
    可用一条SET语句设置多个参数,参数间用逗号分隔,如:
    SET SESSION variable = value1,value2,value3;
    

    SESSION和LOCAL是同义语,可用LOCAL代替SESSION,如:@@LOCAL

    具有SUPER权限才能设置全局参数,新设置值的效力将持续到该参数被再次修改或服务器退出。设置会话级参数不用特殊的权限,新设置值的效力将持续到该值被再次修改或链接断开。显示参数的语句以下:

    SHOW GLOBAL VARIABLES;
    SHOW GLOBAL VARIABLES LIKE 'TEST';
    SHOW SESSION VARIABLES;
    SHOW SESSION VARIABLES LIKE 'TEST';
    如不带限定符,则返回会话级参数,如会话级参数不存在则返回全局级参数。
    也可用命令行方式显示服务器参数变量,如:
    % mysqladmin variables
    
  • 下面介绍一些MySQL服务器通用的参数变量:

    • back_log,当多个客户同时链接服务器时,客户处理过程需进入一个队列排队等待服务器处理。该值定义服务器等待处理队列长度的最大值,若是站点访问量大,需加大该值。

    • delayed_queue_size,在实际插入数据表前,来自insert delayed语句的数据行会进入一个队列等待服务器处理。该值定义该队列能容纳的数据行的最大个数。当队列满时,会阻塞后续的语句。加大该值能提升insert delayed语句的执行速度。

    • flush_time,自动存盘间隔。若是系统常常死机或重启,把这个变量设置为一个适当的非零值,使MySQL服务器每隔flush_time称去刷新一次数据表缓冲区,将其中的信息写入磁盘。这将致使系统性能降低,但可减小数据表被破坏或丢失数据的几率。在命令行上用--flush选项启动服务器可以使数据表在每次修改后被自动存盘。

    • key_buffer_size,用来容纳索引块的缓冲区的长度。加大该值可加快索引建立和修改操做的速度,该索引缓冲区越大,在内存中找到键值的可能性就越大,读盘次数就越少。MySQL3.23前的版本里,该参数叫key_buffer。3.23版本以后,两种叫法均可以。

    • max_allowed_packet,服务器与客户程序之间通讯时使用的缓冲区在最大值。MySQL 4版本以前,该最大值可取16MB,MySQL 4版本之后,该值的最大值是1GB。若是客户端与服务器需传送大容量的数据,如BLOB或TEXT值,就要加大该值。客户端也有一个同名的变量,默认是16MB,该值也要加大。客户端的启动命令为:

      % mysql --set-variable=max_allowed_packet=64M
      
    • max_connections,容许同时打开的链接数,若是站点繁忙,需加大该值。

    • table_cache,数据表缓存区的尺寸。加大该值可以使服务器可以同时打开更多的数据表,从而减小文件打开/关闭操做的次数。

    注意:加大max_connections和table_cache参数的值,会使服务器占用更多的文件描述符。运行多个服务器可绕过该限制。对一些分配给每一个客户的资源变量,设置时不能过大,由于当链接数快速增加时会很快耗尽服务器的资源,形成服务器性能降低。

  • InnoDB处理程序变量:

    • innodb_buffer_pool_size,InnoDB数据库缓冲池的大小,若是有足够的内存,可把该值设置得大些以减小读盘操做。

    • innodb_log_file_size和innodb_log_files_in_group,前者设置日志文件的长度,后者设置日志文件的个数。InnoDB日志文件的总长度是二者的乘积,它的总长度不得超过4GB。

4.8. 运行多个MySQL服务器

 

需运行多个服务器的缘由有不少,好比上面提到的可绕过最大文件描述符的限制,还有是进行版本测试和提供专用服务等。运行多个服务器比运行单个服务器复杂不少,需注意如下问题:

  • 在安装不一样版本的程序时,需分开目录存放程序和数据目录。若是同一版本的服务器软件,则程序目录可同样,但数据目录则要不一样。可用--basedir=dir_name和--datadir=dir_name两个启动选项指时这两个目录。

  • 要为不一样的服务器指定不时的--port=port_name(TCP/IP监听端口),--socket=file_name(套接字文件名)和--pid-file=file_name(进程ID文件)值。

  • 若是激活了日志功能,就要为不一样的服务器指定不一样的日志文件名。

  • 在Windows平台上,被安装为服务的多个MySQL服务器必须有不一样的服务名。

多服务器环境下选项文件的配置方法:

  • 使用--defaults-file选项指定每一个选项文件,这样,每一个服务器就不会去读/etc/my.cnf这些配置文件,而会使用你所指定的配置文件。

  • 可把一些公共的选项放到/etc/my.cnf文件里,再用--defaults-extra-file选项指出特定服务器的特定选项文件。这样就不用在全部的配置文件时重复公共的选项。

  • 用mysql_multi脚本启动服务器,它容许咱们把全部的选项放到同一个选项文件里。每个服务器对应该文件中的一个选项组。

    下面介绍用mysql_multi脚本启动多服务器的方法。

    1. 为每一个服务器编一个编号xxx,对应选项文件的[mysqldxxx]选项组。mysql_multi自己要用到的选项可放到[mysqld_multi]里。这样/etc/my.cnf选项配置文件看起来就象下面这样:

      [mysqld001]
      basedir=/usr/local/mysql/001
      datadir=/usr/local/mysql/001/data
      mysqld=/usr/local/mysql/001/bin/mysqld_safe
      socket=/usr/local/mysql/001/mysql.sock
      port=3306
      local-infile=1
      user=mysqladm
      log=log
      log-update=update-log
      innodb_data_file_path=ibdata1:10M
      
      [mysqld002]
      basedir=/usr/local/mysql/002
      datadir=/usr/local/mysql/002/data
      mysqld=/usr/local/mysql/002/bin/mysqld_safe
      socket=/usr/local/mysql/002/mysql.sock
      port=3307
      local-infile=1
      user=mysqladm
      log=log
      log-update=update-log
      innodb_data_file_path=ibdata1:10M
      
      ...
      
    2. 配置好选项文件后,就可用如下命令启动服务器:

      % mysqld_multi --no-log start 001,002      
      #启动001和002两个服务器,并把启动信息发送到控制台,也可用区间的形式给出服务器编号
      

      用如下命令可查看服务器状态:

      % mysqld_multi --no-log --user=root --password=password report 001
      

      可用如下命令中止MySQL服务器:

      % mysqld_multi --no-log --user=root --password=password stop 001
      
  • 在windows平台下运行多个MySQL服务器的方式有两种,一种是运行同一个MySQL程序的两个实例,一种是运行多个windows服务,下面分别介绍:

    • 第一种状况需设置两个选项文件,指定不一样的数据目录,如:

      c:\mysql\my.cnf1
      
      [mysqld]
      basedir=c:/mysql
      datedir=c:/mysql/data1
      port=3306
      
      c:\mysql\my.cnf2
      
      [mysqld]
      basedir=c:/mysql
      datadir=c:/mysql/data2
      port=3307
      

      在启动服务器时,用--defaults-file选项指出选项文件便可。如:

      c:\> mysqld --defaults-file=c:\mysql\my.cnf1
      c:\> mysqld --defaults-file=c:\mysql\my.cnf2
      
    • 在MySQL 4.0.2版本开始,能够把MySQL安装为一个服务,并可指定一个服务名,如:

      c:\> mysql-nt --install service_name
      在MySQL 4.0.3开始,安装服务还支持--defaults-file=file_name选项
      

      这样,咱们就可把MySQL安装为一系列不一样的服务,若是不指定service_name,则安装的服务名默认为MySql,若是指定service_name,则安装的服务名为指定的service_name,并对应选项文件中的[service_name]选项组。以默认服务名运行的服务器还支持一个名为MySql的命名管道,而明确给出服务名的服务器将只监听TCP/IP链接而不支持命名管道--除非还用socket选项明确指定一个套接字文件。

      移除服务需先用mysqladmin shutdown命令停掉服务器,再执行如下命令:

      c:\> mysql-nt --remove                 #移除默认的服务
      c:\> mysql-nt --remove service_name    #移除指定服务
      

4.9. MySQL服务器镜像配置

 

经过镜像机制可把数据从一个地方复制到另外一个地方,并能实现同步两个或多个地方的数据。MySQL服务器也支持镜像,大提升数据的安全性和稳定性。下面介绍一下MySQL数据中的镜像机制:

  • 在镜像关系中,一个MySQL服务器扮演主服务器角色,另一个或多个服务器扮演从服务器角色,从服务器中的数据和主服务器中的数据彻底同样。

  • 在镜像创建以前,主服务器和从服务器必须进行一次彻底同步。同步以后,在主服务器上所作的操做将会在从服务器上再实现,主服务器上的操做不是直接做用于从服务器上的。

  • 负责在主、从服务器上传输各类修改动做的媒介是主服务器上的二进制变动日志,该日志记录着主服务器上全部的操做动做。所以,主服务器必须激活二进制日志功能。

  • 从服务器必须有足够的权限从主服务器上接收二进制日志文件。镜像协调信息记录从服务器的进展状况,包括,从服务器正在读取的二进制变动日志文件名和它在该文件里的当前读写位置。

  • 每一个主服务器能够有多个从服务器,但每一个从服务器只能有一个主服务器。但MySQL服务器容许把一个从服务器做为另外一个从服务器的主服务器,这样就可建立一个镜像服务器链。

镜像机制在MySQL中仍是一个新生事物,最先实现于3.23.15版。各版本间的镜像能力有差别,通常来讲,建议你们尽可能使用最新的版本,下面列举了不一样版本的MySQL服务器在镜像机制方面的兼容规则:

  • 3.23.x系统版本的从服务器不能与4.x系统版本的主服务器通讯。

  • 4.0.0版本的从服务器只能与4.0.0版本的主服务器通讯。

  • 4.0.1或更高版本的从服务器既能与3.23.x系统版本的主服务器通讯,也能与4.x系统版本的主服务器通讯。但后一种状况要求主服务器的版本号等于或大于从服务器的版本号。

通常来讲,建议遵循如下原则:

  • 要尽量地让主服务器和从服务器都使用同一版本系统。

  • 在选定系统后,尽可能使用该系统的最新版本。

创建主从镜像服务器的步骤:

  • 肯定主从服务器的镜像ID号,主从服务器的ID号不能相同。在启动主从服务器时,用--server_id启动选项给出其ID。

  • 从服务器必须在主服务器上有一个具有足够的权限的账户,从服务器将使用该账户去链接主服务器并请求主服务器把二进制变动日志发送给它。可用如下命令建立这个账户:

    mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'slave_host' IDENTIFIED BY 'slave_pass';
    #REPLICATION权限只MySQL4.0.2后版本,以前的版本请用FILE权限。
    
  • 把主服务器上的数据库文件拷贝到从服务器上完成最初同步工做。也可用备份后再加载的方法。在MySQL 4.0.0及之后版本里,还可用在主服务器上运行LOAD DATA FROM MASTER语句来创建从服务器。但有约束条件:

    • 数据表要所有是MyISAM表

    • 为发出这条指令而在链接从服务器时使用的账户必须有SUPER权限。

    • 从服务器用来链接主服务器的账户必须具有RELOAD和SUPER权限。注意,这是一个主服务器上的账户,而用来发出LOAD DATA FROM MASTER语句的账户是一个从服务器上的账户。

    • LOAD DATA FROM MASTER语句在执行时需申请一个全局性的读操做锁,这个锁在语句执行期间阻塞主服务器上一切的写操做。

    不管用哪一种方法同步数据,都要确保在开始制做备份到给主服务器从新配置好二进制日志功能这段时间,不能在主服务器上发生修改操做。

  • 关闭服务器。

  • 对主服务器的配置进行修改--把它的镜像ID告诉它并激活其二进制日志功能。在主服务器要读取的选项文件内增长如下内容:

    [mysqld]
    server-id=master_server_id
    log-bin=binlog_name
    
  • 从新启动主服务器,从如今开始,它将把客户对数据库的修改操做记录到二进制变动日志里。若是在此以前已经激活了二进制日志功能,则要在重启前把二进制变动日志备份下来,在重启后再发一条RESET MASTER语句去清除现有的二进制变动日志。

  • 关闭从服务器。

  • 对从服务器进行配置,使它知道自已的镜像ID,到哪里去找主服务器以及如何去链接主服务器。配置内容以下:

    [mysqld]
    server-id=slave_server_id
    master-host=master_host
    master-user=slave_user          #在主服务器上为从服务器创建的账户
    msater-password=slave_pass      #在主服务器上为从服务器创建的账户的密码
    master-connet-retry=30         #设置链接重试间隔,默认为60秒
    master-retry-count=100000       #设置重试次数,默认为86400次
    注:最后两个选项在网络链接不可靠时设置
    
  • 从新启动从服务器。从服务器用两个信息源来肯定它自已在镜像工做中的进度位置:一个是数据目录中的master.info文件,另外一个是启动选项所给定的配置信息。第一次启动从服务器时,master.info文件不存在,从服务器会根据选项文件中给出的各类master-xxx选项值去链接主服务器。一旦链接成功,从服务器会建立一个master.info文件以保存各类链接参数和它自已的镜像工做状态。若是之后再重启从服务器,从服务器会优先读取该文件,而不是选项文件。因此若是你修改了选项文件的内容,想该选项生效就要删除master.info文件并重启从服务器。

以上步骤是镜像全部数据库的操做过程,若是咱们想把mysql权限数据保留在主服务器上,排除在镜像机制外的话,可用在选项文件的[mysqld]中加入--binlog-ignore-db=mysql选项,这样,mysql数据库上的操做就不会记录在二进制变动日志里。如要排除其它数据库,只要增长多几个该选项便可。

经过如下几个命令可监控和管理主从服务器:

  • SLAVE STOP,SLAVE START用于挂起来恢复从服务器上镜像,如当备份时,可用该语句让从服务器暂时中止镜像活动。

  • SHOW SLAVE STATUS,在从服务器上查看其镜像协调信息,这些信息能够用来判断哪些二进制变动日志已经再也不使用。

  • PURGE MASTER,在主服务器上对二进制变动日志进行失效处理。删除全部从服务器都再也不使用的二进制变动日志。

  • CHANGE MASTER,在从服务器上修改镜像参数。如正在读取主服务器上哪一个二进制变动日志,正在写哪一个中继日志文件等。

在MySQL4.0.2以后版本中,镜像机制中的从服务器由两个内部线程组成:

  • 一个叫“I/O线程”,负责与主服务器通讯,请求主服务器发送二进制变动日志,并把接收到的数据修改命令写入某个中继日志文件;用SLAVE STOP IO_THREAD或SLAVE START IO_THREAD可挂起或恢复该线程。

  • 另外一个叫“SQL线程”,负责从中继日志中读取数据修改命令并执行。同理,用SLAVE STOP SQL_THREAD或SLAVE START SQL_THREAD可挂起或恢复该线程。

中继日志文件默认的文件为hostname-relay-bin.nnn和hostname-relay-bin.index。可用从服务器的--relay-log和--relay-log-index选项修改。在从服务器中还有一个relay-log.info中继信息文件,可用--relay-log-info-file启动选项修改文件名。

Chapter 5. 数据库安全

 

安全是一个过程,而不是一个方法,它贯穿在咱们使用和维护MySQL数据库的过程当中。这不单是系统管理员工做,用户也要有安全的意识,使安全问题获得有效控制。MySQL服务器的安全问题可分为内部安全和外部安全两部份。内部安全问题大都与系统文件有关,咱们需确保MySQL程序文件和数据文件的安全。外部安全是指经过网络链接到服务器的安全问题,应该只容许合法用户访问数据库,在一些状况下还可用SSL加密信息传输通道。下分别介绍内部安全和外部安全的防范措施。

5.1. 保护MySQL安装程序文件

 
  • 在重设置文件权限时,请先关闭数据库服务器。

  • 用如下命令把MySQL安装程序目录的属主和所属组设置为MySQL管理员账号的用户名和用户组名。

    % chown -R mysql.mysql /usr/local/mysql
    

    另一种方法是把除数据目录外的全部目录属主设置为root全部,如:

    % chown -R root.mysql /usr/local/mysql
    % chown -R mysql.mysql /usr/local/mysql/data
    
  • 设置安装目录及各有关子目录的权限,容许管理员进行全部操做,只容许其余人进行读和执行访问,设置命令以下:

    #设置mysql目录
    % chmod 755 /usr/local/mysql
    or
    % chmod u=rwx,go=rx /usr/local/mysql
    #设置mysql/bin目录
    % chmod 755 /usr/local/mysql/bin
    or
    % chmod u=rwx,go=rx /usr/local/mysql/bin
    #设置mysql/libexec目录
    % chmod 700 /usr/local/mysql/libexec
    or
    % chmod u=rwx,go-rwx /usr/local/mysql/libexec
    
  • 把数据目录及目录中的全部子目录和文件设置为只容许MySQL管理员访问。

    % chmod -R go-rwx /usr/local/mysql/data
    

    若是数据目录下有选项文件或套接字文件,并一些客户需访问这些文件,则可用如下的权限设置,使客户在没有读权限的前提下使用这些文件:

    % chmod go+x /usr/local/mysql/data
    
  • mysql.sock套接字文件通常放以/tmp目录下,要确保该目录设置了粘着位,使自户只能删除自已建立的文件,不能删除其余用户建立的文件。/etc/my.cnf中公共选项文件,是对全部用户可读的,因此不该把一些敏感信息保存在里面。.my.cnf是用户专用选项文件,要确保只有该用户有权访问。

  • 这样设置之后,只有MySQL管理员才能启动服务器。

5.2. 权限表

 

MySQL服务器经过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。下面分别介绍一下这些表的结构和内容:

  • user权限表:记录容许链接到服务器的用户账号信息,里面的权限是全局级的。

  • db权限表:记录各个账号在各个数据库上的操做权限。

  • table_priv权限表:记录数据表级的操做权限。

  • columns_priv权限表:记录数据列级的操做权限。

  • host权限表:配合db权限表对给定主机上数据库级操做权限做更细致的控制。这个权限表不受GRANT和REVOKE语句的影响。

你们注意到,以上权限没有限制到数据行级的设置。在MySQL只要实现数据行级控制就要经过编写程序(使用GET-LOCK()函数)来实现。

MySQL的版本不少,因此权限表的结构在不一样版本间会有不一样。若是出现这种状况,可用mysql_fix_privilege_tables脚原本修正。运行方式以下:

% mysql_fix_privilege_tables rootpassword            #这里要给出MySQL的root用户密码

最好一会儿升级到MySQL 4.0.4版本,由于4.0.2和4.0.3的db表没有Create_tmp_table_priv和Lock_tables_priv权限。

MySQL的权限表定义了两部分内容,一个部份定义权限的范围,即谁(账户)能够从哪里(客户端主机)访问什么(数据库、数据表、数据列);另外一部份定义权限,即控制用户能够进行的操做。下面是一些经常使用的权限介绍,可直接在GRANT语句中使用。

  • CREATE TEMPORARY TABLES,容许建立临时表的权限。

  • EXECUTE,容许执行存储过程的权限,存储过程在MySQL的当前版本中还没实现。

  • FILE,容许你经过MySQL服务器去读写服务器主机上的文件。但有必定限制,只能访问对任何用户可读的文件,经过服务器写的文件必须是还没有存在的,以防止服务器写的文件覆盖重要的系统文件。尽管有这些限制,但为了安全,尽可能不要把该权限授予普通用户。而且不要以root用户来运行MySQL服务器,由于root用户可在系统任何地方建立文件。

  • GRANT OPTION,容许把你自已所拥有的权限再转授给其余用户。

  • LOCK TABLES,能够使用LOCK TABLES语句来锁定数据表

  • PROCESS,容许你查看和终止任何客户线程。SHOW PROCESSLIST语句或mysqladmin processlist命令可查看线程,KILL语句或mysqladmin kill命令可终止线程。在4.0.2版及之后的版本中,PROCESS权限只剩下查看线程的能力,终止线程的能力由SUPER权限控制。

  • RELOAD,容许你进行一些数据库管理操做,如FLUSH,RESET等。它还容许你执行mysqladmin命令:reload,refresh,flush-hosts,flush-logs,flush-privileges,flush-status,flush-tables和flush-threads。

  • REPLICATION CLIENT,容许查询镜像机制中主服务器和从服务器的位置。

  • REPLICATION SLAVE,容许某个客户链接到镜像机制中的主服务器并请求发送二进制变动日志。该权限应授予从服务器用来链接主服务器的账号。在4.0.2版这前,从服务器是用FILE权限来链接的。

  • SHOW DATABASES,控制用户执行SHOW DATABASES语句的权限。

  • SUPER,容许终止线程,使用mysqladmin debug命令,使用CHANGE MASTER,PURGE MASTER LOGS以及修改全局级变量的SET语句。SUPER还容许你根据存放在DES密钥文件里的密钥进行DES解密的工做。

user权限表中有一个ssl_type数据列,用来讲明链接是否使用加密链接以及使用哪一种类型的链接,它是一个ENUM类型的数据列,可能的取值有:

  • NONE,默认值,表示不需加密链接。

  • ANY,表示须要加密链接,能够是任何一种加密链接。由GRANT的REQUIRE SSL子句设置。

  • X509,表示须要加密链接,并要求客户提供一份有效的X509证书。由GRANT的REQUIRE X509子句设置。

  • SPECIFIED,表示加密链接需知足必定要求,由REQUIRE子句的ISSUER,SUBJECT或CIPHER的值进行设置。只要ssl_type列的值为SPECIFIED,则MySQL会去检查ssl_cipher(加密算法)、x509_issuer(证书签发者)和x509_subject(证书主题)列的值。这几列的列类型是BLOB类型的。

user权限表里还有几列是设置账户资源使用状况的,若是如下数据列中的数全为零,则表示没有限制:

  • max_connections,每小时可链接服务器的次数。

  • max_questions,每小时可发出查询命令数。

  • max_updates,每小时能够发出的数据修改类查询命令数。

设置权限表应注意的事项:

  • 删除全部匿名用户。

  • 查出全部没有口令用户,从新设置口令。可用如下命令查询空口令用户:

    mysql> SELECT host,user FROM user WHERE password = '';
    
  • 尽可能不要在host中使用通配符。

  • 最好不要用user权限表进行受权,由于该表的权限都是全局级的。

  • 不要把mysql数据库的权限授予他人,由于该数据库包含权限表。

  • 使用GRANT OPTION权限时不要滥用。

  • FILE权限可访问文件系统中的文件,因此受权时也要注意。一个具备FILE权限的用户执行如下语句就可查看服务器上全体可读的文件:

    mysql> CREATE TABLE etc_passwd(pwd_entry TEXT);
    mysql> LOAD DATA INFILE '/etc/passwd' INTO TABLE etc_passwd;
    mysql> SELECT * FROM etc_passwd;
    

    若是MySQL服务器数据目录上的访问权限设置得很差,就会留下让具备FILE权限的用户进入别人数据库的安全漏洞。因此建议把数据目录设置成只能由MySQL服务器读取。下面演示一个利用具备FILE权限的用户读取数据目录中文件权限设置不严密的数据库数据的过程:

    mysql> use test;
    mysql> create table temp(b longblob);
    mysql> show databases                   #显示数据库名清单,--skip-show-database可禁止该功能
    mysql> load data infile './db/xxx.frm' into table temp fields escaped by '' lines terminated by '';
    mysql> select * from temp into outfile 'xxx.frm' fields escaped by '' lines terminated by '';
    mysql> delete from temp;
    mysql> load data infile './db/xxx.MYD' into table temp fields escaped by '' lines terminated by '';
    mysql> select * from temp into outfile 'xxx.MYD' fields escaped by '' lines terminated by '';
    mysql> delete from temp;
    mysql> load data infile './db/xxx.MYI' into table temp fields escaped by '' lines terminated by '';
    mysql> select * from temp into outfile 'xxx.MYI' fields escaped by '' lines terminated by '';
    mysql> delete from temp;
    

    这样,你的数据库就给人拷贝到本地了。若是服务器是运行在root用户下,那危害就更大了,由于root可在服务器上作任何的操做。因此尽可能不要用root用户来运行服务器。

  • 只把PROCESS权限授予可信用户,该用户可查询其余用户的线程信息。

  • 不要把RELOAD权限授予无关用户,由于该权限可发出FLUSH或RESET语句,这些是数据库管理工具,若是用户不当使用会使数据库管理出现问题。

  • ALTER权限也不要授予通常用户,由于该权限可更改数据表。

GRANT语句对权限表的修改过程:

  • 当你发送一条GRANT语句时,服务器会在user权限表里建立一个记录项并把你用户名、主机名和口令记录在User、Host和Password列中。若是设置了全局权限,由把该设置记录在相在的权限列中。

  • 若是在GRANT里设置了数据库级权限,你给出的用户名和主机名就会记录到db权限表的User和Host列中,数据库名记录在Db列中,权限记录到相关的权限列中。

  • 接着是到数据表和数据列级的权限设置,设置方法和上面的同样。服务器会把用户名、主机名、数据库名以及相应的数据表名和数据列名记录到数据表中。

删除用户权限其实就是把这些权限表中相应的账号记录所有删除便可。

5.3. 创建加密链接

 

加密链接可提升数据的安全性,但会下降性能。要进行加密链接,必须知足如下要求:

  • user权限表里要有相关的SSL数据列。若是安装的MySQL服务器是4.0.0版的,user权限表已包含相关的SSL数据列,不然,咱们也可用mysql_fix_privilege_tables脚本升级权限表。

  • 服务器和客户程序都已经编译有OpenSSL支持。首先要安装openssl,在编译时MySQL服务器时加--with-vio和--with-openssl选项加上openssl支持。可用如下语句查询服务器是否支持SSL:

    mysql> show variables like 'have_openssl';
    
  • 在启动服务器时用有关选项指明证书文件和密钥文件的位置。在创建加密链接前,要准备三个文件,一个CA证书,是由可信赖第三方出具的证书,用来验证客户端和服务器端提供的证书。CA证书可向商业机构购买,也可自行生成。第二个文件是证书文件,用于在链接时向对方证实自已身份的文件。第三个文件是密钥文件,用来对在加密链接上传输数据的加密和解密。MySQL服务器端的证书文件和密钥文件必须首先安装,在sampdb发行版本的ssl目录里有几个供参考的样本文件:ca-cert.pem(CA证书),server-cert.pem(服务器证书),server-key.pem(服务器公共密钥)。把这几个文件拷贝到服务器的数据目录中,再在选项文件里加上如下内容:

    [mysqld]
    ssl-ca=/usr/local/mysql/data/ca-cert.pem
    ssl-cert=/usr/local/mysql/data/server-cert.pem
    ssl-key=/usr/local/mysql/data/server-key.pem
    

    重启服务器,使配置生效。

  • 要想让某个客户程序创建加密链接,必须在调用这个客户程序时用有关选项告诉它在哪里能找到其证书文件和密钥文件。在sampdb发行版的ssl目录中提供了client-cert.pem(客户证书文件),client-key.pem(客户密钥文件),CA证书与服务器使用一样的ca-cert.pem。把他们拷贝到我的目录下,并在.my.cnf选项文件中指出文件位置,如:

    [mysql]
    ssl-ca=/home/mysql/ca-cert.pem
    ssl-cert=/home/mysql/client-cert.pem
    ssl-key=/home/mysql/client-key.pem
    

    配置完成后,调用mysql程序运行\s或SHOW STATUS LIKE 'SSL%'命令,若是看到SSL:的信息行就说明是加密链接了。若是把SSL相关的配置写进选项文件,则默认是加密链接的。也可用mysql程序的--skip-ssl选项取消加密链接。若是用命令行方式启用加密链接能够这样写:

    % mysql --ssl-ca=ca-cert.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem
    

可用GRANT语句的REQUIRE SSL选项来强制用户使用加密链接。

使用sampdb发行版的证书能够创建一个加密链接,但因为该文件已公开,因此安全性很差,咱们能够在测试成功后自行创建证书或购买商业证书,以提升安全性。如何自行创建SSL证书的文档在sampdb发行版的ssl/README文件里有说明。

Chapter 6. 数据库的备份、维护和修复

 

数据库在运行中,会由于人为因素或一些不可抗力因素形成数据损坏。因此为了保护数据的安全和最小停机时间,咱们需制定详细的备份/恢复计划,并按期对计划的有效性进行测试。本章结合MySQL服务器的运行机制和所提供的工具,介绍如何进行数据库的备份、维护和修复。

如下是几点防范的措施:

  • 制定一份数据库备份/恢复计划,并对计划进行仔细测试。

  • 启动数据库服务器的二进制变动日志,该功能的系统开销很小(约为1%),咱们没有理由不这样作。

  • 按期检查数据表,防范于未燃。

  • 按期对备份文件进行备份,以防备份文件失效。

  • 把MySQL的数据目录和备份文件分别放到两个不一样的驱动器中,以平衡磁盘I/O和增长数据的安全。

6.1. 检查/修复数据表

 

对数据表进行维护最好经过发出CHECK TABLE(检查数据表)或REPAIRE TABLE(修复数据表)命令来作,这样MySQL服务器自动进行表锁定以协调数据表中数据的读写一致性问题。也可用myisamchk工具来作数据表的维护,但它直接访问有关的数据表文件,不经过服务器,因此需人为地协调数据表数据的读写一致性问题。使用myisamchk检查数据表的具体操做步骤以下:

  • 以mysql客户端程序链接服务器,并发出LOCK TABLE命令,以只读方式锁住数据表。

    % mysql
    mysql> use db
    mysql> LOCK TABLE table_name READ;     #以只读方式锁定表
    mysql> FLUSH TABLE table_name;        #关闭数据表文件,并把内存中的信息写入磁盘
    
  • 保持上面的状态不退出,另开一个shell窗口,用如下命令维护(检查)数据表。

    % myisamchk table_name
    
    [Note]  
    若是不保持上面状态,退出mysql会话,则表锁定会自动取消。
  • 维护完成,切换回mysql状态的shell窗口,发出如下命令解除表锁定。

    mysql> UNLOCK TABLES;
    

使用myisamchk修复数据表的具体操做步骤以下:

  • 进行修复操做需以读/写方式锁定数据表,命令以下:

    % mysql
    mysql> use db
    mysql> LOCK TABLE table_name WRITE;     #以读/写方式锁定数据表
    mysql> FLUSH TABLE table_name;
    
  • 保持mysql客户端链接状态,切换到第二个shell窗口,运行修复命令:

    % myisamchk --recover table_name
    
    [Note]  
    运行修复命令前最好先备份一下数据文件。
  • 修复完成后,切换回mysql客户端链接窗口,运行如下命令解除数据表锁定:

    mysql> FLUSH TABLE table_name;     #使服务器觉察新产生的索引文件
    mysql> UNLOCK TABLE;
    

还可用如下命令锁定全部表,锁定后,全部用户就只能读不能写数据,这样就可以使咱们能安全地拷贝数据文件。

mysql> FLUSH TABLES WITH READ LOCK;
下面是解除锁语句:
mysql> UNLOCK TABLES;

6.2. 备份数据库

 

按期的备份可以使咱们数据库崩溃形成的损失大大下降。在MySQL中进行数据备份的方法有两种,一种是使用mysqldump程序,一种是使用mysqlhotcopy、cp、tar或cpio等打包程序直接拷贝数据库文件。mysqldump程序备份数据库较慢,但它生成的文本文件便于移植。使用mysqlhotcopy等程序备份速度快,由于它直接对系统文件进行操做,需人为协调数据库数据的备份先后一致性。

  • 使用mysqldump备份数据库其实就是把数据库转储成一系列CREATE TABLE和INSERT语句,经过这些语句咱们就可从新生成数据库。使用mysqldump的方法以下:

    % mysqldump --opt testdb | gzip > /data/backup/testdb.bak
    #--opt选项会对转储过程进行优化,生成的备份文件会小一点,后的管道操做会进行数据压缩
    % mysqldump --opt testdb mytable1,mytable2 | gzip > /data/backup/testdb_mytable.bak
    #可在数据库后接数据表名,只导出指定的数据表,多个数据表可用逗号分隔
    
    [Note]  
    --opt选项还可激活--add-drop-table选项,它将会在备份文件的每条CREATE TABLE前加上一条DROP TABLE IF EXISTS语句。这可方便进行数据表的更新,而不会发生“数据表已存在”的错误。

    用mysqldump命令还可直接把数据库转移到另一台服务器上,不用生成备份文件。重复执行可按期更新远程数据库。

    % mysqladmin -h remote_host create testdb
    % mysqldump --opt testdb | mysql -h remote_host testdb
    另外还可经过ssh远程调用服务器上的程序,如:
    % ssh remote_host mysqladmin create testdb
    % mysqldump --opt testdb | ssh remote_host mysql testdb
    
  • 经过直接拷贝系统文件的方式备份数据库,在备份时,要确保没有人对数据库进行修改操做。要作到这点,最好关闭服务器。若是不能关闭的,要以只读方试锁定有关数据表。下面是一些示例:

    % cp -r db /backup/db                 #备份db数据库到/backup/db目录
    % cp table_name.* /backup/db          #只备份table_name数据表
    % scp -r db remotehot:/usr/local/mysql/data      #用scp把数据库直接拷贝到远程服务器
    
    [Note]  
    在把数据库直接拷贝到远程主机时,应注意两台机器必须有一样的硬件结构,或者将拷贝的数据表所有是可移植数据表类型。
  • 使用mysqlhotcopy工具,它是一个Perl DBI脚本,可在不关闭服务器的状况下备份数据库,它主要的优势是:

    • 它直接拷贝文件,因此它比mysqldump快。

    • 可自动完成数据锁定工做,备份时不用关闭服务器。

    • 能刷新日志,使备份文件和日志文件的检查点能保持同步。

    下面是该工具的使用示例:

    % mysqlhotcopy db  /bakcup/                 #把db数据库备份到backup/db目录里,会自动建立一个db目录
    
  • 使用BACKUP TABLE语句进行备份,该语句最先出如今MySQL 3.23.25版本中,仅适用于MyISAM数据表。用法以下:

    mysql> BACKUP TABLE mytable TO '/backup/db';         #把mytable数据表备份到/backup/db目录下
    

    为了执行该语句,你必须拥有那些表的FILE权限和SELECT权限,备份目录还必须是服务器可写的。该语句执行时,会先把内存中的数据写入磁盘,再把各个数据表的.frm(表结构定义文件)、.MYD(数据)文件从数据目录拷贝到备份目录。它不拷贝.MYI(索引)文件,由于它能用另外两个文件重建。BACKUP TABLE语句备份时,依次锁定数据表,当同时备份多个数据表时,数据表可能会被修改,因此备份0完成时,备份文件中的数据和现时数据表中的数据可能会有差别,为了消除该差别,咱们可用只读方式锁定数据表,在备份完成后再解锁。如:

    mysql> LOCK TABLES tb1 READ,tb2 READ;
    mysql> BACKUP TABLE tb1,tb2 TO 'backup/db';
    mysql> UNLOCK TABLES;
    

    使用BACKUP TABLE语句备份的数据表可用RESTORE TABLE从新加载到服务器。

  • InnoDB和BDB数据库也可用mysqldump和直接拷贝法进行备份。使用直接拷贝法时应注意需把组成InnoDB和BDB数据库的全部文件都拷贝下来,如InnoDB的.frm文件、日志文件和表空间配置文件;BDB的数据文件、日志文件等。

  • 使用镜像机制进行备份,咱们可用SLAVE STOP语句挂起从服务器的镜像,在从服务器上经过直接拷贝法或其它工具制做备份。备份完成,用SLAVE START从新启动镜像,从服务器从新与主服务器同步,接收备份时主服务器所作的修改。

在MySQL中没有为数据库重命名的命令,但咱们可用mysqldump转储数据库,再建立一个新的空数据库,把转储文件加载到该新数据库,这样就完成数据库重命名的工做。如:

% mysqldump old_db >db.sql          #转储db数据库数据
% mysqladmin create new_db          #新建一个空的数据库
% mysql new_db < db.sql             #把db数据库的数据加载到新的数据库中
% mysqladmin drop old_db            #删除旧的数据库

一个更简单的重命名数据库的方法是直接修改数据库目录名,但该方法不适用于InnoDB和BDB数据库。注意,在改名后,需在权限表中更新相关数据表信息,需执行如下语句:

mysql> UPDATE db SET db='new_db' WHERE db='old_db';
mysql> UPDATE tables_priv SET db='new_db' WHERE db='old_db';
mysql> UPDATE columns_priv SET db='new_db' WHERE db='old_db';
mysql> UPDATE host SET db='new_db' WHERE db='old_db';

6.3. 使用备份恢复数据

 

恢复过程包括两个信息源---备份文件和二进制日志,备份文件可以使用数据恢复到执行备份时的状态,而二进制日志可恢复到发生故障时的状态。下面分别介绍如何利用这两个文件恢复一个数据库或恢复单个数据表。

恢复整个数据库的步骤:

  1. 把需恢复的数据库的整个目录的内容拷贝到其它地方,以备用。

  2. 使用最近的备份文件重载数据库。若是使用mysqldump生成的备份,则可以使用它们做为mysql的输入重载;若是是经过拷贝数据库目录来备份的,则要关闭数据库服务器,再把备份从新拷贝到数据目录,再重启数据库服务器。

  3. 经过二进制日志重作事务,恢复到出错点的数据。具体操做是这样的,用mysqlbinlog把日志转换成ASCII格式,再把它做为mysql的输入,并指定--one-database选项,以便mysql只执行你指定的数据库恢复。如:

    % ls -t -r -l binlog.[0-9]* | xargs mysqlbinlog | mysql --one-database db_name
    

    但上面命令只适合全部日志文件名具备相同长度的状况。不然需用下面的Perl代码来处理:

    #!/usr/bin/perl -w
    # sort_num.pl
    
    use strict;
    
    my @files = <>;             #read all input file
    @files = sort { my $anum = $1 if $a =~/\.(\d+)$/;         #sort them by numeric extension
                    my $bnum = $1 if $b =~/\.(\d+)$/;
                    $anum <=> $bnum;
                  } @files;
    print @files;              #print them
    exit(0);
    
    以下使用该脚本:
    % ls -l binlog.[0-9]* | sort_num.pl | xargs mysqlbinlog | mysql --one-database db_name
    

    上面讨论的是需全部日志文件的状况,但多数状况下咱们只需备份后生成的几个日志文件,这时,可用如下命令来重作。

    % mysqlbinlog binlog.1234 | mysql --one-database db_name
    % mysqlbinlog binlog.1235 | mysql --one_database db_name
    ...
    

    若是咱们需恢复因执行DROP DATABASE,DROP TABLE或DELETE语句而损坏的数据库,就需在日志文件中删除该语句,不然重作后结果仍是同样。因此需把日志转换成ASCII格式并保存起来,再用编辑器打开该文件,删除这些语句后再重作。

    [Note]  
    若是使用文本变动日志,则不需使用mysqlbinlog程序,由于该日志文件自己就是ASCII格式。

恢复使用BACKUP TABLE命令备份的数据表可用RESTORE TABLE语句:

备份语句:
mysql> BACKUP TABLE table_name1,table_name2 TO '/backup/table_backup';
恢复语句:
mysql> RESTORE TABLE table_name1,table_name2 FROM '/backup/table_backup';

恢复有外键的数据表,可用SET FOREIGN_KEY_CHECK = 0;语句先关闭键字检查,导入表后再重启它,赋值为1表示检查有效。

恢复InnoDB表空间,当服务器重启时,InnoDB处理程序会执行自动恢复工做,经过选项文件[mysqld]段中的set-variable=innodb_force_recovery=level设置自动恢复的级别,推荐典型的启动值为4。若是需从备份文件恢复,则和上面介绍的方法同样。BDB数据表的恢复也同样,启动服务器时它会进行自动恢复。

Chapter 7. MySQL程序介绍

 

安装完MySQL后,在MySQL的安装目录下会生成不少有用的程序,下面对这些程序进行一一介绍。

  • libmysqld----嵌入式MySQL服务器,它不能独立运行,它是一个函数库,可嵌入到其它程序中,使程序具备MySQL服务器的功能。

  • myisamchk和isamchk----检查和修复数据表、分析键值的分布状况、禁止或启用数据表索引的工具。

  • myisampack和pack_isam----压缩数据表并生成只读数据表。

  • mysql----最经常使用的一个与服务器交互的命令行客户端程序。

  • mysqlaccess----一个用来测试数据库访问权限的脚本。

  • mysqladmin----一个用来执行各类系统维护和管理工做的工具。

  • mysqlbinlog----一个以ASCII格式显示二进制变动日志内容的工具。

  • mysqlbug----一个用来生成程序漏洞报告的脚本。

  • mysql_config----当准备编译基于MySQL的程序时,能够利用这个工具程序来肯定该程序的编译选项和标志。

  • mysqld----MySQL服务器程序,MySQL数据的核心。

  • mysqld_multi----一个用来同时启动和关闭多个MySQL服务器的脚本。

  • mysql_safe----一个用来启动和监控MySQL服务器的脚本。

  • mysqldump----一个用来导出数据表内容的工具。

  • mysqlhotcopy----数据库备份工具。

  • mysqlimport----一个对数据表批量加载数据的工具。

  • mysql_install_db----一个初始化系统权限表和数据目录的脚本。

  • mysql.server----一个用来启动和关闭MySQL服务器的脚本。

  • mysqlshow----一个用来显示数据库中数据表的工具。

Chapter 8. MySQL How-To

 

8.1. 链接数据库服务器

 

$ ./mysql -h host_name -u user_name -p

  • -h host_name(--host=host_name),链接的数据库主机名,若是在本地主机上则可省略。

  • -u user_name(--user=user_name),数据库用户名,在unix系统上,若是系统的登陆名与数据用户名同样,则可省略。在windows系统中,可经过设置环境变量USER来给出数据库用户名,如set USER=username。

  • -p(--password),提供数据库用户密码,有该选项mysql就会提示你输入密码。输入的密码以星号显示,以确保安全。也可直接在-p后写上密码(-p和密码间不能有空格),但这不安全,不推荐。

链接成功后,mysql数据库服务器会显示一些欢迎信息。接着就可用mysql>use database_name命令打开指定的数据库。

[Note]  
$ ./mysql -h host_name -u user_name -p database_name命令可直接打开指定数据库。

8.2. 更新用户密码

 

mysql>update user set password=passowrd('your passowrd') where host='%';

刷新权限设置:mysql>flush privileges;

8.3. MySQL读取配置文件的顺序

 

my.cnf是MySQL数据库的配置文件,它存在多个地方,在/etc目录,数据目录和用户主目录都有。放在不一样位置,里面的选项有不一样的做用范围,下面是MySQL读取配置文件的顺序和做用。

mysql 读取配置文件的顺序:
/etc/my.cnf              Global options.
DATADIR/my.cnf           Server-specific options.
defaults-extra-file      The file specified with the --defaults-extra-file option.
~/.my.cnf                User-specific options.

8.4. 重设置MySQL管理员密码的方法

 

有时咱们会由于设置缘由或时间长了忘记了数据库管理员的密码,使得咱们被关在MySQL服务器外。MySQL服务器提供了一种方法可以使咱们在服务器上重设密码。在windows和linux/unix平台上操做稍有不一样,下面分别介绍:

  • Linux/Unix平台下:

    1. 用 % kill -TERM PID关闭服务器,用-TERM信息可以使服务器在关闭前把内存中的数据写入磁盘。若是服务器没有响应,咱们可用% kill -9 PID来强制删除进程,但不建议这样作。这时内存中的数据不会写入磁盘,形成数据不完整。若是你是用mysql_safe脚本启动MySQL服务器的,这个脚本会监控服务器的运行状况并在它被终止时重启服务器,因此如需关闭服务器,要先终止该进程,而后再真正终止mysqld进程。

    2. 使用--skip-grant-tables参数启动MySQL Server,这时MySQL服务器将不使用权限表对链接操做进行验证。你就可在不提供root密码的状况下链接上服务器,并得到root的权限。

      % mysqld_safe --skip-grant-tables & 
      
    3. 用如下命令登陆服务器,并重设密码:

       % mysql -u root         #不用密码就可链接到服务器
      mysql> use mysql
      mysql> set password for 'root'@'localhost' = password('password');
      
      [Note]  
      修改MySQL服务器账户密码有三种方式,你可参考本笔记中数据库平常管理一章中的相关内容。在这种环境下,使用mysaladmin修改密码好象不行,仍是提示要输入密码。
    4. 关闭服务器,再用正常方式启动服务器。

  • windows平台下:

    1. 用管理员账号登陆服务器,关闭MySQL数据库服务器。

    2. 使用--skip-grant-tables参数启动服务器:

      c:\mysql\bin>mysqld-nt --skip-grant-tables 
      
    3. 从新打开一个console窗口,用mysql命令登陆服务器设置root的新密码:

      c:\mysql\bin>mysql
      mysql> use mysql
      mysql> set password for 'root'@'localhost' = password('password');
      
    4. 关闭服务器,再用正常方式启动服务器。

8.5. NULL值

 

NULL是空值,表明什么也没有。它不能与值进行比较操做和算术操做,也不能和NULL进行比较,由于两个空值比较是没有意义的。咱们可用“is NULL” 或 “is not NULL”来判断是不空值。如:

mysql> select * from test where mytest is NULL;
mysql> select * from test where mytest is not NULL;

在MySQL3.23之后的版本有一个新的比较操做符“<=>”,它可对NULL值进行相等比较。如:

mysql> select * from test where mytest <=> UNLL;
mysql> select * from test where not (mytest <=>);

若是查询后排序中的数据中包含NULL,则从MySQL4.0.2开始,有NULL值的数据行老是出如今查询结果的开头,即便设置的desc参数。4.0.2之前版本,若是设置了asc,则出在查询结果的开头,若是设置了desc,则出如今查询结果的结尾。

8.6. 使用SQL变量

 

MySQL3.23.6之后的版本容许经过查询结果来设置变量,设置好的变量可在之后使用。变量用@name定义,赋值方式用@name:=value。下面是一个在查询语句中进行赋值和使用变量的例子:

mysql> select @name:=id from test where mytest="test";
mysql> select * from test where mytest=@name

8.7. 改变默认提示符

 

用mysql登陆进数据库后,MySQL数据的默认提示符是“mysql”,咱们可设置它根据用户打开的数据库名而变化,如:

mysql>prompt \d>\_
none>use test
test>use mysql
mysql>

prompt为设置命令,\d表明当前数据库,\_表明一个空格。

8.8. 非优化的全数据表DELETE操做

 

为了清空数据表,又需知道删除的行数和保持AUTO_INCREMENT序列的值,需用如下的删除语句:

# delete from table_name where 1;

8.9. MySQL事务处理示例

 

MYSQL高级特性 -- 事务处理下面以两个银行帐户之间的转帐为例子进行演示。要使用MySQL中的事务处理,首先须要建立使用事务表类型(如BDB = Berkeley DB或InnoDB)的表。

CREATE TABLE account (
account_id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
balance DOUBLE
) TYPE = InnoDB;


要在事务表上使用事务处理,必需要首先关闭自动提交:

SET AUTOCOMMIT = 0;

事务处理以BEGIN命令开始:

BEGIN;

如今mysql客户处在于服务器相关的事物上下文中。任何对事务表所作的改变在提交以前不会成为永久性的改变。

UPDATE ACCOUNT SET balance = 50.25 WHERE account_id = 1;
UPDATE ACCOUNT SET balance = 100.25 WHERE account_id = 2;

在作出全部的改变以后,使用COMMIT命令完成事务处理:

COMMIT;

固然,事务处理的真正优势是在执行第二条语句发生错误时体现出来的,若在提交前终止整个事务,能够进行回滚操做:

ROLLBACK;

下面是另外一个例子,经过MYSQL直接进行数学运算:

SELECT @first := balance FROM account WHERE account_id = 1;
SELECT @second := balance FROM account WHERE account_id = 2;
UPDATE account SET balance = @first - 25.00 WHERE account_id = 1;
UPDATE account SET balance = @second + 25.00 WHERE account_id = 2;

除了COMMIT命令外,下列命令也会自动结束当前事务:

ALTER TABLE
BEGIN
CREATE INDEX
DROP DATABASE
DROP TABLE
LOCK TABLES
RENAME TABLE
TRUNCATE
UNLOCK TABLES
相关文章
相关标签/搜索