MySQL 是一个真正的多用户、多线程SQL 数据库服务器。SQL (结构化查询语言) 是世界上最流行的和标准化的数据库语言。
MySQL 是以一个客户机/服务器结构的实现,它由一个服务器守护程序mysqld 和很多不同的客户程序和库组成。MySQL在windows上不区分大小写,Linux上表名区分大小写
MySQL主要目标是快速、健壮和易用
MySQL 具有运行速度很快、容易使用、支持查询语言、多个用户可同时连接客户机和服务器、可以运行在各种版本的UNIX以及非UNIX的系统上等优点。
先创建一个属于自己的数据库,如下:
- create database test;
- use test; //选用数据库
- create table test01( //创建表
- name nvarchar(40),
- age int(5));
可以用show databases语法来显示服务器主机上的数据库,从而找到你想要的那个数据库。
我们看下它的语法:
显示全部数据库
- show databases;
显示全部数据库表
- show tables;
删除数据库的语法
- drop database [if exists] db_name;
从后者的表中复制一份,添加到新的数据库表中语法:
- create table tb_new_name select * from tb_old_name;
显示数据库表信息
有时候我们需要查看某个数据库表的相关信息,比如结构,列名等等;那么我们就需要用到show/describe 语句来查看,看下面语法:
- show tables [from db_name] [like wild]
- show columns from tbl_name [from db_name] [like wild]
- show index from tbl_name [from db_name]
- show table status [from db_name] [like wild]
- {describe| desc} tbl_name {col_name | wild}
第一种语法表示:查看某个数据库下的所有数据库表,或者根据like模糊查看某个数据库表;例如
- show tables from test01;
- show tables from test01 like "%a%";
第二种语法表示:查看某个数据库表中的列属性,like后面跟的是列的名称的某个关键字;例如
- show columns from test01_01;
- show columns from test01_01 from test01 like "%n%";
第三种语法表示:查看某个数据库表中的索引;例如
- show index from test01_01 from test01;
第四种语法表示:查看数据库中全部表或者某个表的状态信息,信息提供的更多;例如
- show table status from test01;
- show table status from test01 like "%t%";
第五种语法表示:查看数据库表的信息,是show的另外一种方式;例如
- desc test01_01;
- describe test01_01 "%n%";
alter修改表结构
有时你可能需要改变一下现有表的结构,那么alter table语句将是你的合适选择。
增加列
- alter table tbl_name add col_name type
例如增加一个weight列:
- alter table test01_01 add weight int;
修改列
- alter table test01_01 modify weight varchar(50);
删除列
- alter table test01_01 drop weight;
另外一种常用方式,例如:
给列更名
- alter table test01_01 change weight wei int;
给表更名
操作表中的数据:
- alter table test01_01 rename test01_04;
利用 insert 语句来增加记录,这是一个 SQL 语句,需要为它指定希望插入数据行的表或将值按行放入的表。如果你设置了主键并且自动增长,添加的时候需要把对应的主键值设置为null或者数字“0”。
基本语法:
- insert [into] tbl_name [(col_name,...)] VALUES (pression,...)
- insert [into] tbl_name SET col_name=expression
可指定所有列的值:
- insert test01_01 values(null,'jack','23','beij');
select查询
select语句的语法如下:
注意:所有使用的关键词必须精确地以上面的顺序给出。例如,一个having子句必须跟在group by子句之后和order by子句之前
- select selection_list //选择哪些列
- from table_list //从何处选择行
- where primary_constraint //行必须满足什么条件
- group by grouping_columns // 怎样对结果分组
- having secondary_constraint //行必须满足的第二条件
- order by sorting_columns //怎样对结果排序
- limit count //结果限定
查询排序
使用 order by子句对查询返回的结果按一列或多列排序。
order by子句的语法格式为:
其中 asc表示升序,为默认值, desc为降序。
- order by column_name [asc|desc] [,…]
分组和行计数
group by从句根据所给的列名返回分组的查询结果,可用于查询具有相同值的列
基本语法:
- group by col_name,….
单独使用group by没有任何意义,它的真正作用在于与各种组合函数配合,用于行计数
看下面实例:
- select name,count(*) from test01_01 group by name;//按name分组,并且统计数量
多表查询
查询多个表,from子句列出表名,并用逗号分隔,因为查询需要从他们两个拉出信息
基本语法:
- select t1.name,t2.name from tb_name1 as t1,tb_name2 as t2 where t1.name=t2.name;
上述代码表示,从t1和t2中取出两张表name相同的值。as表示为这个表取别名。
update更新数据
修改数据我们用update更新,这是最常用的更新数据语句,我们看下语法
- update tbl_name SET 要更改的列
- where 要更新的记录
这里的 where 子句是可选的,因此如果不指定的话,表中的每个记录都被更新。
实例如下:
- update test01_03 set name='tom' where age= '20';
delete删除数据
删除一条语句,我们常用delete关键字。语法定义:
- delete from tbl_name where 要删除的记录
where子句指定哪些记录应该删除。它是可选的,但是如果不选的话,将会删除所有的记录。这意味着最简单的delete语句也是最危险的
实例如下:
- delete from test01_01 where age=10;//删除年龄为10的数据
数值类型
数值类型大致划分为两大类:一个是整数,一个是浮点数或小数。
整数类型常用的为int类型,允许范围在(-2147483648,2147483648)之间。
浮点数或小数常用类型有:float,double和decimal类型。
float类型(单精度浮点数值),double类型(双精度浮点数值),decimal类型(用于要求非常高的精确度计算中,这些类型允许指定数值的精确度和计数方法作为选择参数。精确度在这里是指为这个值保存的有效数字的总个数,而计数方法表示小数点后数字的个数)
字符串类型
常用字符串类型有:char,varchar,text和blob类型
char类型:用于定长字符串,必须在圆括号内用一个大小修饰符来定义,这个大小修饰符范围为0到255,指定了要存储的值的长度。
varchar类型:是char类型的变体,用于变长字符串,也也必须带有一个范围在0到255之间的大小指示器,区别在于MySQL处理这个指示器的方式:char把这个大小视为值的的准确大小,而varchar类型把它视为最大值并且只使用了存储字符串实际上需要的字节数。所以如果不能确定字段要存储多少个字符时,使用这种类型是一个很好的选择。
对于比较长的字符串,MySQL提供了text和blob两种类型,根据要存储数据的大小,它们都有不同的子类型,用于存储图像,大的文本,声音文件那样的二进制数据。区别在于:blob类型区分大小写,text类型不区分。
日期时间类型
MySQL用date和year类型描述简单的日期值,使用time类型描述时间值。这些值可以描述为字符串或不带分隔符的整数序列。如果描述为字符串,date类型的值应该使用连字号作为分隔符分隔开,而time类型的值应该使用冒号作为分隔符分隔开。year类型的值必须用4个数字存储,MySQL会自动转换:把00~69范围内的值转换到2000~2069范围内,而把70~99范围内的值抓换到1970~1999之内。如下例:
- create table data(showtime time,birthday date,graduation year);
- insert into data values('12:02:02','2000-02-02',2002),(120202,20000202,02);//结果是一样的
除了日期和时间数据类型,MySQL还支持一种混合类型:datetime和timestamp数据类型,它们可以把日期和时间作为一个单值的组成成分来存储。这两种类型通常用于自动存储包含当前日期和时间的时间戳,并且对执行大量数据库事务和需要建立一个调试和审查用途的审计跟踪的应用程序可以派上用场。
如果一个行中第一个字段语句为timestamp类型,而且这个字段没有被明确指定值或被指定了一个null值,MySQL将会自动用当前日期和时间填充它。
使用MySQL的now()函数在语句为datetime类型的字段中填充当前的日期和时间可以得到相同的结果。
数据类型选择
数据分类在使存储数据更有一致性和提高效率和速度方面起了重要的作用。从而,当设计一个数据库时对数据类型的选取不能掉以轻心,并且从MySQL可以使用的多组选项做出选择之前,应该对所有涉及的问题做出充分考虑。
下面列出对MySQL选取数据类型需要牢记的几个标准:
允许值,允许输入一个字段中的值的范围和类型是决定哪个数据类型加在这个字段上的最直接因素。
存储效率,考虑字段可能的值的范围并且根据这个范围选取一个适当的、大小合适的数据类型也是很重要的,尤其是在处理数值类型的时候。
格式和显示要求,影响字段类型选择的另一个重要因素是存储在字段内的数据的应用格式和显示要求。
数据处理要求,数据类型的选择还应该考虑数据操作和应用处理的要求,比如说某些类型更适合于加快数据操作而不是其他方面。
排序、索引和比较要求,如果想不同的标准对一列中所有的值进行排序,那么我们需要选择一种能够有效地执行这些功能并且带有最大限度的灵活性的类型。对相应字段添加索引,能够加快检索速度。比较的类型也应该使用的数据类型,需要保证使用的数据类型支持比较运算,并且相互兼容。
算数运算符
MySQL支持大多数通用的、允许我们执行计算的的算数运算符。
"+(加法)、-(减法)、*(乘法)、/(除法,返回商)、%(除法,返回余数)",如下例:
- select 1+2;//加法运算,结果为3
- select 2-1;//减法运算,结果为1
- select 3*2;//乘法运算,结果为6
- select 6/2;//除法运算,结果为3
- select 25%7;//除法运算,结果为4
- select 5/0;//除法运算,结果为null,MySQL除法的除数为0是不允许的
请注意,所有涉及整数的数学运算都是用64位的精度进行计算。
用字符串表示的数字在任何可能便于计算的地方都被自动的转换为字符串。遵循两个转换原则:
1:如果第一位是数字的字符串被用于算数运算中,那么它被转换为这个数字的值
2:如果一个包含字符和数字混合的字符串不能被正确的转换为数字,将被转换成0
- select '100'+'004';//结果为104
- select '90AA'+'0';//结果为90
- select '10x'*'qwe';//结果0
比较运算符
比较运算符,允许我们对表达式的左边和右边进行比较,一个比较运算的结果总是1(真),0(假)或为null(不确定)。
- select 6=6,3.4=4.5,'a'='b';//判断两边是否相等
- select 7<>7,7<>8,'a'<>'b';//判断两边是否不相等
- select 100>100,10<100;//判断左边是否大于右边,左边是否小于右边
- select 10>=100,10<=1;//判断左边是否大于等于右边,左边是否小于等于右边
- select 10 between 0 and 100;//检验一个值是否存在于一个指定的范围内
- select 10 not between 11 and 100;//检验一个值是否不存在于一个指定的范围内
- select 7 in (1,2,3,4,5,6,7,8,9);//检验一个值是否包含在一个指定的值集合中
- select 7 not in (1,2,3,4,5,6,7,8,9);//检验一个值是否不包含在一个指定的值集合中
默认情况下,比较是不区分大小写的。我们可以用binary关键字来执行区分大小写的运算
- select binary 'ross' in ('Chandler','Joey','Ross');
逻辑运算符
逻辑运算符可以测试1个或者多个表达式(或表达式集合)的逻辑有效性。含有这些运算符的运算结果总是1(真),0(假)或null(不能确定)
逻辑运算符中最简单的运算符是not运算符,它对跟在它后面的逻辑测试判断取反,把真变为假,把假变为真
- select not 1,not 0,not (2=2),not (100>20);//结果为0,1,0,1
and 运算符可以测试两个或更多的值(或表达式求值)的有效性,如果它的所有成分为真并且不是null,它返回真值,否则返回假值
- select (2=2) and (900<100),('a'='a') and ('c'<'d');//结果为0,1
or 运算符,如果包含的值或者表达式值为真并且不是null,它返回真值,否则返回假值。
- select (2=2) or (900<100),('a'='a') or ('c'<'d');//结果为1,1
MySQL4.x和更高版本中还包括了一个附加的xor运算符,如果它的参数中的一个(不是两个)为真,它返回真值。
- select (1=1) xor (2=4),(1<2) xor (9<10);//返回结果为1,0
位运算符
MySQL包含了6个专门用于位操作的运算符
"|"运算符用于执行一个位or操作,而&用于执行一个位and操作。
- select 16|32,9|4;//结果为48,13
- select 30 & 10,8 & 16;//结果10,0
还可以分别使用<<和>>运算符向左和向右移动位。
- select 1<<7,64>>1;//结果为128,32
^运算符执行位xor操作
- select 1^0,0^1,17^9,143^66;//结果为1,1,24,205
~运算符执行位取反操作,并返回64位整型结果
- select ~18446744073709551614,~1;//结果为1,18446744073709551614
数学函数
由于MySQL包含了一系列的算术操作,所以关系型数据库管理系统支持很多数学函数
- ABS(x);//返回x的绝对值
- ACOS(x);//返回x(弧度)的反余弦值
- ASIN(x);//返回x(弧度)的反正弦值
- ATAN(x);//返回x(弧度)的反正切值
- CEILING(x);//返回大于x的最小整数值
- COS(x);//返回x(弧度)的余弦值
- COT(x);//返回x(弧度)的余切
- DEGREES(x);//返回弧度值x转化为角度的结果
- EXP(x);//返回值e(自然对数的底)的x次方
- FLOOR(x);//返回小于x的最大整数值
- GREATEST(x1,x2,x3...);//返回集合中最大的值
- LEAST(x1,x2,x3,,,);//返回集合中最小的值
- LN(x);//返回x的自然对数
- LOG(x,y);//返回x的以y为底的对数
- MOD(x,y);//返回x/y的模(余数)
- PI();//返回pi的值(圆周率)
- POW(x,y)或者POWER(x,y);//返回x的y次幂
- RAND();//返回0到1内的随机数
- RADIANS(x);//返回角度x转化为弧度的结果
- ROUND(x,y);//返回参数x的四舍五入的有y位小数的值
- SIGN(x);//返回代表数字x的符号的值
- SQRT(x);//返回x的开方
- SIN(x);//返回x(弧度)的正弦值
- TAN(x);返回x(弧度)的正切值
- TRUNCATE(x,y);//返回数字x截短为y位小数的结果
看下面一些例子
- select ABS(-123);//取绝对值,结果为123
- select GREATEST(100,88,33,156);//获取一组数中最大值,结果为156
聚合函数
MySQL有一组函数是特意为求和或者对表中的数据进行集中概括而设计的,这些函数经常用在包含group by从句的select查询中,当然,它们也可以用于无group的查询
- AVG(col);//返回指定列的平均值
- COUNT(col);//返回指定列中非null值的个数
- MIN(col);//返回指定列的最小值
- MAX(col);//返回指定列的最大值
- SUM(col);//返回指定列的所有值之和
- STD(col)或STDDEV(col);//返回指定列的所有值的标准偏差
- VARIANCE(col);//返回指定列的所有值的标准方差
- GROUP_CONCAT(col);//返回由属于一组的列值连接组合而成的结果
这一组函数中,最常用到的是COUNT()函数,计算出结果集中至少包含一个非null的值的行数
- select count(*) from members;
MIN()和MAX()函数返回数字集的最小或最大值
- select min(quantity) from inventory;//返回最小值
- select max(return) from investments;返回最大值
字符串函数
因为MySQL数据库不仅报含数字数据,还包含字符串,因此MySQL有一套为字符串操作而设计的函数。
通过length()函数可以获得一个字符串的长度
- select length('aasdfgh');//结果为7
通过trim()函数可以让我们在剪切值时指定去除格式,还可以决定是从字符串的首部,尾部,两边剪切。
- select trim(' red alter ');//去掉两边空格
- select trim(leading '!' from '!!!error!!!');//去掉首部“!”符号
concat()函数将提供的参数连接成一个字符串
- select concat('red','hot');//结果为redhot
这里只是简单列出几个常用的字符串函数,更多函数,请查询MySQL相关文档。
日期时间函数
MySQL提供了很多处理日期时间的函数,这里我们只是选择一些常用的讲述。
使用now()函数获取当前的日期和时间,将以YYYY-MM-DD HH:MM:SS的格式返回当前的日期和时间
- select now();//返回当前时间
单独获取日期和时间,可以使用curdate()和curtime()函数
- select curtime();//当前时间,格式为 HH:MM:SS
- select curdate();//当前日期,格式为 YYYY-MM-DD
week()函数返回指定的日期是一年的第几个星期,而yearweek()函数返回指定的日期是哪一年的哪一个星期
- select week('2004-03-01');//结果为9
- select yearweek(20040301);//结果为200409
更多日期时间函数,请参考MySQL官方文档
加密函数
MySQL特意设计了一些函数对数据进行加密。
- AES_ENCRYPT(str,key);//返回使用密钥key对字符串str利用高级加密标准算法加密后的结果
- AES_DECRYPT(str,key); //返回使用密钥key对字符串str利用高级加密标准算法解密后的结果
- DECODE(str,key);//使用key作为密钥解密加密字符串str
- ENCRYPT(str,salt);//使用UNIX crypt()函数,用关键词salt加密字符串str
- ENCODE(str,key);//使用key作为密钥加密字符串str
- MD5();//计算字符串str的MD5校验和
- PASSWORD(str);//返回字符串str的加密版本
- SHA();//计算字符串str的安全散列算法(SHA)校验和
password()函数用来创建一个经过加密的密码字符串,它适合于插入到MySQL的安全系统。这个加密过程是不可以逆转的,和UNIX密码加密使用不同的算法
如果愿意的话,可以通过ENCRYPT()函数使用UNIX crypt()系统加密字符串,ENCRYPT()函数接收要加密的字符串和(可选的)用于加密过程的salt(一个可以唯一确定口令的字符串,就像钥匙一样)。
还可以使用ENCODE()函数和DECODE()函数来加密和解密字符串,ENCODE()有两个参数:被加密的字符串和作为加密基础的密钥:
- insert into users values('','john',ENCODE('asdfasdf','secret_key'));
- select * from users;
- select id,uname,DECODE(upass,'secret_key') from users;
控制流函数
MySQL提供了4个函数是用来进行条件操作的。这些函数实现了sql的条件逻辑,允许开发者将一些应用程序业务逻辑转换到数据库后台。
- case where[test1] then[result1] ... else[defalut] end;//如果testN为真,则返回resultN,否则返回default
- case[test] where[val1] then[result1]...else[default] end;//如果test和valN为真,则返回resultN,否则返回default
- if(test,t,f);//如果test为真,返回t,否则返回f
- ifnull(arg1,arg2);//如果arg1不是空,返回arg1,否则返回arg2
- nullif(arg1,arg2);//如果arg1=arg2返回null,否则返回arg1
这些函数的第一个是ifnull()函数,它有两个参数,并且对第一个参数进行判断。如果第二个参数不是null,函数就会向调用者返回第一个参数,如果是null,返回第二个参数。
- select ifnull(1,2),ifnull(null,10),ifnull(4*null,'false');//结果为1,10,false
nullif()函数将会检验提供的两个参数是否相等,如果相等,则返回null,不相等,返回第一个参数。
if()函数有三个参数,第一个是要被判断的表达式,如果表达式为真,if()函数会返回第二个参数,为假,返回第三个参数。if()函数在只有两种结果时才适合使用
格式化函数
MySQL还有一些函数是特意为格式化数据设计的
- date_format(date,fmt);//依照字符串fmt格式化日期date的值
- format(x,y);//把x格式化为以逗号隔开的数字序列,y是结果的小数位数
- inet_aton(ip);//返回ip地址的数字表示
- inet_ntoa(num);//返回数字所代表的ip地址
- time_format(time,fmt);//依照字符串fmt格式化时间time值
其中最简单的是format()函数,它可以把大的数值格式化为以逗号间隔的易读的序列。format()的第一个参数是被格式化的数据,第二个参数是结果的小数位数
- select format(999999999868595049,2),format(-4512,6);//结果为999,999,999,82;-4.512.000000
更多用法,请查阅相关文档
数据转换函数
为了进行数据类型转换,MySQL提供了cast()函数,它可以把一个值转化为指定的数据类型
通常情况下,当使用数值操作时,字符串会自动的转化为数字
- select 1+'99';//结果为100
- select 1+cast('99' as signed);//结果为100
我们可以强制许多日期和时间函数[包括now(),curtime()和curdate()函数],把它们返回的值作为一个数而不是字符串输出,只需要在数字的环境中使用这些函数或者把它们转化为数字
- select cast(now() as signed integer),curdate()+0;
MySQL4.1支持以下几种类型:binary,char,date,time,datetime,signed,unsigned
系统信息函数
MySQL还具有一些特殊的函数用来获得系统本身的信息
- database();//返回当前数据库名称
- benchmark(count,expr);//将表达式expr重复运行count次
- connection_id();//返回当前客户的连接id
- found_rows();//将最后一个select查询(没有以limit进行限制结果)返回的记录行数返回
- get_lock(str,dur);//获取一个由字符串str命名的并且有dur秒延时的锁定
- is_free_lock(str);//检查以str命名的锁定是否释放
- last_insert_id();//返回由该系统自动产生的最后一个auto increment id的值
- master_pos_wait(log,pos,dur);//锁定主服务器dur秒直到从服务器与主服务器的日志log指定的位置pos同步
- release_lock(str);//释放由字符串str命名的锁定
- user()/system_user();//返回当前登录用户名
- version();//返回MySQL服务器的版本
database(),user()和version()函数分别可以返回当前所选数据库,当前用户和MySQL版本的信息:
- select database(),version(),user();
交叉连接
连接的最简单类型就是交叉连接,它是对涉及到表相乘创建一个包含所有内容的产物。
- select * from color,attribute;//结果是两张表的结合体
两张表的所有列结合起来产生了一个包含所有可能组合的结果集。这种类型成为交叉连接,而且连接后的结果表的行数和用于连接的每个表的行数乘积相同。
上面那样的交叉连接会对数据库服务器的性能产生很大的影响,所以在连接中使用where子句过滤掉一些记录是不错的选择。
内连接/外连接
内连接是最普通的连接类型,而且是最均匀的,因为它要求构成连接的每一部分的每个表的匹配,不匹配的行将会被排除在最后的结果集之外
内连接最常见的的例子是相等连接,也就是连接后的表中的某个字段与每个表中的都相同。这种情况,最后的结果集只包含参加连接的表中与指定字段相符的行。
外连接是不对称的,连接的一方的所有行都包含在最后的记录中,不管它们是否与连接的另外一方的行匹配
根据连接的哪一方被保留,sql定义了左外连接和右外连接。在左外连接中,与where子句相匹配的连接左部的表的所有记录都将出现在最后结果集中。在右外连接中,与where子句相匹配的连接的右部的表的所有记录都将出现在最后结果集中。
左外连接:解释为“从连接的左部选择所有的行,对于选中的每一行,或者从右部显示相匹配的值,或者显示为null的一行”。这种类型的连接称为左连接,或者称为左外连接。右连接或者右外连接刚好与次相反。
自连接与联合
除了交叉连接,内连接和外连接,MySQL还支持第四种类型的连接,也就是自连接。这种类型的连接把一个表与它自身进行连接,它通常用来取出表中彼此包含内连接的记录。
除了连接,MySQL4.0以及更高的版本还支持union运算符,它用来把多个select查询的输出连接成一个单独的结果集。大多数情况下,这个运算符用来把查询产生的结果集添加到不同的表中,同时创建包括所有结果的一个单独表。
使用union运算符组合尽可能多的select查询,但是必须具备两个基本条件。首先,每个select查询返回的字段的个数必须相同。第二,每个select查询的字段的数据类型必须互相符合。
union运算符将会自动从组合结果集中消除重复的行
where/having查询
MySQL可以在where子句或者having子句中包含子查询。包含在圆括号内的子查询,优先级高于比较和逻辑操作符、in操作符或者exists操作符。
也可以在一个having子句中的比较运算符前使用子查询,从而用它对父查询创建的组进行过滤。
in/exists/from查询
只有子查询返回的结果列包含一个值时,比较运算符才适用。加入一个子查询返回的结果集是值的列表,这时比较运算符就必须用in运算符代替。
in运算符可以检测结果集中是否存在某个特定的值,如果检测成功就执行外部的查询。
exists运算符可以用来查询一个子查询是否产生了结果,这使得可以只在exists检测返回真时才执行外部的查询
还可以在一个select语句的from子句中把子查询产生的结果作为一个表。
因而,内查询产生的结果表用在外查询的from子句中。这样的表在sql中成为到导出表。
请注意,当以这种方式使用子查询的结果时,内查询产生的结果表必须首先另取一个表名,否则MySQL不知道如何参照其中的列。
什么是事务
在MySQL环境中,一个事务由作为一个单独单元的一个或者多个sql语句组成。这个单元中的每个sql语句是互相依赖的,而且单元作为一个整体是不可分割的。如果单元中的一个语句不能成功完成,整个单元都会回滚,所有影响到的数据将返回到事务开始之前的状态。因而,只有事务中的所有语句都被成功的执行才能说这个事务被成功执行。
事务的四个特性:
原子性,每个事务都必须被认为是一个不可分割的单元。
一致性,不管事务是完全成功还是中途失败,当事务使系统处于一致的状态时存在一致性。
孤立性,每个事务在它自己的空间发生,和其他发生在系统中的事务隔离,而且事务的结果只有在它完全被执行时才能看到。
持久性,即使系统崩溃,一个提交的事务扔在坚持。
生命周期
为了初始化一个事务,并告诉MySQL所有随后的sql语句需要被认为是一个单元,MySQL提供了start transaction命令来标记一个事务的开始。也可以使用begin或者begin work命令来初始化一个事务。通常情况下,start transction命令后跟随的是组成事务的sql语句。
一旦sql语句被执行,就可使用commit命令来把整个事务保存在磁盘上,或者使用rollback命令来撤销所有的变化。如果事务包括事务表和非事务表的变化,非事务表的事务处理部分是不能使用rollback命令撤销的。在这种情况下,MySQL将会返回一个错误,通知出现一个不完全撤销。
commit命令标记了事务块的结束。
控制事务行为
MySQL提供了两个变量来控制事务行为:autocommit变量和transaction isolation level变量。
自动提交,默认情况下,MySQL的sql查询一旦被执行,就会自动向数据库提交结果。这种默认的行为可以通过特定的autocommit变量来进行修改。设置set autocommit=0,随后表的更新将不会被保存,直到明确发出一个commit命令。
事务孤立级,MySQL默认为repeatable read孤立级,可以使用set来修改。
事务和性能
因为支持事务的数据库在保持不同用户彼此孤立方面要比非事务数据库难,所以自然的反应了系统的性能。
我们需要做一些事情来保证事务不会向系统添加不适当的负担。
使用小事务,两个普遍的策略
1:保证所有要求的用户输入在发出start transaction命令之前都是可行的
2:尝试把大的事务分成小的事务然后分别执行。
选择合适的孤立级,孤立级越高,性能越低,所以选择合适的孤立级,有助于性能优化
避免死锁,在一个事务环境中,当两个或者多个处于不同序列的客户同时想要更新相同的数据时,就会发生死锁,我们应该避免发生死锁。
索引
索引指向数据库中具体数据所在的一个位置,同时在列上创建一个索引可以排列该列上的信息。当服务器需要访问该信息进行查询时,就会知晓在什么地方进行查询,因为索引指向有关位置。
如果一个列涉及查询,分组,排序,索引将可以达到提高性能的效果。
带很多重复值的索引不会产生很好的结果。
可以使用表来联合多个非唯一的索引,以便改善性能。
索引越多,性能不一定越好。添加一个索引,并不一定能改善性能。
查询高速缓存
在运行select查询时,MySQL4.x会记录下查询和返回结果。这是通过select每次进行查询时,在一个特殊的高速缓存中保存结果集实现的。然后,当再次请求服务器做相同的查询时,MySQL将会从高速缓存中检索结果,而不是再次运行该查询。默认情况下是启动这个性能。
注意,一旦表有变化,使用这个表的告诉缓存查询就变成无效,并且将从告诉缓存中删除。这样防止查询从旧表上返回不准确的数据。经常有变化的表,将不会从高速缓存中得到利益。这种情况,可以考虑不使用告诉缓存,可以添加一个选项sql_no_cache来实现。
查询分析
在select查询开始处加上一个explain关键字,将告诉MySQL返回一个图表,说明这个查询如果进行处理,在这个图表里涉及了查询将访问哪个表的信息以及查询希望返回的行数的信息。这个信息可以用来查看哪些表可以添加索引,以便加快执行速度,分析瓶颈的位置。
通过查询的显示结果,可以什么位置可以添加索引,进行迅速的改正。
优化多表查询
子查询是一个嵌套在另一个select语句中的select语句。子查询经常用来把一个复杂的查询拆分为一些列的逻辑步骤,或者使用其他查询结果回答一个查询。其结果是不需要执行两个或者更多的单独查询,就可以执行一项包含一项或者多项子查询的简单查询。
MySQL可以比子查询更好的优化连接,所以如果发现在自己的MySQL服务器上的负载平均值达到了无法接受的高水平,就应该检验应用程序代码,并试着重写作为连接和连接序列的子查询。
可以通过有效的使用MySQL的集合性能和修改程序来把低效的子查询转变为更为有效的连接。
如果希望避免中间使用嵌套查询,还可以使用基于会话的服务器变量。
使用临时表
MySQL还允许使用create temporary table命令创建临时表。这种表之所以这么称呼,是因为它只针对单一的MySQL会话过程而存在的,当使用这些表的客户机关闭了与MySQL服务器的连接时,它将自动删除。
因为临时表保存在内存中,所以要比基于磁盘的表明显的快。结果可以有效的作为中间存储区域,以便提高查询实施的速度,帮助把复杂的的拆分为更简单的部件,或者作为子查询和连接支持的代替。
优化表设计
为了使查询能够更加精炼,需要考虑表设计方面的一些因素。首先,如果经常查询的表会发生很多变化,改进性能的方式就是使用定长字段,不适用变长字段。虽然使用定长字段将浪费更多的磁盘空间,但是从查询角度看,MySQL处理定长字段比变长字段更快。
改善性能的另一项技术是使用optimize table命令处理经常需要修改的表。经常修改表会导致磁盘碎片,以致花费额外的时间去读取没有用的空间块,以便得到希望的数据。
在考虑改善性能时,还要检查是否需要针对已经建立的所有表。额外的表意味着性能降低。没有必要合并的表,则应试着匹配连接的列。
调整服务器设置
如果希望服务器更加有效的运行,最佳解决方案是加大内存空间和使用更大更快的磁盘。但是更多时候,条件是不允许是的。此时,我们需要一些改进服务器的常规技术。
调整服务器变量,key_buffer_size变量控制MySQL索引缓冲可以使用内存的数量。值越高,索引可以使用的内存越多,性能越好。一般情况,这个值保持在可使用内存总量的25%到30%。table_cache变量控制表高速缓存可以使用内存的数量,以及在同一时间内MySQL可以处理表的打开总量。对于有很多数据库和表的非常忙的服务器来说,应该增加这个值,使用set修改。
一旦修改了一个全局服务器变量,关闭服务器之前,这些变量一直存在,但是重启服务器之后,变量恢复默认状态。所以最好是进行永久性修改。