MySQL学习笔记
第一章:
第一节:数据库和实例
数据库:物理操作希望文件或其他形式文件类型的集合。
在MySQL中,数据库文件可以是frm、myd、myi、
ibd结尾的文件。当使用NDB引擎时,数据库的文件可以
不是操作系统上得文件,而是存放于内存中的文件。
数据库实例:由数据库后台进程/线程以及一个共享内存组成的。
共享内存可以被运行的后台进程/ 线程所共享。数据库
实例才是真正用来操作数据库文件的。
数据库是由一个个文件组成,如果对文件进行CRUD等,需通过
数据库实例来完成对数据库操作。
一般情况下:一个数据库对应一个实例,一个实例对应一个数据库。
但在集群情况下,一个数据库可能被多个实例使用。
第二节:MySQL读配置文件
MySQL是按照/etc/my.cnf---->/etc/mysql/my.cnf--->/usr/local/mysql/etc/my.cnf
--->~/.my.cnf的顺序读取配置文件的。如果几个配置文件中都有
同一个参数,MySQL会以最后一个配置文件中读取的参数为准。
第三节:体系结构
由:连接池组件、管理服务和工具组件、SQL接口组件、查询分析器组件、
优化器组件、缓存组件、插件式存储引擎(特有)、物理文件。
第四节:存储引擎分类介绍
INNODB存储引擎:支持事务,主要面向在线事务处理方面的应用。
特点:行锁设计,支持外键,默认情况下读操作不会设计锁。
MyISAM存储引擎:不支持事务。Windows默认InnoDb, Linux 默认MyISAM
特点:表锁和全文索引。
由MYD和MYI组成。MYD:存储数据文件,MYI存储索引文件。
MYSQL5.0之前,MYISAM默认支持表大小为4G.若需要支持大于
4G以上,需制定MAX_ROWS和AVG_ROW_LENGTH.
MySQL5.0后,MyISAM默认支持256T的单表数据。
MyISAM存储引擎表,MYSQL数据库只缓存其索引文件,数据
文件的缓存由操作系统本身定制来完成。对于5.1.23版本前,
无论32还是64,索引缓存最大4G。之后的版本,可支持大于4G.
NDB存储引擎: 是一个集群存储引擎。其结构使用share nothing的集群架构。因此能
提高更高级别的高可用性。NDB特点:数据全存放到内存中,性能会更 高
NDB存储引擎的连接操作(JOIN)是在MySQL数据库完成,而不是在存存储引擎完成。这意味着,复杂的连接操作需要巨大网络开销。因此查询速度很慢。
Memory存储引擎:将表中的数据存放在内存中,如果数据库重启或发生崩溃,表中的数据将消失。特点:只支持表锁,并发性能差,且不支持TEXT和BLOB类型,且存储变长字段时是按照定常字段方式进行。会浪费内存。若Memory存放的结果集,如果结果集大于Memory存储表的容量的设置。又或者中间结果含有TEXT或BLOB类型字段。则MySQL数据库会把其转换到MyISAM存储引擎表而存放到磁盘中。
Archive存储引擎:只支持INSERT和SELECT存储引擎。MySQL5.1开始支持索引。
其使用zlib算法将数据行进行压缩,存储,支持比例最高可达1:10。Archive存储引擎非常
适合存储归档数据,如日志信息等。Archive存储引擎使用行锁来实现高并发的插入操作,
但是本身并不是事务安全存储引擎。
Federated存储引擎:并不存放数据,只指向一台远程MySQL数据库服务器上得表。
另外它只支持MySQL数据库表,不支持其他数据库表。
Maria存储引擎:新开发的存储引擎,为取代MyISAM而设计。
特点:缓存数据和索引文件,行锁设计,提供MVCC
功能,支持事务和非事务安全的选项支持,以及
更好的BLOB字符类型的处理。
第五节:MYSQL问题回答:
(1)MySQL支持全文索引,如:MyISAM、Sphinx存储引擎支持全文索引。
(2)MySQL快,不是因为不支持事务,MySQL MyISAM存储引擎不支持事务,
但是InnoDB支持,快是相对于不同应用来说。对于ETL(Extraction-Transformation-Loading数据提取、转换和加载http://wenku.baidu.com/view/b0a526e8aeaad1f346933f79.html)这种操作,MySQL当然有其优势。
当表的数据量大于1000W时,MySQL性能会急剧下降吗?不会,MySQL
是数据库,不是文件,随着数据行的增加,性能当然有所下降,但不是线性的,
如果选择正确的存储引擎及正确的配置,再打的数据量MySQL也能承受。
第六节:连接MySQL
连接MySQL操作时连接进程和MySQL 实例进行通信。本质是进程通信。
常用的进程通信有:管道、命名管道、命名字,TCP/IP套接字,Unix域名套接子。
TCP/IP:套接字是MySQL在任何平台下都提供的连接方式,也是网络
中使用得最多的一种方式。TCP/IP连接MySQL实例时,会先检查
张权限视图,用来判断发起请求的客户端是否有权限连接。
命名管道:Windows系统,若两个需要通信的进程在同一服务器上,可以用
命名管道。MySQL4.1之后,还提供了共享内存的连接方式,在配置文件
中添加--shared-memory.
UNix域套接字:它不是网络协议,所以只能在MySQL客户端和数据库实例
在同一台服务器上使用。可以指定配置文件中指定套接字文件
路径。当数据库实例启动后,可通过命令来进行Unix域套接字
文件查找。
第二章:Innodb存储引擎
第一节:Innodb简介
Innodb由Innobase公司开发,在windows下为默认的表存储引擎。
该存储引擎是第一个完整支持ACID(ACID:Atomic、Consistent、Isolated、Durable http://wenku.baidu.com/view/9457b6c78bd63186bcebbc90.html)事务的MySQL存储引擎。BDB是第一个支持事务的MySQL存储引擎,现在已停止开发。行锁设计,支持MVCC.支持外键,
第二件:MVCC简介
Multi-Version Concurrency Control 多版本并发控制,大多数的MySQL事务型存储引擎,如InnoDB,Falcon以及PBXT都不使用一种简单的行锁机制。事实上,他们都和另外一种用来增加并发性的被 称为“多版本并发控制(MVCC)”的机制来一直使用。MVCC不只使用在MySQL中,Oracle,PostgreSQL以及其他一些数据库系统也同 样使用它。
你可将MVCC看成行级别锁的一种妥协,它在许多情况下避免了使用锁,同时可以提供更小的开销。根据实现的不同,它可以允许非阻塞式读,在写操作进行时只锁定必要的记录。
MVCC会保存某个时间点上的数据快照。这意味着事务可以看到一个一致的数据视图,不管他们需要跑多久。这同时也意味着不同的事务在同一个时间点看到的同一个表的数据可能是不同的。如果你从来没有过种体验的话,可能理解起来比较抽象,但是随着慢慢地熟悉这种理解将会很容易
InnoDB:通过为每一行记录添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删 除)。但是InnoDB并不存储这些事件发生时的实际时间,相反它只存储这些事件发生时的系统版本号。这是一个随着事务的创建而不断增长的数字。每个事务 在事务开始时会记录它自己的系统版本号。每个查询必须去检查每行数据的版本号与事务的版本号是否相同。让我们来看看当隔离级别是REPEATABLE READ时这种策略是如何应用到特定的操作的:
SELECT InnoDB必须每行数据来保证它符合两个条件:
1、InnoDB必须找到一个行的版本,它至少要和事务的版本一样老(也即它的版本号不大于事务的版本号)。这保证了不管是事务开始之前,或者事务创建时,或者修改了这行数据的时候,这行数据是存在的。
2、这行数据的删除版本必须是未定义的或者比事务版本要大。这可以保证在事务开始之前这行数据没有被删除。
第三介:OLTP(线上交易处理) 简介
OLTP(On-Line Transaction Processing):是传统网络式资料库之主要应用。
后指其基础性的日常事务处理。
OLTP特征:用户的原始资料,可以即时送到计算中心进行处理。且能够
在很短时间内,运算出结果。其对于用户最大的利益在于,可即时第针对输入的
资料加以处理,并即时将结果传回给用户。
第四节:InnoDB体系架构
InnodDB有多个内存块,可以认为这些内存块组成了一个大的内存池。
主要负责:(1)维护所有进程/线程需要访问的多个内部数据结构。
(2)缓存磁盘上得数据,方便快速读取,并在对磁盘文件
的数据进行修改之前在这里处理。
(3)重做日志缓存。
(4)后台线程主要作用是负责刷新新内存池中的数据,保持
缓冲池中内存缓存是最近的数据。此外将已修改的数据
刷新到磁盘文件,保证在数据库发生异常情况下,恢复到
正常运行状态。
InnoDB存储引擎是一个被称做master thread的线程上几乎实现了所有功能。
默认情况下:InnoDB存储引擎的后台线程有7个。
4个IO thread, 1个master thread, 1个锁(lock)监控线程,1个错误监控线程。
Linux 上IO thread线程数不可以调整。Windows可以通过innodb_file_thread调整。
innodb plugin版本开始增加IO thread数量。默认的read thread和write thread已
分别增加到4个。并且不是用innodb_file_io_threads参数。而分别用
innodb_read_io_thread和innodb_write_io_threads参数。
mysql> show variables like 'innodb_version'; +----------------+-------+ | Variable_name | Value | +----------------+-------+ | innodb_version | 1.1.8 | +----------------+-------+ 1 row in set (0.00 sec)
mysql> show variables like 'innodb_%io_threads'; +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | innodb_read_io_threads | 4 | | innodb_write_io_threads | 4 | +-------------------------+-------+ 2 rows in set (0.00 sec) mysql> show engine innodb status; I/O thread 0 state: waiting for completed aio requests (insert buffer thread) I/O thread 1 state: waiting for completed aio requests (log thread) I/O thread 2 state: waiting for completed aio requests (read thread) I/O thread 3 state: waiting for completed aio requests (read thread) I/O thread 4 state: waiting for completed aio requests (read thread) I/O thread 5 state: waiting for completed aio requests (read thread) I/O thread 6 state: waiting for completed aio requests (write thread) I/O thread 7 state: waiting for completed aio requests (write thread) I/O thread 8 state: waiting for completed aio requests (write thread) I/O thread 9 state: waiting for completed aio requests (write thread) |
第五节:InnoDB内存
InnoDB存储引擎内存由:缓冲池(buffer pool)、重做日志缓冲池(read log buffer)
以及额外的内存池(additional memory pool),分别由配置文件中的参数
innodb_buffer_pool_size和innodb_log_buffer_size、innnodb_additional_mem_pool_size的大小决定。
mysql> show variables like 'innodb_buffer_pool_size'; +-------------------------+------------+ | Variable_name | Value | +-------------------------+------------+ | innodb_buffer_pool_size | 1073741824 | +-------------------------+------------+ 1 row in set (0.00 sec)
mysql> show variables like 'innodb_log_buffer_size'; +------------------------+----------+ | Variable_name | Value | +------------------------+----------+ | innodb_log_buffer_size | 20971520 | +------------------------+----------+ 1 row in set (0.00 sec) mysql> show variables like 'innnodb_additional_mem_pool_size'; |
缓冲池是占最大内存的部分,用来存放各种数据。因为Innodb的存储引擎的工作
方式总是将数据文件按页(每页16K)读取到缓冲池,然后按最近最少使用(LRU)的算法
来保留在缓存池的缓存数据。若数据库文件需修改,总是先修改缓冲池中的页(发生修改
后,该页极为脏页),然后按一定频率将缓存池的脏页数据刷新到文件。
mysql> show engine innodb status\G; Log sequence number 204173297 Log flushed up to 204173297 Last checkpoint at 204173297 0 pending log writes, 0 pending chkp writes 1902 log i/o's done, 0.00 log i/o's/second ---------------------- BUFFER POOL AND MEMORY ---------------------- Total memory allocated 2197815296; in additional pool allocated 0 Dictionary memory allocated 198924 Buffer pool size 131071(表名有多少个缓存帧,每个缓存帧16K)所以大小为131071*16/1024=2047M Free buffers 130500 (表示当前空闲的缓存帧) Database pages 568 (表示已使用的缓存帧) Old database pages :216 Modified db pages 0 (表示脏页的数量)因为在缓存池中有大量的空闲页可供数据库进一步使用。 Pending reads 0 Pending writes: LRU 0, flush list 0, single page 0 Pages made young 1, not young 0 |
备注:show engine innodb status命令显示的不是当前时间,而是过去某个时间范围内。如:Per second averages
calculated from the last 24 seconds 表示的信息是过去24秒内的数据库。
具体来说:缓冲池中缓存的数据页类型有:索引页、数据页、undo页、插入缓存、数据字典、
自适应哈希索引、InnoDB存储的锁信息、
日志缓存:将重要的日志信息先放入这个缓存区,然后按一定频率将其刷新到重做日志文件。
额外内存池:InnoDB存储引擎中对内存的管理是通过内存堆的方式进行的。对一些数据
结构分配内存时,需额外的内存池申请。
第六节:master thread
master thread的线程优先级最高,其内部由几个循环组成:主循环(loop)、
后台循环(background loop)、刷新循环(flush loop)、暂停循环(suspend loop).
loop循环:每秒操作和每10秒操作。通过Thread sleep来实现。针对延迟,Innodb采用了
其它方法:(1)日志缓存刷新到磁盘,即使这个事物还没提交。(总是)
(2)合并插入缓存(可能):InnoDB存储引擎判断当前一秒内IO次数 是否小于5次,若小于5次,则IO压力小,可执行合并插入缓存的操作。
(3)至多刷新100个InnoDB的缓冲池中的脏页到磁盘(可能):判断当前缓冲池中的脏页比例buf_get_modified_ratio_pct是否超过了配置文件中innodb_max_dirty_pages_pct这个参数(默认为90,代表90%).如果超过了,InnoDB存储引擎认为需要做磁盘同步操作,将100个脏页写入磁盘。
(4)如果当前没有用户活动,切换到background loop(可能)
Loop循环每 10秒的操作
(1)刷新100个脏页到磁盘(可能):InnoDB存储引擎会先判断过去
10秒内磁盘IO操作是否小于200,若是,则应将100个脏页刷新到磁盘中。
(2)合并至多5个插入缓冲(总是)
(3)将日志缓冲刷新到磁盘(总是)
(4)删除无用的Undo页(总是)
(5)刷新100个或10个脏页到磁盘(总是)
(6)产生一个检查点(总是)
background loop: 当前没有用户活动(数据库空闲时)或数据库关闭时,就会切换到这个
循环。这个循环会执行以下操作.
(1)删除无用的Undo页(总是)
(2)合并20个插入缓冲(总是)
(3)跳回到主循环(总是)
(4)不断刷新100个页,直到符合条件(可能,跳转到flush loop)
如果flush loop中什么事情也没做。InnoDB存储引擎会切换到suspend_loop,将
master thread挂起,等待事件的发生。若启动了InnoDB存储引擎,却没有使用任何
InnoDB存储引擎表,那么master thread总是处于挂起状态。
第七节:InnoDb关键特性
插入缓存:先判断插入的非聚集索引页是否在缓存中,如果在,则直接插入。
如果不在,则先放入一个插入缓冲池区中的。
必须买满足以下两条:(1)索引是辅助性的索(2) 索引不是唯一
两次写:
自适应哈希索引:
第三章:文件
第一节:参数文件
参数:可以理解为键值对。
MySQL参数:文件中参数可以分为两类,动态与静态参数。
动态参数:MySQL实例运行中可以更改。
静态参数:在真个实例生命周期内不得进行更改。
第二节:日志文件。
日志文件记录了影响MySQL数据库的各种类型活动。
日志文件主要分类:
(1)错误日志:通过Warning等对数据库优化有帮助
mysql> show variables like 'log_error'; +---------------+------------------------+ | Variable_name | Value | +---------------+------------------------+ | log_error | /var/lib/mysql/liu.err | +---------------+------------------------+ 1 row in set (0.00 sec) |
(2)二进制日志:记录了对数据库执行更改的所有操作,但不包括SELECT和SHOW
这类操作。二进制日志作用:恢复与复制。
(3)慢查询日志:能对MySQL中SQL语句优化有帮助。
mysql> show variables like '%long%'; +---------------------------------------------------+-----------+ | Variable_name | Value | +---------------------------------------------------+-----------+ | long_query_time | 10.000000 |(代表10秒) | max_long_data_size | 10485760 | | performance_schema_events_waits_history_long_size | 10000 | +---------------------------------------------------+-----------+ 3 rows in set (0.00 sec)
mysql> show variables like 'log_slow_queries'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | log_slow_queries | OFF | +------------------+-------+ 1 row in set (0.00 sec)
mysql> show variables like 'long_query_time'; +-----------------+-----------+ | Variable_name | Value | +-----------------+-----------+ | long_query_time | 10.000000 | +-----------------+-----------+ 1 row in set (0.00 sec)
mysql> show variables like 'log_queries_not_using_indexes'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | log_queries_not_using_indexes | OFF | +-------------------------------+-------+ 1 row in set (0.00 sec) |
(4)查询日志:记录了所有对MySQL数据库请求信息,不论这些请求是否得到正确执行。
第三节:套接字文件
套接字文件可由参数socket控制,一般在/tmp目录下。
mysql> show variables like 'socket'; +---------------+---------------------------+ | Variable_name | Value | +---------------+---------------------------+ | socket | /var/lib/mysql/mysql.sock | +---------------+---------------------------+ |
第四节:Pid文件
当MySQL实例启动时,会将自己的进程ID写入一个文件中--该文件即为pid文件
该文件可由参数pid_file控制。默认路径位于数据库目录下。文件名为主机名.pid。
mysql> show variables like 'pid_file'; +---------------+------------------------+ | Variable_name | Value | +---------------+------------------------+ | pid_file | /var/lib/mysql/liu.pid | +---------------+------------------------+ 1 row in set (0.00 sec)
|
第五节:表结构定义文件
无论采用何种存储引擎,MySQL都有一个以frm为后缀名的文件,这个文件记录了该表结构。
frm还用来存放视图的定义。
第六节:InnoDB存储引擎文件
表空间文件:默认配置下,会有一个初始化大小为10MB、名为ibdata1的文件。该文件就
是默认的表空间文件,你可以通过参数innodb_data_file_path对其进行设置。
另外可以用多个文件组成一个表空间,同时制定文件的属性。
如:innodb_data_file_path=/db/ibdata1:2000M;/db/ibdata2:2000M:autoextend
设置innodb_data_file_path参数后,之后对于所有基于InnoDb存储引擎的表 的数据都会记录到该文件内。而通过参数设置innodb_file_per_table,我们可以将每个基于
InnoDB存储引擎的表单肚产生一个表空间,文件名为.ipd.这些独立的表空间文件仅存储该
表的数据、索引和插入缓冲等信息。其余信息还是存放在默认表空间。
重做日志文件:默认情况下,有两个文件ib_logfile0和ib_logfile1。MySQL官方册
将其存放在InnoDB存储引擎的日志文件。它记录了对于InnoDB存储引擎的事务日志。
重做日志文件的主要目的:实例或则介质失败,重做日志文件就能派上用场。
innodb_log_file_size:重做日志文件的大小。 innodb_log_files_in_group:指定日志文件 组;重做日志文件的数量,默认为2; innodb_mirrored_log_groups:指定了日志镜像文件组的数量,默认为1,代表只看有一个日志文件组,没有镜像。innodb_log_group_home_dir指定了日志文件组所在路径,默认在数据库路径下。
重做日志文件大小设置对MySQL数据库方面还是由影响的。
一方面:设置太大,在恢复时可能需很长时间。设置太小,可能呢会导致事务日志需多长切换重做日志文件。
innodb_flush_log_at_trx_commit可设置为0、1、2。
0:代表当提交事务时,并不将事务的重做日志写入磁盘上得日志文件,而是等待主线程每秒的刷新。
1:在事务commit时,将重要日志缓存同步写入到磁盘。
2:重做日志,异步写到磁盘,即不能完全保证commit时,肯定会写入重做日志文件。
只是有这个动作。
第四章:表
第一节:InnoDB存储引擎表类型
InnoDB存储引擎表中,每个表都有主键,若在创建时,没显示地定义主键,则InnoDB
存储引擎会按如下方式选择或创建主键。(1)表中是否有非空的唯一索引,如果有,则该列即为主键。(2)不符合上述条件,InnoDB 存储引擎自动创建一个6个字节大小的指针。
第二节:InnoDB逻辑存储结构。
所有的逻辑都放在一个表空间。表空间由:段(segment)、区(extent)、页(page)组成。页在一些文档中称为块。
第三节:表空间
每张表空间存放的只是数据、索引和插入缓存,其它类型如:撤销(Undo)信息、系统事务信息、二次写缓存(double write buffer)等还是存放在原来的共享表空间内。
表空间:是由各个段组成的。常见的段有:数据段、索引段、回滚段等。
区:由64个连续的页组成的,每个页带下为1MB.对于大的数据段,InnoDB存储引擎
最多每次可以申请4个区,以此来保证数据的顺序性能。每个段开始时,先有32个页大小的碎片页来存放数据,当这些也使用完之后,才是64个连续页的申请。
页:InnoDb磁盘管理的最小单位。InnoDB 页的大小为16KB,且不可更改。
常见类型有:
数据页(B-tree Node)、Undo页(Undo Log Page)、系统页(System Page)、
事务数据页(Transaction System Page)、插入缓冲位图页(Insert buffer Bitmap)、
插入缓冲空闲列表页(Insert Buffer Free List)、未压缩的二进制大对象页(Uncompressed BLOB Page)、压缩的二进制大对象页(Compressed BLOB Page).
行:InnoDB存储引擎是面向行的,也就是数据存放按行进行存放。每页存放的行记录也是又硬性定义的,最多允许存放16KB(2~200行记录),即7992行记录。MySQL infobright存储引擎是按列来存放数据。面向列的数据库是当前数据库发展的一个方向。
第四节:InnoDB物理存储结构:
物理意义上来看,InnoDB表由共享表空间、日志文件组、表结构定义文件组成。
InnoDB存储引擎和大多数数据库一样,记录是以行的形势存储,它提供了Commpact和Redundant两种格式存放行记录数据。Redundant是为兼容之前版本而保留的。5.1版本后默认以Commpact 方式存放行行记录数据。
mysql> show table status like 'c_user'; +--------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+------------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+ | Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment | +--------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+------------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+ | c_user | InnoDB | 10 | Compact | 1185 | 387 | 458752 | 0 | 475136 | 2062548992 | NULL | 2012-06-15 13:38:54 | NULL | NULL | utf8_general_ci | NULL | | | +--------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+------------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+ 1 row in set (0.00 sec) |
Commpact:MySQL5.0时被引入的,设计目标是能高效存放数据。
变长字段长度列表 |
NULL标志位 |
记录头信息 |
列1数据 |
列2数据 |
...... |
变长字段长度:当列长度小于255字节,用1字节表示;若大于255个字节用2个字节表示。变长字段最多不能超过2个字节。
NULL标志位:指示了该行数据中是否有NULL值,用1表示。该部分所占字节应该是
bytes.
记录头信息:固定 占用5个字节(40位)。
没行数据除了用户定义的列外,还有两个隐藏列,事务ID列和回滚指针列表。分别占6个字节和7个字节大小。若InnoDB表没有定义Primary Key,每行还会增加一个6字节的RowID列。
Redundant:行记录格式:MySQL5.0版本之前记录的存储格式。
字段长度偏移列表 |
记录头信息 |
列表数据1 |
列2数据 |
列3数据 |
...... |
字段长度偏移列表:按照列的顺序逆序放置。当列的长度小于255字节,用1字节表示;当
大于255字节时,用2个字节表示。
记录头信息:只占用6个字节(48位)。
MySQL一个行支持最多的列为1023.
InnoDB Plugin引入新文件格式,为Barracuda。以前的未ANTELOPE.新的Barracuda有两种新的行记录格式Compressed和Dynamic。
第五节:InnoDB数据页结构
InnoDB数据页由以下七个部分组成:Files Header(文件头)、Page Header(页头)、Infimun+Supremum Records、User Records(用户记录,即行记录)、Free Space(空闲空间)、
Page Directory(页目录)、File Trailer(文件结尾信息)
其中:Files Header(文件头)、Page Header(页头)、File Trailer大小是固定的。
第六节:约束性
数据完整性:
(1)实体完整性:保证表中有一个主键。
(2)域完整性:保证数据的值满足特定条件。
(3)参照完整性:保证两张表之间的关系。
对于InnoDB存储引擎而言,提供4种约束:
(1)Primary Key (2)Unique Key (3)Foreign Key
(4)Default (5)NOT NULL
约束与索引区别:约束更是一个逻辑概念,用来保证数据完整性,而索引是一个数据结构,有逻辑上得概念,在数据库上更是一个物理存储方式。
MySQL不支持传统的Check约束,但通过ENUM和SET类型可以解决部分这样的约束请求。如:mysql> create table a(id int ,sex enum('male','femal'));
第七节:触发器
触发器MySQL5.1开始相对稳定。最多可为一个表创建6个触发器,即分别为:INSERT、
UPDATE、DELETE的BEFORE和AFTER各定义一个.
第八节:分区表分区
MySQL数据库在5.1版本时添加了对分区的支持,这个过程是将一个表或者索引物分解为多个更小、更可管理的部分。MYSQL数据库只支持水平分区,不支持垂直分区。MYSQL的数据库分区是局部分区索引,一个分区中既存放了数据又存放了索引。
mysql> show variables like '%partition%';(查看是否启用分区) +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | have_partitioning | YES | +-------------------+-------+ 1 row in set (0.00 sec) |
查看MySQL是否启用了分区功能。
水平分区:指同一表中不同的记录分配到不同的物理文件中。
垂直分区:指同一表中不同的列分配到不同的物理文件中。
误区一:只要启用了分区,数据库就会变得更快。错误。
分区:对于某些SQL语句性能可能带来提高,但是分区主要用于高可用性,利于数据
库管理。在OLTP中,对于分区的使用应格外小心。
MySQL支持以下分区:
(1)RANGE分区:行数据基于属于一个给定连续区间的列值放入分区。5.5开始支持
RANGE COLUMNS的分区。
mysql> create table sales(money int unsigned not null, -> date datetime)engine=innodb -> partition by range(year(date))( -> partition p2008 values less than(2009), -> partition p2009 values less than(2010), -> partition p2010 values less than(2011)); |
(2)LIST分区:和RANGE分区类似,只是LIST分区面向的离散的值。5.5开始支持
LIST COLUMN的分区。
mysql> create table tt( -> a int, -> b int) engine=innodb -> partition by list(b)( -> partition p0 values in (1,3,5,7,9), -> partition p1 values in (0,2,4,6,8) -> ); Query OK, 0 rows affected (0.01 sec) |
另外:在使用Insert插入多行数据的过程中,遇到分区未定义的值时,MyISAM和InnoDB存储引擎处理完全不同。MyISAM引擎会将之前的行数据都插入,但之后的数据都不会被插入。而InnoDB存储引擎将其视为一个事物,因此没有任何数据插入。
(3)HASH分区:根据用户自定义的表达式的返回值来进行分区,返回值不能为负数。
将数据均匀地分布到预先定义的各个分区中,保证各分区数据数量大致都是一样的。在Range和List分区中,必须明确指定一个给定的列值或列值或列值集合应保持在哪个分区中。
另外还有一种LINEAR HASH。
LINEAR HASH:分区的有点在于,增加、删除、合并和拆分分区将变得更加快捷,
这有利于处理含有大量数据的表;它的缺点在于,与使用Hash分区得到的数据分布
相比。各个分区数据的分布可能不大均衡。
mysql> create table t_hash( -> a int, -> b datetime) engine=innodb -> partition by hash(year(b)) -> partitions 4; (指分4个区) Query OK, 0 rows affected (0.00 sec) |
(4)KEY分区:与Hash区分相似,不同之处在于,根据MySQL数据库提供的哈希函数来进行分区。Hash分区使用用户定义的函数进行分区;
不论创建何种类型的分区,如果表中存在主键或是唯一索引时,分区列表必须是唯一索引组成部分。唯一索引可以是允许NULL值得,并且分区列只是唯一索引的一个组成部分,不需要整个唯一索引列都是分区列。
mysql> create table t_key( -> a int, -> b datetime) engine=innodb -> partition by key(b) -> partitions 4; Query OK, 0 rows affected (0.01 sec) |
当表没有指定主键,唯一索引时,可指定任何一个列为分区列。
创建分区 create table t1( col1 int null,col2 date null) engine=innodb partition by hash(col1); 查看分区 mysql> select * from information_schema.partitions where table_schema=database() and table_name='t1'; 修改分区 mysql> alter table t1 add partition (partition col1 values less than maxvalue);其中这个只能用于RANGE PARTITIONING |
以上四种分区,分区的条件必须是整型,如果不是整型,那应该通过函数转换为整型。
MySQL5.5开始支持COLUMNS分区,COLUMN分区可理解为是Range分区和LIST分区的一种进化。
COLUMNS分区可直接使用非整型的数据进行分区,分区根据类型直接比较而得。
(5)COLUMNS分区支持以下的数据类型:
所有的整型类型:如INT,SMALLINT,TINYINT,BIGINT. FLOAT和DECIMAL不支持
日期类型:如:DATE和DATE TIME。其余的日期类型不支持
字符串类型:如:char、varchar、binary和varbinary. BLOB和TEXt类型不支持。
mysql> create table t_columns_range( -> a int, -> b datetime) engine=innodb -> partition by range columns(b)( -> partition p0 values less than ('2009-01-01'), -> partition p1 values less than('2010-01-01')); Query OK, 0 rows affected (0.01 sec) |
子分区:是在分区的基础上再进行分区,有时也称这种分区未符合分区。MySQL数据库允许再RANGE和LIST的分区上再进行HASH或KEY的子分区。
mysql> create table ts(a int, -> b date) engine=innodb -> partition by range(year(b)) -> subpartition by hash(to_days(b)) -> subpartitions 2( -> partition p0 values less than (1990), -> partition p1 values less than (2000), -> partition p2 values less than MAXVALUE); Query OK, 0 rows affected (0.01 sec) |
MySQL数据库允许对NULL值做分区,总是把NULL 值视为小于任何一个非NULL值,这
和MySQL数据库对于NULL的ORDER BY的排序是一样的。
各个分区对NULL值处理不一样。
RANGE分区:将该值放入最左边的分区。
LIST分区:要使用NULL值,则必须显示地指出那个分区中放入NULL值。否则会报错。
HASH和KEY分区:对于NULL处理方式,任何分区函数都会将含有NULL值得记录返回为0;
第九节:分区和性能
数据库应用分类:
(1)OLTP(在线事务处理):如:博客、电子商务、网络游戏等。
(2)OLAP(在线分析处理):如:数据仓库、数据集市。
第五章:索引与算法
第一节:InnoDB索引分类
(1)B+树索引:传统意义上得索引。
B+树索引并不能找到一个给定键值的具体行,只是被查找数据行所在的页。然后由数据库通过把夜读入内容,再在内存中进行查找。最后得到查找的数据。
(2)哈希索引:InnoDb存储引擎根据表的使用情况,自动为表生成哈希索引。
第二节:算法
二分算法:(折半算法):将记录按有序排列,查找过程中采用跳跃式方法查找。
平衡二叉数(AVL):B+树是通过二叉查找数树,再由平衡二叉数、B树演化而来。首先符合二叉查找树的定义,其次必须满足任何节点的左右两个子树的高度最大 差为1.平衡二叉树对于查询速度的确很快,但维护一颗平衡二叉树的代价是非常大的。通过
1次或多次左旋和右旋来得到插入或更新后树的平衡性。
B+树:由B树和索引顺序访问方法演化而来。
B+树是为磁盘或其他直接存取辅助设备而设计的一种平衡查找树,在B+树
中,所有记录节点都是按照键值大小顺序存放在同一层的叶节点。
第三节:索引
B+树索引:其本质就是B+树在数据库中的实现,但是B+索引在数据库有一个特点就是高扇出性。可分为:聚集索引和辅助聚集索引。他们两个不同之处:叶子节点存放的是否是一整行的信息。
聚集索引:按照每张表的主键构造一颗B+树,并且节点中存放着整张表的行记录数据,
因此也让聚集索引的叶节点成为数据页。并且也决定了索引组织表中数据也是索引的一部分。
另外聚集索引的存储并不是按照物理上的连续存储,想发是逻辑上连续的。还有一个特点:
他对于主键的排序查找和范围查找速度非常快。主要针对“主键索引”
辅助索引(非聚集索引):页级别不包含行的全部数据。叶节点除了包含键值意外,每个叶级别中的索引行中还包含一个书签,该书签用来告诉InnoDB存储引擎,那里可以找到与索引相对应的行数据。主要怎对“一般索引”。
索引的创建和删除有两种方法:
一种是:ALTER TABLE:如:ALTER TABLE tbl_name DROP PRIMARY KEY |Drop {INDEX|KEY} index_name
另一种是:CREATE/DROP INDEX如:CREATE [UNIQUE] INDEX index_name[index_type] on
tbl_name(index_col_name,...) 、Drop Index index_name on tbl_name.
MySQL数据库存在的一个普遍问题:对于索引的添加和删除,MySQL数据库是先创建一张新临时表,然后把数据导入临时表,删除原表,再把临时表重名为原来的表名。因此创建和删除索引需要很长时间。
InnoDB存储引擎从版本InnoDB Plugin开始,支持一种称为快速索引创建方法,值针对辅助索引。原理是:为其表添加一个S锁,在创建过程中,需要重建表,因此速度快。但由于上了S锁,因此创建过程只能进行读操作,删除辅助索引就更简单了,只需再InnoDB存储引擎的内部视图更新下,将辅助索引的空间标记为可用,并删除MySQL内部视图上对于该表的索引定义即可。
InnoDB存储引擎只支持B+树索引。
SELECT INDEX FROM TEST;
第四节:B+树索引的使用
B+树索引一般是访问表中很少一部分行时,使用其才有意义。对于性别、地区等我们的取值范围很小,即低选择性。如SELECT * FROM student where sex='M';使用B+树索引才有效。
对于某些字段:如Name,取值范围很广,几乎没有重复,即高选择性,另外只取少量数据时,使用B+树索引最合适。当一个表中取出数据超过20%的数据量时,优化器就不会使用索引,而是进行全表扫表。
InnoDB预读取技术:预读是指通过一次IO请求,将多个页预读到缓冲池中,并估计预读取的多个页马上回被访问。
随机预读:指当一个区中13个页也在缓冲区,并在LRU列表的前端(即页是频繁地访问)。则InnoDB存储引擎会将这个区中剩余的所有页预读到缓冲区。
线性预读:基于缓冲池中页的访问模式,而不是数量。如果一个区中的24个页都被顺序访问了,则InnoDB存储引擎会读取下一个区的所有页。
InnoDB1.0.4开始,随机访问的预读取被取消,而线性的预读取还是保留了,并加入了
innodb_read_ahead_threshold参数。该参数表上一个区中的多少个页被顺序访问时,InnoDB
存储引擎才启用预读取。innodb_read_ahead_threshold的默认值为56.
mysql> show variables like 'innodb_read_ahead_threshold'; +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------+ | innodb_read_ahead_threshold | 56 | +-----------------------------+-------+ 1 row in set (0.00 sec) |
第六节:锁
第一节:锁:
锁是数据库系统区别于文件系统的一个关键特性。锁机制用于管理对共享资源的并发访问。
锁类型:共享锁(允许事务读一行数据)和排它锁(允许事务删除或更新一行数据)
InnoDB存储引擎支持两种意向锁:
(1)意向共享锁(IS Lock):事务想要获得一个表中某几行的共享锁。
(2)意向排它锁(IX Lock):事务想要获得一个表中某几行的排它锁。
第七章:事务
第一节:事务概述
事务:是数据库区别于文件系统的重要特性之一,用来保证数据库的完整性。
事务目的:会把数据库从一种一致状态转换为另一种一致状态。
事务4个特性:
(1)原子性(atomicity):指数据库事务是不可分割的工作单位。
(2)一致性(consistency):指事务将数据库从一种状态转变为下一状态时,数据库的完整性没有被破坏。
(3)隔离性(isolation):一个事务的影响在该事务提交前对其它事务都不可见。
(4)持久性(durability):事务一旦提交,其结果就是永久性的。即使发生宕机等故障,数据库也能将数据恢复。
第二节:事务的实现
事务的实现通过:redo(重做) 和 undo(撤销)
redo:在InnoDB存储引擎中,事务日志通过redo日志文件盒innodb的日志缓冲(innodb log buffer)来实现。当开始一个事务时,会记录该事务的一个LSN(Log Sequence Number日志序列号);当事务执行时,会往InnoDB存储引擎的日志缓冲里插入事务日志;当事务提交时,必须将InnoDB存储引擎的日志写入到磁盘,也就是在写数据前,需先写日志,这种方式称为:预写日志方式。
mysql> show engine innodb status; Log sequence number 569545372 :日志序列编号 Log flushed up to 569545372 : 刷新到重做日志文件的LSN Last checkpoint at 569545372 : 刷新到磁盘的LSN |
undo:重做日志,放在数据库内部一个特殊段(segment)中,这个段称为undo segment。undo段位于共享表空间内。
第三节:事务控制语句
(1)BEGIN、START TRANSACTION:显示地开始一个事务,或者执行SET AUTOCOMMIT=0,以禁用当前会话自动提交。
(2)COMMIT: 提交事务
(3)ROLLBACK: 回滚事务
(4)SAVEPOINT identifier:允许你在事务创建一个保持点,一个事务中可以有多个SAVEPOINT .
(5)RELEASE SAVEPOINT identifier:删除一个事务的保持点,当没有一个保存点执行这句话时,会抛出一个异常。
(6)ROLLBACK TO [SAVEPOINT] identifier:这个语句与SAVEPOINT命令一起使用。可以把事务回滚到标记点,而不回滚在此标记点之前的任何工作。
(7)SET TRANSACTION:设置事务的隔离级别。InnoDB存储引擎提供的事务隔离级别有:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE
第四节:事务的隔离级别
(1)READ UNCOMMITTED:浏览访问,仅仅只对事务而言
(2)READ COMMITTED:游标稳定
(3)REPEATABLE READ:是2.9999度的隔离,没有幻读的保护,InnoDB存储引擎默认事物
(4)SERIALIZABLE:隔离,或3度。
隔离级别越低,事务请求的锁越少,或者保存锁的时间就越短。
设置事务隔离级别
[mysqld] transaction-isolation=READ-COMMITTED |
查看当前事务隔离级别。
mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+ 1 row in set (0.00 sec) |
查看全局事务隔离级别:
mysql> select @@global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +-----------------------+ | REPEATABLE-READ | +-----------------------+ 1 row in set (0.00 sec)
|
第五节:分布式事务
InnoDB存储引擎支持XA事务,通过XA事务可以支持分布式事务的实现。分布式事务允许多个独立的事务资源参与一个全局的事务中。事务资源通常是关系型数据库系统。全局事务要求在其中所有参与的事务要么都提交,要么都回滚,这对于事务原有的ACID要求又有了提高。分布式事务时,InnoDB存储引擎的事务隔离级别必须设置为SERIALIABLE。
分布式事务组成:
(1)一个活多个资源管理器:提供访问事务资源的方法。通常一个数据库就是一个资源管理器。
(2)一个事务管理器:协调参与全局事务中的各个事务。需要和参与全局事务中的所有资源管理器进行通信。
(3)一个应用程序:定义事务的编辑,指定全局事务中的操作。
查看MySQL是否支持分布式事务:
mysql> show variables like 'innodb_support_xa'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | innodb_support_xa | ON | +-------------------+-------+ 1 row in set (0.00 sec) |
第六节:使用事务不好习惯:
(1)循环提交 (2)使用自动提交 (3)使用自动回滚
第8章 备份与恢复
第一节:备份与恢复概述
按备份的方法可以分为:
(1)Hot Backup(热备份):对正在运行中的数据库进行直接备份,不对其照常影响,即(Online Backup在线备份)
(2)Cold Backup(冷备份):数据库停止的情况下,进行的备份,这种备份最为简单,一般只拷贝相关的数据库物理文件即可。即Offline Backup(离线备份)
(3)Warm Backup(温备份):在数据库运行时备份,但是会对当前数据库的操作有所影响。
按备份后的文件内容分为:
(1)逻辑备份:指备份后的文件内容是可读的,通常是文本文件,内容一般是SQL语句,或者是表内的实际数据。如:mysqldump和select * into outfile的方法。这类方法的好处是可以看到导出文件的内容,一般适用于数据库的升级、迁移等。但是恢复所需要的时间较长。
(2)裸文件备份:指拷贝数据库的物理文件,数据库可以处于运行状态(如:ibbackup、xtrabackup这类工具),也可以处于停止状态。这类备份的恢复时间比逻辑备份短很多。
按照备份数据库的内容来分,又可以分为:
(1)完全备份:对数据库进行一个完整的备份。
(2)增量备份:在上次的完全备份基础上,对更新的数据库进行备份。
(3)日志备份:指对MySQL数据库二进制日志的备份,通过对一个完全备份进行二进制日志的重做来完成数据库point-in-time的恢复工作。
冷备份优点:
(1)备份简单,只拷贝相关文件即可。
(2)备份文件易于在不同操作系统,不同MySQL版本上进行恢复。
(3)恢复相当简单,只需要把文件恢复到指定位置即可。
(4)恢复速度快,不需要执行任何SQL语句,也不需要重建索引。
缺点:
(1)InnoDB存储引擎冷备的文件通常比逻辑文件大很多,因为表空间存放着很多其他数据,如Undo段,插入缓存等信息。
(2)冷备份不总是可以轻易地跨平台。操作系统、MySQL版本、文件大小写敏感和浮点数格式都会成为问题。
第二节:逻辑备份
mysqldump:通常用来完成转成数据库的备份以及不同数据库之间的迁移。
备份所有数据库 [root@liu ~]# mysqldump --all-databases --user=root --password>/201207062.sql Enter password: 备份指定数据库: [root@liu ~]# mysqldump --databases ding test --user=root --password>/root/20120 7063.sql Enter password: 备份数据库保存一致性【在一个事务中执行的】: [root@liu ~]# mysqldump --single-transaction --databases ding --user=root --password>/root/201207063.sql Enter password: |
mysqldump:通过mysqldump --help可以看到其参数。
其重要参数介绍:
--single-transaction:在备份开始前,先执行Start Transaction命令,以此来获得备份的一致性,当前该参数只对InnoDB存储引擎由效,当启用参数 并进行备份时,确保没有其他任何DDL语句执行,因为一致性读并不能隔离DDL;
--lock-tables :在备份中,依次锁住每个架构下的所有表。一般用于MyISAM存储引擎,备份时只对数据库进行读取操作,不过备份依然可以保证一致性。对于InnoDB存储引擎,不需要使用该参数,用--single-transaction即可。--lock-tables和--single-transaction是互斥的。
--lock-all-tables: 在备份过程中,对所有架构的所有表上锁,这可避免--lock-tables参数不能同时锁住所有表问题。
--add-drop-database:在CREATE DATABASE前运行DROP DATABASE。这个参数需要和--all-database或--database选项以前 使用。默认情况下,导出的文本文件中不会有create database,除非你指定了这个参数。 |
SELECT...INTO:也是一种逻辑备份,准确地说是导出一张表中的数据。
第三节:逻辑备份的恢复
source /root/ding20120703.sql
mysqldump可以恢复数据库,但常常发生一个问题是:mysqldump可以导出存储过程、
触发器、事件、数据,但是却不能导出视图。因此若数据库中还用了视图,那么mysqldump
备份完数据库后还需要导出视图定义或者保存视图定义的frm文件,并在恢复时进行导入。
这样才能保证mysqldump数据库的完全恢复。注意:但经过测试发现:mysqldump能够导入与导出视图。(Windows能,但Linux不能导出数据)Linux MySQL必须设置
mysql> SET SESSION binlog_format = 'ROW'; |
否则报错:
annot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED. |
http://blog.csdn.net/tianlesoftware/article/details/7028304
http://skysfw.blog.51cto.com/926181/920126
http://www.cppblog.com/flyonok/archive/2010/07/10/119972.html
第五节:二进制日志备份与恢复
二进制日志非常关键,我们可以通过它完成point-in-time来恢复工作。MySQL数据库的复制同样需要二进制日志。
第四节:二进制日志备份与恢复
二进制日志非常关键,我们可以通过它来完成point-in-time的恢复工作。MySQL数据库的复制同样需要二进制日志。默认情况下并不启用二进制日志,要使用二进制日志,首先
必须启用它,在配置文件中进行如下设置。
[mysqld]
log-bin
另外还需要启用一些其他参数来保证安全和正确地记录二进制日志,推荐的二进制日志服务器配置应该是:
[mysqld]
log-bin
sync_binlog=1
innodb_support_xa=1
第九章:性能调优
第一节:选择合适的CPU
数据库应用一般分为两类:OLTP(Online Transaction Processing在线事务处理)和OLAP
(Online Analytical Processing,在线分析处理)。这是完全两种不同的数据库应用。
OLAP:多应用在数据仓库货数据集市中,一般需要执行副总的SQL语句来进行查询;
OLTP:多用在日常的事务处理应用中,如:银行交易、在线商品交易、Blog、网络游戏等应用。相对于:OLA P,数据库的容量较小。
InnoDB存储引擎一般用OLTP的数据库应用。其特点
(1)用户操作的并发量大(2)事务处理的时间一般比较短(3)查询语句较为简单,
一般都走索引 (4)复杂的查询较少。
第二节:内存的重要性
内存的大小最能直接反应数据库的性能。InnoDB存储引擎既缓存数据,又缓存索引。
mysql> show global status like 'innodb%read%'; +---------------------------------------+-----------+ | Variable_name | Value | +---------------------------------------+-----------+ | Innodb_buffer_pool_read_ahead_rnd | 0 | | Innodb_buffer_pool_read_ahead | 0 |预读的次数 | Innodb_buffer_pool_read_ahead_evicted | 0 |预读的页,但是没有被读取就从缓冲池中被替换的页数量,预读效率 | Innodb_buffer_pool_read_requests | 248188642 |从缓冲池中读取页的次数 | Innodb_buffer_pool_reads | 589 |从物理磁盘读取页的次数 | Innodb_data_pending_reads | 0 | | Innodb_data_read | 11833344 |总共读入的字节数 | Innodb_data_reads | 599 |发起读取的次数,每次读取可能需要读取多个页。 | Innodb_pages_read | 588 | | Innodb_rows_read | 258912055 | +---------------------------------------+-----------+ 缓冲池命中率= Innodb_buffer_pool_read_request/( Innodb_buffer_pool_read_requests+Innodb_buffer_pool_read_ahead+ Innodb_buffer_pool_reads )=99.99% 大于99%表示当前内存的压力不是很大。 平均每次读取的字节数= Innodb_data_read/ Innodb_data_reads |
第三节:硬盘对数据库性能的影响
传统机械硬盘:在服务器领域一般使用SAS或SATA接口的音光盘。
特点:(1)寻道时间(2)转速
固态硬盘:基于闪存的固态硬盘。因为闪存具有:低延迟性、低功耗以及
防震性。
第12章:MySQL设计优化
第一节:设计类别:
命名规则:
字段类型:
编码选择:
其它注意问题: