1. MySQL 存储引擎
1.1. 存储引擎和 MySQL
MySQL 提供并维护多个存储引擎,每个引擎具有不同的特征和含义。创建表时可以选择特定存储引擎, MySQL 使用InnoDB 存储引擎在硬盘上为该表创建存储。可以选择替代存储引擎来用于每个表。通常,根据哪些存储引擎可以提供最适合您的应用程序需求的功能来做出此选择。每个存储引擎具有一组特定运行特征。这些特征包括用于管理查询争用的锁的类型以及该存储引擎是否支持事务。这些引擎属性对查询处理性能、并发性以及死锁预防具有一定影响。
虽然可以使用许多其他存储引擎,但对于大多数用例, InnoDB 都是最适合的。
MySQL 提供以下存储引擎:
² InnoDB
² MyISAM
² MEMORY
² ARCHIVE
² FEDERATED
² EXAMPLE
² BLACKHOLE
² MERGE
² NDBCLUSTER
² CSV
还可以使用第三方存储引擎。
MySQL 提供并维护多个存储引擎。 MySQL 服务器还可以与许多第三方存储引擎兼容。 MySQL 存储引擎是数据库服务器内的低级别引擎,它负责存储和检索数据,并且可以通过内部 MySQL API 进行访问,在某些情况下,可以由应用程序直接访问。请注意,一个应用程序可以在任何给定时间使用多个存储引擎。幻灯片中列出了当前支持的存储引擎。
请注意, InnoDB 和 NDBCLUSTER 是具有事务性的唯一两个 MySQL 存储引擎。
第三方引擎具有不同的源和功能, MySQL 不技术支持这些引擎。有关这些引擎的进一步信息、文档、安装指南、错误报告或任何帮助或协助,请直接与该引擎的开发人员联系。有关第三方存储引擎的简要论述,请参见以下链接中的“ Other Storage Engines (其他存储引擎)”文档:
http://dev.mysql.com/doc/refman/5.6/en/storage-engines-other.html 。
有关 MySQL 存储引擎的更多信息,请参阅《 MySQL 参考手册》:
http://dev.mysql.com/doc/refman/5.6/en/storage-engines.html 。
1.2. 显示存储引擎设置
使用 SELECT 确认会话存储引擎:
SELECT @@default_storage_engine;
使用 SHOW 确认每个表的存储引擎:
SHOW CREATE TABLE City\G
SHOW TABLE STATUS LIKE 'CountryLanguage'\G
使用 INFORMATION_SCHEMA 确认每个表的存储引擎:
SELECT TABLE_NAME, ENGINE FROM
INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'City'
AND TABLE_SCHEMA = 'world_innodb'\G
1.3. 设置存储引擎
在启动配置文件中设置服务器存储引擎:
[mysqld]
default-storage-engine=<Storage Engine>
使用 SET 命令为当前客户机会话设置:
SET @@storage_engine=<Storage Engine>;
使用 CREATE TABLE 语句指定:
CREATE TABLE t (i INT) ENGINE = <Storage Engine>;
如果创建表时没有使用 ENGINE 选项显式指定存储引擎, MySQL 服务器使用默认引擎创建该表,该引擎由 storage_engine系统变量的值给定。可以通过使用 SET 命令在会话级别覆盖服务器默认值。
1.4. InnoDB 存储引擎
InnoDB 是 MySQL 的默认存储引擎,提供高可靠性和高性能以及下面的主要优点:
² 事务安全(遵从 ACID )
² MVCC ( Multi-Versioning Concurrency Control ,多版本并发控制)
² 表数据进行整理来优化基于主键的查询
² 支持外键引用完整性约束
² 大型数据卷上的最大性能
² 将对表的查询与不同存储引擎混合
² 出现故障后快速自动恢复
² 用于在内存中缓存数据和索引的缓冲区池
任何其他磁盘相关的关系数据库引擎很难比得上 InnoDB 的效率。下面介绍使用 InnoDB 的一些其他优点:
事务安全 :通过事务提交、回滚以及用于保护用户数据的故障恢复功能,可以实现 ACID 遵从性。
外键支持 :包括级联删除和更新。
恢复和备份 :支持一致而联机的逻辑备份。
混合查询 :在同一语句内,可以将 InnoDB 表与来自其他 MySQL 存储引擎的表混合。例如,可以使用 join 运算在单个查询中合并来自 InnoDB 和 MEMORY 表的数据。
全文索引 :可以在文本列中有效地搜索单词或短语。
有关 InnoDB 存储引擎功能的更多信息,请参阅《 MySQL 参考手册》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html 。
InnoDB 作为默认存储引擎内置到 MySQL 服务器中,新表的默认存储引擎是 InnoDB 。使用 ENGINE=<Storage Engine> 等子句创建或更改表时选择替代存储引擎。
1.4.1 InnoDB 功能
功能 | 支持 | 功能 | 支持 |
存储限制 | 64 TB | 索引高速缓存 | 是 |
MVCC | 是 | 数据高速缓存 | 是 |
B 树索引 | 是 | 自适应散列索引 | 是 |
群集索引 | 是 | 复制 [ c ] | 是 |
压缩数据 | 是 [ a ] | 更新数据字典 | 是 |
加密数据 [ b ] | 是 | 地理空间数据类型 | 是 |
查询高速缓存 | 是 [ c ] | 地理空间索引 | 否 |
事务 | 是 | 全文搜索索引 | 是 |
Lock 粒度 | 行 | 群集数据库 | 否 |
外键 | 是 | 备份和恢复 [ c ] | 是 |
文件格式管理 | 是 | 快速索引创建 | 是 |
多个缓冲区池 | 是 | PERFORMANCE_SCHEMA | 是 |
更改缓冲 | 是 | 自动故障恢复 | 是 |
注意:
[a] 需要 InnoDB Barracuda 文件格式。
[b] 在服务器中(通过加密功能)而不是在存储引擎中实现。
[c] 在服务器中而不是在存储产品中实现。使用 MEB 进行备份时例外,其不是在服务器级别进行。
有关这些功能的更多信息,请参见 MySQL 术语词汇表,网址为:
http://dev.mysql.com/doc/refman/5.6/en/glossary.html 。
有关 InnoDB 功能的完整信息,请参阅《 MySQL 参考手册》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html 。
1.4.2 将现有表转换为 InnoDB
使用 ALTER TABLE 更改引擎是一项成本很高的操作,因为它在内部将所有数据从一个引擎复制到另一个引擎。建议不要将mysql 数据库(例如 user 或 host )中的 MySQL 系统表转换为 InnoDB ,系统表使用 MyISAM 引擎,此操作不受支持。转换方法如下:
方法一:使用 ALTER TABLE 更改存储引擎
ALTER TABLE t ENGINE = InnoDB;
方法二:从其他存储引擎克隆表,例如使用相同定义创建空 InnoDB 表,创建适当的索引,然后插入行
INSERT INTO <innodb_table> SELECT * FROM<other_table>;
创建作为使用其他存储引擎的表的克隆的 InnoDB 表时,还可以在插入数据后创建索引。要更好地控制插入过程,您可以小块形式插入大型表:
INSERT INTO newtable SELECT * FROM oldtable
WHERE yourkey > something AND yourkey <= somethingelse;
注:插入了所有记录后,可以重命名表。
在转换大型表的过程中,增加 InnoDB 缓冲区池的大小来减少磁盘 I/O 。还可以增加 InnoDB 日志文件的大小。第一次启动MySQL 服务器并且启用 InnoDB 时,最好从命令提示符运行 MySQL 服务器 mysqld ,而不是从 mysqld_safe 运行或者作为Windows 服务运行。
有关涉及的步骤,请参阅《 MySQL 参考手册》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-init.html 。
1.4.3 InnoDB 系统表空间
默认情况下, InnoDB 元数据、撤消日志和缓冲区存储在系统“表空间”中。这是单个逻辑存储区域,可以包含一个或多个文件。每个文件可以是常规文件或原始分区。最后的文件可以自动扩展。 InnoDB 使用两个主要的基于磁盘的资源来运行:
表空间 :在单个逻辑存储区域中存储表内容(数据行)和索引
日志文件 :记录回滚和恢复的事务活动
InnoDB 在表空间中存储数据、索引、元数据、日志和缓冲区。默认情况下,数据和索引存储在基于表的表空间中。 InnoDB使用共享表空间来包含元数据、撤消日志、更改缓冲区以及两次写缓冲区。
共享表空间可以占用多个文件。可以将共享表空间中的最后一个文件配置为自动扩展,在这种情况下,如果表空间装满,InnoDB 会自动扩展该表空间。
默认情况下,共享表空间还包含回滚段。事务修改行时,将在回滚段中存储撤消日志信息。此信息用于回滚失败的事务。通过将 innodb_undo_logs 选项设置为非零值并配置 innodb_undo_tablespaces 的值,来将回滚段移出共享表空间。
1.4.4 InnoDB 数据表空间
除了系统表空间之外, InnoDB 还在数据库目录中创建另外的表空间,用于每个 InnoDB 表的 .ibd 文件。 InnoDB 创建的每个新表在数据库目录中设置一个 .ibd 文件来搭配表的 .frm 文件。 .ibd 文件用作表自己的表空间文件, InnoDB 存储表内容和索引。
基于表的表空间(独立表空间)支持表压缩、支持空间回收(通过 TRUNCATE )、– 支持动态行格式;
使用共享表空间的好处是移除大量数据的语句使用较少文件系统开销,例如 DROP TABLE 或 TRUNCATE TABLE ,同时避免冗余临时数据文件。另外,共享表空间包含 InnoDB 数据字典和回滚段,可以使用 innodb_file_per_table 选项控制此设置。如果不想将数据存储在基于表的表空间中,可以通过使用 skip_innodb_file_per_table 选项或者将 innodb_file_per_table 选项设置为OFF 来将数据存储在共享数据库中。禁用该选项不会影响已经创建的任何 InnoDB 表的可访问性。仍然可以访问这些表。
同一数据库也可以不同表混合使用不同的表空间类型。更改该设置仅会更改已创建的新表的默认值,或者已更改来将引擎设置为 InnoDB 的表(甚至已经在使用 InnoDB 的表)的默认值。
1.4.5 Innodb 表空间目录结构
除了其表空间文件, InnoDB 存储引擎还管理一组特定于 InnoDB 的日志文件,其中包含关于正在进行的事务的信息。客户机执行事务时,其进行的更改存放在 InnoDB 日志 (ib_logfile) 中。最新日志内容缓存在内存中。通常,缓存的日志信息会在事务提交时写入并刷新到磁盘上的日志文件中,虽然也可能提前发生该操作。
1.4.6 共享表空间配置
共享表空间通过添加数据文件增加表空间大小。如果命名了多个数据文件,则通过分号 (;) 符号分隔这些文件。增加 InnoDB系统表空间的一种更容易(但是不太可取)的方式是从一开始就将其配置为自动扩展。在表空间定义中指定最后一个数据文件的autoextend 属性。然后, InnoDB 在用完空间时会以 64 MB 增量自动增加该文件的大小。可以通过设置innodb_autoextend_increment 系统变量的值来更改该增量大小,以 MB 为单位。如果使用关键字 autoextend 定义了最后一个数据文件,重新配置表空间的过程必须考虑最后一个数据文件已经增长到的大小。获取数据文件的大小,将其向下舍入到 1024 ×1024 字节 (= 1 MB) 的最近倍数,并在 innodb_data_file_path 中显式指定舍入的大小。然后,可以添加其他数据文件(使用尚不存在的文件名)。
在 my.cnf 文件中使用 innodb_data_file_path 选项。
[mysqld]
innodb_data_file_path=datafile_spec1[;datafile_spec2]...
示例 :创建一个表空间,其中包含一个名为 ibdata1 且大小为 50 MB (固定)的数据文件和一个名为 ibdata2 且大小为 50 MB(自动扩展)的数据文件:
[mysqld]
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend
默认情况下将文件放置在 data 目录中。如果需要,显式指定文件位置。
请记住,仅 innodb_data_file_path 中的最后一个数据文件可以指定为自动扩展。
有关 InnoDB 配置参数的更多信息,请参阅《 MySQL 参考手册》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html 。
1.4.7 日志文件和缓冲区
A. 日志文件
客户机执行事务时,其进行的更改存放在 InnoDB 日志中。最新日志内容缓存在内存中(日志缓冲区)。缓存的日志信息会在事务提交时写入并刷新到磁盘上的日志文件中,虽然也可能提前发生该操作。
如果修改表时发生故障,将使用日志文件进行自动恢复。 MySQL 服务器重新启动时,它会重新应用日志中记录的更改,以确保表中反映所有已提交事务。有关更改 InnoDB 日志文件的数量和大小的信息,请参阅《 MySQL 参考手册》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-data-log-reconfiguration.html 。
B. 缓冲区
InnoDB 维护其自己的缓冲区池以在主内存中缓存常用的数据和索引。 InnoDB 在表空间中存储其表和索引。 InnoDB 表可以非常大,甚至在文件大小限制为 2 GB 的操作系统上也是如此。可以启用多个缓冲区池来最大程度地降低争用。此高速缓存应用于如此多种类型的信息并且将处理速度提高如此多,您应该将多达 80% 的数据库服务器的物理内存分配给 InnoDB 缓冲区池。
如果未指定 InnoDB 配置选项,则 MySQL 在 MySQL 数据目录中创建一个名为 ibdata1 且大小为 10 MB 的自动扩展数据文件以及名为 ib_logfile0 和 ib_logfile1 且大小为 5 MB 的两个日志文件。要获得良好性能,您应该指定显式 InnoDB 参数。
配置缓冲区池以获得良好性能
MySQL 使用多个缓冲区池来改进大型缓冲区池(通常为多 GB 范围)的性能。
InnoDB 缓冲区池很大时,可以从内存(而不是硬盘)快速检索许多数据请求。 MySQL 使用多个缓冲区池实例来最大程度地降低线程之间的争用。存储在缓冲区池中或者从缓冲区池读取的每个页将基于散列值分配给一个缓冲区池。每个缓冲区池管理其自己的数据。使用散列函数将缓冲区池中的每个页随机分配给一个缓冲区池。每个缓冲区池管理其自己的空闲列表、刷新列表、LRU 以及连接到缓冲区池的所有其他数据结构,并由其自己的缓冲区池互斥锁进行保护。
默认情况下, MySQL 配置八个缓冲区池实例(除了在 32 位 Windows 系统上)。要更改此设置,请将innodb_buffer_pool_instances 配置选项设置为从 1 (最小值)到 64 (最大值)的一个值。仅当将 innodb_buffer_pool_size 设置为大小为 1 GB 或更大时,此选项才生效。您指定的总大小在所有缓冲区池之间分割。您应指定 innodb_buffer_pool_instances和 innodb_buffer_pool_size 的组合,从而每个缓冲区池实例至少为 1 GB 。
在启动时预装入缓冲区池来提高性能,请启用选项:
– innodb_buffer_pool_load_at_startup
– innodb_buffer_pool_dump_at_shutdown
1.4.8 NoSQL 和 Memcached API
InnoDB 支持具有集成的 Memcached 守护进程的插件,其在相同进程空间中运行,从而以较低开销进行高效数据通信。对于某些操作,通过使用较简单的 Memcached API (基于文本的协议和二进制协议),而不是使用 SQL 层,您的应用程序可以在提交 SQL 语句时绕过所需的解析和优化阶段,并避免检查强类型数据的开销。此类型的应用程序称为 NoSQL ( Not Only SQL ,不仅仅是 SQL )。
除了传统的 Memcached 环境(其在重新启动 Memcached 时会丢失键 / 值存储), InnoDB 集成表示您可以将 Memcached存储配置为持久存储到 InnoDB 。因为 InnoDB 支持该存储,所以您可以受益于 InnoDB 的其他功能,例如缓冲数据访问和故障恢复。这意味着您可以使用内存存储的 Memcached 存储(由强大而持久的 InnoDB 表支持)来获得速度和简化。
您仍可以通过 SQL 访问基础表以进行报告、分析、即席查询、批量载入、集合运算(例如并集和交集)以及非常适合于 SQL的表达性和灵活性的其他运算(例如汇总和聚合)。因为 Memcached 消耗相对较少的 CPU 并且易于控制其内存容量,所以可以与 MySQL 实例在同一系统上一起顺利运行。
1.4.8.1. 配置 Memcached
A. 配置 Memcached 表
MySQL>SOURCE <MYSQL_HOME>/scripts/innodb_memcached_config.sql
或者
MySQL>SOURCE /usr/share/mysql/innodb_memcached_config.sql
innodb_memcached_config.sql 脚本设置 Memcached 配置数据库及其表。默认 InnoDB 后备存储是 test 数据库中的demo_test 表。可以通过修改 innodb_memcache 数据库中的容器表来更改此项。
innodb_memcache 数据库,其包含下列表:
l cache_policies :存放每个 Memcached 操作的后备存储策略;本地 RAM 高速缓存、 InnoDB 或两者
l Containers :存放用作 Memcached 后备存储的每个 InnoDB 表的配置
l config_options :存放 separator 和 table_map_delimiter 配置选项的值
test 数据库,其包含下列表: demo_test
B. 安装 Memcached 插件:
INSTALL PLUGIN daemon_memcached SONAME "libmemcached.so";
该插件启用许多可配置变量。要查看 Memcached 配置变量,请发出以下命令:
SHOW VARIABLES LIKE 'daemon_memcached%';
例如,以下参数配置 Memcached 插件的行为:
l daemon_memcached_enable_binlog :启用 Memcached 操作的二进制日志记录,其允许复制 Memcached API 操作。
l daemon_memcached_r_batch_size :控制读取批处理大小,出于性能考虑。
l daemon_memcached_w_batch_size :控制写入批处理大小。默认值为 1 ,所以会立即提交每个 Memcached 写入操作
C. 配置 Memcached 变量:
– daemon_memcached_option :在启动时传递给 Memcached 守护进程的空格分隔的选项
1.4.8.2. Memcached 的键 / 值数据
Memcached 协议支持 add 、 delete 、 set 、 get 、 incr 和 decr 等操作。
l 每个操作处理高速缓存中的键 / 值对。
键和值作为字符串来传递。键不能包含空格、回车符、换行符、制表符等空白字符。键类似于表中的主键,值类似于同一表中的另一列。
l 高速缓存是平面名称空间。
确保每个键都是唯一的。例如,如果您提供其他表中的键 / 值,则在键前面附加该表名称。
l 值可以是简单字符串(或存储为字符串的数值)或序列化复杂数据。
使用 Memcached 的主要好处是读取或写入键 / 值数据时效率较高。在概念上,这类似于一个包含两列的表,其中键列是主键(因此是唯一的)。键和值存储为字符串,由于 Memcached 协议的性质,键值不能包含空格或换行符。
对于键 / 值查找, Memcached 插件使用的直接低级别数据库访问路径比等效 SQL 查询高效得多。
值存储为字符串,可以表示简单值,例如数值、字符串或已经序列化的复杂值(即,置于可以重新构造原始指针和嵌套的文本形式)。必须在 API 接口的 Memcached 外部执行此序列化(例如,通过在代码中实现 Java Serializable 接口)或者通过将复杂数据格式化为 JSON 或 XML 。
类似地,必须在访问 memcached 表的 SQL 语句中将简单数值从字符串转换为数值(例如,通过使用 CAST() 函数)。
1.4.8.3. 将 NoSQL 用于 MySQL 数据库
使用 InnoDB 表作为 Memcached 操作的容器(后备存储)。要从 Memcached 获得最大好处,请将其用作快速键 / 值访问方法,并使用 InnoDB 后备存储。 Memcached 协议不支持简单聚合、联接数据或 SQL 协议支持的其他功能。使用 InnoDB 表作为 Memcached 键 / 值对的容器,您可以运行功能强大的 SQL 语句,来执行使用 Memcached 协议创建和修改的数据分组、聚合和联接。
键和值是字符串。键最大大小为 250 字节。对于更长的键:将键值散列到小于 250 字节的值,为 Memcached 键重新配置允许的大小;
通过指定不同类的 Memcached 数据来使用多个 InnoDB 表作为 Memcached 容器。在 containers 表中配置此项。例如,以get @@newcontainer 形式发出 Memcached 请求,将后续请求重定向到名为“ newcontainer ” 的容器。
使用 innodb_memcache.containers 表可以配置一个或多个 InnoDB 表来用作 Memcached 后备存储。指定容器表的名称、模式和键列、值、标志以及其他设置。每个容器具有一个 Memcached 名称,可以用来标识 Memcached 操作的容器。操作定位于名为“ default ” 的容器,直到被要求更改容器。
/usr/share/mysql/innodb_memcached_config.sql 文件创建和填充 innodb_memcache.containers 表,是配置容器的很好示例。
1.4.9 引用完整性
将相关的数据分割到单独表中时,可以使用主键和外键来加强表关系。一个表的主键被另一个表中的键引用,引用键称为外键,每个表都需要主键。
INSERT 到辅助表(而没有指向主表的外键)不会完成。通过在联接的列上使用外键将提高 JOIN 性能。 UPDATE 或DELETE 数据时,可以使用 CASCADE 选项自动更新或删除辅助表中的任何相关数据。
使用外键:
l 通过使用最常查询的列为每个表指定主键,如果没有明显主键则指定自动增量值。
l 可以尝试将数据插入在主表中没有相应数据的辅助表,但是其返回错误且插入失败。
l 为了获得快速联接性能,在联接列上定义外键,并在每个表中使用相同数据声明这些列。如果您启用 CASCADE 选项,外键将删除或更新传播到所有受影响的表,并且当父表中没有相应列时禁止在子表中插入数据。
在 City 表中指定主键的示例:
CREATE TABLE City (
ID int(11) NOT NULL AUTO_INCREMENT,
Name char(35) NOT NULL DEFAULT '',
CountryCode char(3) NOT NULL DEFAULT '',
District char(20) NOT NULL DEFAULT '',
Population int(11) DEFAULT NULL,
PRIMARY KEY (ID),
KEY CountryCode (CountryCode),
CONSTRAINT city_ibfk_1 FOREIGN KEY (CountryCode) REFERENCES country (Code)
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=latin1
1.4.10 多版本控制
多版本控制保存关于已更改行的旧版本的信息,支持并发和回滚等事务功能,并使用称为回滚段的数据结构在表空间中存储信息。
回滚段是包含撤消日志的存储区域,其默认情况下是系统表空间的一部分。 InnoDB 使用回滚段中的信息执行事务回滚中所需的撤消操作。它还使用该信息来构建行的早期版本以实现一致读取。在内部向数据库中存储的每行添加三个字段:
DB_TRX_ID :六个字节的字段,指示插入或更新该行的最后一个事务的事务标识符。此外,删除在内部被视为更新处理,其中设置行的特殊位来将其标记为删除。
DB_ROLL_PTR :称为滚动指针的七个字节的字段。它指向写入回滚段的撤消日志记录。如果更新了行,撤消日志记录包含重建行被更新前的内容所需的信息。
DB_ROW_ID :包含行 ID 的六个字节的字段,随着插入新行而单调增加。如果 InnoDB 自动生成群集索引,该索引包含行ID 值。否则, DB_ROW_ID 列不显示在任何索引中。
如果在表中按相同速度以小批量插入和删除行,清除线程会滞后,表会因为所有“死”行而变得越来越大,使所有操作受到磁盘限制并且非常慢。在这种情况下,通过使用 innodb_max_purge_lag 系统变量限制新行操作并向清除线程分配更多资源。
1.4.11 Lock
InnoDB Lock 无需设置锁即可实现一致读取。对 DML 语句使用行级别 Lock ,从不提升锁,死锁的等待图形检测。
InnoDB 具有下列一般 Lock 属性:
l InnoDB 无需设置锁即可实现一致读取,因为它使用多版本控制,从而不需要锁。修改行的事务可以查看其自己版本的那些行,撤消日志使其他事务可以查看原始行。要强制 SELECT 语句 Lock 数据,可以向该语句添加 Lock 修饰符。
l 需要锁时, InnoDB 使用行级别 Lock 。与多版本控制一起,这将产生良好的查询并发性,因为给定表可以由不同客户机同时读取和修改。
l InnoDB 在发现需要锁时可以获取行锁。从不通过将锁转换为页锁或表锁来提升该锁。这样可以最大程度降低锁争用,提高并发性(虽然其对 DDL 操作使用表级别 Lock )。
l 可能会出现死锁,因为 InnoDB 在事务过程中直到需要锁时才获取锁。 InnoDB 可以删除死锁并回滚一个事务来解决死锁。
l 失败的事务最终开始超时, InnoDB 将回滚这些事务。
有关死锁的更多信息,请参见 MySQL 术语词汇表,网址为:
http://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_deadlock 。
1.4.12 Next-Key Lock
InnoDB 使用一种称为 Next-Key Lock 的算法,其使用行级别 Lock ,搜索 / 扫描表索引并在索引记录上设置共享锁或互斥锁;
Next-Key Lock 会影响索引记录前面的“间隙”,即新索引记录无法正好插在 Lock 记录前面。
Gap Lock 可防止出现“幻影问题”。在下面的示例中,第一个事务 Lock 大于 10 的任何值,即使该值不存在也是如此:
事务 1 :
SELECT c FROM t WHERE c > 10 FOR UPDATE;
事务 2 :
INSERT INTO t(c) VALUES (50);
InnoDB 将一种称为 Next-Key Lock 的算法用于行级别 Lock 。按以下方式执行 Lock :搜索或扫描表的索引时,会在遇到的索引记录上设置共享锁或互斥锁。因此,行级别锁实际是索引记录锁。 InnoDB 在索引记录上设置的 Next-Key Lock 会影响索引记录前面的“间隙”。如果用户在索引中的记录上具有共享锁或互斥锁,其他用户无法按索引顺序正好在 Lock 记录前面(间隙)插入新记录。
执行此间隙的 Next-Key Lock 可以防止所谓的幻影问题。同一查询在不同时间产生不同行集时,事务内会出现幻影问题。例如,如果 SELECT 执行两次,但第二次返回的行不是第一次返回的行,该行是“幻影”行。
1.4.13 非 Lock 一致性读取
时间 | 会话 1 | 会话 2 |
| | s1> START TRANSACTION; | s2> START TRANSACTION; |
| | | s1> SELECT * FROM t; Empty Set | |
| | s2> INSERT INTO t VALUES (1, 2); | |
| V | s1> SELECT * FROM t; Empty Set | |
| | s2> COMMIT; | |
| | | s1> SELECT * FROM t; | |
| | s1> COMMIT; | |
| V | s1> SELECT * FROM t; |
一致读取表示 InnoDB 使用多版本控制对您的查询提供某个时间点的数据库快照。您的查询看见在时间点之前提交的事务所进行的更改,不会看见后面或未提交事务进行的更改。示例中,仅当会话 2 已提交了插入并且会话 1 也已提交(从而时间点超过会话 2 的提交)时,会话 1 才看见会话 2 插入的行。如果要查看数据库的“最新”状态,请使用 READ COMMITTED 隔离级别或Lock 读取。
1.4.14 减少死锁
要减少死锁的可能性,请使用事务,而不是 LOCK TABLE 语句:
l 将插入或更新数据的事务保持足够小(很少行数),从而其不会保持打开状态很长时间。经常提交事务。
l 不同的事务更新多个表或大范围的行时,在每个事务中使用相同顺序的操作(例如, SELECT ... FOR UPDATE )。
l 在 WHERE 子句中使用的列上创建索引。
不要设置隔离级别以避免死锁,此操作没有作用,因为隔离级别更改读取操作的行为,而死锁是由于写入操作而出现的,与读取操作无关。
如果事务由于死锁而失败则重新发出该事务。死锁并不危险,只需要重试。另外,按固定顺序访问表和行,或者向表添加精心选择的索引也有助于减少死锁。
如果出现死锁, InnoDB 会检测到该情况并回滚一个事务(牺牲者)。因此,即使您的应用程序逻辑完全正确,您仍须处理必须重试事务的情况。要监视死锁出现的频率(以及许多其他 InnoDB 统计信息),请使用 SHOW ENGINE INNODB STATUS 命令:
mysql> SHOW ENGINE INNODB STATUS\G
=====================================
110222 16:54:12 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 5 seconds
...
1.4.15 外键 Lock
创建表时添加外键约束:
CREATE TABLE City (
...
CountryCode char(3) NOT NULL DEFAULT '',
...
KEY CountryCode (CountryCode),
CONSTRAINT city_ibfk_1 FOREIGN KEY
(CountryCode) REFERENCES country (Code)
...
约束就是在表中的一个或多个列值上放置的限制,从而积极强制执行完整性规则。约束使用索引来实现。如果在表上定义了外键约束,将在用于引用外键约束的插入、更新或删除操作中的任何记录上放置共享记录级别锁。 InnoDB 在约束失败的情况下也设置这些锁。
InnoDB 逐行检查外键约束。执行外键检查时, InnoDB 在其必须查看的子或父记录上设置共享行级别锁。 InnoDB 立即检查外键约束;该检查不会延迟到事务提交时。示例显示 City 表的 CountryCode 列与 Country 表的 Code 列相关。对任一列的任何更改都受到此关系的约束。
有关外键约束的更多信息,请参见《 MySQL 参考手册》:
http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html 。
1.5. MyISAM 存储引擎
MyISAM 存储引擎将磁盘上的每个表存储在三个文件中( .frm 、 .MYD 和 .MYI )并具有以下功能:
l 支持 FULLTEXT 搜索和空间数据类型
l 灵活的 AUTO_INCREMENT
l 压缩式只读表,可以节省空间
l 表级别 Lock 来管理查询之间的争用
l 可移植存储格式
l 可以指定表的行数
l 可以控制非唯一索引的更新以便将数据载入到空表中
在 MySQL 服务器版本 5.5.5 之前, MyISAM 是默认 MySQL 存储引擎。当前默认是 InnoDB 存储引擎。 mysql 数据库包含MyISAM 格式的表。
每个 MyISAM 表由三个文件表示:
l 格式文件: 存储表结构的定义 (mytable.frm)
l 数据文件: 存储表行的内容 (mytable.MYD)
l 索引文件: 存储表上的所有索引 (mytable.MYI)
其他功能:
l MyISAM 表占用的空间非常小。
l 表存储格式是可移植的,所以表文件可以直接复制到其他主机并由该主机上的服务器使用。
l 将数据载入到空表中时,可以禁用非唯一索引的更新,然后在载入数据后重新启用。
l MyISAM 支持几何空间扩展。
l MyISAM 可以通过将表大小限制为特定数量的行来提高性能。
有关 MyISAM 存储引擎功能的更多信息,请参阅《 MySQL 参考手册》:
http://dev.mysql.com/doc/refman/5.6/en/myisam-storage-engine.html 。
1.6. MEMORY 存储引擎
MEMORY 存储引擎使用内存中存储的、通过 .frm 文件表示在磁盘上的内容创建表。
它具有以下功能:
l 表数据和索引存储在内存中
l 由于是内存中存储所以具有很高性能
l 固定长度行存储格式
l 重新启动后表内容将丢失
l 最大大小选项 --max-heap-table-size
l 表级别 Lock
MEMORY 表:
l 不能包含 TEXT 或 BLOB 列
l 可以针对不同的列使用不同字符集
l 每个表通过数据库目录中的 .frm 格式文件表示在磁盘上。
l 服务器重新启动后内容将丢失(结构存在,但是表包含零行)。
l MySQL 使用表级别 Lock 管理查询争用。不会出现死锁。
HEAP 可能仍旧以旧 SQL 代码显示, MySQL 服务器仍旧可识别 HEAP 以实现向后兼容。处理更新时, MEMORY 性能受到由於单线程执行所导致的争用和表锁开销的约束。这限制了负载增加时的可伸缩性,特别是对于包括写入的语句混合情况。此外,MEMORY 在服务器重新启动过程中不保留表内容。
MEMORY 是有效且有用的存储引擎,对于设计用来提高性能以及满足特定业务规则的几乎所有应用,应该考虑该引擎。
有关 MEMORY 存储引擎功能的更多信息,请参阅《 MySQL 参考手册》:
http://dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html 。
1.7. ARCHIVE 存储引擎
ARCHIVE 存储引擎用于以压缩格式存储大量数据从而占用非常少的资源。它具有下列主要特征:
l 由 .frm 文件表示
l 数据文件: .ARZ
l 不支持索引
l 支持 INSERT 和 SELECT ,但不支持 DELETE 、 REPLACE 或 UPDATE
l 支持 ORDER BY 操作和 BLOB 列
l 接受除空间数据类型之外的所有数据类型
l 使用行级别 Lock
l 支持 AUTO_INCREMENT 列
郑州妇科医院:http://jbk.39.net/yiyuanzaixian/sysdfkyy/
1.8. BLACKHOLE 存储引擎
BLACKHOLE 存储引擎充当“黑洞” ,其接受数据,但是将其丢弃而不存储。此存储引擎具有下列主要特征:
l 由 .frm 文件表示
l 用于复制
l 支持所有种类的索引
l 检索始终返回空结果
l 验证转储文件语法
l 根据二进制日志记录度量开销
l “空操作” 存储引擎,可用于查找与存储引擎无关的性能瓶颈
l 识别事务
提交的事务写入二进制日志,回滚的事务不写入