登入帳戶  | 訂單查詢  | 購物車/收銀台(0) | 在線留言板  | 付款方式  | 聯絡我們  | 運費計算  | 幫助中心 |  加入書簽
會員登入   新用戶註冊
HOME新書上架暢銷書架好書推介特價區會員書架精選月讀2023年度TOP分類閱讀雜誌 香港/國際用戶
最新/最熱/最齊全的簡體書網 品種:超過100萬種書,正品正价,放心網購,悭钱省心 送貨:速遞 / 物流,時效:出貨後2-4日

2024年10月出版新書

2024年09月出版新書

2024年08月出版新書

2024年07月出版新書

2024年06月出版新書

2024年05月出版新書

2024年04月出版新書

2024年03月出版新書

2024年02月出版新書

2024年01月出版新書

2023年12月出版新書

2023年11月出版新書

2023年10月出版新書

2023年09月出版新書

『簡體書』MySQL技术精粹---架构、高级特性、性能优化与集群实战

書城自編碼: 2700747
分類: 簡體書→大陸圖書→計算機/網絡數據庫
作者: 张工厂
國際書號(ISBN): 9787302420439
出版社: 清华大学出版社
出版日期: 2015-12-01
版次: 1 印次: 1
頁數/字數: 405页
書度/開本: 16 釘裝: 平装

售價:NT$ 656

我要買

share:

** 我創建的書架 **
未登入.



新書推薦:
读书是一辈子的事(2024年新版)
《 读书是一辈子的事(2024年新版) 》

售價:NT$ 352.0
乐道文库·什么是秦汉史
《 乐道文库·什么是秦汉史 》

售價:NT$ 367.0
汉娜·阿伦特与以赛亚·伯林 : 自由、政治与人性
《 汉娜·阿伦特与以赛亚·伯林 : 自由、政治与人性 》

售價:NT$ 500.0
女性与疯狂(女性主义里程碑式著作,全球售出300万册)
《 女性与疯狂(女性主义里程碑式著作,全球售出300万册) 》

售價:NT$ 500.0
药食同源中药鉴别图典
《 药食同源中药鉴别图典 》

售價:NT$ 305.0
设计中的比例密码:建筑与室内设计
《 设计中的比例密码:建筑与室内设计 》

售價:NT$ 398.0
冯友兰和青年谈心系列:看似平淡的坚持
《 冯友兰和青年谈心系列:看似平淡的坚持 》

售價:NT$ 254.0
舍不得星星:全2册
《 舍不得星星:全2册 》

售價:NT$ 356.0

建議一齊購買:

+

NT$ 656
《 PaaS实现与运维管理:基于Mesos +Docker+ELK的实战指南 》
+

NT$ 656
《 奔跑吧Ansible 》
+

NT$ 573
《 Python算法教程 》
+

NT$ 413
《 Kali Linux无线网络渗透测试详解 》
+

NT$ 413
《 设计模式解析 第2版 修订版 》
+

NT$ 739
《 深入理解MariaDB与MySQL 》
編輯推薦:
将*实用的MySQL技术融入到每个案例中,教你快速成为MySQL数据库*高手
內容簡介:
本书针对 MySQL中高级用户,详细讲解 MySQL高级使用技术。书中详解了每一个知识点以及数据库操作的方法和技巧。本书注重实战操作,帮助读者循序渐进地掌握 MySQL中的各项高级技术。
本书主要包括 MySQL架构介绍、MySQL权限与安全、MySQL备份与还原、MySQL的高级特性、MySQL锁定机制、使用 MySQL Workbench管理数据库、SQL性能优化、MySQL服务器性能优化、MySQL性能监控、MySQL Replication、MySQL Cluster实战、企业中 MySQL的高可用架构实战。同时,本书还提供了所有示例的源码,读者可以直接查看和调用。
本书适合有一定基础的 MySQL数据库学习者,MySQL数据库开发人员和 MySQL数据库管理人员,同时也能作为高等院校和培训学校相关专业师生的教学参考用书。
目錄
目 录
第1章 MySQL架构介绍........... 1
1.1 MySQL架构... 1
1.1.1 MySQL物理文件的组成........... 2
1.1.2 MySQL各逻辑块简介................ 4
1.1.3 MySQL各逻辑块协调工作....... 6
1.2 MySQL存储引擎概述....... 7
1.3 MySQL各种存储引擎的特性.............. 10
1.3.1 MyISAM............... 10
1.3.2 InnoDB................... 12
1.3.3 MEMORY.............. 15
1.3.4 MERGE................... 18
1.3.5 BerkeleyDB存储引擎............... 20
1.4 MySQL工具. 21
1.4.1 MySQL命令行实用程序......... 21
1.4.2 MySQL Workbench................... 33
1.5 本章小结....... 34
第2章
MySQL权限与安全..... 35
2.1 权 限 表....... 35
2.1.1 user表.................... 35
2.1.2 db表和host表.... 37
2.1.3 tables_priv表和columns_priv表................ 39
2.1.4 procs_priv表........ 40
2.2 账户管理....... 41
2.2.1 登录和退出MySQL服务器.... 41
2.2.2 新建普通用户....... 43
2.2.3 删除普通用户....... 47
2.2.4 root用户修改自己的密码....... 48
2.2.5 root用户修改普通用户密码... 50
2.2.6 普通用户修改密码.................... 51
2.2.7 root用户密码丢失的解决办法..................... 51
2.3 权限管理....... 53
2.3.1 MySQL的各种权限.................. 53
2.3.2 授权.. 55
2.3.3 收回权限............... 57
2.3.4 查看权限............... 58
2.4 访问控制....... 59
2.4.1 连接核实阶段....... 59
2.4.2 请求核实阶段....... 60
2.5 MySQL的安全问题.......... 61
2.5.1 操作系统相关的安全问题....... 61
2.5.2 数据库相关的安全问题........... 62
2.6 使用SSL安全连接........... 71
2.7 综合管理用户权限............ 77
2.8 小结................ 80
第3章
数据备份与还原.......... 81
3.1 数据备份....... 81
3.1.1 使用mysqldump命令备份...... 81
3.1.2 直接复制整个数据库目录....... 88
3.1.3 使用mysqlhotcopy工具快速备份.............. 88
3.2 数据还原....... 89
3.2.1 使用MySQL命令还原............. 89
3.2.2 直接复制到数据库目录........... 90
3.2.3 mysqlhotcopy快速恢复........... 90
3.3 数据库迁移... 90
3.3.1 相同版本的MySQL数据库之间的迁移.... 91
3.3.2 不同版本的MySQL数据库之间的迁移.... 91
3.3.3 不同数据库之间的迁移........... 92
3.4 表的导出和导入................ 92
3.4.1 使用SELECTINTO OUTFILE导出文本文件............... 92
3.4.2 用mysqldump命令导出文本文件............... 95
3.4.3 用MySQL命令导出文本文件98
3.4.4 使用LOAD DATA INFILE方式导入文本文件............. 101
3.4.5 使用mysqlimport命令导入文本文件....... 103
3.5 综合实例数据的备份与恢复...... 105
3.6 小结.............. 109
第4章
MySQL的高级特性... 110
4.1 MySQL 查询缓存........... 110
4.1.1 认识查询缓存..... 110
4.1.2 监控和维护查询缓存.............. 115
4.1.3 如何检查缓存命中率.............. 117
4.1.4 优化查询缓存..... 118
4.2 合并表和分区表.............. 119
4.2.1 合并表.................. 119
4.2.2 分区表.................. 121
4.3 事务控制..... 131
4.4 MySQL分布式事务........ 135
4.4.1 了解分布式事务的原理......... 135
4.4.2 分布式事务的语法.................. 136
4.5 小结.............. 137
第5章
MySQL锁定机制....... 138
5.1 MySQL锁定机制概述... 138
5.2 MyISAM表级锁............. 143
5.2.1 MyISAM表级锁的锁模式.... 143
5.2.2 获取MyISAM表级锁的争用情况............ 145
5.2.3 MyISAM表级锁加锁方法.... 146
5.2.4 MyISAM Concurrent Insert的特性........... 148
5.2.5 MyISAM表锁优化建议........ 150
5.3 InnoDB行级锁................ 150
5.3.1 InnoDB行级锁模式................ 150
5.3.2 获取InnoDB行级锁的争用情况............... 155
5.3.3 InnoDB行级锁的实现方法... 157
5.3.4 间隙锁(Net-Key锁)........... 162
5.3.5 InnoDB 在不同隔离级别下加锁的差异.. 163
5.3.6 InnoDB 存储引擎中的死锁.. 164
5.3.7 InnoDB行级锁优化建议....... 166
5.4 小结.............. 167
第6章
使用MySQL Workbench 管理数据库.................... 168
6.1 MySQL Workbench简介..................... 168
6.1.1 MySQL Workbench 的概述.. 168
6.1.2 MySQL Workbench 的优势.. 169
6.1.3 MySQL Workbench 的安装.. 169
6.2 SQL Development的基本操作........... 171
6.2.1 创建数据库连接171
6.2.2 创建新的数据库173
6.2.3 创建和删除新的数据表......... 174
6.2.4 添加、修改表记录.................. 177
6.2.5 查询表记录......... 178
6.2.6 修改表结构......... 178
6.3 Data Modeling的基本操作................. 179
6.3.1 建立ER模型...... 179
6.3.2 导入ER模型...... 184
6.4 Server Administration的基本操作..... 185
6.4.1 管理MySQL用户................... 186
6.4.2 备份MySQL数据库............... 188
6.4.3 还原MySQL数据库............... 191
6.5 小结.............. 192
第7章
SQL性能优化........... 193
7.1 优化简介..... 193
7.2 MySQL Query Optimizer概述............. 194
7.3 SQL 语句优化的基本思路.................. 194
7.4 利用EXPLAIN分析查询语句............ 196
7.4.1 EXPLAIN语句的基本语法.... 196
7.4.2 EXPLAIN语句分析实例........ 208
7.5 利用Profiling分析查询语句............... 212
7.6 合理地使用索引.............. 216
7.6.1 索引对查询速度的影响......... 216
7.6.2 如何使用索引查询.................. 217
7.7 不同类型SQL语句优化方法............. 220
7.7.1 优化INSERT语句................... 220
7.7.2 优化ORDER BY语句............. 221
7.7.3 优化GROUP BY语句............. 222
7.7.4 优化嵌套查询..... 223
7.7.5 优化OR条件...... 224
7.7.6 优化插入记录的速度.............. 226
7.8 优化数据库结构.............. 228
7.8.1 将字段很多的表分解成多个表.................. 228
7.8.2 增加中间表......... 230
7.8.3 增加冗余字段..... 231
7.9 分析表、检查表和优化表................... 232
7.9.1 分析表.................. 232
7.9.2 检查表.................. 233
7.9.3 优化表.................. 233
7.10 小结............ 234
第8章
MySQL服务器性能优化.................. 235
8.1 MySQL源码安装的性能优化............ 235
8.2 MySQL服务器配置优化..................... 238
8.2.1 查看性能参数的方法.............. 238
8.2.2 key_buffer_size的设置.......... 243
8.2.3 table_cache的设置................. 246
8.2.4 内存参数的设置248
8.2.5 日志和事务参数的设置......... 252
8.2.6 存储和IO相关参数的设置.. 253
8.2.7 其他重要参数的设置.............. 254
8.3 MySQL日志设置优化... 256
8.4 MySQL IO设置优化..... 257
8.5 MySQL并发设置优化... 259
8.6 线程、Table Cache和临时表的优化261
8.6.1 线程的优化......... 261
8.6.2 关于table_cache相关的优化..................... 262
8.6.3 关于临时表的优化.................. 263
8.7 小结.............. 264
第9章
MySQL 性能监控...... 265
9.1 基本监控系统方法.......... 265
9.1.1 ps命令................. 265
9.1.2 top命令............... 266
9.1.3 vmstat命令......... 268
9.1.4 mytop命令.......... 269
9.1.5 sysstat工具........ 272
9.2 开源监控利器Nagios实战................. 277
9.2.1 安装Nagios之前的准备工作..................... 277
9.2.2 安装Nagios主程序................ 279
9.2.3 整合Nagios到Apache服务280
9.2.4 安装Nagios插件包................ 284
9.2.5 监控服务器的CPU、负载、磁盘IO使用情况........... 286
9.2.6 配置Nagios监控MySQL服务器.............. 291
9.3 MySQL监控利器Cacti实战.............. 293
9.3.1 Cacti工具的安装..................... 294
9.3.2 Cacti监控MySQL服务器..... 299
9.4 小结.............. 304
第10章
MySQL Replication. 305
10.1 MySQL Replication概述.................... 305
10.2 Windows环境下的MySQL主从复制................. 306
10.2.1 复制前的准备工作................ 306
10.2.2 Windows环境下实现主从复制............... 306
10.2.3 Windows环境下主从复制测试............... 314
10.3 Linux环境下的MySQL复制............ 315
10.3.1 下载并安装MySQL 5.6........ 315
10.3.2 单机主从复制前的准备工作..................... 316
10.3.3 mysqld_multi实现单机主从复制............. 320
10.3.4 不同服务器之间实现主从复制................ 328
10.3.5 MySQL 主要复制启动选项329
10.3.6 指定复制的数据库或者表... 330
10.4 查看Slave的复制进度338
10.5 日常管理和维护............ 339
10.5.1 了解服务器的状态................ 339
10.5.2 服务器复制出错的原因....... 340
10.6 切换主从服务器............ 343
10.7 小结............ 347
第11章
MySQL Cluster实战348
11.1 MySQL Cluster概述..... 348
11.1.1 MySQL Cluster基本概念..... 348
11.1.2 理解MySQL Cluster节点.... 349
11.2 Linux环境下MySQL Cluster安装和配置........... 350
11.2.1 安装MySQL Cluster 7.2.8软件................. 352
11.2.2 管理节点配置步骤................ 357
11.2.3 配置SQL节点和数据节点.. 358
11.3 管理MySQL Cluster..... 358
11.3.1 Cluster的启动.. 358
11.3.2 Cluster的测试.. 360
11.3.3 Cluster的关闭.. 363
11.4 维护MySQL Cluster..... 363
11.4.1 Cluster的日志的管理........... 366
11.4.2 Cluster的联机备份............... 367
11.4.3 Cluster的数据恢复............... 368
11.5 Windows操作系统中配置Cluster.. 369
11.6 小结............ 374
第12章
企业中MySQL的高可用架构........ 375
12.1 MySQL高可用的简单介绍............... 375
12.2 MySQL主从复制.......... 375
12.2.1 MySQL主从架构设计.......... 376
12.2.2 配置环境........... 376
12.2.3 服务器的安装配置................ 376
12.2.4 LVS的安装配置..................... 379
12.3 MySQL DRBD HA...... 381
12.3.1 什么是DRBD... 381
12.3.2 MySQL DRBD HA架构设计.................. 382
12.3.3 配置环境........... 382
12.3.4 安装配置Heartbeat............... 383
12.3.5 安装配置DRBD..................... 385
12.4 Lvs Keepalived MySQL 单点写入主主同步方案.................. 388
12.4.1 配置环境........... 388
12.4.2 Lvs Keepalived的安装........ 393
12.4.3 Lvs Keepalived的配置........ 394
12.4.4 Master和Backup的启动.... 397
12.5 MMM高可用MySQL方案.............. 397
12.5.1 MMM的架构... 398
12.5.2 配置环境........... 398
12.5.3 MMM的安装... 402
12.5.4 Monitor服务器的配置......... 402
12.5.5 各个数据库服务器的配置... 404
12.5.6 MMM的管理... 404
12.6 小结 405
內容試閱
第 4 章 MySQL的高级特性


本章主要讲解MySQL的一些高级特性,其中包括MySQL查询缓存,查询缓存会存储一个SELECT查询的文本与被传送到客户端的相应结果。如果执行相同的一个SQL语句,MySQL数据库会将数据缓存起来以供下次直接使用,MySQL数据库以此优化查询缓存来提高缓存命中率。
MySQL 5.1及高版本支持分区表(partitioned table),分区表的使用大大增加了MySQL执行效率。另外本章还讲解到MySQL数据库事务,其中包括分布式事务的原理和语法。MySQL分布式事务涉及多个事务性的活动,本章介绍分布式事务使用的同时也涉及MySQL分布式事务技术存在的一些漏洞。
4.1 MySQL 查询缓存
MySQL服务器有一个重要特征是查询缓存。缓存机制简单地说就是缓存SQL语句和查询的结果,如果运行相同的SQL语句,服务器会直接从缓存中取到结果,而不需要再去解析和执行SQL语句。查询缓存会存储最新数据,而不会返回过期数据。当数据被修改后,在查询缓存中的任何相关数据均被清除。对于频繁更新的表,查询缓存是不适合的;而对于一些不经常改变数据且有大量相同SQL查询的表,查询缓存会提高很大的性能。
4.1.1 认识查询缓存
MySQL数据库设置了查询缓存后,当服务器接收到一个和之前同样的查询时,会从查询缓存中检索查询结果,而不是直接分析并检索查询。
在MySQL数据库中,使用查询缓存功能的具体操作步骤如下。
设置query_cache_type为ON,命令如下:
mysql set session query_cache_type=ON;
Query OK, 0 rows affected 0.01 sec
查看查询缓存功能是否被开启,命令如下:
mysql select @@query_cache_type;
--------------------
| @@query_cache_type |
--------------------
| ON
|
--------------------
1 row in set 0.00 sec
从结果可以看出,查询缓存功能已经被开启。
如果要禁用查询缓存功能,直接执行命令如下:
mysql
set session query_cache_type=OFF;
查看系统变量have_query_cache是否为YES,该参数表示MySQL的查询缓存是否可用,查看命令如下。
mysql show variables like ''have_query_cache'';
------------------ -------
| Variable_name
| Value |
------------------ -------
| have_query_cache | YES |
------------------ -------
1 row in set 0.00 sec
查询系统变量query_cache_size的大小,该参数表示数据库分配给查询缓存的内存大小,如果该参数的值设置为0,那么查询缓存功能将不起任何作用。
mysql select @@global.query_cache_size;
---------------------------
| @@global.query_cache_size |
---------------------------
| 0 |
---------------------------
1 row in set 0.00 sec
从结果可知,系统默认的query_cache_size参数值是0。
设置系统变量query_cache_size的大小,命令如下:
mysql set @@global.query_cache_size=1000000;
Query OK, 0 rows affected 0.00 sec
查询系统变量query_cache_size设置后的大小,命令如下:
mysql select @@global.query_cache_size;
---------------------------
| @@global.query_cache_size |
---------------------------
| 1000000 |
---------------------------
1 row in set 0.00 sec
如果需要将该参数永久修改,需要修改etcmy.cnf配置文件,添加该参数的选项,添加如下:
[mysqld]
port = 3306
query_cache_size = 1000000

如果查询结果很大,也可能缓存不了,需要设置query_cache_limit参数的值,该参数用来设置查询缓存的最大值,该值默认是1MB。
查询该参数的值的命令如下:
mysql select @@global.query_cache_limit;
----------------------------
| @@global.query_cache_limit |
----------------------------
|
1000000 |
----------------------------
1 row in set 0.00 sec
设置query_cache_limit参数值的大小,命令如下:
mysql set @@global.query_cache_limit=2000000;
Query OK, 0 rows affected 0.00 sec
如果需要将该参数永久修改,需要修改etcmy.cnf配置文件,添加该参数的选项,添加如下:
[mysqld]
port = 3306
query_cache_size=1000000
query_cache_limit=2000000

通过以上步骤的设置,MySQL数据库已经成功地开启查询缓存功能。在实际工作中,需要关注查询缓存的使用效率和性能,可以使用SHOW VARIABLES命令查询缓存的相关参数,命令如下。
mysql show variables like ''%query_cache%'';
------------------------------ ---------
| Variable_name | Value |
------------------------------ ---------
| have_query_cache
| YES |
| query_cache_limit | 1000000 |
| query_cache_min_res_unit | 4096
|
| query_cache_size | 0 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
------------------------------ ---------
6 rows in set 0.00 sec
下面具体介绍查询缓存功能相关参数的含义。
l have_query_cache用来设置是否支持查询缓存区,YES表示支持查询缓存区。
l query_cache_limit 用来设置MySQL可以缓存的最大结果集,大于此值的结果集不会被缓存,该参数默认值是1MB。
l query_cache_min_res_unit用来设置分配内存块的最小体积。每次给查询缓存结果分配内存的大小,默认分配4096个字节。如果此值较小,那么会节省内存,但是这样会使系统频繁分配内存块。
l query_cache_size 用来设置查询缓存使用的总内存字节数,必须是1024字节的倍数。
l query_cache_type用来设置是否启用查询缓存。如果设置为OFF,表示不进行缓存;如果设置为ON,表示除了SQL_NO_CACHE的查询以外,缓存所有的结果;如果设置为DEMAND,表示仅缓存SQL_CACHE的查询。
l query_cache_wlock_invalidate 用来设置是否允许在其他连接处于lock状态时,使用缓存结果,默认是OFF,不会影响大部分应用。在默认情况下,一个查询中使用的表即使被LOCK TABLES命令锁住了,查询也能被缓存下来。可以通过设置该参数来关闭这个功能。
下面通过一个简单的例子来了解查询缓存的过程。
设置缓存内存大小为10240字节,开启查询缓存功能,命令如下。
mysql set global query_cache_size=10240;
Query OK, 0 rows affected 0.00 sec
mysql set session query_cache_type=ON;
Query OK, 0 rows affected 0.01 sec
查询t表中总共记录的条数,命令如下。
mysql use test;
Database changed
mysql show tables;
----------------
| Tables_in_test |
----------------
| rep_t1
|
| rep_t2
|
| t
|
----------------
3 rows in set 0.00 sec
mysql use test;
Database changed
mysql select count* from t;
----------
| count* |
----------
| 64 |
----------
1 row in set 0.05 sec
查询在缓存中命中的累计次数,命令如下:
mysql show status like ''Qcache_hits'';
--------------- -------
| Variable_name | Value |
--------------- -------
| Qcache_hits
| 0 |
--------------- -------
1 row in set 0.00 sec
从结果可知,第一次查询发现查询缓存累计命中的数是0。
再次查询t表的总的记录数据,然后查询缓存累计命中数,命令如下:
mysql select count* from t;
----------
| count* |
----------
| 64 |
----------
1 row in set 0.00 sec
mysql show status like ''Qcache_hits'';
--------------- -------
| Variable_name | Value |
--------------- -------
| Qcache_hits
| 1 |
--------------- -------
1 row in set 0.00 sec
从结果可知,第二次查询后发现该缓存累计命中数已经发生了变化,此时查询出参数Qcache_hists的值是1,表示查询直接从缓存中获取结果,不需要再去解析SQL语句。
连续两次查询t表的总的记录数据,然后再查询缓存累计命中数,此时会发现缓存累计命中数已经变成了3,本次查询也是直接从缓存中取到结果,执行命令如下。
mysql select count* from t;
----------
| count* |
----------
| 64 |
----------
1 row in set 0.00 sec

mysql select count* from t;
----------
| count* |
----------
| 64 |
----------
1 row in set 0.00 sec

mysql show status like ''Qcache_hits'';
--------------- -------
| Variable_name | Value |
--------------- -------
| Qcache_hits
| 3 |
--------------- -------
1 row in set 0.00 sec
增加了一条记录到t表,插入数据后,跟该表所有相关的查询缓存就会被清空掉,然后重新查询t表的总的记录,此时发现缓存累计命中数没有发生变化,说明本次查询没有直接从缓存中取到数据,执行命令如下。
mysql insert into t values2;
Query OK, 1 row affected 0.00 sec
mysql select count* from t;
----------
| count* |
----------
| 65 |
----------
1 row in set 0.00 sec

mysql show status like ''Qcache_hits'';
--------------- -------
| Variable_name | Value |
--------------- -------
| Qcache_hits
| 3 |
--------------- -------
1 row in set 0.00 sec
重新查询t表的总的记录,此时发现缓存累计命中数发生了变化,说明缓存继续起作用了,执行命令如下。
mysql select count* from t;
----------
| count* |
----------
| 65 |
----------
1 row in set 0.00 sec

mysql show status like ''Qcache_hits'';
--------------- -------
| Variable_name | Value |
--------------- -------
| Qcache_hits
| 4 |
--------------- -------
1 row in set 0.00 sec
通过上面的例子不难发现,查询缓存适合更新不频繁的表,当表更改后,查询缓存值的相关条目被清空。
4.1.2 监控和维护查询缓存
在日常工作中,经常使用以下命令监控和维护查询缓存。
(1)flush query cache:该命令用于整理查询缓存,以便更好地利用查询缓存的内存,这个命令不会从缓存中移除任何查询结果。命令运行如下:
mysql flush query
cache;
Query OK, 0 rows
affected 0.00 sec
(2)reset query cache:该命令用于移除查询缓存中所有的查询结果。命令运行如下:
mysql reset
query cache;
Query OK, 0 rows affected 0.00 sec
(3)show status like ''Qcache%'':该命令可以监视查询缓存的使用状况,可以计算出缓存命中率。命令运行如下:
mysql show status like ''Qcache%'';
------------------------- ---------
| Variable_name | Value |
------------------------- ---------
| Qcache_free_blocks | 4984
|
| Qcache_free_memory | 30097400|
| Qcache_hits | 24 |
| Qcache_inserts
| 4342 |
| Qcache_lowmem_prunes | 41224
|
| Qcache_not_cached | 2654
|
| Qcache_queries_in_cache | 20527 |
| Qcache_total_blocks | 46362
|
------------------------- ---------
8 rows in set 0.00 sec
结果中的性能监控参数含义如表4-1所示。
表4-1 查询缓存的性能监控参数含义





变量


含义




Qcache_queries_in_cache


在缓存中已注册的查询数目




Qcache_inserts


被加入到缓存中的查询数目




Qcache_hits


缓存采样数的数目




Qcache_lowmem_prunes


因为缺少内存而被从缓存中删除的查询数目




Qcache_not_cached


没有被缓存的查询数目




Qcache_free_memory


查询缓存的空闲内存总数




Qcache_free_blocks


查询缓存中的空闲内存块的数目




Qcache_total_blocks


查询缓存中的块的总数目





如果空闲内存块是总内存块的一半左右,则表示存在严重的内存碎片。通常使用flush
query cache命令整理碎片,然后采用reset query cache命令清理查询缓存。
如果碎片很少,但是缓存命中率很低,则说明设置的缓存内存空间过小,服务器频繁删除旧的查询缓存,腾出空间,以保存新的查询缓存,此时,参数Qcache_lowmeme_preunes状态值将会增加,如果此值增加过快,可能是有以下原因造成:
l 如果存在大量空闲块,则是因为碎片的存在而引起的。
l 空闲内存块较少,可以适当地增加缓存大小。
4.1.3 如何检查缓存命中率
MySQL检查缓存命中率的方式十分简单快捷。缓存就是一个查找表(Lookup
Table)。查找的键就是查询文本﹑当前数据库﹑客户端协议的版本,以及其他少数会影响实际查询结果的因素的哈希值。
下面主要学习MySQL数据库中缓存的管理技巧,以及如何合理配置MySQL数据库缓存,提高缓存命中率。
首先,在配置数据库客户端或者是第三方工具与服务器连接时,应该保证数据库客户端的字符集跟服务器的字符集保持一致。在实际工作中,经常发现客户端配置的字符集和服务器字符集兼容没有完全一致,即使此时客户端没有出现乱码情况,查询数据可能就因为字符集不同的原因而没有被数据库缓存起来。
其次,为了提高数据库缓存的命中率,应该在客户端和服务器端采用一样的SQL语句。从数据库缓存的角度考虑,数据库查询SQL的语句是不区分大小写的,比如第一个查询语句采用大写语句,第二个查询语句采用小写语句,但对于缓存来讲,大小写不同的SQL语句会被当作不同的查询语句。
查询缓存不会存储不确定结果的查询,任何一个包含不确定函数比如NOW或CURRENT_DATE的查询不会被缓存。同样地,CURRENT_USER或CONNECTION_ID这些由不同用户执行,将会产生不同的结果的查询也不会被缓存。实际上,查询缓存不会缓存引用了用户自定义函数﹑存储函数﹑用户自定义变量﹑临时表的查询。
查询缓存只是发生在服务器第一次接收到SQL查询语句,然后把查询结果缓存起来,对于查询中的子查询、视图查询和存储过程查询都不能缓存结果,对于预存储语句同样也不能使用缓存。
使用查询缓存有利也有弊。一方面,查询缓存可以使查询变得更加高效,改善了MySQL服务器的性能;另一方面,查询缓存本身也需要消耗系统IO资源,所以说,查询缓存也增加了服务器额外的开销,主要体现以下几个方面。
l MySQL服务器在进行查询之前首先会检测查询缓存是否存在相同的查询条目。
l MySQL服务器在进行查询操作时,如果缓存中没有相同的查询条目,会将查询的结果缓存到查询缓存,这个过程也需要开销系统资源。
l 如果数据库表发生增加操作,MySQL服务器查询缓存中相对应的查询结果将会无效,这时同样需要消耗系统资源。
除了注意以上问题可以提高查询缓存的命中率外,还可以通过分区表提高缓存的命中率。通常我们会遇到这样的问题,对于某张表某个时间段内的数据更新比较频繁,其他时间段查询和更新比较多,一旦数据表数据执行更新操作,那么查询缓存中的信息将会清空,查询缓存的命中率不会很高。此时,可以考虑采用分区表,把某个时间段的数据存放在一个单独的分区表中,这样可以提高服务器的查询缓存的命中率。
4.1.4 优化查询缓存
MySQL查询缓存优化方案的大致步骤如图4-1所示。

图4-1 MySQL优化查询缓存的大致步骤
优化查询缓存通常需要注意如下几点。
(1)在数据库设计的时候,尽量不要使用一张比较大的表,可以使用很多小的表,这样可以提高数据查询缓存的效率。
(2)在对数据库进行写操作的时候,尽量一次性写入。因为如果逐个写入操作,每次写操作都会让数据库缓存功能失效或清理缓存数据,此时服务器可能会挂起相当长时间。
(3)尽量不要在数据库或者表的基础上控制查询缓存,可以采用SQL_CACHE 和SQL_NO_CACHE来决定是否使用缓存查询。
(4)可以基于某个连接来运行或禁止缓存,可以通过用适当的值设定query_cache_size 来开启或关闭对某个连接的缓存。
(5)对于包含很多写入任务的应用程序,关闭查询缓存功能可以改进服务器性能。
(6)禁用查询缓存的时候可以将query_cache_size参数设置为0,这样就不会消耗任何内存。
(7)如果想少数查询使用缓存,而多数查询都不使用查询缓存,此时可以将全局变量query_cache_type 设置为DEMAND,然后可以在想使用缓存功能的语句后面加上SQL_CACHE,不想使用缓存查询的语句后面可以加上SQL_NO_CACHE,这样可以通过语句来控制查询缓存,提高缓存的使用率。
4.2 合并表和分区表
分区表是MySQL 5.1的新特性,而合并表已经有很长的历史了,合并表和分区表的概念比较相似,合并表是将许多个MyISAM表合并成一个续表,类似于使用UNION语句将多个表合并,合并表不是真的创造一个真正的表,它就像一个用于放置相似表的容器。而分区表则通过一些特殊的语句,创建独立的空间,事实上创建分区表的每个分区都是有索引的独立表。分区看上去像一个单独的表,MySQL在对分区表和合并表的实现上有很多共通之处。
4.2.1 合并表
MySQL的合并表可以把多个结果相同的表合并成为一个续表,事实上是容纳真正表的容器,可以使用UNION语句来创建表,下面是一个合并表的例子。
创建数据存储引擎是MyISAM类型的表mtable1和mtable2,命令如下:
mysql create table
mtable1
-
data int not null primary key
- engine=myisam;
Query OK, 0 rows
affected 0.03 sec

mysql create table
mtable2
-
data int not null primary key
- engine=myisam;
Query OK, 0 rows
affected 0.02 sec
向表mtable1和mtable2中插入数据,命令如下:
mysql insert into
mtable1 values1,2,3;
Query OK, 3 rows
affected 0.00 sec
Records: 3 Duplicates: 0
Warnings: 0

mysql insert into
mtable2 values2,3,4;
Query OK, 3 rows
affected 0.00 sec
Records: 3 Duplicates: 0
Warnings: 0
使用UNION语句创建表mtable1和mtable2的合并表mergtable,命令如下:
mysql create table
mergtable
-
data int not null primary key
- engine=merge union=mtable1,mtable2
insert_method=last;
Query OK, 0 rows
affected 0.03 sec
insert_method=last的含义是,如果向表mergtable中插入一条记录,那么就将这条记录插入到合并表所合并的最后一个表里面,以上例子就是将记录插入到mtable2表中。
查询合并表mergtable的信息,命令如下:
mysql select *from
mergtable;
------
| data |
------
| 1 |
| 2 |
| 2 |
| 3 |
| 3 |
| 4 |
------
6 rows in set 0.00
sec
值得注意的是合并表所包含的表列的数量和类型跟所合并的表的列的数量和类型都是一样的。同时也可以看到每个表的列有主键,这会导致合并表有重复的行,这是合并表的一个局限。
直接插入数据到mergtable中,命令如下:
mysql insert into
mergtable values5;
Query OK, 1 row
affected 0.00 sec
查询mtable1表中的数据是否发生变化,命令如下:
mysql select *
from mtable1;
------
| data |
------
| 1 |
| 2 |
| 3 |
------
3 rows in set 0.00
sec
从结果可以看出,数据没有发生变化。
查询mtable2表中的数据是否发生变化,命令如下:
mysql select *
from mtable2;
------
| data |
------
| 2 |
| 3 |
| 4 |
| 5 |
------
4 rows in set 0.00
sec
从结果可以看出,插入到合并表mergtable的一条数据记录已经插入到mtable2表中了。
删除表mtable1和mtabl2,命令如下:
mysql drop table
mtable1,mtable2;
Query OK, 0 rows
affected 0.00 sec
在linux环境查询mergtable,发生错误,命令如下:
mysql select * from
mergtable;
ERROR 114642502:
Tabletest.mtable1doesnt
exist;
值得注意的是,在Windows环境下的MySQL数据库做同样的操作,没有发生错误。
MySQL合并表的实现对性能有一定的影响,下面是一些需要注意的事项:
l 合并表看上去是一个表,事实上是逐个打开各个子表,这样的情况下,可能会因为缓存过多的表而导致超过MySQL缓存的最大设置。
l 创建合并表的CREATE语句不会检查子表是否兼容,如果创建了一个有效的合并表后对某个表进行了修改,那么合并表也会发生错误。
4.2.2 分区表
从MySQL 5.1版本开始支持数据表分区,通俗地讲,表分区是将一张大表,根据条件分割成若干小表。例如,某用户表的记录超过了600万条,那么就可以根据入库日期或者所在地将表分区。
笔者的数据库版本是5.0.89,此时需要安装MySQL 5.1以上版本,这里以安装mysql-5.6.10-linux-i686-glibc23为例,具体操作步骤如下:
将mysql-5.6.10-linux-i686-glibc23.tat.gz解压。
[root@localhost tools]# gunzip mysql-5.6.10-linux-i686-glibc23.tar.gz
[root@localhost tools]# tar -xvf mysql-5.6.10-linux-i686-glibc23.tar
开始安装MySQL程序。
[root@localhost mysql-5.6.10-linux-i686-glibc23]#
.scriptsmysql_install_db --user=root
修改etcmysql.cnf中数据库配置选项,具体设置如下:
###########################################################################
# The MySQL server
[mysqld_multi]
mysqld = usrlocalmysqlbinmysqld_safe
mysqladmin = usrlocalmysqlbinmysqladmin
#user = root
#password = root

[mysqld1]
port = 3306
socket = tmpmysql.sock
pid-file = usrlocalvarmysql1mysql1.pid
datadir = usrlocalvarmysql1
skip-locking
key_buffer = 16M
max_allowed_packet = 1M
query_cache_type = on
query_cache_size =
999424
table_cache = 64
sort_buffer_size =
512K
net_buffer_length = 8K
read_buffer_size =
256K
read_rnd_buffer_size =
512K
myisam_sort_buffer_size
= 8M
log-bin =
usrlocalvarmysql1mysql-bin.log
server-id = 1
[mysqld2]
port = 3307
socket = tmpmysql2.sock
pid-file = usrlocalvarmysql2mysql2.pid
datadir = usrlocalvarmysql2
skip-locking
key_buffer = 16M
max_allowed_packet = 1M
table_cache = 64
sort_buffer_size =
512K
net_buffer_length = 8K
read_buffer_size =
256K
read_rnd_buffer_size =
512K
myisam_sort_buffer_size
= 8M
server-id = 2
#replicate-do-table=test.rep_t1
#replicate-ignore-table=test.rep_t2
#replicate-do-db=test
#replicate-do-db=cc
#replicate-ignore-db=tt
log-bin =
usrlocalvarmysql2mysql-bin.log
[mysqld3]
port = 3308
socket = tmpmysql3.sock
pid-file = usrlocalvarmysql3mysql3.pid
datadir = usrlocalvarmysql3
skip-locking
key_buffer = 16M
max_allowed_packet = 1M
table_cache = 64
sort_buffer_size =
512K
net_buffer_length = 8K
read_buffer_size =
256K
read_rnd_buffer_size =
512K
myisam_sort_buffer_size
= 8M
server-id = 3

#ssl
#ssl-ca=etcmyqlnewcertsca-cert.pem
#ssl-cert=etcmysqlnewcertsserver-cert.pem
#ssl-key=etcmysqlnewcertsserver-key.pem
###########################################################################
[mysqld]
port = 3309
socket = tmpmysql.sock
skip-locking
key_buffer = 16M
max_allowed_packet = 1M
query_cache_size =
999424
table_cache = 64
sort_buffer_size =
512K
net_buffer_length = 8K
read_buffer_size =
256K
read_rnd_buffer_size =
512K
myisam_sort_buffer_size
= 8M
server-id = 1
启动MySQL,如下所示。
[root@localhost ~]#
mysql -u root
Welcome to the MySQL
monitor. Commands end with ; or \g.
Your MySQL connection
id is 1
Server version: 5.6.10-log
MySQL Community Server GPL

Type ''help;'' or ''\h''
for help. Type ''\c'' to clear the current input statement.

mysql
数据库分区是一种物理数据库设计技术,分区的主要目的是为了让某些特定的查询操作减少响应时间,同时对于应用来讲分区完全是透明的。MySQL的分区主要有两种形式:水平分区(Horizontal Partitioning)和垂直分区(Vertical Partitioning)。
水平分区(Horizontal Partitioning)是根据表的行进行分割,这种形式的分区一定是通过表的某个属性作为分割的条件,例如,某张表里面数据日期为2011年的数据和日期为2012年的数据分割开,就可以采用这种分区形式。
垂直分区(Vertical Partitioning)是通过对表的垂直划分来减少目标表的宽度,是某些特定的列被划分到特定的分区。
通常可以通过下面命令查看是否支持分区,命令如下:
mysql show
variables like ''%partition%'';
------------------- -------
| Variable_name | Value |
------------------- -------
| have_partitioning |
YES |
------------------- -------
1 row in set 0.01
sec
下面介绍MySQL各种分区表常用的操作案例。
1. RANGE分区
RANGE分区使用values
less than 操作符来进行定义,把连续且不相互重叠的字段分配给分区,命令如下。
mysql create table
emp
- empno varchar20 not null,
- empname varchar20,
-
deptno int,
- birthdate date,
- salary int
-
- partition by rangesalary
-
- partition p1 values less than1000,
- partition p2 values less than2000,
- partition p3 values less than3000
- ;
Query OK, 0 rows
affected 0.01 sec

mysql insert into
emp values1000,''kobe'',12,''1888-08-08'',1500;
Query OK, 1 row
affected 0.01 sec

mysql insert into
emp values1000,''kobe'',12,''1888-08-08'',3500;
ERROR 1526 HY000:
Table has no partition for value 3500
此时,按照工资级别(字段salary)进行表分区,partition
by range 的语法类似于switchcase的语法,如果salary小于1000,数据存储在p1分区;如果salary小于2000,数据存储在p2分区;如果salary小于3000,数据存储在p3分区。
上面插入的第二条数据工资级别(字段salary)为3500,此时没有分区用来存储该范围的数据,所以发生了错误。为了解决这种问题,加入PARTITION p4 VALUES LESS THAN MAXVALUE语句即可,命令如下。
mysql drop table emp;
Query OK, 0 rows affected 0.00 sec

mysql create table
emp
- empno varchar20 not null,
- empname varchar20,
- deptno int,
- birthdate date,
- salary int
-
- partition by rangesalary
-
- partition p1 values less than1000,
- partition p2 values less than2000,
- partition p3 values less than3000,
- partition p4 values less than
maxvalue
- ;
Query OK, 0 rows
affected 0.01 sec

mysql insert into emp
values1000,''kobe'',12,''1888-08-08'',1000;
Query OK, 1 row
affected 0.00 sec

mysql insert into
emp values1000,''durant'',12,''1888-08-08'',3500;
Query OK, 1 row
affected 0.00 sec
maxvalue 表示最大的可能的整数值。值得注意的是values less than子句中也可以使用一个表达式,不过表达式结果不能为NULL,下面按照日期进行分区,命令如下。
mysql create table
emp
- empno varchar20 not null,
- empname varchar20,
- deptno int,
- birthdate date,
- salary int
-
- partition by rangeyearbirthdate
-
partition p0 values less than1980,
-
partition p1 values less than1990,
-
partition p2 values less than2000,
-
partition p3 values less than maxvalue
- ;
Query OK, 0 rows
affected 0.01 sec
该方案中,生日1980年以前的员工信息存储在p0分区中,生日1990年以前的员工信息存储在p1分区中,生日2000年以前的员工信息存储在p2分区中,2000年以后出生的员工信息存储在p3分区中。
RANGE分区很有用,常常使用在以下几种情况。
(1)如果要删除某个时间段的数据时,只需要删除分区即可。例如,要删除1980年以前出生员工的所有信息,此时会执行alter table emp drop partition p0的效率要比执行delete from emp where
yearbirthdate=1980高效得多。
(2)如果使用包含日期或者时间的列可以考虑用到RANGE分区。
(3)经常运行直接依赖于分割表的列的查询。比如,当执行某个查询,如select count(*) from emp
where yearbirthdate = 1999 group by empno,此时MySQL数据库可以很迅速地确定只有分区p2需要扫描,这是因为查询条件对于其他分区不符合。
2. LIST分区
LIST分区类似RANGE分区,他们的区别主要在于,LIST分区中每个分区的定义和选择是基于某列的值从属于一个集合,而RANGE分区是从属于一个连续区间值的集合。创建LIST分区命令如下:
mysql create table employees
- empname varchar20,
- deptno int,
- birthdate date not null,
- salary int
-
- partition by
listdeptno
-

-
partition p1 values in 10,20,
-
partition p2 values in 30,
-
partition p3 values in 40
- ;
Query OK, 0 rows
affected 0.01 sec
以上示例以部门编号划分分区,10号部门和20号部门的员工信息存储在p1分区,30号部门的员工信息存储在p2分区,40号部门的员工信息存储在p3分区,同RANG分区一样,如果插入数据的部门编号不在分区值列表中时,那么insert插入操作将失败并报错。
3. HASH分区
HASH分区是基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL中有效的、产生非负整数值的任何表达式。
HASH分区主要用来确保数据在预先确定数目的分区中平均分布。在RANGE和LIST分区中,必须明确指定一个给定的列值或列值集合应该保存在哪个分区中;而在HASH分区中,MySQL自动完成这些工作,用户所要做的只是基于将要被哈希的列值指定一个列值或表达式,以及指定被分区的表将要被分割成的分区数量。
先看下面的例子:
mysql create table
htable
-
id int,
-
name varchar20,
-
birthdate date not null,
-
salary int
-
- partition by hashyearbirthdate
- partitions 4;
Query OK, 0 rows
affected 0.00 sec
当使用了PARTITION BY HASH时,MySQL将基于用户函数结果的模数来确定使用哪个编号的分区。将要保存记录的分区编号为N = MOD表达式, num。如果表htable中插入一条birthdate为2010-09-23的记录,可以通过如下方法计算该记录的分区。
modyear2010-09-23,4
=mode2010,4
=2
此时,该条记录的数据将会存储在分区编号为2的分区空间。
4. 线性HASH分区
线性HASH分区和HASH分区的区别在于,线性哈希功能使用的一个线性的2的幂运算法则,而HASH分区使用的是哈希函数的模数。
先看下面的例子:
mysql create table
lhtable
-
id int not null,
-
name varchar20,
-
hired date not null default ''1999-09-09'',
-
deptno int
-
-
partition by linear hashyearhired
-
partitions 4;
Query OK, 0 rows
affected 0.03 sec
如果表lhtable中插入一条hireddate为2010-09-23的记录,记录将要保存的分区是num个分区中的分区N,可以通过如下方法计算N。
找到下一个大于num的2的幂,把这个值称作V,可以通过下面的公式得到。V =
POWR2,CEILINGLOG2,num,假设,num的值是13,那么LOG2,13就是3.70043。CEILING3.70043就是4,则V
= POWER2,4,即等于16。
计算 N
= Fcolumn_list V 1 此时当N=num时,V = CEILV2, 此时N
= N V-1。
下面使用一个示例来说明通过线性哈希分区算法计算分区N的值,线性哈希分区表t1是通过下面的语句创建。
mysql create table
t1
-
col1 int,
-
col2 char5,
-
col3 date
-
- partition by linear hash yearcol3

- partitions 6;
Query OK, 0 rows
affected 0.59 sec
现在假设要插入两条记录到表t1中,其中一条记录col3列的值为2003-04-14,另一条记录cols列值为1998-10-19。第一条记录要保存到的分区计算过程如下:
记录将要保存到的分区num分区中的分区N,假设num是7个分区,假设表t1使用线性HASH分区且有4个分区。
V = POWR2,CEILINGLOG2,num
V = POWR2,CEILINGLOG2,7 = 8
N = YEAR''2003-04-14''
8 - 1
= 2003
7
= 3
N的值是3,很显然 3=4 不成立,所以附件条件不执行,所以第一条记录的信息将存储在3号分区中。
第二条记录将要保存到的分区序号计算如下:
V =
POWR2,CEILINGLOG2,num
V =
POWR2,CEILINGLOG2,7 = 8
= YEAR''1998-10-19''
8 - 1
= 1998 7
= 6
N的值是6,很显然 6=4成立,所以附件条件会执行。
V = CEIL62 = 3
N = N V-1
= 6 2
= 2
此时发现2 = 4不成立,记录将被保存到#2分区中。按照线性哈希分区的优点在于增加﹑删除﹑合并和拆分分区将变得更加快捷,有利于处理含有极其大量(1000GB)数据的表。它的缺点在于,与使用常规HASH分区得到的数据分布相比,各个分区间数据的分布可能不大均衡。
5. KEY分区
类似于HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数,这些函数是基于与PASSWORD一样的运算法则。
先看下面的例子:
mysql create table
keytable
-
id int,
-
name varchar20 not null,
-
deptno int,
-
birthdate date not null,
-
salary int
-
- partition by keybirthdate
- partitions 4;
Query OK, 0 rows
affected 0.11 sec
在KEY分区中使用关键字LINEAR和在HASH分区中使用具有同样的作用,分区的编号是通过2的幂算法得到,而不是通过模数算法。
6. 复合分区
复合分区是分区表中每个分区的再次分割,子分区既可以使用HASH分区,也可以使用KEY分区。这也被称为子分区。
复合分区需要注意以下问题:
l 如果一个分区中创建了复合分区,其他分区也要有复合分区。
l 如果创建了复合分区,每个分区中的复合分区数必有相同。
l 同一分区内的复合分区,名字不相同,不同分区内的复合分区名字可以相同。
下面通过案例讲述不同的复合分区的创建方法。
创建RANGE - HASH复合分区的命令如下:
mysql create table rhtable
-
-
empno varchar20 not null,
-
empname varchar20,
-
deptno int,
-
birthdate date not null,
-
salary int
-
- partition by rangesalary
- subpartition by hash yearbirthdate

- subpartition 3
-
-
partition p1 values less than 2000,
-
partition p2 values less than maxvalue
- ;
Query OK, 0 rows
affected 0.23 sec
创建RANGE - KEY复合分区的命令如下:
mysql create table
rktable
- no varchar20 not null,
- name varchar20,
- deptno int,
- birth date not null,
- salary int
-
- partition by rangesalary
- subpartition by keybirth
- subpartitions 3
-
-
partition p1 values less than 2000,
-
partition p2 values less than maxvalue
- ;
Query OK, 0 rows
affected 0.07 sec
创建LIST - HASH复合分区的命令如下:
mysql create table
lhtable
-
no varchar20 not null,
-
name varchar20,
-
deptno int,
-
birth date not null,
-
salary int
-
- partition by listdeptno
- subpartition by hash yearbirth
- subpartitions 3
-
-
partition p1 values in 10,
- partition p2 values in 20
- ;
Query OK, 0 rows
affected 0.08 sec
创建LIST - KEY复合分区的命令如下:
mysql create table
lktable
-
no varchar20 not null,
-
name varchar20,
-
deptno int,
-
birthdate date not null,
-
salary int
-
- partition by listdeptno
- subpartition by keybirthdate
- subpartitions 3
-
-
partition p1 values in 10,
-
partition p2 values in 20
- ;
Query OK, 0 rows
affected 0.09 sec
4.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}
其中START TRANSACTION表示开启事务、COMMIT表示提交事务、ROLLBACK表示回滚事务、SET
AUTOCOMMIT用于设置是否自动提交事务。
默认情况下,MySQL事务是自动提交的,如果需要通过明确的COMMIT和ROLLBACK再提交和回滚事务,那么需要通过明确的事务控制命令来开始事务,这是和Oracle的事务管理有明显不同的地方。如果应用从Oracle数据库迁移到MySQL数据库,则需要确保应用中是否对事务进行了明确的管理。
MySQL的AUTOCOMMIT(自动提交)默认是开启,对MySQL的性能有一定影响,举个例子来说,如果用户插入了1000条数据,MySQL会提交事务1000次。这时可以把自动提交关闭掉,通过程序来控制,只要一次提交事务就可以了。
可以通过如下方式关掉自动提交功能,命令如下:
mysql set
@@autocommit=0;
Query OK, 0 rows
affected 0.00 sec
查看自动提交功能是否被关闭,命令如下:
mysql show
variables like "autocommit";
--------------- -------
| Variable_name |
Value |
--------------- -------
| autocommit | ON
|
--------------- -------
1 row in set 0.02
sec
下面通过两个Session(Session1和Session2)来理解事务控制的过程,具体操作步骤如下:
在Session1中,打开自动提交事务功能,然后创建表ctable并插入两条记录。命令如下:
mysql set
@@autocommit=1;
Query OK, 0 rows
affected 0.00 sec

CREATE TABLE ctable
data INT4,
;

mysql insert into
ctable values1;
Query OK, 1 row
affected 0.02 sec

mysql insert into
ctable values2;
Query OK, 1 row
affected 0.00 sec
在Session2中,打开自动提交事务功能,然后查询表ctable,命令如下:
mysql set
@@autocommit=1;
Query OK, 0 rows
affected 0.00 sec

mysql select *
from ctable;
------
| data |
------
| 1 |
| 2 |
------
2 rows in set 0.00
sec
在Session1中,关闭自动提交事务功能,然后向表ctable中插入两条记录,命令如下:
mysql set
@@autocommit=0;
Query OK, 0 rows
affected 0.00 sec

mysql insert into
ctable values3;
Query OK, 1 row
affected 0.00 sec

mysql insert into
ctable values4;
Query OK, 1 row
affected 0.00 sec
在Session2中,查询表ctable,命令如下:
mysql select *
from ctable;
------
| data |
------
| 1 |
| 2 |
------
2 rows in set 0.00
sec
从结果可以看出,在session1中新插入的两条记录没有查询出来。
在Session1中,提交事务,命令如下:
mysql commit;
Query OK, 0 rows
affected 0.01 sec
在Session2中,查询表ctable,命令如下:
mysql select *
from ctable;
------
| data |
------
| 1 |
| 2 |
| 3 |
| 4 |
------
4 rows in set 0.00
sec
如果在表的锁定期间,如果使用START TRANSACTION 命令开启一个新的事务,会造成一个隐含的unlock tables被执行,该操作存在一定的隐患。下面通过一个案例来理解。
在Session1中,查询nbaplayer表,结果为空,命令如下:
mysql select *
from nbaplayer;
Empty set 0.00 sec
在Session2中,查询nbaplayer表,结果为空,命令如下:
mysql select *
from nbaplayer;
Empty set 0.00 sec
在Session1中,对表nbaplayer加写锁,命令如下:
mysql lock table
nbaplayer write;
Query OK, 0 rows
affected 0.00 sec
在Session2中,向表nbaplayer中增加一条记录,命令如下:
mysql insert into
nbaplayer values
1,''kobe'',10000;
在Session1中,插入一条记录,命令如下:
mysql insert into
nbaplayer values
2,''durant'',40000;
Query OK, 1 row
affected 0.02 sec
在Session1中,回滚刚才插入的记录,命令如下:
mysql rollback;
Query OK, 0 rows
affected 0.00 sec
在Session1中,开启一个新的事务,命令如下:
mysql start
transaction;
Query OK, 0 rows
affected 0.00 sec
在Session2中,表锁被释放,此时成功增加该条记录,命令如下:
mysql insert into
nbaplayer values
1,''kobe'',10000;
Query OK, 1 row
affected 2 min 32.99 sec
在Session2中,查询nbaplayer,命令如下:
mysql select *
from nbaplayer;
------ -------- --------
| id | name
| salary |
------ -------- --------
| 2 | durant | 40000 |
| 1 | kobe |
10000 |
------ -------- --------
2 rows in set 0.00
sec
从结果可以看出,此时发现Session1的回滚操作并没有执行成功。
MySQL提供的LOCK IN SHARE MODE锁可以保证会停止任何对它要读的数据行的更新或者删除操作。下面通过一个例子来理解。
在Session1中,开启一个新的事务,然后查询数据表nbaplayer的salary列的最大值,命令如下:
mysql begin;
Query OK, 0 rows
affected 0.00 sec
mysql select
maxsalary from nbaplayer lock in share mode;
-----------------
| maxsalary |
-----------------
| 40000
|
-----------------
1 row in set 0.00
sec
在Session2中,尝试做更新操作,命令如下:
mysql update
nbaplayer set salary = 90000 where id = 1;
等待
在Session1中,提交事务,命令如下:
mysql commit;
Query OK, 0 rows
affected 0.00 sec
在Session2中,等Session1的事务提交后,此时更新操作成功执行,结果如下:
mysql update
nbaplayer set salary = 90000 where id = 1;
Query OK, 1 row
affected 16.25 sec
Rows matched: 1 Changed: 1
Warnings: 0
4.4 MySQL分布式事务
在MySQL中,使用分布式事务的应用程序涉及一个或多个资源管理器和一个事务管理器,分布式事务的事务参与者、资源管理器、事务管理器等位于不同的节点上,这些不同的节点相互协作共同完成一个具有逻辑完整性的事务。分布式事务的主要作用在于确保事务的一致性和完整性。
4.4.1 了解分布式事务的原理
资源管理器(Resource Manager,简称RM)用于向事务提供资源,同时还具有管理事务提交或回滚的能力。数据库就是一种资源管理器。
事务管理器(Transaction Manager,简称TM)用于和每个资源管理器通信,协调并完成事务的处理。一个分布式事务中各个事务均是分布式事务的分支事务。分布式事务和各分支通过一种命名方法进行标识。
MySQL执行分布式事务,首先要考虑网络中涉及多少个事务管理器,MySQL分布式事务管理,简单地讲就是同时管理若干管理器事务的一个过程,每个资源管理器的事务当执行到被提交或者被回滚的时候,根据每个资源管理器报告的有关情况决定是否将这些事务作为一个原子性的操作执行全部提交或者全部回滚。因为MySQL分布式事务同时涉及多台MySQL服务器,所以在管理分布式事务的时候,必须要考虑网络可能存在的故障。
用于执行分布式事务的过程使用两个阶段。
(1)第一阶段:所有的分支被预备。它们被事务管理器告知要准备提交,每个分支资源管理器记录分支的行动并指示任务的可行性。
(2)第二阶段:事务管理器告知资源管理器是否要提交或者回滚。如果预备分支时,所有的分支指示它们将能够提交,那么所有的分支被告知提交。如果有一个分支出错,那么就全部都要回滚。特殊情况下,只有一个分支的时候,第二阶段则被省略。
分布式事务的主要作用在于确保事务的一致性和完整性。它利用分布式的计算机环境,将多个事务性的活动合并成一个事务单元,这些事务组合在一起构成原子操作,这些事务的活动要么一起执行并提交事务,要么回滚所有的操作,从而保证了多个活动之间的一致性和完整性。
4.4.2 分布式事务的语法
在MySQL中,执行分布式事务的语法格式如下:
XA {START|BEGIN} xid
[JOIN|RESUME]
XA
START xid 表示用于启动一个事务标识为xid的事务。xid分布式事务表示的值既可以由客户端提供,也可以由MySQL服务器生成。
结束分布式事务的语法格式如下:
XA END xid [SUSPEND
[FOR MIGRATE]]
其中xid包括:gtrid [, bqual [, formatID ]],含义如下:
l gtrid是一个分布式事务标识符。
l bqual表示一个分支限定符,默认值是空字符串。对于一个分布式事务中的每个分支事务,bqual值必须是唯一的。
l
formatID是一个数字,用于标识由gtrid和bqual值使用的格式,默认值是1。
XA PREPARE xid
该命令使事务进入PREPARE状态,也就是两个阶段提交的第一个阶段。
XA COMMIT xid [ONE
PHASE]
该命令用来提交具体的分支事务。
XA ROLLBACK xid
该命令用来回滚具体的分支事务。也就是两阶段提交的第二个提交阶段,分支事务被实际地提交或者回滚。
XA RECOVER
该命令用于返回数据库中处于PREPARE状态的分支事务的详细信息。
分布式的关键在于如何确保分布式事务的完整性,以及在某个分支出现问题时如何解决故障。
分布式事务的相关命令就是提供给应用如何在多个独立的数据库之间进行分布式事务的管理,包括启动一个分支事务、使事务进入准备阶段以及事务的实际提交回滚操作等。
MySQL 分布式事务分为两类:内部分布式事务和外部分布式事务。内部分布式事务用于同一实例下跨多个数据引擎的事务,由二进制日志作为协调者;而外部分布式事务用于跨多个MySQL实例的分布式事务,需要应用层介入作为协调者,全局提交还是回滚,都是由应用层决定的,对应用层的要求比较高。
MySQL分布式事务在某些特殊的情况下会存在一定的漏洞,当一个事务分支在PREPARE状态的时候失去了连接,在服务器重启以后,可以继续对分支事务进行提交或者回滚操作,没有写入二进制日志,这将导致事务部分丢失或者主从数据库不一致。
4.5 小结
本章主要讲解MySQL的一些高级特性,其中包括MySQL查询缓存,优化查询缓存来提高缓存命中率,并且详细介绍了MySQL合并表和分区,MySQL提供的事务控制和锁定语法,并对MySQL事务管理和分布式事务进行了简单的介绍。值得注意的是MySQL分布式事务存在一定的漏洞,MySQL分布式事务在特殊情况下是无法保证事务的完整性。

 

 

書城介紹  | 合作申請 | 索要書目  | 新手入門 | 聯絡方式  | 幫助中心 | 找書說明  | 送貨方式 | 付款方式 台灣用户 | 香港/海外用户
megBook.com.tw
Copyright (C) 2013 - 2024 (香港)大書城有限公司 All Rights Reserved.