深入浅出My sql数据库开发、优化与管理维护

2,068 views

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,068
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
68
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

深入浅出My sql数据库开发、优化与管理维护

  1. 1. www.163.com第一篇 开发篇............................................................................................................................. 8第 1 章 帮助的使用........................................................................................................................... 8 1.1 按照层次看帮助.................................................................................................................. 8 1.2 快速查阅帮助.................................................................................................................... 10第 2 章 表类型(存储引擎)的选择............................................................................................. 11 2.1 Mysql 存储引擎概述.......................................................................................................... 11 2.2 各种存储引擎的特性........................................................................................................ 11 2.3 如何选择合适的存储引擎................................................................................................12第 3 章 选择合适的数据类型.........................................................................................................13 3.1 选择数据类型的基本原则................................................................................................13 3.2 固定长度数据列与可变长度的数据列........................................................................... 13 3.2.1 char 与 varchar......................................................................................................... 13 3.2.2 text 和 blob............................................................................................................... 15 3.3 浮点数与定点数................................................................................................................ 15第 4 章 字符集................................................................................................................................. 16 4.1 字符集概述........................................................................................................................ 16 4.2 Mysql 支持的字符集简介................................................................................................. 17 4.3 Unicode 简述...................................................................................................................... 17 4.4 怎样选择合适的字符集....................................................................................................17 4.5 Mysql 字符集的设置......................................................................................................... 18第 5 章 索引的设计和使用............................................................................................................. 18 5.1 Mysql 索引概述..................................................................................................................18 5.2 设计索引的原则................................................................................................................ 19 5.3 btree 索引与 hash 索引...................................................................................................... 20 5.4 Mysql 如何使用索引......................................................................................................... 21第 6 章 锁机制和事务控制............................................................................................................. 21 6.1 如何加锁............................................................................................................................ 21 6.2 死锁.................................................................................................................................... 22 6.3 事务控制............................................................................................................................ 22第 7 章 SQL 中的安全问题............................................................................................................ 29 网易技术部 1
  2. 2. www.163.com 7.1 SQL 注入简述.................................................................................................................... 29 7.2 开发中可以采取的措施....................................................................................................30 7.2.1 prepareStatement + Bind-variable ........................................................................... 30 7.2.2 使用应用程序提供的转换函数:........................................................................ 31 7.2.3 自己定义函数进行校验........................................................................................ 31第 8 章 SQL Mode 及相关问题...................................................................................................... 31 8.1 Mysql SQL Mode 简介.......................................................................................................31 8.2 SQL Mode 与可移植性...................................................................................................... 33 8.3 SQL Mode 与数据效验...................................................................................................... 34第 9 章 常用 SQL 技巧................................................................................................................... 34 9.1 检索包含最大/最小值的行.............................................................................................. 34 9.2 巧用 rand()/rand(n)提取随机行........................................................................................ 34 9.3 利用 group by 的 with rollup 子句做统计...................................................................... 35 9.4 用 bit group functions 做统计........................................................................................... 36第 10 章 其他需注意的问题...........................................................................................................39 10.1 数据库名、表名大小写问题..........................................................................................39 10.2 使用外键需注意的地方..................................................................................................41第二篇 优化篇................................................................................................................................. 45第 11 章 SQL 优化.......................................................................................................................... 45 11.1 优化 SQL 的一般步骤.................................................................................................... 45 11.1.1 通过 show status 和应用特点了解各种 SQL 的执行频率................................ 45 11.1.2 定位执行效率较低的 SQL 语句:..................................................................... 46 11.1.3 通过 EXPLAIN 分析低效 SQL 的执行计划:..................................................46 11.1.4 确定问题,并采取相应的优化措施:.............................................................. 47 11.2 索引问题.......................................................................................................................... 48 11.2.1 索引的存储分类................................................................................................... 48 10.2.2 MySQL 如何使用索引....................................................................................... 49 10.2.3 查看索引使用情况......................................................................................... 49 11.3 两个简单实用的优化方法.............................................................................................. 50 11.3.1 定期分析表:....................................................................................................... 50 网易技术部 2
  3. 3. www.163.com 11.3.2 使用 optimize table :........................................................................................... 50 11.4 常用 SQL 的优化............................................................................................................ 51 11.4.1 大批量插入数据:............................................................................................... 51 11.4.2 优化 insert 语句:................................................................................................ 52 11.4.3 优化 group by 语句:.......................................................................................... 52 11.4.4 优化 order by 语句:........................................................................................... 52 11.4.5 优化 join 语句:...................................................................................................53 11.4.6 mysql 如何优化 or 条件:................................................................................... 54 11.4.7 查询优先还是更新(insert、update、delete)优先:..................................... 54 11.4.8 使用 SQL 提示:................................................................................................. 55 11.5 其他优化措施.................................................................................................................. 56第 12 章 优化数据库对象............................................................................................................... 56 12.1 优化表的数据类型.......................................................................................................... 56 12.2 通过拆分,提高表的访问效率..................................................................................... 57 12.3 逆规范化.......................................................................................................................... 57 12.4 使用冗余统计表.............................................................................................................. 57 12.5 选择更合适的表类型......................................................................................................58第 13 章 锁问题............................................................................................................................... 58 13.1 获取锁等待情况.............................................................................................................. 58 13.2 什么情况下使用表锁......................................................................................................59 13.3 什么情况下使用行锁......................................................................................................59 13.4 insert …select …带来的问题..........................................................................................60 13.5 next-key 锁对并发插入的影响....................................................................................... 61 13.6 隔离级别对并发插入的影响..........................................................................................61 13.7 如何减少锁冲突.............................................................................................................. 62第 14 章 优化 Mysql Server............................................................................................................ 63 14.1 查看 Mysql server 当前参数...........................................................................................63 14.2 影响 Mysql 性能的重要参数......................................................................................... 63 14.2.1 key_buffer_size 的设置......................................................................................... 63 14.2.2 table_cache 的设置................................................................................................ 65 网易技术部 3
  4. 4. www.163.com 14.2.3 innodb_buffer_pool_size 的设置:...................................................................... 65 14.2.4 innodb_flush_log_at_trx_commit 的设置:........................................................ 65 14.2.5 innodb_additional_mem_pool_size :................................................................... 66 14.2.6 innodb_table_locks:............................................................................................ 66 14.2.7 innodb_lock_wait_timeout:................................................................................ 66 14.2.8 innodb_support_xa:............................................................................................. 67 14.2.9 innodb_doublewrite:........................................................................................... 67 14.2.10 innodb_log_buffer_size: ...................................................................................... 67 14.2.11 innodb_log_file_size :........................................................................................ 67第 15 章 I/O 问题.............................................................................................................................67 15.1 使用磁盘阵列或虚拟文件卷分布 I/O........................................................................... 68 15.2 使用 Symbolic Links 分布 I/O........................................................................................ 68第 16 章 应用优化........................................................................................................................... 69 16.1 使用连接池...................................................................................................................... 69 16.2 减少对 Mysql 的访问..................................................................................................... 70 16.2.1 避免对同一数据做重复检索:.......................................................................... 70 16.2.2 使用 mysql query cache:................................................................................... 70 16.2.3 加 cache 层:........................................................................................................71 16.3 负载均衡.......................................................................................................................... 71 16.3.1 利用 mysql 复制分流查询操作:......................................................................71 16.3.2 采用分布式数据库架构:.................................................................................. 71第三篇 管理维护篇......................................................................................................................... 73第 17 章 mysql 安装升级................................................................................................................ 73 17.1 安装.................................................................................................................................. 73 17.1.1 安装方法比较.....................................................................................................73 17.1.2 rpm 安装步骤......................................................................................................74 17.1.3 二进制安装步骤.................................................................................................74 17.2 源码安装步骤.................................................................................................................. 75 17.3 源码安装的性能考虑:..................................................................................................75 17.3.1 去掉不需要的模块:.........................................................................................75 网易技术部 4
  5. 5. www.163.com 17.3.2 只选择要使用的字符集:................................................................................ 76 17.3.3 使用 pgcc 编译:...............................................................................................76 17.3.4 使用静态编译以提高性能:............................................................................ 77 17.4 mysql 升级........................................................................................................................ 77 17.5 mysql 降级........................................................................................................................ 78第 18 章 Mysql 日志管理................................................................................................................ 78 18.1 错误日志:...................................................................................................................... 78 18.2 BINLOG:........................................................................................................................ 79 18.3 查询日志.......................................................................................................................... 80 18.4 慢查询日志:.................................................................................................................. 80第 19 章 数据备份与恢复:...........................................................................................................81 19.1 备份/恢复策略:.............................................................................................................81 19.2 冷备份:.......................................................................................................................... 81 19.3 逻辑备份:...................................................................................................................... 81 19.4 单个表的备份:.............................................................................................................. 82 19.5 使用备份工具 ibbackup:.............................................................................................. 82 19.6 时间点恢复:.................................................................................................................. 83 19.7 位置恢复:...................................................................................................................... 84 19.8 MyISAM 表修复:.......................................................................................................... 84第 20 章 Mysql 安全:.................................................................................................................... 85 20.1 正确设置目录权限:......................................................................................................85 20.2 尽量避免以 root 权限运行 mysql:.............................................................................. 85 20.3 删除匿名帐号:.............................................................................................................. 85 20.4 给 mysql root 帐号设置口令:...................................................................................... 86 20.5 设置安全密码并定期修改:..........................................................................................86 20.6 只授予帐号必须的权限:..............................................................................................86 20.7 除 root 外,任何用户不应有 mysql 库 user 表的存取权限:.................................... 86 20.8 不要把 FILE、PROCESS 或 SUPER 权限授予管理员以外的帐号:..................... 86 20.9 load data local 带来的安全问题:.................................................................................. 87 20.10 尽量避免通过 symlinks 访问表:............................................................................... 88 网易技术部 5
  6. 6. www.163.com 20.11 使用 merge 存储引擎潜藏的安全漏洞:....................................................................88 20.12 防止 DNS 欺骗:.......................................................................................................... 88 20.13 drop table 命令并不收回以前的相关访问授权:....................................................... 88 20.14 使用 SSL:.................................................................................................................... 88 20.15 如果可能,给所有用户加上访问 IP 限制:.............................................................. 90 20.16 严格控制操作系统帐号和权限:............................................................................... 90 20.17 增加防火墙:................................................................................................................ 90 20.18 其他安全设置选项:....................................................................................................90 20.18.1 allow-suspicious-udfs:............................................................................ 90 20.18.2 old-passwords:.............................................................................................90 20.18.3 safe-user-create:...................................................................................... 91 20.18.4 secure-auth:.................................................................................................91 20.18.5 skip-grant-tables:.................................................................................... 91 20.18.6 skip-networking:.........................................................................................91 20.18.7 skip-show-database:.................................................................................. 91第 21 章 Mysql 复制:.................................................................................................................... 92 21.1 Mysql 复制概述:........................................................................................................... 92 21.2 安装配置:...................................................................................................................... 92 21.3 日常管理维护:.............................................................................................................. 93 21.3.1 经常查看 slave 状态........................................................................................ 93 21.3.2 怎样强制主服务器阻塞更新直到从服务器同步?........................................ 94 21.3.3 master 执行的语句在 slave 上执行失败怎么办?....................................... 94 21.3.4 Slave 上出现 log event entry exceeded max_allowed_packet 错误怎么 办?................................................................................................................................... 94 21.3.5 多主复制时,自动增长变量的冲突问题........................................................ 95 21.3.6 怎么样知道 slave 上现在复制到什么地方了................................................ 95 21.4 需要注意的问题:.......................................................................................................... 95第 22 章 Mysql Cluster:............................................................................................................. 95 22.1 Mysql Cluster 概述:....................................................................................................... 95 22.2 Mysql Cluster 架构:....................................................................................................... 96 网易技术部 6
  7. 7. www.163.com 22.3 安装配置:...................................................................................................................... 96 22.3.1 管理节点配置步骤:.........................................................................................96 22.3.2 sql 节点和数据节点的配置:......................................................................... 98 22.4 管理维护:...................................................................................................................... 98 22.4.1 Cluster 的启动..................................................................................................98 22.4.2 Cluster 的关闭..................................................................................................99 22.5 数据备份和恢复:.......................................................................................................... 99第 23 章 Oracle 向 Mysql 数据迁移:....................................................................................... 100 23.1 数据类型的差异:........................................................................................................100 23.2 利用导出文本迁移:....................................................................................................100 23.2.1 导出为 insert sql 文本................................................................................ 100 23.2.2 导出为固定格式文本...................................................................................... 101 23.3 利用工具软件迁移:....................................................................................................102 23.4 使用 DBA 组开发的迁移工具:................................................................................. 102 23.5 数据迁移常见问题:....................................................................................................103 23.5.1 字符集问题:...................................................................................................103 23.5.2 特殊字符处理:...............................................................................................103 23.5.3 日期字段的处理:...........................................................................................103 23.5.4 如何使迁移过程不被 SQL 错误中断:.......................................................... 104 23.5.5 如何查找产生 warnings 的原因:................................................................ 104第 24 章 应急处理:..................................................................................................................... 104 24.1 一般处理流程:............................................................................................................ 104 24.2 忘记 root 密码:........................................................................................................... 105 24.3 表损坏如何处理:........................................................................................................105 24.4 MyISAM 表超过 4G 无法访问:................................................................................. 106 24.5 数据目录磁盘空间不足怎么办?............................................................................... 106 24.6 如何禁止 DNS 反向解析?..........................................................................................107第 25 章 Mysql 管理中一些常用的命令和技巧:..................................................................... 107 25.1 参数设置方法:............................................................................................................ 107 25.2 mysql.sock 丢失后怎么连接数据库?......................................................................... 107 网易技术部 7
  8. 8. www.163.com 25.3 同一台机器运行多个 mysql:..................................................................................... 108 25.4 查看用户权限:............................................................................................................ 109 25.5 修改用户密码:............................................................................................................ 110 25.6 怎样灵活的指定连接的主机:.................................................................................... 111 25.7 到底匹配哪个符合条件的用户:................................................................................ 111 25.8 不进入 mysql,怎样运行 sql 语句?.......................................................................... 112 25.9 客户端怎么访问内网数据库?.................................................................................... 113 第一篇 开发篇 第 1 章 帮助的使用在不同的 mysql 版本中,很多特性和语法有可能是不一样的,我们怎么样才能知道当前版本的语法是什么样呢?最好的办法是学会使用 mysql 的帮助。方法很简单:1.1 按照层次看帮助如果不知道帮助能够提供些什么,可以一层一层往下看:命令如下:mysql> ? contentsYou asked for help about help category: "Contents"For more information, type help <item>, where <item> is one of the followingcategories: Account Management Administration Data Definition Data Manipulation Data Types Functions 网易技术部 8
  9. 9. www.163.com Functions and Modifiers for Use with GROUP BY Geographic Features Language Structure Plugins Storage Engines Stored Routines Table Maintenance Transactions Triggers对于列出的分类,可以进行看自己感兴趣的部分,例如:mysql> ? data typesYou asked for help about help category: "Data Types"For more information, type help <item>, where <item> is one of the followingtopics: AUTO_INCREMENT BIGINT BINARY BIT BLOB BLOB DATA TYPE BOOL EAN。。。。。。对于列出的具体数据类型,可以进一步看详细情况:mysql> ? intName: INTDescription:INT[(M)] [UNSIGNED] [ZEROFILL] 网易技术部 9
  10. 10. www.163.comA normal-size integer. The signed range is -2147483648 to 2147483647.The unsigned range is 0 to 4294967295.1.2 快速查阅帮助实际当中,如果我们需要快速查阅某项语法时,可以使用关键字进行快速查询。例如,我想知道 show 命令都能看些什么东西,可以用如下命令:mysql> ? showName: SHOWDescription:SHOW has many forms that provide information about databases, tables,columns, or status information about the server. This section describesthose following:SHOW AUTHORSSHOW CHARACTER SET [LIKE pattern]SHOW COLLATION [LIKE pattern]SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE pattern]SHOW CONTRIBUTORSSHOW CREATE DATABASE db_nameSHOW CREATE EVENT event_nameSHOW CREATE FUNCTION funcname。。。。。。我想知道 create table 的语法,可以命令如下:mysql> ? create tableName: CREATE TABLEDescription:Syntax:CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name (create_definition,...) 网易技术部 10
  11. 11. www.163.com [table_option ...] [partition_options]Or:CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_option ...] [partition_options] select_statement、 。。。。。。 第 2 章 表类型(存储引擎)的选择2.1 Mysql 存储引擎概述 mysql支持多种存储引擎,在处理不同类型的应用时,可以通过选择使用不同的存储引擎提高应用的效率,或者提供灵活的存储。 mysql的存储引擎包括:MyISAM、 InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDB Cluster、ARCHIVE、CSV、BLACKHOLE、FEDERATED等,其中InnoDB和BDB提供事务安全表,其他存储引擎都是非事务安全表。2.2 各种存储引擎的特性 下面我们重点介绍几种常用的存储引擎并对比各个存储引擎之间的区别和推荐使用方式。 特点 Myisam BDB Memory InnoDB Archive存储限制 没有 没有 有 64TB 没有事务安全 支持 支持锁机制 表锁 页锁 表锁 行锁 行锁 网易技术部 11
  12. 12. www.163.comB 树索引 支持 支持 支持 支持哈希索引 支持 支持全文索引 支持集群索引 支持数据缓存 支持 支持索引缓存 支持 支持 支持数据可压缩 支持 支持空间使用 低 低 N/A 高 非常低内存使用 低 低 中等 高 低批量插入的速度 高 高 高 低 非常高支持外键 支持最常使用的 2 种存储引擎:1. Myisam是Mysql的默认存储引擎,当create创建新表时,未指定新表的存储引擎时,默 认使用Myisam。 每个MyISAM在磁盘上存储成三个文件。文件名都和表名相同,扩展名分别是 .frm (存储表定义)、.MYD (MYData,存储数据)、.MYI (MYIndex,存储索引)。数据文件和 索引文件可以放置在不同的目录,平均分布io,获得更快的速度。2. InnoDB 存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比 Myisam 的存储引擎,InnoDB 写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索 引。2.3 如何选择合适的存储引擎选择标准: 根据应用特点选择合适的存储引擎,对于复杂的应用系统可以根据实际情况选择多种存储引擎进行组合.下面是常用存储引擎的适用环境:1. MyISAM:默认的 MySQL 插件式存储引擎,它是在 Web、数据仓储和其他应用环境下最常 使用的存储引擎之一2. InnoDB:用于事务处理应用程序,具有众多特性,包括 ACID 事务支持。 网易技术部 12
  13. 13. www.163.com3. Memory:将所有数据保存在 RAM 中,在需要快速查找引用和其他类似数据的环境下,可 提供极快的访问。4. Merge:允许 MySQL DBA 或开发人员将一系列等同的 MyISAM 表以逻辑方式组合在一起, 并作为 1 个对象引用它们。对于诸如数据仓储等 VLDB 环境十分适合。 第 3 章 选择合适的数据类型3.1 选择数据类型的基本原则 前提: 使用适合存储引擎。 选择原则: 根据选定的存储引擎,确定如何选择合适的数据类型 下面的选择方法按存储引擎分类:1. MyISAM 数据存储引擎和数据列 MyISAM数据表,最好使用固定长度的数据列代替可变长度的数据列。2. MEMORY存储引擎和数据列 MEMORY数据表目前都使用固定长度的数据行存储,因此无论使用CHAR或VARCHAR列都没 有关系。两者都是作为CHAR类型处理的。3. InnoDB 存储引擎和数据列 建议使用 VARCHAR类型 对于InnoDB数据表,内部的行存储格式没有区分固定长度和可变长度列(所有数据行 都使用指向数据列值的头指针),因此在本质上,使用固定长度的 CHAR列不一定比使 用可变长度VARCHAR列简单。因而,主要的性能因素是数据行使用的存储总量。 CHAR 由于 平均占用的空间多于VARCHAR, 此使用VARCHAR来最小化需要处理的数据行的存储总 因 量和磁盘I/O是比较好的。3.2 固定长度数据列与可变长度的数据列 3.2.1 char 与 varchar� CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾 部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。 网易技术部 13
  14. 14. www.163.com下面的表显示了将各种字符串值保存到 CHAR(4)和 VARCHAR(4)列后的结果,说明了 CHAR 和VARCHAR 之间的差别:值 CHAR(4) 存储需求 VARCHAR(4) 存储需求 4 个字节 1 个字节ab ab 4 个字节 ab 3 个字节abcd abcd 4 个字节 abcd 5 个字节abcdefgh abcd 4 个字节 abcd 5 个字节请注意上表中最后一行的值只适用不使用严格模式时;如果 MySQL 运行在严格模式,超过列长度不的值不保存,并且会出现错误。从 CHAR(4)和 VARCHAR(4)列检索的值并不总是相同,因为检索时从 CHAR 列删除了尾部的空格。通过下面的例子说明该差别:mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));Query OK, 0 rows affected (0.02 sec)mysql> INSERT INTO vc VALUES (ab , ab );Query OK, 1 row affected (0.00 sec)mysql> SELECT CONCAT(v, +), CONCAT(c, +) FROM vc;+----------------+----------------+| CONCAT(v, +) | CONCAT(c, +) |+----------------+----------------+| ab + | ab+ |+----------------+----------------+1 row in set (0.00 sec) 网易技术部 14
  15. 15. www.163.com 3.2.2 text 和 blob在使用 text 和 blob 字段类型时要注意以下几点,以便更好的发挥数据库的性能.1. BLOB和TEXT值也会引起自己的一些问题,特别是执行了大量的删除或更新操作的时候。 删除这种值会在数据表中留下很大的 "空洞",以后填入这些"空洞"的记录可能长度不 同,为了提高性能,建议定期使用 OPTIMIZE TABLE 功能对这类表进行碎片整理.2. 使用合成的(synthetic)索引。合成的索引列在某些时候是有用的。一种办法是根据 其它的列的内容建立一个散列值,并把这个值存储在单独的数据列中。接下来你就可以 通过检索散列值找到数据行了。但是,我们要注意这种技术只能用于精确匹配的查询 (散 列值对于类似<或>=等范围搜索操作符 是没有用处的) 我们可以使用MD5()函数生成散 。 列值,也可以使用SHA1()或CRC32(),或者使用自己的应用程序逻辑来计算散列值。请 记住数值型散列值可以很高效率地存储。同样,如果散列算法生成的字符串带有尾部空 格,就不要把它们存储在CHAR或VARCHAR列中,它们会受到尾部空格去除的影响。 合成的散列索引对于那些BLOB或TEXT数据列特别有用。用散列标识符值查找的速度比搜索BLOB列本身的速度快很多。3. 在不必要的时候避免检索大型的BLOB或TEXT值。例如,SELECT *查询就不是很好的想 法,除非你能够确定作为约束条件的WHERE子句只会找到所需要的数据行。否则,你可 能毫无目的地在网络上传输大量的值。这也是 BLOB或TEXT标识符信息存储在合成的索 引列中对我们有所帮助的例子。你可以搜索索引列,决定那些需要的数据行,然后从合 格的数据行中检索BLOB或 TEXT值。4. 把BLOB或TEXT列分离到单独的表中。在某些环境中,如果把这些数据列移动到第二张数 据表中,可以让你把原数据表中 的数据列转换为固定长度的数据行格式,那么它就是 有意义的。这会减少主表中的碎片,使你得到固定长度数据行的性能优势。它还使你在 主数据表上运行 SELECT *查询的时候不会通过网络传输大量的BLOB或TEXT值。3.3 浮点数与定点数 为了能够引起大家的重视,在介绍浮点数与定点数以前先让大家看一个例子:mysql> CREATE TABLE test (c1 float(10,2),c2 decimal(10,2));Query OK, 0 rows affected (0.29 sec) 网易技术部 15
  16. 16. www.163.commysql> insert into test values(131072.32,131072.32);Query OK, 1 row affected (0.07 sec)mysql> select * from test;+-----------+-----------+| c1 | c2 |+-----------+-----------+| 131072.31 | 131072.32 |+-----------+-----------+1 row in set (0.00 sec) 从上面的例子中我们看到 c1 列的值由 131072.32 变成了 131072.31,这就是浮点数的不精确性造成的。 在 mysql 中 float、double(或 real)是浮点数,decimal(或 numberic)是定点数。 浮点数相对于定点数的优点是在长度一定的情况下,浮点数能够表示更大的数据范围;它的缺点是会引起精度问题。 在今后关于浮点数和定点数的应用中,大家要记住以下几点: 1、浮点数存在误差问题; 2、对货币等对精度敏感的数据,应该用定点数表示或存储; 3、编程中,如果用到浮点数,要特别注意误差问题,并尽量避免做浮点数比较; 4、要注意浮点数中一些特殊值的处理。 第 4 章 字符集4.1 字符集概述 字符集是一套符号和编码的规则,不论是在 oracle 数据库还是在 mysql 数据库,都存在字符集的选择问题,而且如果在数据库创建阶段没有正确选择字符集,那么可能在后期需要更换字符集,而字符集的更换是代价比较高的操作,也存在一定的风险,所以,我们推荐在应用开始阶段,就按照需求正确的选择合适的字符集,避免后期不必要的调整。 网易技术部 16
  17. 17. www.163.com4.2 Mysql 支持的字符集简介 mysql服务器可以支持多种字符集(可以用show character set命令查看所有mysql支持的字符集),在同一台服务器、同一个数据库、甚至同一个表的不同字段都可以指定使用不同的字符集,相比oracle等其他数据库管理系统,在同一个数据库只能使用相同的字符集,mysql明显存在更大的灵活性。 mysql的字符集包括字符集(CHARACTER)和校对规则(COLLATION)两个概念。字符集是用来定义mysql存储字符串的方式,校对规则则是定义了比较字符串的方式。字符集和校对规则是一对多的关系, MySQL支持30多种字符集的70多种校对规则。 每个字符集至少对应一个校对规则。可以用SHOW COLLATION LIKE utf8%;命令查看相关字符集的校对规则。4.3 Unicode 简述 Unicode 是一种编码规范。我们在这里简述一下 Unicode 编码产生的历史。 先从 ASCII 码说起,ASCII 码也是一种编码规范,只不过 ASCII 码只能最多表示 256个字符,是针对英文产生的,而面对中文、阿拉伯文之类的复杂文字,256 个字符显然是不够用的。于是各个国家或组织都相继制定了符合自己语言文字的标准,比如 gb2312、big5等等。但是这种各自制定自己的标准的做法显然是有很多弊端的,于是 Unicode 编码规范应运而生。 Unicode 也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案。 Unicode 的学名是"Universal Multiple-Octet Coded Character Set",简称为 UCS。UCS 可以看作是"Unicode Character Set"的缩写。 Unicode 有两套标准 UCS-2 和 UCS-4,前者用 2 个字节表示一个字符,后者用 4 个字节表示一个字符。以目前常用的 UCS-2 为例,它可以表示的字符数为 2^16=65535,基本上可以容纳所有的欧美字符和绝大多数亚洲字符。4.4 怎样选择合适的字符集 我们建议在能够完全满足应用的前提下,尽量使用小的字符集。因为更小的字符集意 网易技术部 17
  18. 18. www.163.com味着能够节省空间、减少网络传输字节数,同时由于存储空间的较小间接的提高了系统的性能。 有很多字符集可以保存汉字,比如 utf8、gb2312、gbk、latin1 等等,但是常用的是gb2312 和 gbk。因为 gb2312 字库比 gbk 字库小,有些偏僻字(例如:洺)不能保存,因此在选择字符集的时候一定要权衡这些偏僻字在应用出现的几率以及造成的影响,不能做出肯定答复的话最好选用 gbk。4.5 Mysql 字符集的设置 mysql 的字符集和校对规则有 4 个级别的默认设置:服务器级、数据库级、表级和字段级。分别在不同的地方设置,作用也不相同。 服务器字符集和校对,在 mysql 服务启动的时候确定。可以在 my.cnf 中设置:[mysqld]default-character-set=utf8或者在启动选项中指定:mysqld --default-character-set=utf8或者在编译的时候指定:./configure --with-charset=utf8 如果没有特别的指定服务器字符集,默认使用 latin1 作为服务器字符集。上面三种设置的方式都只指定了字符集,没有指定校对规则,这样是使用该字符集默认的校对规则,如果要使用该字符集的非默认校对规则,则需要在指定字符集的同时指定校对规则。 可以用 show variables like character_set_server;命令查询当前服务器的字符集和校对规则。 第 5 章 索引的设计和使用5.1 Mysql 索引概述 所有 MySQL 列类型可以被索引。对相关列使用索引是提高 SELECT 操作性能的最佳途径。根据存储引擎定义每个表的最大索引数和最大索引长度。所有存储引擎支持每个表至少 网易技术部 18
  19. 19. www.163.com16 个索引,总索引长度至少为 256 字节。大多数存储引擎有更高的限制。 在 MySQL 5.1 中,对于 MyISAM 和 InnoDB 表,前缀可以达到 1000 字节长。请注意前缀的限制应以字节为单位进行测量,而 CREATE TABLE 语句中的前缀长度解释为字符数。当为使用多字节字符集的列指定前缀长度时一定要加以考虑。 还可以创建 FULLTEXT 索引。该索引可以用于全文搜索。只有 MyISAM 存储引擎支持FULLTEXT 索引,并且只为 CHAR、VARCHAR 和 TEXT 列。索引总是对整个列进行,不支持局部(前缀)索引。也可以为空间列类型创建索引。只有 MyISAM 存储引擎支持空间类型。空间索引使用 R-树。默认情况 MEMORY(HEAP)存储引擎使用 hash 索引,但也支持 B-树索引。5.2 设计索引的原则1. 搜索的索引列,不一定是所要选择的列。换句话说,最适合索引的列是出现在 WHERE 子 句中的列,或连接子句中指定的列,而不是出现在 SELECT 关键字后的选择列表中的列。2. 使用惟一索引。考虑某列中值的分布。对于惟一值的列,索引的效果最好,而具有多个 重复值的列,其索引效果最差。例如,存放年龄的列具有不同值,很容易区分 各 行 。 而用来记录性别的列,只含有“ M”和“F”,则对此列进行索引没有多大用处(不管 搜索哪个值,都会得出大约一半的行)3. 使用短索引。如果对串列进行索引,应该指定一个前缀长度,只要有可能就应该这样做 。 例如,如果有一个 CHAR(200) 列,如果在前 10 个或 20 个字符内,多数值是惟一的, 那么就不要对整个列进行索引。对前 10 个或 20 个字符进行索引能够节省大量索引空 间,也可能会使查询更快。较小的索引涉及的磁盘 I/O 较少,较短的值比较起来更快。 更为重要的是,对于较短的键值,索引高速缓存中的块能容纳更多的键值,因此,MySQL 也可以在内存中容纳更多的值。这增加 了找到行而不用读取索引中较多块的可能性。 (当然,应该利用一些常识。如仅用列值的第一个字符进行索引是不可能有多大好处的 , 因为这个索引中不会有许多不 同 的 值 。)4. 利用最左前缀。在创建 一个 n 列的索引时,实际是创建了 MySQL 可利用的 n 个索引。 多列索引可起几个索引的作用,因为可利用索引中最左边的列集来匹配行。这样的列集 称为最左前缀。(这与索引一个列的前缀不同,索引一个列的前缀是利用该的前 n 个字 符作为索引值。)5. 不要过度索引。不要以为索引“越多越好”,什么东西都用索引是错的。每个额外的索 引都要占用额外的磁盘空间,并降低写操作的性能,这一点我们前面已经介绍 过。在 网易技术部 19
  20. 20. www.163.com 修改表的内容时,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时 间越长。如果有一个索引很少利用或从不使用,那么会不必要地减缓表 的修改速度。 此外,MySQL 在生成一个执行计划时,要考虑各个索引,这也要费时间。创建多余的索 引给查询优化带来了更多的工作。索引太多,也可能会使 MySQL 选择不到所要使用的 最好索引。只保持所需的索引有利于查询优化。如果想给已索引的表增加索引,应该考 虑所要增加的索引是否是现有多列索引的最左 索引。如果是,则就不要费力去增加这 个索引了,因为已经有了。6. 考虑在列上进行的比较类型。索引可用于“ <”、“ < = ”、“ = ”、“ > =”、“ > ”和 BETWEEN 运算。在模式具有一个直接量前缀时,索引也用于 LIKE 运算。如果只 将某个列用于其他类型的运算时(如 STRCMP( )),对其进行索引没有价值。5.3 btree 索引与 hash 索引 对于 BTREE 和 HASH 索引,当使用=、<=>、IN、IS NULL 或者 IS NOT NULL 操作符时 ,关键元素与常量值的比较关系对应一个范围条件。Hash 索引还有一些其它特征:它们只用于使用=或<=>操作符的等式比较(但很快)。优化器不能使用 hash 索引来加速 ORDER BY 操作 。(该类索引不能用来按顺序搜索下一个条目)。MySQL 不能确定在两个值之间大约有多少行(这被范围优化器用来确定使用哪个索引)。如果你将一个 MyISAM 表改为 hash-索引的 MEMORY表,会影响一些查询。只能使用整个关键字来搜索一行。(用 B-树索引,任何关键字的最左面的前缀可用来找到行)。 对于 BTREE 索引,当使用>、<、>=、<=、BETWEEN、!=或者<>,或者 LIKE pattern(其中 pattern不以通配符开始)操作符时,关键元素与常量值的比较关系对应一个范围条件。“常量值”系指:查询字符串中的常量、同一联接中的 const 或 system 表中的列、无关联子查询的结果、完全从前面类型的子表达式组成的表达式下面是一些 WHERE 子句中有范围条件的查询的例子:下列范围查询适用于 btree 索引和 hash 索引SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,20);下列范围查询适用于 btree 索引 网易技术部 20
  21. 21. www.163.comSELECT * FROM t1 WHERE key_col > 1 AND key_col < 10;SELECT * FROM t1 WHERE key_col LIKE ab% OR key_col BETWEEN bar ANDfoo;5.4 Mysql 如何使用索引 索引用于快速找出在某个列中有一特定值的行。不使用索引,MySQL 必须从第 1 条记录开始然后读完整个表直到找出相关的行。表越大,花费的时间越多。如果表中查询的列有一个索引,MySQL 能快速到达一个位置去搜寻到数据文件的中间,没有必要看所有数据。如果一个表有 1000 行,这比顺序读取至少快 100 倍。注意如果你需要访问大部分行,顺序读取要快得多,因为此时我们避免磁盘搜索。 大多数 MySQL 索引(PRIMARY KEY、UNIQUE、INDEX 和 FULLTEXT)在 B 树中存储。只是空间列类型的索引使用 R-树,并且 MEMORY 表还支持 hash 索引。 关于什么情况下数据库会使用索引以及什么情况下数据库不会使用索引的详细解释请看优化篇的相关章节,这里就不再累述。 第 6 章 锁机制和事务控制6.1 如何加锁 锁定表的语法: LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ... 解锁语法: UNLOCK TABLES innodb 的存储引擎提供行级锁,支持共享锁和排他锁两种锁定模式,以及四种不同的隔离级别。 网易技术部 21
  22. 22. www.163.com6.2 死锁 InnoDB自动检测事务的死锁,并回滚一个或几个事务来防止死锁。 InnoDB不能在MySQLLOCK TABLES设定表锁定的地方或者涉及 InnoDB之外的存储引擎设置锁定的地方检测死锁。你必须通过设定innodb_lock_wait_timeout系统变量的值来解决这些情况。如果要依靠锁等待超时来解决死锁问题,对于更新事务密集的应用,将有可能导致大量事务的锁等待,导致系统异常,所以不推荐在一个事务中混合更新不同存储类型的表,也不推荐相同类型的表采用不同的锁定方式加锁。6.3 事务控制 MySQL通过SET AUTOCOMMIT, START TRANSACTION, COMMIT和ROLLBACK等语句支持本地事务。 语法: START TRANSACTION | BEGIN [WORK] COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE] ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE] SET AUTOCOMMIT = {0 | 1} 默认情况下,mysql是autocommit的,如果需要通过明确的commit和rollback来提交和回滚事务,那么需要通过明确的事务控制命令来开始事务,这是和oracle的事务管理明显不同的地方,如果应用是从oracle数据库迁移到mysql数据库,则需要确保应用中是否对事务进行了明确的管理。 START TRANSACTION或BEGIN语句可以开始一项新的事务。 COMMIT和ROLLBACK用来提交或者回滚事务。 CHAIN和RELEASE子句分别用来定义在事务提交或者回滚之后的操作,chain会立即启动一个新事物,并且和刚才的事务具有相同的隔离级别,release则会断开和客户端的连接。 SET AUTOCOMMIT可以修改当前连接的提交方式,如果设置了SET AUTOCOMMIT=0,则设置之后的所有事务都需要通过明确的命令进行提交或者回滚。 如果我们只是对某些语句需要进行事务控制,则使用START TRANSACTION开始一个事务 网易技术部 22
  23. 23. www.163.com比较方便,这样事务结束之后可以自动回到自动提交的方式,如果我们希望我们所有的事务都不是自动提交的,那么通过修改AUTOCOMMIT来控制事务比较方便,这样不用在每个事务开始的时候再执行START TRANSACTION。time session_1 session_2---- mysql> select * from tt3; mysql> select * from tt3;---- Empty set (0.00 sec) Empty set (0.00 sec)---- mysql> start transaction;---- Query OK, 0 rows affected (0.00---- sec)---- mysql> insert into tt3---- values(1,1);---- Query OK, 1 row affected (0.03---- sec)---- mysql> select * from tt3;---- Empty set (0.00 sec)---- mysql> commit;---- Query OK, 0 rows affected (0.05---- sec)-> mysql> select * from tt3; +------+------+ | id | name | +------+------+ | 1 | 1.00 | +------+------+ 1 row in set (0.00 sec) 网易技术部 23
  24. 24. www.163.commysql> insert into tt3values(2,2);Query OK, 1 row affected (0.04sec)这个事务是按照自动提交执行的 mysql> select * from tt3; +------+------+ | id | name | +------+------+ | 1 | 1.00 | | 2 | 2.00 | +------+------+ 2 rows in set (0.00 sec) 网易技术部 24
  25. 25. www.163.commysql> start transaction;Query OK, 0 rows affected (0.00sec)mysql> insert into tt3values(3,3);Query OK, 1 row affected (0.00sec)mysql> commit and chain;Query OK, 0 rows affected (0.05sec)自动开始一个新的事务mysql> insert into tt3values(4,4);Query OK, 1 row affected (0.00sec) mysql> select * from tt3; +------+------+ | id | name | +------+------+ | 1 | 1.00 | | 2 | 2.00 | | 3 | 3.00 | +------+------+ 3 rows in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.06sec) 网易技术部 25
  26. 26. www.163.com mysql> select * from tt3; +------+------+ | id | name | +------+------+ | 1 | 1.00 | | 2 | 2.00 | | 3 | 3.00 | | 4 | 4.00 | +------+------+ 4 rows in set (0.00 sec) 开始一个事务,会造成一个隐含的unlock tables被执行:time session_1 session_2---- mysql> select * from tt3; mysql> select * from tt3;---- Empty set (16.65 sec) Empty set (16.65 sec)---- mysql> lock table tt3 write;---- Query OK, 0 rows affected (0.00---- sec)---- mysql> select * from tt3;---- 等待---- mysql> insert into tt3 等待---- values(1,1);---- Query OK, 1 row affected (0.07---- sec)---- mysql> rollback; 等待---- Query OK, 0 rows affected (0.00---- sec)-> 网易技术部 26
  27. 27. www.163.com mysql> start transaction; 等待 Query OK, 0 rows affected (0.00 sec) mysql> select * from tt3; +------+------+ | id | name | +------+------+ | 1 | 1.00 | +------+------+ 1 row in set (37.71 sec) 开始一个事务时,表锁被释放。 对 lock 方式加的表锁,不能通过 rollback 进行回滚。 因此,在同一个事务中,最好不使用不同存储引擎的表,否则rollback时需要对非事务类型的表进行特别的处理,因为commit、rollback只能对事务类型的表进行提交和回滚。 通常情况下,只对提交的事务纪录到二进制的日志中,但是如果一个事务中包含非事务类型的表,那么回滚操作也会被记录到二进制日志中,以确保非事务类型表的更新可以被复制到从的数据库中。 和oracle的事务管理相同,所有的DDL语句是不能回滚的,并且部分的DDL语句会造成隐式的提交。 在事务中可以通过定义savepoint,指定回滚事务的一个部分,但是不能指定提交事务的一个部分。对于复杂的应用,可以定义多个不同的savepoint,满足不同的条件时,回滚不同的 savepoint。需要注意的是, 如果定义了 相同名字的 savepoint ,则后面定义的savepoint会覆盖之前的定义。对于不再需要使用的savepoint,可以通过release savepoint命令删除savepoint,删除后的savepoint,不能再执行rollback to savepoint命令。 下面我们例子就是模拟回滚事务的一个部分,通过定义savepoint来指定需要回滚的事务的位置。 网易技术部 27
  28. 28. www.163.comtime session_1 session_2---- mysql> select * from tt3; mysql> select * from tt3;---- +------+------+ +------+------+---- | id | name | | id | name |---- +------+------+ +------+------+---- | 2 | 2.00 | | 2 | 2.00 |---- | 3 | 3.00 | | 3 | 3.00 |---- | 4 | 4.00 | | 4 | 4.00 |---- +------+------+ +------+------+---- 3 rows in set (0.00 sec) 3 rows in set (0.00 sec)---- mysql> start transaction;---- Query OK, 0 rows affected (0.00---- sec)-------- mysql> delete from tt3 where id =-> 2; Query OK, 1 row affected (0.00 sec) mysql> select * from tt3; mysql> select * from tt3; +------+------+ +------+------+ | id | name | | id | name | +------+------+ +------+------+ | 3 | 3.00 | | 2 | 2.00 | | 4 | 4.00 | | 3 | 3.00 | +------+------+ | 4 | 4.00 | 3 rows in set (0.00 sec) +------+------+ 3 rows in set (0.00 sec) 网易技术部 28
  29. 29. www.163.commysql> savepoint test;Query OK, 0 rows affected (0.00sec)mysql> delete from tt3 where id =3;Query OK, 1 row affected (0.00sec)mysql> select * from tt3; mysql> select * from tt3;+------+------+ +------+------+| id | name | | id | name |+------+------+ +------+------+| 4 | 4.00 | | 2 | 2.00 |+------+------+ | 3 | 3.00 |3 rows in set (0.00 sec) | 4 | 4.00 | +------+------+ 3 rows in set (0.00 sec)mysql> rollback to savepoint test;Query OK, 0 rows affected (0.00sec)mysql> select * from tt3; mysql> select * from tt3;+------+------+ +------+------+| id | name | | id | name |+------+------+ +------+------+| 3 | 3.00 | | 2 | 2.00 || 4 | 4.00 | | 3 | 3.00 |+------+------+ | 4 | 4.00 |2 rows in set (0.00 sec) +------+------+ 3 rows in set (0.00 sec) 网易技术部 29
  30. 30. www.163.com mysql> commit; Query OK, 0 rows affected (0.05 sec) mysql> select * from tt3; mysql> select * from tt3; +------+------+ +------+------+ | id | name | | id | name | +------+------+ +------+------+ | 3 | 3.00 | | 3 | 3.00 | | 4 | 4.00 | | 4 | 4.00 | +------+------+ +------+------+ 2 rows in set (0.00 sec) 2 rows in set (0.00 sec) 第 7 章 SQL 中的安全问题7.1 SQL 注入简述 SQL Injection 攻击具有很大的危害,攻击者可以利用它读取、修改或者删除数据库内的数据,获取数据库中的用户名和密码等敏感信息,甚至可以 获得数据库管理员的权限。如果能够再利用 SQLServer 扩展存储过程和自定义扩展存储过程来执行一些系统命令,攻击者还可以获得该系统的控制权。而且,SQL Injection 也很难防范。网站管理员无法通过安装系统 补丁 或者 进行 简单 的安 全配 置 进行 自我 保护 ,一 般的 防火 墙也 无 法拦 截 SQLInjection 攻击。 SQL Injection 原理: 结构化查询语言 (SQL)是一种用来和数据库交互的文本语言。 SQL Injection 就是利用某些数据库的外部接口把用户数据插入到实际的数据库操作语言(SQL)当中,从而达到入侵数据库乃至操作系统的目的。它的产生主要是由于程序对用户输入 的数据没有进行严格的过滤,导致非法数据库查询语句的执行。 如下面的用户登陆验证程序: $sql = "SELECT * FROM user WHERE username=$username ANDpassword=$password"; 网易技术部 30
  31. 31. www.163.com $result = mysql_db_query($dbname, $sql); 如果我们提交如下 url: http://127.0.0.1/injection/user.php?username=angel or 1=1 那么就可以成功登陆系统,但是很显然这并不是我们预期的,同样我们也可以利用 sql的注释语句实现 sql 注入,如下面的例子: http://127.0.0.1/injection/user.php?username=angel/* http://127.0.0.1/injection/user.php?username=angel%23 这样就把后面的语句给注释掉了!说说这两种提交的不同之处,我们提交的第一句是利用逻辑运算,第二、三句是根据 mysql 的特性,mysql 支持/*和#两种注释格式,所以我们提交的时候是把后面的代码注释掉,值得注意的是由于编码问题,在 IE 地址栏里提交 #会变成空的,所以我们在地址栏提交的时候,应该提交%23,才会变成#,就成功注释了, 这个比逻辑运算简单得多了。7.2 开发中可以采取的措施 7.2.1 prepareStatement + Bind-variable 对 Java ,Jsp 开发的应用,可以使用 prepareStatement + Bind-variable 来防止sql 注入,另外从 PHP 5 开始,也在扩展的 mysqli 中支持 prepared statements,所以在使用这类语言作数据库开发时 ,强烈建议使用 prepareStatement + Bind-variable 来实现,而尽量不要使用拼接的 sql。 7.2.2 使用应用程序提供的转换函数: 很多应用程序接口都提供了对特殊的字符进行转换的函数,恰当的使用这些函数,可以防止应用程序用户输入使应用程序生成不期望的效果的语句的数值。 MySQL C API:使用 mysql_real_escape_string() API 调用。 MySQL++ :使用 escape 和 quote 修饰符。 PHP :使用 mysql_real_escape_string()函数(适用于 PHP 4.3.0,之前的版本请使用 mysql_escape_string(), PHP 4.0.3 之前的版本请使用 addslashes())。 PHP 5 从开始,可以使用扩展的 mysqli,这是对 MYSQL 新特性的一个扩展支持,其中的一个优点就是支持 prepared statements。 网易技术部 31
  32. 32. www.163.com Perl DBI :使用 placeholders 或者 quote()方法。 Ruby DBI :使用 placeholders 或者 quote()方法。 Java JDBC :使用 PreparedStatement 和 placeholders。 7.2.3 自己定义函数进行校验 如果现有的转换函数仍然不能满足要求,则需要自己编写函数进行输入校验。输入验证是一个很复杂的问题。输入验证的途径可以分为以下几种: 整理数据使之变得有效; 拒绝已知的非法输入; 只接受已知的合法的输入。 所以如果想要获得最好的安全状态,目前最好的解决办法就是对用户提交或者可能改变的数据进行简单分类,分别应用正则表达式来对用户提供的输入数据进行严格的检测和验证。 第 8 章 SQL Mode 及相关问题8.1 Mysql SQL Mode 简介 MySQL 服务器能够工作在不同的 SQL 模式下,并能针对不同的客户端以不同的方式应用这些模式。这样,应用程序就能对服务器操作进行量身定制以满足自己的需求。这类模式定义了 MySQL 应支持的 SQL 语法,以及应该在数据上执行何种确认检查。这样,就能在众多不同的环境下、与其他数据库服务器一起更容易地使用 MySQL。可以使用“--sql-mode="modes"”选项,通过启动 mysqld 来设置默认的 SQL 模式。从 MySQL 4.1 开始,也能在启动之后,使用 SET [SESSION|GLOBAL] sql_mode=modes语句,通过设置 sql_mode 变量更改模式。通常在 linux 下安装完 mysql 后,默认的 sql-mode 值是空,在这种情形下 mysql 执行的是一种不严格的检查,例如日期字段可以插入 ’0000-00-00 00:00:00 ’这样的值,还有如果要插入的字段长度超过列定义的长度,那么 mysql 不会终止操作,而是会自动截断后面的字符继续插入操作,如下例: 网易技术部 32
  33. 33. www.163.commysql> create table t5 (c1 char(3));mysql> insert into t5 values(abcd);mysql> select * from t5;+------+| c1 |+------+| abc |+------+1 row in set (0.00 sec)我们发现插入的字符被自动截断了,但是如果我们本意希望如果长度超过限制就报错,那么我们可以设置 sql_mode 为 STRICT_TRANS_TABLES,如下:mysql> set session sql_mode=STRICT_TRANS_TABLES这样我们再执行同样的操作,mysql 就会告诉我们插入的值太长,操作被终止,如下:mysql> insert into t5 values(abcd);ERROR 1406 (22001): Data too long for column c1 at row 1经常使用的 sql_mode 值如下表:Sql_mode 值 描述ANSI 更改语法和行为,使其更符合标准 SQL。STRICT_TRANS_T 如果不能将给定的值插入到事务表中,则放弃该语句。对于非事务表 ,ABLES 如果值出现在单行语句或多行语句的第 1 行,则放弃该语句。本节后 面给出了更详细的描述。TRADITIONAL Make MySQL 的行为象“传统”SQL 数据库系统。该模式的简单描述是 当在列中插入不正确的值时“给出错误而不是警告”。注释:一旦发 现错误立即放弃 INSERT/UPDATE。如果你使用非事务存储引擎,这种 方式不是你想要的,因为出现错误前进行的数据更改不会“滚动”, 结果是更新“只进行了一部分”。说明:如果把 sql_mode 的值设置成后面的两个值(也就是我们说的严格模式),那么当在列中插入或更新不正确的值时,mysql 将会给出错误,并且放弃 insert/update 操作。在我们的一般应用中建议使用这两种模式,而不是使用默认的空或 ANSI 模式。但是需要注意的问题是,如果数据库运行在严格模式下,并且你的存储引擎不支持事务,那么有数据不一致的风 网易技术部 33
  34. 34. www.163.com险存在,比如一组 sql 中有两个 dml 语句,如果后面的一个出现了问题,但是前面的已经操作成功,那么 mysql 并不能回滚前面的操作。因此说设置 sql_mode 需要应用人员权衡各种得失,从而得到一个合适的选择。Sql_mode 的值还有很多,这里不再累述,可以参考相关的手册。8.2 SQL Mode 与可移植性 如果 mysql 与其它异构数据库之间有数据移植的需求的话,那么下面的 sql_mode 的组合设置可以达到相应的效果:数据库 Sql_mode 值DB2 PIPES_AS_CONCAT 、 ANSI_QUOTES 、 IGNORE_SPACE 、 NO_KEY_OPTIONS 、 NO_TABLE_OPTIONS、NO_FIELD_OPTIONSMAXDB PIPES_AS_CONCAT 、 ANSI_QUOTES 、 IGNORE_SPACE 、 NO_KEY_OPTIONS 、 NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、 NO_AUTO_CREATE_USERMSSQL PIPES_AS_CONCAT 、 ANSI_QUOTES 、 IGNORE_SPACE 、 NO_KEY_OPTIONS 、 NO_TABLE_OPTIONS、 NO_FIELD_OPTIONSORACLE PIPES_AS_CONCAT 、 ANSI_QUOTES 、 IGNORE_SPACE 、 NO_KEY_OPTIONS 、 NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、NO_AUTO_CREATE_USERPOSTGRESQL PIPES_AS_CONCAT 、 ANSI_QUOTES 、 IGNORE_SPACE 、 NO_KEY_OPTIONS 、 NO_TABLE_OPTIONS、NO_FIELD_OPTIONS8.3 SQL Mode 与数据效验SQL Mode 还可以实现对数据效验和转移等功能如:·效验日期数据合法性.·在 INSERT 或 UPDATE 过程中,如果被零除(或 MOD(X,0)),则产生错误·将‘"’视为识别符引号(‘`’引号字符)·禁用反斜线字符(‘’)做为字符串内的退出字符。启用 NO_BACKSLASH_ESCAPES 模式,反斜线则成为普通字符。·将||视为字符串连接操作符(+)(同 CONCAT()),而不视为 OR。 网易技术部 34
  35. 35. www.163.com 第 9 章 常用 SQL 技巧9.1 检索包含最大/最小值的行MIN([DISTINCT] expr), MAX([DISTINCT] expr) 返回 expr 的最小值和最大值。 MIN() 和 MAX() 的取值可以是一个字符串参数;在这些情况下, 它们返回最小或最大字符串值。DISTINCT 关键词可以被用来查找 expr 的不同值的最小或最大值,然而,这产生的结果与省略 DISTINCT 的结果相同。若找不到匹配的行,MIN()和 MAX()返回 NULL 。mysql> SELECT student_name, MIN(test_score), MAX(test_score) -> FROM student -> GROUP BY student_name;9.2 巧用 rand()/rand(n)提取随机行可按照如下的随机顺序检索数据行,如下:mysql> SELECT * FROM tbl_name ORDER BY RAND();ORDER BY RAND()同 LIMIT 的结合可以从一组列中选择随机样本,如下:mysql> SELECT * FROM table1, table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000;9.3 利用 group by 的 with rollup 子句做统计create table sales( year int not null, country varchar(20) not null, product varchar(32) not null, profit int 网易技术部 35
  36. 36. www.163.com); select year, sum(profit) from sales group by year; select year, sum(profit) from sales group by year with rollup; select year, country, product, sum(profit) from sales group by year, country, product; select year, country, product, sum(profit) from sales group by year, country, product with rollup; insert into sales values(2004,china,tnt2004,2001); insert into sales values(2004,china,tnt2004,2002); insert into sales values(2004,china,tnt2004,2003); insert into sales values(2005,china,tnt2005,2004); insert into sales values(2005,china,tnt2005,2005); insert into sales values(2005,china,tnt2005,2006); insert into sales values(2005,china,tnt2005,2007); insert into sales values(2005,china,tnt2005,2008); insert into sales values(2005,china,tnt2005,2009); insert into sales values(2006,china,tnt2006,2010); insert into sales values(2006,china,tnt2006,2011); insert into sales values(2006,china,tnt2006,2012); select year, country, product, sum(profit) from sales group by year, country, product;select year, country, product, sum(profit)from salesgroup by year, country, product with rollup; 网易技术部 36
  37. 37. www.163.comSELECT year, country, product, SUM(profit)FROM salesGROUP BY year, country, product WITH ROLLUPLIMIT 5; 当你使用 ROLLUP时, 你不能同时使用 ORDER BY子句进行结果排序。换言之, ROLLUP和ORDER BY 是互相排斥的LIMIT 用在 ROLLUP 后面9.4 用 bit group functions 做统计Group by 统计语句的一般用法:SELECT student_name, AVG([DISTINCT] expr) -> FROM student -> GROUP BY student_name; 在本小节,主要介绍 group by 语句和 bit_and ,bit_or 函数共同使用完成统计工作,先来了解一下 bit_and 和 bit_or 函数,举例如下:mysql> CREATE TABLE `ta` ( -> `id` smallint(5) unsigned NOT NULL default 0, -> KEY `id` (`id`) -> ) TYPE=MyISAM;Query OK, 0 rows affected (0.01 sec)mysql> INSERT INTO `ta` VALUES("1"),("2"),("3"),("4");Query OK, 8 rows affected (0.00 sec)Records: 4 Duplicates: 0 Warnings: 0mysql> SELECT BIT_OR(id) from ta;+------------+| BIT_OR(id) |+------------+| 7| 网易技术部 37
  38. 38. www.163.com+------------+1 row in set (0.00 sec)# ..0001# ..0010# ..0011# ..0100# OR ..0000# ---------# ..0111mysql> SELECT BIT_AND(id) from ta;+-------------+| BIT_AND(id) |+-------------+| 0|+-------------+1 row in set (0.00 sec)# ..0001# ..0010# ..0011# ..0100# AND ..1111# ----------# ..0000 熟悉了 bit_and 和 bit_or 后我们一起来学习一下 bit_and ,bit_or 和 group by 函数共同使用进行统计工作. 针对 上面的表 ta 我们增加字段 cust_type 并按这个字段的值进行分类统计alter table ta add column cust_type varchar(100);update ta set cust_type =2 where id>3;update ta set cust_type =1 where cust_type is null;mysql> SELECT cust_type,BIT_OR(id) from ta group by cust_type; 网易技术部 38
  39. 39. www.163.com+-----------+------------+| cust_type | BIT_OR(id) |+-----------+------------+|1 | 3||2 | 4|+-----------+------------+2 rows in set (0.00 sec)mysql> SELECT cust_type,BIT_and(id) from ta group by cust_type;+-----------+-------------+| cust_type | BIT_and(id) |+-----------+-------------+|1 | 0||2 | 4|+-----------+-------------+2 rows in set (0.00 sec)BIT_AND(expr)返回 expr 中所有比特的 bitwise AND 。计算执行的精确度为 64 比特(BIGINT) 。若找不到匹配的行,则这个函数返回 18446744073709551615 。(这是无符号 BIGINT 值 ,所有比特被设置为 1)。BIT_OR(expr)返回 expr 中所有比特的 bitwise OR。计算执行的精确度为 64 比特(BIGINT) 。若找不到匹配的行,则函数返回 0 。BIT_XOR(expr) 网易技术部 39
  40. 40. www.163.com返回 expr 中所有比特的 bitwise XOR。计算执行的精确度为 64 比特(BIGINT) 。若找不到匹配的行,则函数返回 0 。 第 10 章 其他需注意的问题10.1 数据库名、表名大小写问题 在 MySQL 中,数据库对应数据目录中的目录。数据库中的每个表至少对应数据库目录中的一个文件(也可能是多个,取决于存储引擎)。因此,所使用操作系统的大小写敏感性决定了数据库名和表名的大小写敏感性。这说明在大多数 Unix 中数据库名和表名对大小写敏感,而在 Windows 中对大小写不敏感。一个显著的例外情况是 Mac OS X,它基于 Unix 但使用默认文件系统类型(HFS+),对大小写不敏感。然而,Mac OS X 也支持 UFS 卷,该卷对大小写敏感,就像 Unix 一样。注释:尽管在某些平台中数据库名和表名对大小写不敏感,不应在同一查询中使用不同的大小写来引用给定的数据库或表。下面的查询不会工作,因为它同时引用了表 my_tables 和 asMY_tables:mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1; 列、索引、存储子程序和触发器名在任何平台上对大小写不敏感,列的别名也不敏感 。默认情况,表别名在 Unix 中对大小写敏感,但在 Windows 或 Mac OS X 中对大小写不敏感。下面的查询在 Unix 中不会工作,因为它同时引用了别名 a 和 A:mysql> SELECT col_name FROM tbl_name AS a -> WHERE a. col_name = 1 OR A. col_name = 2; 然而,该查询在 Windows 中是可以的。要想避免出现差别,最好采用一致的转换,例如总是用小写创建并引用数据库名和表名。在大多数移植和使用中建议使用该转换。 网易技术部 40
  41. 41. www.163.com 在 MySQL 中如何在硬盘上保存和使用表名和数据库名由 lower_case_tables_name 系统变量确定,可以在启动 mysqld 时设置。lower_case_tables_name 可以采用下面的任一值 :值 含义 使用 CREATE TABLE 或 CREATE DATABASE 语句指定的大写和小写在硬盘上保存表名和数据 库名。名称比较对大小写敏感。在 Unix 系统中的默认设置即如此。请注意如果在大小写0 不敏感的文件系统上用--lower-case-table-names=0 强制设为 0,并且使用不同的大小 写访问 MyISAM 表名,会导致索引破坏。 表名在硬盘上以小写保存,名称比较对大小写敏感。MySQL 将所有表名转换为小写以便存1 储和查找。该行为也适合数据库名和表的别名。该值为 Windows 和 Mac OS X 系统中的默 认值。 表名和数据库名在硬盘上使用 CREATE TABLE 或 CREATE DATABASE 语句指定的大小写进行 保存,但 MySQL 将它们转换为小写以便查找。名称比较对大小写敏感。注释:只在对大2 小写不敏感的文件系统上适用! InnoDB 表名以小写保存,例如 lower_case_tables_name=1。在 Windows 和 Mac OS X 中,lower_case_tables_name 的 默认值是 1。 如果只在一个平台上使用 MySQL,通常不需要更改 lower_case_tables_name 变 量 。然而,如果你想要在对大小写敏感不同的文件系统的平台之间转移表,会遇到困难。例如,在 Unix 中,my_tables 和 MY_tables 是两个不同的表,但在 Windows 中,这两个表名相同。要想避免由于数据库或表名的大小写造成的数据转移问题,可使用两个选项:在任何系统中可以使用 lower_case_tables_name=1。使用该选项的不利之处是当使用 SHOW TABLES 或 SHOW DATABASES 时,看不出名字原来是用大写还是小写。在 Unix 中使用 lower_case_tables_name=0,在 Windows 中使用 lower_case_tables_name=2。 这样了可以保留数据库名和表名的大小写。不利之处是必须确保在 Windows 中查询总是 用正确大小写引用数据库名和表名。如果将查询转移到 Unix 中,由于在 Unix 中大小写 很重要,如果大小写不正确,它们不工作。 网易技术部 41
  42. 42. www.163.com例外:如果你正使用 InnoDB 表,在任何平台上均应将 lower_case_tables_name 设置为 1,以强制将名转换为小写。 请注意在 Unix 中将 lower_case_tables_name 设置为 1 之前,重启 mysqld 之前,必须先将旧的数据库名和表名转换为小写10.2 使用外键需注意的地方 在 MySQL 中,InnoDB 表支持对外部关键字约束条件的检查。 对于除 InnoDB 类型的表,当使用 REFERENCES tbl_name(col_name)子句定义列时可以使用外部关键字,该子句没有实际的效果,只作为备忘录或注释来提醒,你目前正定义的列指向另一个表中的一个列。执行该语句时,实现下面很重要:MySQL 不执行表 tbl_name 中的动作,例如作为你正定义的表中的行的动作的响应而删除行; 换句话说,该句法不会致使 ON DELETE 或 ON UPDATE 行为(如果你在 REFERENCES 子句 中写入 ON DELETE 或 ON UPDATE 子句,将被忽略)。该句法可以创建一个 column;但不创建任何索引或关键字。如果用该句法定义 InnoDB 表,将会导致错误。你可以使用作为联接列创建的列,如下所示:CREATE TABLE person ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, name CHAR(60) NOT NULL, PRIMARY KEY (id));CREATE TABLE shirt ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, style ENUM(t-shirt, polo, dress) NOT NULL, 网易技术部 42
  43. 43. www.163.com color ENUM(red, blue, orange, white, black) NOT NULL, owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id), PRIMARY KEY (id));INSERT INTO person VALUES (NULL, Antonio Paz);SELECT @last := LAST_INSERT_ID();INSERT INTO shirt VALUES(NULL, polo, blue, @last),(NULL, dress, white, @last),(NULL, t-shirt, blue, @last);INSERT INTO person VALUES (NULL, Lilliana Angelovska);SELECT @last := LAST_INSERT_ID();INSERT INTO shirt VALUES(NULL, dress, orange, @last),(NULL, polo, red, @last),(NULL, dress, blue, @last),(NULL, t-shirt, white, @last);SELECT * FROM person;+----+---------------------+| id | name |+----+---------------------+| 1 | Antonio Paz || 2 | Lilliana Angelovska | 网易技术部 43
  44. 44. www.163.com+----+---------------------+SELECT * FROM shirt;+----+---------+--------+-------+| id | style | color | owner |+----+---------+--------+-------+| 1 | polo | blue | 1|| 2 | dress | white | 1|| 3 | t-shirt | blue | 1|| 4 | dress | orange | 2|| 5 | polo | red | 2|| 6 | dress | blue | 2|| 7 | t-shirt | white | 2|+----+---------+--------+-------+SELECT s.* FROM person p, shirt s WHERE p.name LIKE Lilliana% AND s.owner = p.id AND s.color <> white;+----+-------+--------+-------+| id | style | color | owner |+----+-------+--------+-------+| 4 | dress | orange | 2|| 5 | polo | red | 2|| 6 | dress | blue | 2|+----+-------+--------+-------+ 按照这种方式使用,REFERENCES 子句不会显示在 SHOW CREATE TABLE 或 DESCRIBE 的输出中: 网易技术部 44
  45. 45. www.163.comSHOW CREATE TABLE shirtG*************************** 1. row ***************************Table: shirtCreate Table: CREATE TABLE `shirt` (`id` smallint(5) unsigned NOT NULL auto_increment,`style` enum(t-shirt,polo,dress) NOT NULL,`color` enum(red,blue,orange,white,black) NOT NULL,`owner` smallint(5) unsigned NOT NULL,PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 在列定义中,按这种方式使用 REFERENCES 作为注释或“提示”适用于表 MyISAM 和BerkeleyDB。 网易技术部 45
  46. 46. www.163.com 第二篇 优化篇第 11 章 SQL 优化11.1 优化 SQL 的一般步骤 11.1.1 通过 show status 和应用特点了解各种 SQL 的执行 频率 通过 SHOW STATUS 可以提供服务器状态信息,也可以使用 mysqladmin extended- status 命令获得。SHOW STATUS 可以根据需要显示 session 级别的统计结果和 global 级别的统计结果。 以下几个参数对 Myisam 和 Innodb 存储引擎都计数: 1. Com_select 执行 select 操作的次数,一次查询只累加 1; 2. Com_insert 执行 insert 操作的次数,对于批量插入的 insert 操作,只累加一次; 3. Com_update 执行 update 操作的次数; 4. Com_delete 执行 delete 操作的次数; 以下几个参数是针对 Innodb 存储引擎计数的,累加的算法也略有不同: 1. Innodb_rows_read select 查询返回的行数; 2. Innodb_rows_inserted 执行 Insert 操作插入的行数; 3. Innodb_rows_updated 执行 update 操作更新的行数; 4. Innodb_rows_deleted 执行 delete 操作删除的行数; 通过以上几个参数,可以很容易的了解当前数据库的应用是以插入更新为主还是 以查询操作为主,以及各种类型的 SQL 大致的执行比例是多少。对于更新操作的计数 , 是对执行次数的计数,不论提交还是回滚都会累加。 对于事务型的应用,通过 Com_commit 和 Com_rollback 可以了解事务提交和回滚 的情况,对于回滚操作非常频繁的数据库,可能意味着应用编写存在问题。 此外,以下几个参数便于我们了解数据库的基本情况: 网易技术部 46
  47. 47. www.163.com 1. Connections 试图连接 Mysql 服务器的次数 2. Uptime 服务器工作时间 3. Slow_queries 慢查询的次数 11.1.2 定位执行效率较低的 SQL 语句: 可以通过以下两种方式定位执行怰ed/reA

×