22
MySQL开发规范与实用技术交流 姓名:金官丁 旺旺:Eugene198312

MySQL Base Skill

Embed Size (px)

DESCRIPTION

MySQL,BaseSkill,InnoDB,utf8,培训,规范,流程

Citation preview

Page 1: MySQL Base Skill

MySQL开发规范与实用技术交流

姓名:金官丁

旺旺:Eugene198312

Page 2: MySQL Base Skill

内 容

1.开发实用技术

2.MySQL开发规范

3.项目支持

4.变更管理

5.SQL REVIEW

6.开发测试服务器说明

7.MySQL相关项目建议

8.简述InnoDB引擎锁与索引

Page 3: MySQL Base Skill

1.开发实用技术1.1 自增字段定义

1.2 CHAR(N)或VARCHAR(N)中的N解释

1.3 字符串函数

1.4 日期操作函数

1.5 类型转换函数

Page 4: MySQL Base Skill

1.1 自增字段定义

自增字段类型必须是整型,推荐类型为INT或者BIGINT类型。并且

自增字段必须是主键或主键的一部分。

1.2 CHAR(N)或VARCHAR(N)中的N解释

MySQL中此两类字符串定义时候填写的长度N,不是字节数的意思 ,

而是字符数的意思。

我们MySQL所有数据库的字符集都为UTF8,字符集校对规则为UTF8_general_ci。对于中文汉字,实际存储的时候占三个字节,而数据或字母,则只占一个字节。例如:

CREATE TABEL gl_user(username VARCHAR(40));

则username最多能存储40个字符 。

Page 5: MySQL Base Skill

1.3 字符串函数

MySQL中字符串连接方法,使用CONCAT() 或CONCAT_ WS()函数,语法如下:

CONCAT(string1,string2,...)

CONCAT_ WS(separator,string1,string2,..)

字符串长度统计:

LENGTH(string) #返回string所占的字节数

CHAR_LENGTH(string) #返回string中的字符个数

统计字符个数,就不区分是汉字还是字母或数字,也跟字符集没有关系,

若统计的是字节数,则由字符是汉字、字母或数字类型,以及字符集共同决定。

请各位牢记:我们所有的MySQL数据库都将会采用UTF8编码,所以一个汉字占3个字节,一个字母或数字占一个字节。

Page 6: MySQL Base Skill

1.4 日期操作函数

获取当前时间:NOW(),CURDATE()、CURTIME()

其中,NOW()函数精确到秒,格式:YYYY-MM-DD HH:MM:SS

CURDATE函数精确到天,格式:YYYY-MM-DD

CURTIME函数精确到秒,格式:HH:MM:SS

日期数值的加减函数:

DATE_ADD(date,INTERVAL expr type)

DATE_ SUB(date,INTERVAL expr type)

常用的几种type类型:YEAR、MONTH、DAY、HOUR、MINUTE,其中expr可以为正数或负数,我们在开过程中,一般使用DATE_ADD()

函数,若要作日期减去一个数字的方式,就使用负数。

DATEDIFF(expr1,expr2),是返回 开始日期expr1与 结束日期expr2

之间,相差的天数 ,返回值为正数或负数。

返回日期某部分信息的函数:

YEAR(expr1) 返回日期expr1部分的年份; MONTH(expr1) 返回日期expr1部分的月份;DAY(expr1)返回expr1部分的天数;

WEEKDAY(expr1)返回expr1对应的星期数字

Page 7: MySQL Base Skill

1.5 类型转换函数

字符串转换成日期方式,DATE_FORMAT()或STR_TO_DATE(),

两个函数的格式如下:

DATE_FORMAT(expr1,format)

STR_TO_DATE(expr1, format)

常用的日期格式YYYY-MM-DD HH:MM:SS 对应的format为

%Y-%m-%d %H:%i:%S

通用的类型转换函数:

CAST(expr AS type)

CONVERT(expr,type)

CONVERT(expr USING transcoding_name)

Page 8: MySQL Base Skill

2.MySQL开发规范

2.1 字段定义规范

2.2 绑定变量和替代变量使用规范

2.3 数据类型转换规范

2.4 SELECT * 的使用规范

2.5 字段上添加函数使用规范

2.6 表连接规范

2.7 分页查询规范

2.8 特殊操作符使用规范

2.9 特殊函数使用规范

Page 9: MySQL Base Skill

2.1 字段定义规范

MySQL中用到的相关列数据类型存储需求与范围描述信息如下表:

列类型 表达的范围 存储需求

TINYINT[(M)] [UNSIGNED] [ZEROFILL]

-128到127 或 0到255 1个字节

SMALLINT[(M)] [UNSIGNED] [ZEROFILL]

-32768到32767 或 0到65535 2个字节

INT[(M)] [UNSIGNED] [ZEROFILL]

-2147483648到2147483647 或 0到4294967295

4个字节

BIGINT[(M)] [UNSIGNED] [ZEROFILL]

-9223372036854775808到9223372036854775807 或 0到18446744073709551615

8个字节

DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]

整数最大位数(M)为65,小数位数最大(D)为30

变长

DATE YYYY-MM-DD 3个字节

DATETIMEYYYY-MM-DD HH:MM:SS(1001年到9999年的范围)

8个字节

TIMESTAMPYYYY-MM-DD HH:MM:SS(1970年到2037年的范围)

4个字节

CHAR(M)0<M<=255(建议CHAR(1)外,超过此长度的用VARCHAR)

M个字符(所占空间跟字符集等有关系)

VARCHAR(M) 0<M<65532/NM个字符(N大小由字符集,以及是否为中文还是字母数字等有关系)

TEXT 64K个字符所占空间跟字符集等有关系

Page 10: MySQL Base Skill

详细说明:

1. 所有动态长度字符串全部使用 VARCHAR 类型,类似于状态,有限类别的字

段, 也使用可以比较明显表示出实际意义的字符串,而不应该使用INT之类

的数字来代替;

2. 固定长度的字符串使用 CHAR 类型,所有单个字符的全部使用 CHAR 类型,

而不应该使用VARCHAR 类型;

3. 仅仅当字符数量可能超过 20000 个的时候,可以使用 TEXT 类型来存放字符

类数据。所有使用 TEXT 类型的字段必须和原表迚行分拆,与原表主键单独组

成另外一个表迚行存放;

4. 需要精确到时间(年月日时分秒)的字段可以使用DATETIME 或TIMESTAMP,

但请注意各自能表达的范围,以及是否需要用到TIMESTAMP的特性;

5. 所有只需要精确到天的字段全部使用 DATE 类型,而不应该使用 TIMESTAMP

或者DATETIME 类型;

6. 自增序列类型的字段只能使用 INT 或者 BIGINT,且明确标识出为无符号型

(UNSIGNED),除非确实会出现负数,仅当该字段数字取值会超过42亿,才使

用 BIGINT 类型;

Page 11: MySQL Base Skill

2.2 绑定变量和替代变量使用规范基本原则:

所有 Query 的 Where 条件中的变量,都需要使用绑定变量来实现,此要求并

不完全是基于性能的考虑,更多是基于安全方面的考虑,如若有任何不使用绑定变

量的需求,都必须通过安全部门的审核并征得同意。详细说明:

. 在 iBatis 的 SqlMap 文件中绑定变量使用 “#var_name#”表示,替代变量使用

$var_name$”;所有需要动态 Order By 条件的 Query,在使用替代变量过程中,

需要将可能传入的内容以枚举类写死在代码中,禁止接受任何外部传入内容;

. 对于不变的常量条件,请使用常量而不是变量;

. IN子句,使用"Iterate + 数组类型变量"的方式实现绑定变量而不是通过代码拼接

Query 语句,例如:

<isNotEmpty prepend="and" property="userIds">

<iterate property="userIds" open="t.user_id in (" close=")" conjunction=",">

#userIds[]#

</iterate>

</isNotEmpty>

iBatis会生成t.user_id in (1,2,3,4,5 ...)的语句

Page 12: MySQL Base Skill

2.3 数据类型转换规范

基本原则:

在所有 Query 的 Where 条件中必须使用和过滤字段完全一致的数据类型,杜绝

任何隐式类型转换,避免造成因为数据类型不匹配而导致 Query 执行计划的出错,

造成性能问题.

详细说明:

1> 所有 Where 条件的字段上不允许使用函数做类型转换,如有需要转换类型,只

能转换过滤值,而不是转换字段.

2> 最为常见的隐式类型转换常见于时间类型与字符串类型之间,建议所有时间类型

字段在iBatis中均以时间类型传入,或者以字符串传入然后通过时间函数转换字符串

为合法的时间格式 ,如下:

SELECT * FROM member WHERE

gmt_create=DATE_FORMATE('2009010101:02:03','%Y-%m-%d %H:%i:%s');

3> 在表连接 Query 中,如果连接条件两端的数据类型不一致,必须保证将驱动表的

连接条件数据类型转换为与被驱动表一致的数据类型.

Page 13: MySQL Base Skill

2.4 SELECT * 的使用规范

基本原则:

在不必要查询中使用“*”列出所有字段,且需存在GROUP BY或ORDER BY的

时候,禁止使用SELECT * 一次取出所有的字段。对于表连接的 JOIN 语句,禁止使

用 SELECT * 来迚行查询,除非明确获得 DBA 允许。含有 text 字段的表,当不需

要取出 TEXT 字段的时候,也禁止使用SELECT * 迚行查询.

详细说明:

1> 迚行GROUP BY或ORDER BY的时候不允许使用 SELECT * 是为了确保 MySQL

能够使用最新的优化排序算法.

2> JOIN 语句不允许使用 SELECT * 是为了防止仅仅只需要索引即可完成的查询需

要回表取数.

3> 存有 TEXT 字段表,在不需要取出TEXT字段的时候,不允许使用 SELECT * ,因为

TEXT 字段是存放在和普通记录不一样的物理位置,会造成大量的io操作.

4> 避免因增删字段而没有修改相关SQL及相关程序代码导致程序BUG,而禁用

SELECT *.

Page 14: MySQL Base Skill

2.5 字段上添加函数使用规范

基本原则:

禁止在 WHERE 条件中出现的过滤字段上,使用任何函数迚行类型或格式的

转换;正确的做法是把传入比较的值转换为列类型所需要的。

错误的写法:

SELECT username FROM gl_user WHERE DATE_FORMAT(gmt_create,

'%Y%m%d%H%i%s')='20090501022300‘;

正确的写法:

SELECT username FROM gl_user WHERE

gmt_create=DATE_FORMAT('20090501022300', '%Y-%m-%d %H:%i:s');

Page 15: MySQL Base Skill

2.6 表连接规范

基本原则:

所有非外连接SQL(即INNER JOIN),请把关联表统一写到 FROM字句中,

关联条件与过滤条件统一写到WHERE字句中.

出于代码的可读性原因,所有外连接SQL语句中,请一律使用LEFT JOIN,禁

用RIGHT JOIN。

另外,请注意LEFT JOIN字句中,右边位置表的条件书写位置不同的影响:

SELECT A.rolename,A.gmt_create,B.nickname FROM gl_role A LEFT JOIN gl_roledetail B ON A.ID=B.roleid AND

B.roleID=2;

+-------------+---------------------+----------+

| rolename | gmt_create | nickname |

+-------------+---------------------+----------+

| 163.com | 0000-00-00 00:00:00 | test2 |

| sina.com | 0000-00-00 00:00:00 | NULL |

| hotmail.com | 0000-00-00 00:00:00 | NULL |

| 126.com | 2009-08-20 18:20:18 | NULL |

+-------------+---------------------+----------+

SELECT A.rolename,A.gmt_create,B.nickname FROM gl_role A LEFT JOIN gl_roledetail B ON A.ID=B.roleid WHERE

B.roleID=2;

+----------+---------------------+----------+

| rolename | gmt_create | nickname |

+----------+---------------------+----------+

| 163.com | 0000-00-00 00:00:00 | test2 |

+----------+---------------------+----------+

Page 16: MySQL Base Skill

2.7 分页查询规范

基本原则:

分页查询语句全部都需要带有排序条件,除非商业方明确要求不要使用任何排

序来随机展示数据。详细说明:

1> 常规分页语句写法(start:起始记录数,page_offset:每页记录数):

SELECT ID,username FROM gl_user WHERE username like '%@163.com'

ORDER BY M.gmt_create LIMIT start, page_offset;

2> 多表 Join 的分页语句,如果过滤条件在单个表上,需要先分页,再 Join:

低性能写法:

SELECT M.username,P.rolename FROM gl_user M INNER JOIN gl_role P ON

M.ID=P.userid WHERE username like '%@163.com' ORDER BY M.gmt_create

LIMIT start, page_offset;

高性能写法:

SELECT M.username,P.rolename

FROM (SELECT ID,username FROM gl_user WHERE username like

'%@163.com' ORDER BY M.gmt_create LIMIT start, page_offset)M,gl_role P

WHERE M.ID=P.userid;

这样写的前提是关联的表之间记录一一对应,否则可能会返回的记录数目少于或多

于page_offset的值。

Page 17: MySQL Base Skill

3.项目支持

3.1 重设计,轻需求:从设计阶段开始参与,不会过

多干涉需求

3.2 针对重点部分详细 Review,非重点部分仅针对性

检查是否符合规范

3.3 线上的MySQL产品库依然由MySQL团队的DBA负责实施与

维护。各个站点的MySQL 项目,在开发测试阶段,以各个

站点的DBA Team接口人为主要负责人:

国际站DBA Team方接口人:

中文站DBA Team方接口人:

CRM DBA Team方接口人:

Page 18: MySQL Base Skill

4.变更管理

4.1 结构变更先迚入数据库变更系统记,访问地址:

http://dba.hz.alibaba-inc.com:8080/dbadmin/default.jsp

4.2 有非核心小表(不超过10W条记录)结构变更的发

布至少提前1星期通知发布具体时间,超过10w条

记录的结构变更必须提前2星期通知发布时间

4.3 每天的09:00 – 12:00 与 14:00 – 16:00

之间一般不对产品数据库做任何变更(备注:数据库结

构变更)操作

Page 19: MySQL Base Skill

5.SQL REVIEW

每个项目都会在Confluence上创建相关页面,用于提交与审核SQL。

编号

变化Sql语句

变化类型 开发

功能描述

执行频率 前台

是否cache

审核

审核

修改意见 是否修改完成

(新增/修改)负责人

(数量级/天)/后台

人员

结果

1 SELECT relation_type FROM brmms_contact

新增090510 张三 通过

memberId,friend_id查询两者关系类型

100万/天 后台 否

WHERE member_id= #memberId# AND friend_id = #friendId#

Page 20: MySQL Base Skill

6.开发测试服务器说明1> 开发测试服务器,不保证其能做性能测试,而是大家公用.

2> 开发测试各有一套数据库,开发人员库名称一般为项目名称,测试人员的库:开发库_test

3> 项目开发人员帐号密码规则:库名称或项目名称或即为帐号密码.

4> 测试人员帐号密码规则:库名称或项目名称或即为帐号,密码单独发给各个站点的接口人.

5> 开发测试人员的权限一般为仅有四种权限:SELECT,INSERT,UPDATE,DELETE.

6> 开发库的结构变更必须先提交到变更系统,然后通知下DBA(目前还不能自动提醒我们)

7> 开发库结构发生变更,是否一起变更测试数据库,需要项目中约定,目前主要采用两种方

式:

第一种,约定测试库等待测试人员发送变更信息(邮件,旺旺为主);

第二种,约定开发人员变动数据库结构,同时修改测试库;

8> 关于数据库性能测试,DBA,开发人员,测试人员三方共同协调与借调短期内专用且配置

相当的性能测试数据库服务器,DBA负责搭建.

Page 21: MySQL Base Skill

7.MySQL使用建议1>. 迚行数据库结构设计的时候,考虑适当的冗余,尽量确保应用读写数据的SQL简洁.

2>. 所有字符集为utf8,校对规则为utf8_general_ci ,默认是不区分英文字母大小写,若有需求

区分大小写,请跟DBA特别声明,或者表定义语句指定 COLLATE ‘utf8_bin’.

3>.尽量不需要使用子查询,特别是IN的方式,可考虑转化为EXISTS.

SELECT * FROM A WHRE A.ColName1 IN (SELECT DISTINCT ID FROM B WHERE ..);

建议改写为:

SELECT * FROM A WHRE EXISTS (SELECT 1 FROM B WHERE B.ID= A.ColName1...);

4> 要返回MySQL自增序列的ID值,可以考虑使用函数LAST_INSERT_ID(),此函数只能返回同

一个SESSION最近一次对有AUTO_INCREMENT属性表INSERT的ID值.

5> 所有的时间字段值,请以MySQL数据库的时钟为准,除用户输入的时间值外.

6> 对于项目的数据量、PV等合理评估,我们DBA TEAM相关人员,会给大家推荐合理成熟的数

据存取架构,增强系统的扩展性与用户体验,以及高可用性等.

Page 22: MySQL Base Skill

您们的满意也是我们的满意;

您们的成功也是我们的成功;

让我们大家携手共创美好未来.

谢谢各位的聆听!