提交 5f64cece 编写于 作者: 茶陵後's avatar 茶陵後 👍

#1 add zh

上级 a8061c46

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
## 16.5 The ARCHIVE Storage Engine
[]()[]()
The `ARCHIVE` storage engine produces special-purpose tables that store large amounts of unindexed data in a very small footprint.
[]()
**Table 16.5 ARCHIVE Storage Engine Features**
| Feature | Support |
|-------------------------------------------------------------------------------------------------|---------------------------------------------------------|
| **B-tree indexes** | No |
|**Backup/point-in-time recovery** (Implemented in the server, rather than in the storage engine.)| Yes |
| **Cluster database support** | No |
| **Clustered indexes** | No |
| **Compressed data** | Yes |
| **Data caches** | No |
| **Encrypted data** |Yes (Implemented in the server via encryption functions.)|
| **Foreign key support** | No |
| **Full-text search indexes** | No |
| **Geospatial data type support** | Yes |
| **Geospatial indexing support** | No |
| **Hash indexes** | No |
| **Index caches** | No |
| **Locking granularity** | Row |
| **MVCC** | No |
| **Replication support** (Implemented in the server, rather than in the storage engine.) | Yes |
| **Storage limits** | None |
| **T-tree indexes** | No |
| **Transactions** | No |
| **Update statistics for data dictionary** | Yes |
The `ARCHIVE` storage engine is included in MySQL binary distributions. To enable this storage engine if you build MySQL from source, invoke **CMake** with the [`-DWITH_ARCHIVE_STORAGE_ENGINE`](source-configuration-options.html#option_cmake_storage_engine_options) option.
To examine the source for the `ARCHIVE` engine, look in the `storage/archive` directory of a MySQL source distribution.
You can check whether the `ARCHIVE` storage engine is available with the [`SHOW ENGINES`](show-engines.html) statement.
When you create an `ARCHIVE` table, the storage engine creates files with names that begin with the table name. The data file has an extension of `.ARZ`. An `.ARN` file may appear during optimization operations.
The `ARCHIVE` engine supports [`INSERT`](insert.html), [`REPLACE`](replace.html), and [`SELECT`](select.html), but not [`DELETE`](delete.html) or [`UPDATE`](update.html). It does support `ORDER BY` operations, [`BLOB`](blob.html) columns, and spatial data types (see [Section 11.4.1, “Spatial Data Types”](spatial-type-overview.html)). Geographic spatial reference systems are not supported. The `ARCHIVE` engine uses row-level locking.
The `ARCHIVE` engine supports the `AUTO_INCREMENT` column attribute. The `AUTO_INCREMENT` column can have either a unique or nonunique index. Attempting to create an index on any other column results in an error. The `ARCHIVE` engine also supports the `AUTO_INCREMENT` table option in [`CREATE TABLE`](create-table.html) statements to specify the initial sequence value for a new table or reset the sequence value for an existing table, respectively.
`ARCHIVE` does not support inserting a value into an `AUTO_INCREMENT` column less than the current maximum column value. Attempts to do so result in an [`ER_DUP_KEY`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_dup_key) error.
The `ARCHIVE` engine ignores [`BLOB`](blob.html) columns if they are not requested and scans past them while reading.
The `ARCHIVE` storage engine does not support partitioning.
**Storage:** Rows are compressed as they are inserted. The `ARCHIVE` engine uses `zlib` lossless data compression (see [http://www.zlib.net/](http://www.zlib.net/)). You can use [`OPTIMIZE TABLE`](optimize-table.html) to analyze the table and pack it into a smaller format (for a reason to use [`OPTIMIZE TABLE`](optimize-table.html), see later in this section). The engine also supports [`CHECK TABLE`](check-table.html). There are several types of insertions that are used:
* An [`INSERT`](insert.html) statement just pushes rows into a compression buffer, and that buffer flushes as necessary. The insertion into the buffer is protected by a lock. A [`SELECT`](select.html) forces a flush to occur.
* A bulk insert is visible only after it completes, unless other inserts occur at the same time, in which case it can be seen partially. A [`SELECT`](select.html) never causes a flush of a bulk insert unless a normal insert occurs while it is loading.
**Retrieval**: On retrieval, rows are uncompressed on demand; there is no row cache. A [`SELECT`](select.html) operation performs a complete table scan: When a [`SELECT`](select.html) occurs, it finds out how many rows are currently available and reads that number of rows. [`SELECT`](select.html) is performed as a consistent read. Note that lots of [`SELECT`](select.html) statements during insertion can deteriorate the compression, unless only bulk inserts are used. To achieve better compression, you can use [`OPTIMIZE TABLE`](optimize-table.html) or [`REPAIR TABLE`](repair-table.html). The number of rows in `ARCHIVE` tables reported by [`SHOW TABLE STATUS`](show-table-status.html) is always accurate. See [Section 13.7.3.4, “OPTIMIZE TABLE Statement”](optimize-table.html), [Section 13.7.3.5, “REPAIR TABLE Statement”](repair-table.html), and [Section 13.7.7.38, “SHOW TABLE STATUS Statement”](show-table-status.html).
### Additional Resources
* A forum dedicated to the `ARCHIVE` storage engine is available at [https://forums.mysql.com/list.php?112](https://forums.mysql.com/list.php?112).
## 16.5 ARCHIVE 存储引擎
[](<>)[](<>)
`档案`存储引擎生成专用表,在很小的空间内存储大量未索引的数据。
[](<>)
**表 16.5 ARCHIVE 存储引擎功能**
| 特征 | 支持 |
| --- | --- |
| **B树索引** | 不 |
| **备份/时间点恢复**(在服务器中实现,而不是在存储引擎中。) | 是的 |
| **集群数据库支持** | 不 |
| **聚集索引** | 不 |
| **压缩数据** | 是的 |
| **数据缓存** | 不 |
| **加密数据** | 是(通过加密功能在服务器中实现。) |
| **外键支持** | 不 |
| **全文检索索引** | 不 |
| **地理空间数据类型支持** | 是的 |
| **地理空间索引支持** | 不 |
| **哈希索引** | 不 |
| **索引缓存** | 不 |
| **锁定粒度** | 排 |
| **MVCC** | 不 |
| **复制支持**(在服务器中实现,而不是在存储引擎中。) | 是的 |
| **存储限制** | 没有 |
| **T-树索引** | 不 |
| **交易** | 不 |
| **更新数据字典的统计信息** | 是的 |
`档案`存储引擎包含在 MySQL 二进制发行版中。如果您从源代码构建 MySQL,要启用此存储引擎,请调用**制作**[`-DWITH_ARCHIVE_STORAGE_ENGINE`](source-configuration-options.html#option_cmake_storage_engine_options)选项。
检查源`档案`发动机,看看`存储/归档`MySQL 源代码分发的目录。
您可以检查是否`档案`存储引擎可与[`显示引擎`](show-engines.html)陈述。
当你创建一个`档案`表,存储引擎创建名称以表名开头的文件。数据文件的扩展名为`.ARZ`.一个`.ARN`文件可能会在优化操作期间出现。
`档案`发动机支架[`插入`](insert.html),[`代替`](replace.html), 和[`选择`](select.html), 但不是[`删除`](delete.html)要么[`更新`](update.html).它确实支持`订购方式`操作,[`斑点`](blob.html)列和空间数据类型(请参阅[第 11.4.1 节,“空间数据类型”](spatial-type-overview.html))。不支持地理空间参考系统。这`档案`引擎使用行级锁定。
`档案`引擎支持`自动递增`列属性。这`自动递增`列可以有唯一或非唯一索引。尝试在任何其他列上创建索引会导致错误。这`档案`引擎还支持`自动递增`表选项在[`创建表`](create-table.html)语句分别指定新表的初始序列值或重置现有表的序列值。
`档案`不支持将值插入`自动递增`列小于当前最大列值。尝试这样做会导致[`ER_DUP_KEY`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_dup_key)错误。
`档案`引擎忽略[`斑点`](blob.html)如果没有请求它们,则在阅读时扫描它们。
`档案`存储引擎不支持分区。
**贮存:**行在插入时被压缩。这`档案`发动机用途`zlib`无损数据压缩(见<http://www.zlib.net/>)。您可以使用[`优化表`](optimize-table.html)分析表格并将其打包成更小的格式(出于使用的原因[`优化表`](optimize-table.html),见本节后面)。该引擎还支持[`检查表`](check-table.html).使用了几种类型的插入:
- 一个[`插入`](insert.html)语句只是将行推入压缩缓冲区,并根据需要刷新该缓冲区。插入缓冲区受锁保护。一种[`选择`](select.html)强制冲洗发生。
- 批量插入仅在完成后才可见,除非同时发生其他插入,在这种情况下可以部分看到它。一种[`选择`](select.html)除非在加载时发生正常插入,否则绝不会导致批量插入刷新。
**恢复**:检索时,行按需解压缩;没有行缓存。一种[`选择`](select.html)操作执行完整的表扫描:当一个[`选择`](select.html)发生时,它会找出当前可用的行数并读取该行数。[`选择`](select.html)作为一致读取执行。请注意,很多[`选择`](select.html)插入期间的语句会降低压缩性能,除非只使用批量插入。为了实现更好的压缩,您可以使用[`优化表`](optimize-table.html)要么[`维修台`](repair-table.html).中的行数`档案`报告的表格[`显示表状态`](show-table-status.html)总是准确的。看[第 13.7.3.4 节,“优化 TABLE 语句”](optimize-table.html),[第 13.7.3.5 节,“REPAIR TABLE 语句”](repair-table.html), 和[第 13.7.7.38 节,“SHOW TABLE STATUS 语句”](show-table-status.html).
### 其他资源
- 一个专门的论坛`档案`存储引擎可在<https://forums.mysql.com/list.php?112>.
## 16.6 The BLACKHOLE Storage Engine
[]()[]()
The `BLACKHOLE` storage engine acts as a “black hole” that accepts data but throws it away and does not store it. Retrievals always return an empty result:
```
mysql> CREATE TABLE test(i INT, c CHAR(10)) ENGINE = BLACKHOLE;
Query OK, 0 rows affected (0.03 sec)
mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM test;
Empty set (0.00 sec)
```
To enable the `BLACKHOLE` storage engine if you build MySQL from source, invoke **CMake** with the [`-DWITH_BLACKHOLE_STORAGE_ENGINE`](source-configuration-options.html#option_cmake_storage_engine_options) option.
To examine the source for the `BLACKHOLE` engine, look in the `sql` directory of a MySQL source distribution.
When you create a `BLACKHOLE` table, the server creates the table definition in the global data dictionary. There are no files associated with the table.
The `BLACKHOLE` storage engine supports all kinds of indexes. That is, you can include index declarations in the table definition.
The maximum key length is 3072 bytes as of MySQL 8.0.27. Prior to 8.0.27, the maximum key length is 1000 bytes.
The `BLACKHOLE` storage engine does not support partitioning.
You can check whether the `BLACKHOLE` storage engine is available with the [`SHOW ENGINES`](show-engines.html) statement.
Inserts into a `BLACKHOLE` table do not store any data, but if statement based binary logging is enabled, the SQL statements are logged and replicated to replica servers. This can be useful as a repeater or filter mechanism.
Suppose that your application requires replica-side filtering rules, but transferring all binary log data to the replica first results in too much traffic. In such a case, it is possible to set up on the replication source server a “dummy” replica process whose default storage engine is `BLACKHOLE`, depicted as follows:
[]()
**Figure 16.1 Replication using BLACKHOLE for Filtering**
<img alt="The replication source server uses a source mysqld process and a dummy mysqld process. On the replica, the mysqld process replicates from the dummy mysqld process." src="images/blackhole-1.png" height="300" width="575" />
The source writes to its binary log. The “dummy” [**mysqld**](mysqld.html) process acts as a replica, applying the desired combination of `replicate-do-*` and `replicate-ignore-*` rules, and writes a new, filtered binary log of its own. (See [Section 17.1.6, “Replication and Binary Logging Options and Variables”](replication-options.html).) This filtered log is provided to the replica.
The dummy process does not actually store any data, so there is little processing overhead incurred by running the additional [**mysqld**](mysqld.html) process on the replication source server. This type of setup can be repeated with additional replicas.
[`INSERT`](insert.html) triggers for `BLACKHOLE` tables work as expected. However, because the `BLACKHOLE` table does not actually store any data, [`UPDATE`](update.html) and [`DELETE`](delete.html) triggers are not activated: The `FOR EACH ROW` clause in the trigger definition does not apply because there are no rows.
Other possible uses for the `BLACKHOLE` storage engine include:
* Verification of dump file syntax.
* Measurement of the overhead from binary logging, by comparing performance using `BLACKHOLE` with and without binary logging enabled.
* `BLACKHOLE` is essentially a “no-op” storage engine, so it could be used for finding performance bottlenecks not related to the storage engine itself.
The `BLACKHOLE` engine is transaction-aware, in the sense that committed transactions are written to the binary log and rolled-back transactions are not.
**Blackhole Engine and Auto Increment Columns**
The `BLACKHOLE` engine is a no-op engine. Any operations performed on a table using `BLACKHOLE` have no effect. This should be borne in mind when considering the behavior of primary key columns that auto increment. The engine does not automatically increment field values, and does not retain auto increment field state. This has important implications in replication.
Consider the following replication scenario where all three of the following conditions apply:
1. On a source server there is a blackhole table with an auto increment field that is a primary key.
2. On a replica the same table exists but using the MyISAM engine.
3. Inserts are performed into the source's table without explicitly setting the auto increment value in the `INSERT` statement itself or through using a `SET INSERT_ID` statement.
In this scenario replication fails with a duplicate entry error on the primary key column.
In statement based replication, the value of `INSERT_ID` in the context event is always the same. Replication therefore fails due to trying insert a row with a duplicate value for a primary key column.
In row based replication, the value that the engine returns for the row always be the same for each insert. This results in the replica attempting to replay two insert log entries using the same value for the primary key column, and so replication fails.
**Column Filtering**
When using row-based replication, ([`binlog_format=ROW`](replication-options-binary-log.html#sysvar_binlog_format)), a replica where the last columns are missing from a table is supported, as described in the section [Section 17.5.1.9, “Replication with Differing Table Definitions on Source and Replica”](replication-features-differing-tables.html).
This filtering works on the replica side, that is, the columns are copied to the replica before they are filtered out. There are at least two cases where it is not desirable to copy the columns to the replica:
1. If the data is confidential, so the replica server should not have access to it.
2. If the source has many replicas, filtering before sending to the replicas may reduce network traffic.
Source column filtering can be achieved using the `BLACKHOLE` engine. This is carried out in a way similar to how source table filtering is achieved - by using the `BLACKHOLE` engine and the [`--replicate-do-table`](replication-options-replica.html#option_mysqld_replicate-do-table) or [`--replicate-ignore-table`](replication-options-replica.html#option_mysqld_replicate-ignore-table) option.
The setup for the source is:
```
CREATE TABLE t1 (public_col_1, ..., public_col_N,
secret_col_1, ..., secret_col_M) ENGINE=MyISAM;
```
The setup for the trusted replica is:
```
CREATE TABLE t1 (public_col_1, ..., public_col_N) ENGINE=BLACKHOLE;
```
The setup for the untrusted replica is:
```
CREATE TABLE t1 (public_col_1, ..., public_col_N) ENGINE=MyISAM;
```
## 16.6 黑洞存储引擎
[](<>)[](<>)
`黑洞`存储引擎充当“黑洞”,接受数据但将其丢弃而不存储。检索总是返回空结果:
```
mysql> CREATE TABLE test(i INT, c CHAR(10)) ENGINE = BLACKHOLE;
Query OK, 0 rows affected (0.03 sec)
mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM test;
Empty set (0.00 sec)
```
要启用`黑洞`存储引擎,如果你从源代码构建 MySQL,调用**制作**[`-DWITH_BLACKHOLE_STORAGE_ENGINE`](source-configuration-options.html#option_cmake_storage_engine_options)选项。
检查源`黑洞`发动机,看看`sql`MySQL 源代码分发的目录。
当你创建一个`黑洞`表,服务器在全局数据字典中创建表定义。没有与该表关联的文件。
`黑洞`存储引擎支持各种索引。也就是说,您可以在表定义中包含索引声明。
从 MySQL 8.0.27 开始,最大密钥长度为 3072 字节。在 8.0.27 之前,最大密钥长度为 1000 字节。
`黑洞`存储引擎不支持分区。
您可以检查是否`黑洞`存储引擎可与[`显示引擎`](show-engines.html)陈述。
插入一个`黑洞`table 不存储任何数据,但如果启用了基于语句的二进制日志记录,则会记录 SQL 语句并将其复制到副本服务器。这可用作中继器或过滤器机制。
假设您的应用程序需要副本端过滤规则,但首先将所有二进制日志数据传输到副本会导致流量过多。在这种情况下,可以在复制源服务器上设置一个“虚拟”副本进程,其默认存储引擎为`黑洞`,描绘如下:
[](<>)
**图 16.1 使用 BLACKHOLE 进行过滤的复制**
<img alt="The replication source server uses a source mysqld process and a dummy mysqld process. On the replica, the mysqld process replicates from the dummy mysqld process." src="images/blackhole-1.png" height="300" width="575" />
源写入其二进制日志。“假人”[**mysqld**](mysqld.html)过程充当复制品,应用所需的组合`复制做-*``复制忽略-*`规则,并写入自己的新过滤二进制日志。(看[第 17.1.6 节,“复制和二进制日志记录选项和变量”](replication-options.html).) 此过滤后的日志提供给副本。
虚拟进程实际上并不存储任何数据,因此运行附加进程所产生的处理开销很小[**mysqld**](mysqld.html)复制源服务器上的进程。可以使用其他副本重复这种类型的设置。
[`插入`](insert.html)触发`黑洞`表按预期工作。然而,由于`黑洞`表实际上并不存储任何数据,[`更新`](update.html)[`删除`](delete.html)触发器未激活:`每一行`触发器定义中的子句不适用,因为没有行。
其他可能的用途`黑洞`存储引擎包括:
- 验证转储文件语法。
- 通过比较性能来测量二进制日志记录的开销`黑洞`启用和不启用二进制日志记录。
- `黑洞`本质上是一个“无操作”的存储引擎,因此它可以用于查找与存储引擎本身无关的性能瓶颈。
这`黑洞`引擎是事务感知的,从某种意义上说,已提交的事务被写入二进制日志,而回滚事务则没有。
**黑洞引擎和自动增量列**
`黑洞`引擎是无操作引擎。使用对表执行的任何操作`黑洞`没有效果。在考虑自动递增的主键列的行为时,应牢记这一点。引擎不会自动递增字段值,也不会保留自动递增字段状态。这对复制具有重要意义。
考虑以下所有三个条件都适用的复制场景:
1. 在源服务器上,有一个黑洞表,其中包含一个作为主键的自动增量字段。
2. 在副本上存在同一个表,但使用的是 MyISAM 引擎。
3. 插入是在源表中执行的,而无需在`插入`声明本身或通过使用`设置 INSERT_ID`陈述。
在这种情况下,复制失败,主键列出现重复条目​​错误。
在基于语句的复制中,值`INSERT_ID`在上下文中事件总是相同的。因此,由于尝试为主键列插入具有重复值的行,复制失败。
在基于行的复制中,引擎为行返回的值对于每个插入始终是相同的。这导致副本尝试使用相同的主键列值重播两个插入日志条目,因此复制失败。
**列过滤**
使用基于行的复制时,([`binlog_format=行`](replication-options-binary-log.html#sysvar_binlog_format)),支持表中缺少最后一列的副本,如 部分所述[第 17.5.1.9 节,“在源和副本上具有不同表定义的复制”](replication-features-differing-tables.html).
此过滤在副本端起作用,即列在被过滤掉之前被复制到副本中。至少有两种情况不希望将列复制到副本:
1. 如果数据是机密的,那么副本服务器应该无权访问它。
2. 如果源有许多副本,则在发送到副本之前进行过滤可能会减少网络流量。
源列过滤可以使用`黑洞`引擎。这以类似于实现源表过滤的方式执行 - 通过使用`黑洞`发动机和[`--replicate-do-table`](replication-options-replica.html#option_mysqld_replicate-do-table)要么[`--复制忽略表`](replication-options-replica.html#option_mysqld_replicate-ignore-table)选项。
源的设置是:
```
CREATE TABLE t1 (public_col_1, ..., public_col_N,
secret_col_1, ..., secret_col_M) ENGINE=MyISAM;
```
受信任副本的设置是:
```
CREATE TABLE t1 (public_col_1, ..., public_col_N) ENGINE=BLACKHOLE;
```
不受信任副本的设置是:
```
CREATE TABLE t1 (public_col_1, ..., public_col_N) ENGINE=MyISAM;
```
#### 16.2.3.3 Compressed Table Characteristics
[]()[]()[]()[]()
Compressed storage format is a read-only format that is generated with the [**myisampack**](myisampack.html) tool. Compressed tables can be uncompressed with [**myisamchk**](myisamchk.html).
Compressed tables have the following characteristics:
* Compressed tables take very little disk space. This minimizes disk usage, which is helpful when using slow disks (such as CD-ROMs).
* Each row is compressed separately, so there is very little access overhead. The header for a row takes up one to three bytes depending on the biggest row in the table. Each column is compressed differently. There is usually a different Huffman tree for each column. Some of the compression types are:
* Suffix space compression.
* Prefix space compression.
* Numbers with a value of zero are stored using one bit.
* If values in an integer column have a small range, the column is stored using the smallest possible type. For example, a [`BIGINT`](integer-types.html) column (eight bytes) can be stored as a [`TINYINT`](integer-types.html) column (one byte) if all its values are in the range from `-128` to `127`.
* If a column has only a small set of possible values, the data type is converted to [`ENUM`](enum.html).
* A column may use any combination of the preceding compression types.
* Can be used for fixed-length or dynamic-length rows.
Note
While a compressed table is read only, and you cannot therefore update or add rows in the table, DDL (Data Definition Language) operations are still valid. For example, you may still use `DROP` to drop the table, and [`TRUNCATE TABLE`](truncate-table.html) to empty the table.
#### 16.2.3.3 压缩表特性
[](<>)[](<>)[](<>)[](<>)
压缩存储格式是一种只读格式,由[**myisampack**](myisampack.html)工具。压缩表可以用[**迈萨姆奇克**](myisamchk.html).
压缩表具有以下特点:
- 压缩表占用很少的磁盘空间。这最大限度地减少了磁盘使用,这在使用慢速磁盘(如 CD-ROM)时很有帮助。
- 每行都是单独压缩的,因此访问开销很小。根据表中最大的行,行的标题占用一到三个字节。每列的压缩方式不同。每列通常有一个不同的霍夫曼树。一些压缩类型是:
- 后缀空间压缩。
- 前缀空间压缩。
- 零值的数字使用一位存储。
- 如果整数列中的值范围较小,则使用可能的最小类型存储该列。例如,一个[`大整数`](integer-types.html)列(八个字节)可以存储为[`小音`](integer-types.html)列(一个字节),如果它的所有值都在范围内`-128`到`127`.
- 如果一列只有一小组可能的值,则数据类型转换为[`枚举`](enum.html).
- 列可以使用上述压缩类型的任意组合。
- 可用于固定长度或动态长度的行。
笔记
虽然压缩表是只读的,因此您无法在表中更新或添加行,但 DDL(数据定义语言)操作仍然有效。例如,您仍然可以使用`降低`放下桌子,然后[`截断表`](truncate-table.html)清空表。
#### 16.2.4.1 Corrupted MyISAM Tables
Even though the `MyISAM` table format is very reliable (all changes to a table made by an SQL statement are written before the statement returns), you can still get corrupted tables if any of the following events occur:
* The [**mysqld**](mysqld.html) process is killed in the middle of a write.
* An unexpected computer shutdown occurs (for example, the computer is turned off).
* Hardware failures.
* You are using an external program (such as [**myisamchk**](myisamchk.html)) to modify a table that is being modified by the server at the same time.
* A software bug in the MySQL or `MyISAM` code.
Typical symptoms of a corrupt table are:
* You get the following error while selecting data from the table:
```
Incorrect key file for table: '...'. Try to repair it
```
* Queries don't find rows in the table or return incomplete results.
You can check the health of a `MyISAM` table using the [`CHECK TABLE`](check-table.html) statement, and repair a corrupted `MyISAM` table with [`REPAIR TABLE`](repair-table.html). When [**mysqld**](mysqld.html) is not running, you can also check or repair a table with the [**myisamchk**](myisamchk.html) command. See [Section 13.7.3.2, “CHECK TABLE Statement”](check-table.html), [Section 13.7.3.5, “REPAIR TABLE Statement”](repair-table.html), and [Section 4.6.4, “myisamchk — MyISAM Table-Maintenance Utility”](myisamchk.html).
If your tables become corrupted frequently, you should try to determine why this is happening. The most important thing to know is whether the table became corrupted as a result of an unexpected server exit. You can verify this easily by looking for a recent `restarted mysqld` message in the error log. If there is such a message, it is likely that table corruption is a result of the server dying. Otherwise, corruption may have occurred during normal operation. This is a bug. You should try to create a reproducible test case that demonstrates the problem. See [Section B.3.3.3, “What to Do If MySQL Keeps Crashing”](crashing.html), and [Section 5.9, “Debugging MySQL”](debugging-mysql.html).
#### 16.2.4.1 损坏的 MyISAM 表
尽管`MyISAM`表格式非常可靠(SQL 语句对表的所有更改都在语句返回之前写入),如果发生以下任何事件,您仍然可以得到损坏的表:
-[**mysqld**](mysqld.html)进程在写入过程中被杀死。
- 发生意外的计算机关闭(例如,计算机已关闭)。
- 硬件故障。
- 您正在使用外部程序(例如[**迈萨姆奇克**](myisamchk.html)) 来修改同时被服务器修改的表。
- MySQL 中的软件错误或`MyISAM`代码。
损坏表的典型症状是:
- 从表中选择数据时出现以下错误:
```
Incorrect key file for table: '...'. Try to repair it
```
- 查询不会在表中找到行或返回不完整的结果。
你可以检查一个健康`MyISAM`表使用[`检查表`](check-table.html)声明,并修复损坏的`MyISAM`表与[`维修台`](repair-table.html).什么时候[**mysqld**](mysqld.html)没有运行,你也可以检查或修复一个表[**迈萨姆奇克**](myisamchk.html)命令。看[第 13.7.3.2 节,“CHECK TABLE 语句”](check-table.html),[第 13.7.3.5 节,“REPAIR TABLE 语句”](repair-table.html), 和[第 4.6.4 节,“myisamchk - MyISAM 表维护实用程序”](myisamchk.html).
如果您的表经常损坏,您应该尝试确定发生这种情况的原因。要知道的最重要的事情是表是否由于意外的服务器退出而损坏。您可以通过查找最近的`重启mysqld`错误日志中的消息。如果有这样的消息,很可能表损坏是服务器死机的结果。否则,可能在正常操作期间发生损坏。这是一个错误。您应该尝试创建一个可重现的测试用例来演示该问题。看[第 B.3.3.3 节,“如果 MySQL 不断崩溃怎么办”](crashing.html), 和[第 5.9 节,“调试 MySQL”](debugging-mysql.html).
## 16.4 The CSV Storage Engine
[16.4.1 Repairing and Checking CSV Tables](se-csv-repair.html)
[16.4.2 CSV Limitations](se-csv-limitations.html)
[]()[]()
The `CSV` storage engine stores data in text files using comma-separated values format.
The `CSV` storage engine is always compiled into the MySQL server.
To examine the source for the `CSV` engine, look in the `storage/csv` directory of a MySQL source distribution.
When you create a `CSV` table, the server creates a plain text data file having a name that begins with the table name and has a `.CSV` extension. When you store data into the table, the storage engine saves it into the data file in comma-separated values format.
```
mysql> CREATE TABLE test (i INT NOT NULL, c CHAR(10) NOT NULL)
ENGINE = CSV;
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.05 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM test;
+---+------------+
| i | c |
+---+------------+
| 1 | record one |
| 2 | record two |
+---+------------+
2 rows in set (0.00 sec)
```
Creating a `CSV` table also creates a corresponding metafile that stores the state of the table and the number of rows that exist in the table. The name of this file is the same as the name of the table with the extension `CSM`.
If you examine the `test.CSV` file in the database directory created by executing the preceding statements, its contents should look like this:
```
"1","record one"
"2","record two"
```
This format can be read, and even written, by spreadsheet applications such as Microsoft Excel.
## 16.4 CSV 存储引擎
[16.4.1 修复和检查 CSV 表](se-csv-repair.html)
[16.4.2 CSV 限制](se-csv-limitations.html)
[](<>)[](<>)
`CSV`存储引擎使用逗号分隔值格式将数据存储在文本文件中。
`CSV`存储引擎总是编译到 MySQL 服务器中。
检查源`CSV`发动机,看看`存储/csv`MySQL 源代码分发的目录。
当你创建一个`CSV`表,服务器创建一个纯文本数据文件,其名称以表名开头,并具有`.CSV`延期。当您将数据存储到表中时,存储引擎会将其以逗号分隔值格式保存到数据文件中。
```
mysql> CREATE TABLE test (i INT NOT NULL, c CHAR(10) NOT NULL)
ENGINE = CSV;
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two');
Query OK, 2 rows affected (0.05 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM test;
+---+------------+
| i | c |
+---+------------+
| 1 | record one |
| 2 | record two |
+---+------------+
2 rows in set (0.00 sec)
```
创建一个`CSV`table 还创建了一个相应的元文件,用于存储表的状态和表中存在的行数。此文件的名称与带有扩展名的表的名称相同`CSM`.
如果你检查`测试.CSV`执行上述语句创建的数据库目录中的文件,其内容应如下所示:
```
"1","record one"
"2","record two"
```
这种格式可以被 Microsoft Excel 等电子表格应用程序读取,甚至写入。
#### 16.2.3.2 Dynamic Table Characteristics
[]()[]()
Dynamic storage format is used if a `MyISAM` table contains any variable-length columns ([`VARCHAR`](char.html), [`VARBINARY`](binary-varbinary.html), [`BLOB`](blob.html), or [`TEXT`](blob.html)), or if the table was created with the `ROW_FORMAT=DYNAMIC` table option.
Dynamic format is a little more complex than static format because each row has a header that indicates how long it is. A row can become fragmented (stored in noncontiguous pieces) when it is made longer as a result of an update.
[]()
You can use [`OPTIMIZE TABLE`](optimize-table.html) or [**myisamchk -r**](myisamchk.html) to defragment a table. If you have fixed-length columns that you access or change frequently in a table that also contains some variable-length columns, it might be a good idea to move the variable-length columns to other tables just to avoid fragmentation.
Dynamic-format tables have these characteristics:
* All string columns are dynamic except those with a length less than four.
* Each row is preceded by a bitmap that indicates which columns contain the empty string (for string columns) or zero (for numeric columns). This does not include columns that contain `NULL` values. If a string column has a length of zero after trailing space removal, or a numeric column has a value of zero, it is marked in the bitmap and not saved to disk. Nonempty strings are saved as a length byte plus the string contents.
* `NULL` columns require additional space in the row to record whether their values are `NULL`. Each `NULL` column takes one bit extra, rounded up to the nearest byte.
* Much less disk space usually is required than for fixed-length tables.
* Each row uses only as much space as is required. However, if a row becomes larger, it is split into as many pieces as are required, resulting in row fragmentation. For example, if you update a row with information that extends the row length, the row becomes fragmented. In this case, you may have to run [`OPTIMIZE TABLE`](optimize-table.html) or [**myisamchk -r**](myisamchk.html) from time to time to improve performance. Use [**myisamchk -ei**](myisamchk.html) to obtain table statistics.
* More difficult than static-format tables to reconstruct after a crash, because rows may be fragmented into many pieces and links (fragments) may be missing.
* The expected row length for dynamic-sized rows is calculated using the following expression:
```
3
+ (number of columns + 7) / 8
+ (number of char columns)
+ (packed size of numeric columns)
+ (length of strings)
+ (number of NULL columns + 7) / 8
```
There is a penalty of 6 bytes for each link. A dynamic row is linked whenever an update causes an enlargement of the row. Each new link is at least 20 bytes, so the next enlargement probably goes in the same link. If not, another link is created. You can find the number of links using [**myisamchk -ed**](myisamchk.html). All links may be removed with [`OPTIMIZE TABLE`](optimize-table.html) or [**myisamchk -r**](myisamchk.html).
#### 16.2.3.2 动态表特征
[](<>)[](<>)
使用动态存储格式,如果`MyISAM`表包含任何可变长度列 ([`VARCHAR`](char.html),[`变量`](binary-varbinary.html),[`斑点`](blob.html), 要么[`文本`](blob.html)),或者如果表是使用`ROW_FORMAT=动态`表选项。
动态格式比静态格式稍微复杂一点,因为每一行都有一个标头来指示它的长度。当由于更新而使行变长时,行可能会变得碎片化(存储在不连续的片段中)。
[](<>)
您可以使用[`优化表`](optimize-table.html)要么[**myisamchk -r**](myisamchk.html)对表进行碎片整理。如果您在还包含一些可变长度列的表中经常访问或更改固定长度列,则最好将可变长度列移动到其他表中以避免碎片。
动态格式表具有以下特征:
- 除长度小于四的字符串外,所有字符串列都是动态的。
- 每行前面都有一个位图,指示哪些列包含空字符串(对于字符串列)或零(对于数字列)。这不包括包含`空值`价值观。如果删除尾随空格后字符串列的长度为零,或者数字列的值为零,则它会在位图中进行标记并且不会保存到磁盘。非空字符串保存为长度字节加上字符串内容。
- `空值`列在行中需要额外的空间来记录它们的值是否`空值`.每个`空值`column 需要额外的一位,四舍五入到最接近的字节。
- 与固定长度表相比,通常需要更少的磁盘空间。
- 每行仅使用所需的空间。但是,如果一行变大,它会被拆分为所需的多个部分,从而导致行碎片。例如,如果您使用扩展行长度的信息更新行,则该行将变得碎片化。在这种情况下,您可能需要运行[`优化表`](optimize-table.html)要么[**myisamchk -r**](myisamchk.html)不时提高性能。采用[**myisamchk-ei**](myisamchk.html)获取表统计信息。
- 崩溃后重建比静态格式表更困难,因为行可能会被分割成许多块并且链接(片段)可能会丢失。
- 使用以下表达式计算动态大小行的预期行长度:
```
3
+ (number of columns + 7) / 8
+ (number of char columns)
+ (packed size of numeric columns)
+ (length of strings)
+ (number of NULL columns + 7) / 8
```
每个链接有 6 个字节的惩罚。每当更新导致行扩大时,就会链接动态行。每个新链接至少有 20 个字节,因此下一次放大可能会在同一个链接中进行。如果不是,则创建另一个链接。您可以使用[**myisamchk 编辑**](myisamchk.html).所有链接都可以删除[`优化表`](optimize-table.html)要么[**myisamchk -r**](myisamchk.html).
## 16.9 The EXAMPLE Storage Engine
[]()[]()
The `EXAMPLE` storage engine is a stub engine that does nothing. Its purpose is to serve as an example in the MySQL source code that illustrates how to begin writing new storage engines. As such, it is primarily of interest to developers.
To enable the `EXAMPLE` storage engine if you build MySQL from source, invoke **CMake** with the [`-DWITH_EXAMPLE_STORAGE_ENGINE`](source-configuration-options.html#option_cmake_storage_engine_options) option.
To examine the source for the `EXAMPLE` engine, look in the `storage/example` directory of a MySQL source distribution.
When you create an `EXAMPLE` table, no files are created. No data can be stored into the table. Retrievals return an empty result.
```
mysql> CREATE TABLE test (i INT) ENGINE = EXAMPLE;
Query OK, 0 rows affected (0.78 sec)
mysql> INSERT INTO test VALUES(1),(2),(3);
ERROR 1031 (HY000): Table storage engine for 'test' doesn't »
have this option
mysql> SELECT * FROM test;
Empty set (0.31 sec)
```
The `EXAMPLE` storage engine does not support indexing.
The `EXAMPLE` storage engine does not support partitioning.
## 16.9 示例存储引擎
[](<>)[](<>)
`例子`存储引擎是一个不做任何事情的存根引擎。其目的是作为 MySQL 源代码中的示例,说明如何开始编写新的存储引擎。因此,它主要是开发人员感兴趣的。
要启用`例子`存储引擎,如果你从源代码构建 MySQL,调用**制作**[`-DWITH_EXAMPLE_STORAGE_ENGINE`](source-configuration-options.html#option_cmake_storage_engine_options)选项。
检查源`例子`发动机,看看`存储/示例`MySQL 源代码分发的目录。
当你创建一个`例子`表,没有文件被创建。没有数据可以存储到表中。检索返回空结果。
```
mysql> CREATE TABLE test (i INT) ENGINE = EXAMPLE;
Query OK, 0 rows affected (0.78 sec)
mysql> INSERT INTO test VALUES(1),(2),(3);
ERROR 1031 (HY000): Table storage engine for 'test' doesn't »
have this option
mysql> SELECT * FROM test;
Empty set (0.31 sec)
```
`例子`存储引擎不支持索引。
`例子`存储引擎不支持分区。
#### 16.8.2.1 Creating a FEDERATED Table Using CONNECTION
To use the first method, you must specify the `CONNECTION` string after the engine type in a [`CREATE TABLE`](create-table.html) statement. For example:
```
CREATE TABLE federated_table (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
other INT(20) NOT NULL DEFAULT '0',
PRIMARY KEY (id),
INDEX name (name),
INDEX other_key (other)
)
ENGINE=FEDERATED
DEFAULT CHARSET=utf8mb4
CONNECTION='mysql://fed_user@remote_host:9306/federated/test_table';
```
Note
`CONNECTION` replaces the `COMMENT` used in some previous versions of MySQL.
The `CONNECTION` string contains the information required to connect to the remote server containing the table in which the data physically resides. The connection string specifies the server name, login credentials, port number and database/table information. In the example, the remote table is on the server `remote_host`, using port 9306. The name and port number should match the host name (or IP address) and port number of the remote MySQL server instance you want to use as your remote table.
The format of the connection string is as follows:
```
scheme://user_name[:password]@host_name[:port_num]/db_name/tbl_name
```
Where:
* *`scheme`*: A recognized connection protocol. Only `mysql` is supported as the *`scheme`* value at this point.
* *`user_name`*: The user name for the connection. This user must have been created on the remote server, and must have suitable privileges to perform the required actions ([`SELECT`](select.html), [`INSERT`](insert.html), [`UPDATE`](update.html), and so forth) on the remote table.
* *`password`*: (Optional) The corresponding password for *`user_name`*.
* *`host_name`*: The host name or IP address of the remote server.
* *`port_num`*: (Optional) The port number for the remote server. The default is 3306.
* *`db_name`*: The name of the database holding the remote table.
* *`tbl_name`*: The name of the remote table. The name of the local and the remote table do not have to match.
Sample connection strings:
```
CONNECTION='mysql://username:password@hostname:port/database/tablename'
CONNECTION='mysql://username@hostname/database/tablename'
CONNECTION='mysql://username:password@hostname/database/tablename'
```
#### 16.8.2.1 Creating a FEDERATED Table Using CONNECTION
To use the first method, you must specify the`CONNECTION`string after the engine type in a[`CREATE TABLE`](create-table.html)statement. For example:
```
CREATE TABLE federated_table (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
other INT(20) NOT NULL DEFAULT '0',
PRIMARY KEY (id),
INDEX name (name),
INDEX other_key (other)
)
ENGINE=FEDERATED
DEFAULT CHARSET=utf8mb4
CONNECTION='mysql://fed_user@remote_host:9306/federated/test_table';
```
Note
`CONNECTION`replaces the`COMMENT`used in some previous versions of MySQL.
The`CONNECTION`string contains the information required to connect to the remote server containing the table in which the data physically resides. The connection string specifies the server name, login credentials, port number and database/table information. In the example, the remote table is on the server`remote_host`, using port 9306. The name and port number should match the host name (or IP address) and port number of the remote MySQL server instance you want to use as your remote table.
The format of the connection string is as follows:
```
scheme://user_name[:password]@host_name[:port_num]/db_name/tbl_name
```
Where:
- *`scheme`*: A recognized connection protocol. Only`mysql`is supported as the*`scheme`*此时的价值。
- *`用户名`*:连接的用户名。此用户必须已在远程服务器上创建,并且必须具有适当的权限才能执行所需的操作 ([`选择`](select.html),[`插入`](insert.html),[`更新`](update.html)等)在远程表上。
- *`密码`*:(可选)对应的密码*`用户名`*.
- *`主机名`*:远程服务器的主机名或IP地址。
- *`端口号`*:(可选)远程服务器的端口号。默认值为 3306。
- *`数据库名称`*: 保存远程表的数据库的名称。
- *`tbl_name`*:远程表的名称。本地和远程表的名称不必匹配。
示例连接字符串:
```
CONNECTION='mysql://username:password@hostname:port/database/tablename'
CONNECTION='mysql://username@hostname/database/tablename'
CONNECTION='mysql://username:password@hostname/database/tablename'
```
#### 16.8.2.2 Creating a FEDERATED Table Using CREATE SERVER
If you are creating a number of `FEDERATED` tables on the same server, or if you want to simplify the process of creating `FEDERATED` tables, you can use the [`CREATE SERVER`](create-server.html) statement to define the server connection parameters, just as you would with the `CONNECTION` string.
The format of the [`CREATE SERVER`](create-server.html) statement is:
```
CREATE SERVER
server_name
FOREIGN DATA WRAPPER wrapper_name
OPTIONS (option [, option] ...)
```
The *`server_name`* is used in the connection string when creating a new `FEDERATED` table.
For example, to create a server connection identical to the `CONNECTION` string:
```
CONNECTION='mysql://fed_user@remote_host:9306/federated/test_table';
```
You would use the following statement:
```
CREATE SERVER fedlink
FOREIGN DATA WRAPPER mysql
OPTIONS (USER 'fed_user', HOST 'remote_host', PORT 9306, DATABASE 'federated');
```
To create a `FEDERATED` table that uses this connection, you still use the `CONNECTION` keyword, but specify the name you used in the [`CREATE SERVER`](create-server.html) statement.
```
CREATE TABLE test_table (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
other INT(20) NOT NULL DEFAULT '0',
PRIMARY KEY (id),
INDEX name (name),
INDEX other_key (other)
)
ENGINE=FEDERATED
DEFAULT CHARSET=utf8mb4
CONNECTION='fedlink/test_table';
```
The connection name in this example contains the name of the connection (`fedlink`) and the name of the table (`test_table`) to link to, separated by a slash. If you specify only the connection name without a table name, the table name of the local table is used instead.
For more information on [`CREATE SERVER`](create-server.html), see [Section 13.1.18, “CREATE SERVER Statement”](create-server.html).
The [`CREATE SERVER`](create-server.html) statement accepts the same arguments as the `CONNECTION` string. The [`CREATE SERVER`](create-server.html) statement updates the rows in the `mysql.servers` table. See the following table for information on the correspondence between parameters in a connection string, options in the [`CREATE SERVER`](create-server.html) statement, and the columns in the `mysql.servers` table. For reference, the format of the `CONNECTION` string is as follows:
```
scheme://user_name[:password]@host_name[:port_num]/db_name/tbl_name
```
| Description |`CONNECTION` string|[`CREATE SERVER`](create-server.html) option|`mysql.servers` column|
|-----------------|-------------------|--------------------------------------------|----------------------|
|Connection scheme| *`scheme`* | `wrapper_name` | `Wrapper` |
| Remote user | *`user_name`* | `USER` | `Username` |
| Remote password | *`password`* | `PASSWORD` | `Password` |
| Remote host | *`host_name`* | `HOST` | `Host` |
| Remote port | *`port_num`* | `PORT` | `Port` |
| Remote database | *`db_name`* | `DATABASE` | `Db` |
#### 16.8.2.2 使用 CREATE SERVER 创建 FEDERATED 表
如果您正在创建多个`联邦`同一服务器上的表,或者如果您想简化创建过程`联邦`表,您可以使用[`创建服务器`](create-server.html)语句来定义服务器连接参数,就像使用`联系`细绳。
的格式[`创建服务器`](create-server.html)声明是:
```
CREATE SERVER
server_name
FOREIGN DATA WRAPPER wrapper_name
OPTIONS (option [, option] ...)
```
*`服务器名称`*在创建新的连接字符串中使用`联邦`桌子。
例如,要创建一个与`联系`细绳:
```
CONNECTION='mysql://fed_user@remote_host:9306/federated/test_table';
```
您将使用以下语句:
```
CREATE SERVER fedlink
FOREIGN DATA WRAPPER mysql
OPTIONS (USER 'fed_user', HOST 'remote_host', PORT 9306, DATABASE 'federated');
```
创建一个`联邦`使用此连接的表,您仍然使用`联系`关键字,但指定您在[`创建服务器`](create-server.html)陈述。
```
CREATE TABLE test_table (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
other INT(20) NOT NULL DEFAULT '0',
PRIMARY KEY (id),
INDEX name (name),
INDEX other_key (other)
)
ENGINE=FEDERATED
DEFAULT CHARSET=utf8mb4
CONNECTION='fedlink/test_table';
```
此示例中的连接名称包含连接的名称 (`联通`) 和表名 (`测试表`) 链接到,用斜杠分隔。如果只指定连接名而不指定表名,则使用本地表的表名。
有关更多信息[`创建服务器`](create-server.html), 看[第 13.1.18 节,“CREATE SERVER 语句”](create-server.html).
[`创建服务器`](create-server.html)语句接受与`联系`细绳。这[`创建服务器`](create-server.html)语句更新`mysql.servers`桌子。连接字符串中的参数、选项中的选项之间的对应关系见下表[`创建服务器`](create-server.html)语句,以及`mysql.servers`桌子。供参考,格式`联系`字符串如下:
```
scheme://user_name[:password]@host_name[:port_num]/db_name/tbl_name
```
| 描述 | `联系`细绳 | [`创建服务器`](create-server.html)选项 | `mysql.servers`柱子 |
| --- | ------ | ------------------------------- | ----------------- |
| 连接方案 | *`方案`* | `包装器名称` | `包装器` |
| 远程用户 | *`用户名`* | `用户` | `用户名` |
| 远程密码 | *`密码`* | `密码` | `密码` |
| 远程主机 | *`主机名`* | `主持人` | `主持人` |
| 远程端口 | *`端口号`* | `港口` | `港口` |
| 远程数据库 | *`数据库名称`* | `数据库` | `D b` |
### 16.8.2 How to Create FEDERATED Tables
[16.8.2.1 Creating a FEDERATED Table Using CONNECTION](federated-create-connection.html)
[16.8.2.2 Creating a FEDERATED Table Using CREATE SERVER](federated-create-server.html)
To create a `FEDERATED` table you should follow these steps:
1. Create the table on the remote server. Alternatively, make a note of the table definition of an existing table, perhaps using the [`SHOW CREATE TABLE`](show-create-table.html) statement.
2. Create the table on the local server with an identical table definition, but adding the connection information that links the local table to the remote table.
For example, you could create the following table on the remote server:
```
CREATE TABLE test_table (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
other INT(20) NOT NULL DEFAULT '0',
PRIMARY KEY (id),
INDEX name (name),
INDEX other_key (other)
)
ENGINE=MyISAM
DEFAULT CHARSET=utf8mb4;
```
To create the local table that is federated to the remote table, there are two options available. You can either create the local table and specify the connection string (containing the server name, login, password) to be used to connect to the remote table using the `CONNECTION`, or you can use an existing connection that you have previously created using the [`CREATE SERVER`](create-server.html) statement.
Important
When you create the local table it *must* have an identical field definition to the remote table.
Note
You can improve the performance of a `FEDERATED` table by adding indexes to the table on the host. The optimization occurs because the query sent to the remote server includes the contents of the `WHERE` clause and is sent to the remote server and subsequently executed locally. This reduces the network traffic that would otherwise request the entire table from the server for local processing.
### 16.8.2 如何创建联合表
[16.8.2.1 使用 CONNECTION 创建一个 FEDERATED 表](federated-create-connection.html)
[16.8.2.2 使用 CREATE SERVER 创建 FEDERATED 表](federated-create-server.html)
创建一个`联邦`表,您应该按照以下步骤操作:
1. 在远程服务器上创建表。或者,记下现有表的表定义,可能使用[`显示创建表`](show-create-table.html)陈述。
2. 在本地服务器上创建具有相同表定义的表,但添加将本地表链接到远程表的连接信息。
例如,您可以在远程服务器上创建下表:
```
CREATE TABLE test_table (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
other INT(20) NOT NULL DEFAULT '0',
PRIMARY KEY (id),
INDEX name (name),
INDEX other_key (other)
)
ENGINE=MyISAM
DEFAULT CHARSET=utf8mb4;
```
要创建与远程表联合的本地表,有两个选项可用。您可以创建本地表并指定用于连接远程表的连接字符串(包含服务器名称、登录名、密码),使用`联系`,或者您可以使用之前使用[`创建服务器`](create-server.html)陈述。
重要的
当您创建本地表时*必须*具有与远程表相同的字段定义。
笔记
您可以提高`联邦`通过向主机上的表添加索引来创建表。发生优化是因为发送到远程服务器的查询包括`在哪里`子句并被发送到远程服务器并随后在本地执行。这减少了网络流量,否则会从服务器请求整个表进行本地处理。
### 16.8.1 FEDERATED Storage Engine Overview
When you create a table using one of the standard storage engines (such as `MyISAM`, `CSV` or `InnoDB`), the table consists of the table definition and the associated data. When you create a `FEDERATED` table, the table definition is the same, but the physical storage of the data is handled on a remote server.
A `FEDERATED` table consists of two elements:
* A *remote server* with a database table, which in turn consists of the table definition (stored in the MySQL data dictionary) and the associated table. The table type of the remote table may be any type supported by the remote `mysqld` server, including `MyISAM` or `InnoDB`.
* A *local server* with a database table, where the table definition matches that of the corresponding table on the remote server. The table definition is stored in the data dictionary. There is no data file on the local server. Instead, the table definition includes a connection string that points to the remote table.
When executing queries and statements on a `FEDERATED` table on the local server, the operations that would normally insert, update or delete information from a local data file are instead sent to the remote server for execution, where they update the data file on the remote server or return matching rows from the remote server.
The basic structure of a `FEDERATED` table setup is shown in [Figure 16.2, “FEDERATED Table Structure”](federated-description.html#figure-se-federated-structure).
[]()
**Figure 16.2 FEDERATED Table Structure**
<img alt="Content is described in the surrounding text." src="images/se-federated-structure.png" height="392" width="384" />
When a client issues an SQL statement that refers to a `FEDERATED` table, the flow of information between the local server (where the SQL statement is executed) and the remote server (where the data is physically stored) is as follows:
1. The storage engine looks through each column that the `FEDERATED` table has and constructs an appropriate SQL statement that refers to the remote table.
2. The statement is sent to the remote server using the MySQL client API.
3. The remote server processes the statement and the local server retrieves any result that the statement produces (an affected-rows count or a result set).
4. If the statement produces a result set, each column is converted to internal storage engine format that the `FEDERATED` engine expects and can use to display the result to the client that issued the original statement.
The local server communicates with the remote server using MySQL client C API functions. It invokes [`mysql_real_query()`](https://dev.mysql.com/doc/c-api/8.0/en/mysql-real-query.html) to send the statement. To read a result set, it uses [`mysql_store_result()`](https://dev.mysql.com/doc/c-api/8.0/en/mysql-store-result.html) and fetches rows one at a time using [`mysql_fetch_row()`](https://dev.mysql.com/doc/c-api/8.0/en/mysql-fetch-row.html).
### 16.8.1 联合存储引擎概述
当您使用标准存储引擎之一创建表时(例如`MyISAM`,`CSV`要么`InnoDB`),表由表定义和相关数据组成。当你创建一个`联邦`表,表定义相同,但数据的物理存储在远程服务器上处理。
一种`联邦`表由两个元素组成:
- 一种*远程服务器*使用数据库表,该表又由表定义(存储在 MySQL 数据字典中)和关联的表组成。远程表的表类型可以是远程支持的任何类型`mysqld`服务器,包括`MyISAM`要么`InnoDB`.
- 一种*本地服务器*使用数据库表,其中表定义与远程服务器上相应表的定义匹配。表定义存储在数据字典中。本地服务器上没有数据文件。相反,表定义包含一个指向远程表的连接字符串。
在执行查询和语句时`联邦的`在本地服务器上,通常会从本地数据文件插入、更新或删除信息的操作会被发送到远程服务器执行,在远程服务器上更新数据文件或从远程服务器返回匹配行。
a的基本结构`联邦的`表格设置如所示[图16.2,“联邦表结构”](federated-description.html#figure-se-federated-structure).
[](<>)
**图16.2联邦表结构**
<img alt="Content is described in the surrounding text." src="images/se-federated-structure.png" height="392" width="384" />
当客户机发出引用`联邦的`表中,本地服务器(执行SQL语句的地方)和远程服务器(物理存储数据的地方)之间的信息流如下所示:
1. 存储引擎会查看`联邦的`表具有并构造了一个引用远程表的适当SQL语句。
2. 该语句使用MySQL客户端API发送到远程服务器。
3. 远程服务器处理该语句,本地服务器检索该语句生成的任何结果(受影响的行数或结果集)。
4. 如果语句生成一个结果集,则每个列都将转换为`联邦的`引擎期望并可以用于向发出原始语句的客户端显示结果。
本地服务器使用MySQL客户端C API函数与远程服务器通信。它调用[`mysql_real_query()`](https://dev.mysql.com/doc/c-api/8.0/en/mysql-real-query.html)发送声明。要读取结果集,它使用[`mysql_存储_结果()`](https://dev.mysql.com/doc/c-api/8.0/en/mysql-store-result.html)并使用[`mysql_fetch_row()`](https://dev.mysql.com/doc/c-api/8.0/en/mysql-fetch-row.html).
### 16.8.4 FEDERATED Storage Engine Resources
The following additional resources are available for the `FEDERATED` storage engine:
* A forum dedicated to the `FEDERATED` storage engine is available at [https://forums.mysql.com/list.php?105](https://forums.mysql.com/list.php?105).
### 16.8.4 联合存储引擎资源
以下附加资源可用于`联邦`存储引擎:
- 一个专门的论坛`联邦`存储引擎可在<https://forums.mysql.com/list.php?105>.
## 16.8 The FEDERATED Storage Engine
[16.8.1 FEDERATED Storage Engine Overview](federated-description.html)
[16.8.2 How to Create FEDERATED Tables](federated-create.html)
[16.8.3 FEDERATED Storage Engine Notes and Tips](federated-usagenotes.html)
[16.8.4 FEDERATED Storage Engine Resources](federated-storage-engine-resources.html)
[]()[]()
The `FEDERATED` storage engine lets you access data from a remote MySQL database without using replication or cluster technology. Querying a local `FEDERATED` table automatically pulls the data from the remote (federated) tables. No data is stored on the local tables.
To include the `FEDERATED` storage engine if you build MySQL from source, invoke **CMake** with the [`-DWITH_FEDERATED_STORAGE_ENGINE`](source-configuration-options.html#option_cmake_storage_engine_options) option.
The `FEDERATED` storage engine is not enabled by default in the running server; to enable `FEDERATED`, you must start the MySQL server binary using the `--federated` option.
To examine the source for the `FEDERATED` engine, look in the `storage/federated` directory of a MySQL source distribution.
## 16.8 联合存储引擎
[16.8.1 联邦存储引擎概述](federated-description.html)
[16.8.2 如何创建 FEDERATED 表](federated-create.html)
[16.8.3 联合存储引擎注意事项和提示](federated-usagenotes.html)
[16.8.4 联合存储引擎资源](federated-storage-engine-resources.html)
[](<>)[](<>)
`联邦`存储引擎允许您访问远程 MySQL 数据库中的数据,而无需使用复制或集群技术。查询本地`联邦`table 自动从远程(联合)表中提取数据。本地表上不存储任何数据。
包括`联邦`存储引擎,如果你从源代码构建 MySQL,调用**制作**[`-DWITH_FEDERATED_STORAGE_ENGINE`](source-configuration-options.html#option_cmake_storage_engine_options)选项。
`联邦`运行服务器默认不开启存储引擎;启用`联邦`,您必须使用以下命令启动 MySQL 服务器二进制文件`--联合的`选项。
检查源`联邦`发动机,看看`存储/联合`MySQL 源代码分发的目录。
### 16.8.3 FEDERATED Storage Engine Notes and Tips
You should be aware of the following points when using the `FEDERATED` storage engine:
* `FEDERATED` tables may be replicated to other replicas, but you must ensure that the replica servers are able to use the user/password combination that is defined in the `CONNECTION` string (or the row in the `mysql.servers` table) to connect to the remote server.
The following items indicate features that the `FEDERATED` storage engine does and does not support:
* The remote server must be a MySQL server.
* The remote table that a `FEDERATED` table points to *must* exist before you try to access the table through the `FEDERATED` table.
* It is possible for one `FEDERATED` table to point to another, but you must be careful not to create a loop.
* A `FEDERATED` table does not support indexes in the usual sense; because access to the table data is handled remotely, it is actually the remote table that makes use of indexes. This means that, for a query that cannot use any indexes and so requires a full table scan, the server fetches all rows from the remote table and filters them locally. This occurs regardless of any `WHERE` or `LIMIT` used with this [`SELECT`](select.html) statement; these clauses are applied locally to the returned rows.
Queries that fail to use indexes can thus cause poor performance and network overload. In addition, since returned rows must be stored in memory, such a query can also lead to the local server swapping, or even hanging.
* Care should be taken when creating a `FEDERATED` table since the index definition from an equivalent `MyISAM` or other table may not be supported. For example, creating a `FEDERATED` table fails if the table uses an index prefix on any [`VARCHAR`](char.html), [`TEXT`](blob.html) or [`BLOB`](blob.html) columns. The following definition using `MyISAM` is valid:
```
CREATE TABLE `T1`(`A` VARCHAR(100),UNIQUE KEY(`A`(30))) ENGINE=MYISAM;
```
The key prefix in this example is incompatible with the `FEDERATED` engine, and the equivalent statement fails:
```
CREATE TABLE `T1`(`A` VARCHAR(100),UNIQUE KEY(`A`(30))) ENGINE=FEDERATED
CONNECTION='MYSQL://127.0.0.1:3306/TEST/T1';
```
If possible, you should try to separate the column and index definition when creating tables on both the remote server and the local server to avoid these index issues.
* Internally, the implementation uses [`SELECT`](select.html), [`INSERT`](insert.html), [`UPDATE`](update.html), and [`DELETE`](delete.html), but not [`HANDLER`](handler.html).
* The `FEDERATED` storage engine supports [`SELECT`](select.html), [`INSERT`](insert.html), [`UPDATE`](update.html), [`DELETE`](delete.html), [`TRUNCATE TABLE`](truncate-table.html), and indexes. It does not support [`ALTER TABLE`](alter-table.html), or any Data Definition Language statements that directly affect the structure of the table, other than [`DROP TABLE`](drop-table.html). The current implementation does not use prepared statements.
* `FEDERATED` accepts [`INSERT ... ON DUPLICATE KEY UPDATE`](insert-on-duplicate.html) statements, but if a duplicate-key violation occurs, the statement fails with an error.
* Transactions are not supported.
* `FEDERATED` performs bulk-insert handling such that multiple rows are sent to the remote table in a batch, which improves performance. Also, if the remote table is transactional, it enables the remote storage engine to perform statement rollback properly should an error occur. This capability has the following limitations:
* The size of the insert cannot exceed the maximum packet size between servers. If the insert exceeds this size, it is broken into multiple packets and the rollback problem can occur.
* Bulk-insert handling does not occur for [`INSERT ... ON DUPLICATE KEY UPDATE`](insert-on-duplicate.html).
* There is no way for the `FEDERATED` engine to know if the remote table has changed. The reason for this is that this table must work like a data file that would never be written to by anything other than the database system. The integrity of the data in the local table could be breached if there was any change to the remote database.
* When using a `CONNECTION` string, you cannot use an '@' character in the password. You can get round this limitation by using the [`CREATE SERVER`](create-server.html) statement to create a server connection.
* The [`insert_id`](server-system-variables.html#sysvar_insert_id) and [`timestamp`](server-system-variables.html#sysvar_timestamp) options are not propagated to the data provider.
* Any [`DROP TABLE`](drop-table.html) statement issued against a `FEDERATED` table drops only the local table, not the remote table.
* User-defined partitioning is not supported for `FEDERATED` tables.
### 16.8.3 联合存储引擎注意事项和提示
使用时应注意以下几点`联邦`存储引擎:
- `联邦`表可以复制到其他副本,但您必须确保副本服务器能够使用在`联系`字符串(或`mysql.servers`表)连接到远程服务器。
以下各项表示功能,`联邦`存储引擎支持和不支持:
- 远程服务器必须是 MySQL 服务器。
- 一个远程表`联邦`表指向*必须*在您尝试通过`联邦`桌子。
- 一个是可能的`联邦`表指向另一个,但你必须小心不要创建一个循环。
- 一种`联邦`table 不支持通常意义上的索引;因为对表数据的访问是远程处理的,所以实际上是远程表使用了索引。这意味着,对于不能使用任何索引并因此需要全表扫描的查询,服务器会从远程表中获取所有行并在本地过滤它们。无论发生这种情况`在哪里`要么`限制`与此一起使用[`选择`](select.html)陈述;这些子句在本地应用于返回的行。
因此,未能使用索引的查询会导致性能不佳和网络过载。此外,由于返回的行必须存储在内存中,这样的查询也可能导致本地服务器交换,甚至挂起。
- 制作时应注意`联邦`表,因为索引定义来自等价`MyISAM`或其他表可能不受支持。例如,创建一个`联邦`如果表在任何表上使用索引前缀,表就会失败[`VARCHAR`](char.html),[`文本`](blob.html)要么[`斑点`](blob.html)列。以下定义使用`MyISAM`已验证:
```
CREATE TABLE `T1`(`A` VARCHAR(100),UNIQUE KEY(`A`(30))) ENGINE=MYISAM;
```
此示例中的键前缀与`联邦`引擎,等效语句失败:
```
CREATE TABLE `T1`(`A` VARCHAR(100),UNIQUE KEY(`A`(30))) ENGINE=FEDERATED
CONNECTION='MYSQL://127.0.0.1:3306/TEST/T1';
```
如果可能,您应该在远程服务器和本地服务器上创建表时尝试将列和索引定义分开,以避免这些索引问题。
- 在内部,实现使用[`选择`](select.html),[`插入`](insert.html),[`更新`](update.html), 和[`删除`](delete.html), 但不是[`处理程序`](handler.html).
-`联邦`存储引擎支持[`选择`](select.html),[`插入`](insert.html),[`更新`](update.html),[`删除`](delete.html),[`截断表`](truncate-table.html), 和索引。它不支持[`更改表`](alter-table.html),或任何直接影响表结构的数据定义语言语句,除了[`删除表`](drop-table.html).当前的实现不使用准备好的语句。
- `联邦`接受[`插入 ... 在重复密钥更新时`](insert-on-duplicate.html)语句,但如果发生重复键冲突,该语句将失败并出现错误。
- 不支持交易。
- `联邦`执行批量插入处理,以便将多行批量发送到远程表,从而提高性能。此外,如果远程表是事务性的,它使远程存储引擎能够在发生错误时正确执行语句回滚。此功能具有以下限制:
- 插入的大小不能超过服务器之间的最大数据包大小。如果插入超过这个大小,它会被分成多个数据包,并且可能会出现回滚问题。
- 批量插入处理不会发生[`插入 ... 在重复密钥更新时`](insert-on-duplicate.html).
- 没有办法`联邦`引擎知道远程表是否已更改。这样做的原因是该表必须像数据文件一样工作,除了数据库系统之外,其他任何东西都不会写入数据文件。如果远程数据库发生任何更改,则可能会破坏本地表中数据的完整性。
- 当使用一个`联系`字符串,您不能在密码中使用“@”字符。您可以通过使用[`创建服务器`](create-server.html)创建服务器连接的语句。
-[`insert_id`](server-system-variables.html#sysvar_insert_id)[`时间戳`](server-system-variables.html#sysvar_timestamp)选项不会传播到数据提供者。
- 任何[`删除表`](drop-table.html)针对某项发表的声明`联邦`table 只删除本地表,不删除远程表。
- 不支持用户定义的分区`联邦`表。
### 16.2.2 Space Needed for Keys
[]()
`MyISAM` tables use B-tree indexes. You can roughly calculate the size for the index file as `(key_length+4)/0.67`, summed over all keys. This is for the worst case when all keys are inserted in sorted order and the table doesn't have any compressed keys.
String indexes are space compressed. If the first index part is a string, it is also prefix compressed. Space compression makes the index file smaller than the worst-case figure if a string column has a lot of trailing space or is a [`VARCHAR`](char.html) column that is not always used to the full length. Prefix compression is used on keys that start with a string. Prefix compression helps if there are many strings with an identical prefix.
In `MyISAM` tables, you can also prefix compress numbers by specifying the `PACK_KEYS=1` table option when you create the table. Numbers are stored with the high byte first, so this helps when you have many integer keys that have an identical prefix.
### 16.2.2 键所需的空间
[](<>)
`MyISAM`表使用 B 树索引。您可以粗略地计算索引文件的大​​小为`(key_length+4)/0.67`,对所有键求和。当所有键都按排序顺序插入并且表没有任何压缩键时,这是最坏的情况。
字符串索引是空间压缩的。如果第一个索引部分是一个字符串,它也是前缀压缩的。如果字符串列有很多尾随空格或者是[`VARCHAR`](char.html)不总是使用全长的列。前缀压缩用于以字符串开头的键。如果有许多具有相同前缀的字符串,则前缀压缩会有所帮助。
`MyISAM`表,您还可以通过指定`PACK_KEYS=1`创建表时的表选项。数字首先以高字节存储,因此当您有许多具有相同前缀的整数键时,这会有所帮助。
## 16.3 The MEMORY Storage Engine
[]()[]()[]()[]()
The `MEMORY` storage engine (formerly known as `HEAP`) creates special-purpose tables with contents that are stored in memory. Because the data is vulnerable to crashes, hardware issues, or power outages, only use these tables as temporary work areas or read-only caches for data pulled from other tables.
[]()
**Table 16.4 MEMORY Storage Engine Features**
| Feature | Support |
|-------------------------------------------------------------------------------------------------|---------------------------------------------------------|
| **B-tree indexes** | Yes |
|**Backup/point-in-time recovery** (Implemented in the server, rather than in the storage engine.)| Yes |
| **Cluster database support** | No |
| **Clustered indexes** | No |
| **Compressed data** | No |
| **Data caches** | N/A |
| **Encrypted data** |Yes (Implemented in the server via encryption functions.)|
| **Foreign key support** | No |
| **Full-text search indexes** | No |
| **Geospatial data type support** | No |
| **Geospatial indexing support** | No |
| **Hash indexes** | Yes |
| **Index caches** | N/A |
| **Locking granularity** | Table |
| **MVCC** | No |
| **Replication support** (Implemented in the server, rather than in the storage engine.) | Limited (See the discussion later in this section.) |
| **Storage limits** | RAM |
| **T-tree indexes** | No |
| **Transactions** | No |
| **Update statistics for data dictionary** | Yes |
* [When to Use MEMORY or NDB Cluster](memory-storage-engine.html#memory-storage-engine-compared-cluster)
* [Partitioning](memory-storage-engine.html#memory-storage-engine-partitioning)
* [Performance Characteristics](memory-storage-engine.html#memory-storage-engine-performance-characteristics)
* [Characteristics of MEMORY Tables](memory-storage-engine.html#memory-storage-engine-characteristics-of-memory-tables)
* [DDL Operations for MEMORY Tables](memory-storage-engine.html#memory-storage-engine-ddl-operations-for-memory-tables)
* [Indexes](memory-storage-engine.html#memory-storage-engine-indexes)
* [User-Created and Temporary Tables](memory-storage-engine.html#memory-storage-engine-user-created-and-temporary-tables)
* [Loading Data](memory-storage-engine.html#memory-storage-engine-loading-data)
* [MEMORY Tables and Replication](memory-storage-engine.html#memory-tables-replication)
* [Managing Memory Use](memory-storage-engine.html#memory-storage-engine-managing-memory-use)
* [Additional Resources](memory-storage-engine.html#memory-storage-engine-additional-resources)
### When to Use MEMORY or NDB Cluster
Developers looking to deploy applications that use the `MEMORY` storage engine for important, highly available, or frequently updated data should consider whether NDB Cluster is a better choice. A typical use case for the `MEMORY` engine involves these characteristics:
* Operations involving transient, non-critical data such as session management or caching. When the MySQL server halts or restarts, the data in `MEMORY` tables is lost.
* In-memory storage for fast access and low latency. Data volume can fit entirely in memory without causing the operating system to swap out virtual memory pages.
* A read-only or read-mostly data access pattern (limited updates).
NDB Cluster offers the same features as the `MEMORY` engine with higher performance levels, and provides additional features not available with `MEMORY`:
* Row-level locking and multiple-thread operation for low contention between clients.
* Scalability even with statement mixes that include writes.
* Optional disk-backed operation for data durability.
* Shared-nothing architecture and multiple-host operation with no single point of failure, enabling 99.999% availability.
* Automatic data distribution across nodes; application developers need not craft custom sharding or partitioning solutions.
* Support for variable-length data types (including [`BLOB`](blob.html) and [`TEXT`](blob.html)) not supported by `MEMORY`.
### Partitioning
`MEMORY` tables cannot be partitioned.
### Performance Characteristics
`MEMORY` performance is constrained by contention resulting from single-thread execution and table lock overhead when processing updates. This limits scalability when load increases, particularly for statement mixes that include writes.
Despite the in-memory processing for `MEMORY` tables, they are not necessarily faster than [`InnoDB`](innodb-storage-engine.html) tables on a busy server, for general-purpose queries, or under a read/write workload. In particular, the table locking involved with performing updates can slow down concurrent usage of `MEMORY` tables from multiple sessions.
Depending on the kinds of queries performed on a `MEMORY` table, you might create indexes as either the default hash data structure (for looking up single values based on a unique key), or a general-purpose B-tree data structure (for all kinds of queries involving equality, inequality, or range operators such as less than or greater than). The following sections illustrate the syntax for creating both kinds of indexes. A common performance issue is using the default hash indexes in workloads where B-tree indexes are more efficient.
### Characteristics of MEMORY Tables
The `MEMORY` storage engine does not create any files on disk. The table definition is stored in the MySQL data dictionary.
`MEMORY` tables have the following characteristics:
* Space for `MEMORY` tables is allocated in small blocks. Tables use 100% dynamic hashing for inserts. No overflow area or extra key space is needed. No extra space is needed for free lists. Deleted rows are put in a linked list and are reused when you insert new data into the table. `MEMORY` tables also have none of the problems commonly associated with deletes plus inserts in hashed tables.
* `MEMORY` tables use a fixed-length row-storage format. Variable-length types such as [`VARCHAR`](char.html) are stored using a fixed length.
* `MEMORY` tables cannot contain [`BLOB`](blob.html) or [`TEXT`](blob.html) columns.
* `MEMORY` includes support for `AUTO_INCREMENT` columns.
* Non-`TEMPORARY` `MEMORY` tables are shared among all clients, just like any other non-`TEMPORARY` table.
### DDL Operations for MEMORY Tables
To create a `MEMORY` table, specify the clause `ENGINE=MEMORY` on the [`CREATE TABLE`](create-table.html) statement.
```
CREATE TABLE t (i INT) ENGINE = MEMORY;
```
As indicated by the engine name, `MEMORY` tables are stored in memory. They use hash indexes by default, which makes them very fast for single-value lookups, and very useful for creating temporary tables. However, when the server shuts down, all rows stored in `MEMORY` tables are lost. The tables themselves continue to exist because their definitions are stored in the MySQL data dictionary, but they are empty when the server restarts.
This example shows how you might create, use, and remove a `MEMORY` table:
```
mysql> CREATE TABLE test ENGINE=MEMORY
SELECT ip,SUM(downloads) AS down
FROM log_table GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;
```
The maximum size of `MEMORY` tables is limited by the [`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size) system variable, which has a default value of 16MB. To enforce different size limits for `MEMORY` tables, change the value of this variable. The value in effect for [`CREATE TABLE`](create-table.html), or a subsequent [`ALTER TABLE`](alter-table.html) or [`TRUNCATE TABLE`](truncate-table.html), is the value used for the life of the table. A server restart also sets the maximum size of existing `MEMORY` tables to the global [`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size) value. You can set the size for individual tables as described later in this section.
### Indexes
The `MEMORY` storage engine supports both `HASH` and `BTREE` indexes. You can specify one or the other for a given index by adding a `USING` clause as shown here:
```
CREATE TABLE lookup
(id INT, INDEX USING HASH (id))
ENGINE = MEMORY;
CREATE TABLE lookup
(id INT, INDEX USING BTREE (id))
ENGINE = MEMORY;
```
For general characteristics of B-tree and hash indexes, see [Section 8.3.1, “How MySQL Uses Indexes”](mysql-indexes.html).
`MEMORY` tables can have up to 64 indexes per table, 16 columns per index and a maximum key length of 3072 bytes.
If a `MEMORY` table hash index has a high degree of key duplication (many index entries containing the same value), updates to the table that affect key values and all deletes are significantly slower. The degree of this slowdown is proportional to the degree of duplication (or, inversely proportional to the index cardinality). You can use a `BTREE` index to avoid this problem.
`MEMORY` tables can have nonunique keys. (This is an uncommon feature for implementations of hash indexes.)
Columns that are indexed can contain `NULL` values.
### User-Created and Temporary Tables
`MEMORY` table contents are stored in memory, which is a property that `MEMORY` tables share with internal temporary tables that the server creates on the fly while processing queries. However, the two types of tables differ in that `MEMORY` tables are not subject to storage conversion, whereas internal temporary tables are:
* If an internal temporary table becomes too large, the server automatically converts it to on-disk storage, as described in [Section 8.4.4, “Internal Temporary Table Use in MySQL”](internal-temporary-tables.html).
* User-created `MEMORY` tables are never converted to disk tables.
### Loading Data
To populate a `MEMORY` table when the MySQL server starts, you can use the [`init_file`](server-system-variables.html#sysvar_init_file) system variable. For example, you can put statements such as [`INSERT INTO ... SELECT`](insert-select.html) or [`LOAD DATA`](load-data.html) into a file to load the table from a persistent data source, and use [`init_file`](server-system-variables.html#sysvar_init_file) to name the file. See [Section 5.1.8, “Server System Variables”](server-system-variables.html), and [Section 13.2.7, “LOAD DATA Statement”](load-data.html).
### MEMORY Tables and Replication
When a replication source server shuts down and restarts, its [`MEMORY`](memory-storage-engine.html) tables become empty. To replicate this effect to replicas, the first time that the source uses a given [`MEMORY`](memory-storage-engine.html) table after startup, it logs an event that notifies replicas that the table must be emptied by writing a [`DELETE`](delete.html) or (from MySQL 8.0.22) [`TRUNCATE TABLE`](truncate-table.html) statement for that table to the binary log. When a replica server shuts down and restarts, its [`MEMORY`](memory-storage-engine.html) tables also become empty, and it writes a [`DELETE`](delete.html) or (from MySQL 8.0.22) [`TRUNCATE TABLE`](truncate-table.html) statement to its own binary log, which is passed on to any downstream replicas.
When you use [`MEMORY`](memory-storage-engine.html) tables in a replication topology, in some situations, the table on the source and the table on the replica can differ. For information on handling each of these situations to prevent stale reads or errors, see [Section 17.5.1.21, “Replication and MEMORY Tables”](replication-features-memory.html).
### Managing Memory Use
The server needs sufficient memory to maintain all `MEMORY` tables that are in use at the same time.
Memory is not reclaimed if you delete individual rows from a `MEMORY` table. Memory is reclaimed only when the entire table is deleted. Memory that was previously used for deleted rows is re-used for new rows within the same table. To free all the memory used by a `MEMORY` table when you no longer require its contents, execute [`DELETE`](delete.html) or [`TRUNCATE TABLE`](truncate-table.html) to remove all rows, or remove the table altogether using [`DROP TABLE`](drop-table.html). To free up the memory used by deleted rows, use `ALTER TABLE ENGINE=MEMORY` to force a table rebuild.
The memory needed for one row in a `MEMORY` table is calculated using the following expression:
```
SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)
+ SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))
```
`ALIGN()` represents a round-up factor to cause the row length to be an exact multiple of the `char` pointer size. `sizeof(char*)` is 4 on 32-bit machines and 8 on 64-bit machines.
As mentioned earlier, the [`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size) system variable sets the limit on the maximum size of `MEMORY` tables. To control the maximum size for individual tables, set the session value of this variable before creating each table. (Do not change the global [`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size) value unless you intend the value to be used for `MEMORY` tables created by all clients.) The following example creates two `MEMORY` tables, with a maximum size of 1MB and 2MB, respectively:
```
mysql> SET max_heap_table_size = 1024*1024;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t1 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.01 sec)
mysql> SET max_heap_table_size = 1024*1024*2;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t2 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.00 sec)
```
Both tables revert to the server's global [`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size) value if the server restarts.
You can also specify a `MAX_ROWS` table option in [`CREATE TABLE`](create-table.html) statements for `MEMORY` tables to provide a hint about the number of rows you plan to store in them. This does not enable the table to grow beyond the [`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size) value, which still acts as a constraint on maximum table size. For maximum flexibility in being able to use `MAX_ROWS`, set [`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size) at least as high as the value to which you want each `MEMORY` table to be able to grow.
### Additional Resources
A forum dedicated to the `MEMORY` storage engine is available at [https://forums.mysql.com/list.php?92](https://forums.mysql.com/list.php?92).
## 16.3 MEMORY 存储引擎
[](<>)[](<>)[](<>)[](<>)
`记忆`存储引擎(以前称为`堆`) 创建具有存储在内存中的内容的专用表。由于数据容易受到崩溃、硬件问题或断电的影响,因此只能将这些表用作临时工作区或只读缓存,用于从其他表中提取的数据。
[](<>)
**表 16.4 内存存储引擎特性**
| 特征 | 支持 |
| --- | --- |
| **B树索引** | 是的 |
| **备份/时间点恢复**(在服务器中实现,而不是在存储引擎中。) | 是的 |
| **集群数据库支持** | 不 |
| **聚集索引** | 不 |
| **压缩数据** | 不 |
| **数据缓存** | 不适用 |
| **加密数据** | 是(通过加密功能在服务器中实现。) |
| **外键支持** | 不 |
| **全文检索索引** | 不 |
| **地理空间数据类型支持** | 不 |
| **地理空间索引支持** | 不 |
| **哈希索引** | 是的 |
| **索引缓存** | 不适用 |
| **锁定粒度** | 桌子 |
| **MVCC** | 不 |
| **复制支持**(在服务器中实现,而不是在存储引擎中。) | 有限(参见本节后面的讨论。) |
| **存储限制** | 内存 |
| **T-树索引** | 不 |
| **交易** | 不 |
| **更新数据字典的统计信息** | 是的 |
- [何时使用 MEMORY 或 NDB Cluster](memory-storage-engine.html#memory-storage-engine-compared-cluster)
- [分区](memory-storage-engine.html#memory-storage-engine-partitioning)
- [性能特点](memory-storage-engine.html#memory-storage-engine-performance-characteristics)
- [MEMORY 表的特征](memory-storage-engine.html#memory-storage-engine-characteristics-of-memory-tables)
- [MEMORY 表的 DDL 操作](memory-storage-engine.html#memory-storage-engine-ddl-operations-for-memory-tables)
- [索引](memory-storage-engine.html#memory-storage-engine-indexes)
- [用户创建的临时表](memory-storage-engine.html#memory-storage-engine-user-created-and-temporary-tables)
- [加载数据中](memory-storage-engine.html#memory-storage-engine-loading-data)
- [内存表和复制](memory-storage-engine.html#memory-tables-replication)
- [管理内存使用](memory-storage-engine.html#memory-storage-engine-managing-memory-use)
- [其他资源](memory-storage-engine.html#memory-storage-engine-additional-resources)
### 何时使用 MEMORY 或 NDB Cluster
希望部署使用`记忆`重要、高可用或经常更新数据的存储引擎应考虑 NDB Cluster 是否是更好的选择。一个典型的用例`记忆`引擎涉及以下特性:
- 涉及瞬态、非关键数据的操作,例如会话管理或缓存。当 MySQL 服务器停止或重新启动时,`记忆`表丢失。
- 内存存储,可实现快速访问和低延迟。数据量可以完全适合内存,而不会导致操作系统换出虚拟内存页面。
- 只读或以读取为主的数据访问模式(有限更新)。
NDB Cluster 提供与`记忆`引擎具有更高的性能水平,并提供其他功能不可用`记忆`:
- 用于客户端之间低争用的行级锁定和多线程操作。
- 即使是包含写入的语句混合也具有可伸缩性。
- 用于数据持久性的可选磁盘支持操作。
- 无共享架构和多主机操作,无单点故障,可实现 99.999% 的可用性。
- 跨节点的自动数据分发;应用程序开发人员不需要制作自定义分片或分区解决方案。
- 支持可变长度数据类型(包括[`BLOB`](blob.html)and[`TEXT`](blob.html)) not supported by`MEMORY`.
### Partitioning
`MEMORY`tables cannot be partitioned.
### Performance Characteristics
`MEMORY`performance is constrained by contention resulting from single-thread execution and table lock overhead when processing updates. This limits scalability when load increases, particularly for statement mixes that include writes.
Despite the in-memory processing for`MEMORY`tables, they are not necessarily faster than[`InnoDB`](innodb-storage-engine.html)tables on a busy server, for general-purpose queries, or under a read/write workload. In particular, the table locking involved with performing updates can slow down concurrent usage of`MEMORY`tables from multiple sessions.
Depending on the kinds of queries performed on a`MEMORY`table, you might create indexes as either the default hash data structure (for looking up single values based on a unique key), or a general-purpose B-tree data structure (for all kinds of queries involving equality, inequality, or range operators such as less than or greater than). The following sections illustrate the syntax for creating both kinds of indexes. A common performance issue is using the default hash indexes in workloads where B-tree indexes are more efficient.
### Characteristics of MEMORY Tables
The`MEMORY`storage engine does not create any files on disk. The table definition is stored in the MySQL data dictionary.
`MEMORY`tables have the following characteristics:
- 空间`记忆`表被分配在小块中。表对插入使用 100% 动态散列。不需要溢出区域或额外的键空间。空闲列表不需要额外的空间。删除的行被放在一个链表中,并在您向表中插入新数据时重复使用。`记忆`表也​​没有通常与哈希表中的删除和插入相关的问题。
- `记忆`表使用固定长度的行存储格式。可变长度类型,例如[`VARCHAR`](char.html)使用固定长度存储。
- `记忆`表不能包含[`斑点`](blob.html)要么[`文本`](blob.html)列。
- `记忆`包括支持`自动递增`列。
- 非-`暂时的` `记忆`表在所有客户端之间共享,就像任何其他非`暂时的`桌子。
### MEMORY 表的 DDL 操作
创建一个`记忆`表,指定子句`引擎=内存`[`创建表`](create-table.html)陈述。
```
CREATE TABLE t (i INT) ENGINE = MEMORY;
```
如引擎名称所示,`记忆`表存储在内存中。它们默认使用哈希索引,这使得它们对于单值查找非常快,并且对于创建临时表非常有用。但是,当服务器关闭时,所有存储在`记忆`表丢失。表本身继续存在,因为它们的定义存储在 MySQL 数据字典中,但在服务器重新启动时它们是空的。
此示例展示了如何创建、使用和删除`记忆`桌子:
```
mysql> CREATE TABLE test ENGINE=MEMORY
SELECT ip,SUM(downloads) AS down
FROM log_table GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;
```
最大尺寸`记忆`表是由[`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size)系统变量,默认值为 16MB。强制执行不同的大小限制`记忆`表,更改此变量的值。有效值[`创建表`](create-table.html),或随后的[`更改表`](alter-table.html)要么[`截断表`](truncate-table.html), 是用于表生命周期的值。服务器重新启动还会设置现有的最大大小`记忆`表到全球[`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size)价值。您可以设置单个表格的大小,如本节后面所述。
### 索引
`记忆`存储引擎同时支持`哈希``BTREE`索引。您可以通过添加一个给定索引指定一个或另一个`使用`子句如下所示:
```
CREATE TABLE lookup
(id INT, INDEX USING HASH (id))
ENGINE = MEMORY;
CREATE TABLE lookup
(id INT, INDEX USING BTREE (id))
ENGINE = MEMORY;
```
有关 B 树和哈希索引的一般特征,请参阅[第 8.3.1 节,“MySQL 如何使用索引”](mysql-indexes.html).
`记忆`每个表最多可以有 64 个索引,每个索引 16 列,最大键长度为 3072 字节。
如果一个`记忆`表哈希索引具有高度的键重复(许多索引条目包含相同的值),对影响键值的表的更新和所有删除都明显变慢。这种放缓的程度与重复程度成正比(或与索引基数成反比)。你可以使用一个`BTREE`索引来避免这个问题。
`记忆`表可以有非唯一键。(对于哈希索引的实现来说,这是一个不常见的特性。)
被索引的列可以包含`空值`价值观。
### 用户创建的临时表
`记忆`表内容存储在内存中,这是一个属性`记忆`表与服务器在处理查询时动态创建的内部临时表共享。但是,这两种类型的表的不同之处在于`记忆`表不受存储转换的影响,而内部临时表是:
- 如果内部临时表变得太大,服务器会自动将其转换为磁盘存储,如中所述[第 8.4.4 节,“MySQL 中的内部临时表使用”](internal-temporary-tables.html).
- 用户创建`记忆`表永远不会转换为磁盘表。
### 加载数据中
填充一个`记忆`MySQL 服务器启动时的表,您可以使用[`初始化文件`](server-system-variables.html#sysvar_init_file)系统变量。例如,您可以将语句如[`插入...选择`](insert-select.html)要么[`加载数据`](load-data.html)到文件中以从持久数据源加载表,并使用[`初始化文件`](server-system-variables.html#sysvar_init_file)命名文件。看[第 5.1.8 节,“服务器系统变量”](server-system-variables.html), 和[第 13.2.7 节,“加载数据语句”](load-data.html).
### 内存表和复制
当复制源服务器关闭并重新启动时,其[`记忆`](memory-storage-engine.html)表变空。要将这种效果复制到副本,源第一次使用给定的[`记忆`](memory-storage-engine.html)表启动后,它会记录一个事件,通知副本必须通过写入一个表来清空表[`删除`](delete.html)或(来自 MySQL 8.0.22)[`截断表`](truncate-table.html)将该表的语句写入二进制日志。当副本服务器关闭并重新启动时,它的[`记忆`](memory-storage-engine.html)表也​​变空了,它写了一个[`删除`](delete.html)或(来自 MySQL 8.0.22)[`截断表`](truncate-table.html)声明到它自己的二进制日志,它被传递到任何下游副本。
当你使用[`记忆`](memory-storage-engine.html)复制拓扑中的表,在某些情况下,源上的表和副本上的表可能不同。有关处理每种情况以防止过时读取或错误的信息,请参阅[第 17.5.1.21 节,“复制和内存表”](replication-features-memory.html).
### 管理内存使用
服务器需要足够的内存来维护所有`记忆`同时使用的表。
如果您从`记忆`桌子。只有当整个表被删除时才会回收内存。以前用于删除行的内存将重新用于同一表中的新行。释放所有使用的内存`记忆`当您不再需要表的内容时,执行[`删除`](delete.html)要么[`截断表`](truncate-table.html)删除所有行,或使用完全删除表[`删除表`](drop-table.html).要释放已删除行使用的内存,请使用`更改表引擎=内存`强制重建表。
一行中需要的内存`记忆`使用以下表达式计算表:
```
SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)
+ SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))
```
`对齐()`表示一个舍入因子,以使行长度成为行长度的精确倍数`字符`指针大小。`大小(字符*)`在 32 位机器上为 4,在 64 位机器上为 8。
如前所述,[`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size)系统变量设置最大大小的限制`记忆`表。要控制单个表的最大大小,请在创建每个表之前设置此变量的会话值。(不要改变全局[`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size)值,除非您打算将该值用于`记忆`所有客户端创建的表。)以下示例创建两个`记忆`表,最大大小分别为 1MB 和 2MB:
```
mysql> SET max_heap_table_size = 1024*1024;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t1 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.01 sec)
mysql> SET max_heap_table_size = 1024*1024*2;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t2 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.00 sec)
```
两个表都恢复到服务器的全局[`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size)服务器重新启动时的值。
您还可以指定一个`MAX_ROWS`表选项在[`创建表`](create-table.html)声明为`记忆`表以提供有关您计划在其中存储的行数的提示。这不会使表超出[`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size)值,它仍然作为最大表大小的约束。为了能够使用的最大灵活性`MAX_ROWS`, 放[`max_heap_table_size`](server-system-variables.html#sysvar_max_heap_table_size)至少与您希望每个的值一样高`记忆`表能够增长。
### 其他资源
一个专门的论坛`记忆`存储引擎可在<https://forums.mysql.com/list.php?92>.
## 16.7 The MERGE Storage Engine
[16.7.1 MERGE Table Advantages and Disadvantages](merge-table-advantages.html)
[16.7.2 MERGE Table Problems](merge-table-problems.html)
[]()[]()[]()[]()[]()
The `MERGE` storage engine, also known as the `MRG_MyISAM` engine, is a collection of identical `MyISAM` tables that can be used as one. “Identical” means that all tables have identical column data types and index information. You cannot merge `MyISAM` tables in which the columns are listed in a different order, do not have exactly the same data types in corresponding columns, or have the indexes in different order. However, any or all of the `MyISAM` tables can be compressed with [**myisampack**](myisampack.html). See [Section 4.6.6, “myisampack — Generate Compressed, Read-Only MyISAM Tables”](myisampack.html). Differences between tables such as these do not matter:
* Names of corresponding columns and indexes can differ.
* Comments for tables, columns, and indexes can differ.
* Table options such as `AVG_ROW_LENGTH`, `MAX_ROWS`, or `PACK_KEYS` can differ.
An alternative to a `MERGE` table is a partitioned table, which stores partitions of a single table in separate files and enables some operations to be performed more efficiently. For more information, see [Chapter 24, *Partitioning*](partitioning.html).
When you create a `MERGE` table, MySQL creates a `.MRG` file on disk that contains the names of the underlying `MyISAM` tables that should be used as one. The table format of the `MERGE` table is stored in the MySQL data dictionary. The underlying tables do not have to be in the same database as the `MERGE` table.
You can use [`SELECT`](select.html), [`DELETE`](delete.html), [`UPDATE`](update.html), and [`INSERT`](insert.html) on `MERGE` tables. You must have [`SELECT`](privileges-provided.html#priv_select), [`DELETE`](privileges-provided.html#priv_delete), and [`UPDATE`](privileges-provided.html#priv_update) privileges on the `MyISAM` tables that you map to a `MERGE` table.
Note
The use of `MERGE` tables entails the following security issue: If a user has access to `MyISAM` table *`t`*, that user can create a `MERGE` table *`m`* that accesses *`t`*. However, if the user's privileges on *`t`* are subsequently revoked, the user can continue to access *`t`* by doing so through *`m`*.
Use of [`DROP TABLE`](drop-table.html) with a `MERGE` table drops only the `MERGE` specification. The underlying tables are not affected.
To create a `MERGE` table, you must specify a `UNION=(*`list-of-tables`*)` option that indicates which `MyISAM` tables to use. You can optionally specify an `INSERT_METHOD` option to control how inserts into the `MERGE` table take place. Use a value of `FIRST` or `LAST` to cause inserts to be made in the first or last underlying table, respectively. If you specify no `INSERT_METHOD` option or if you specify it with a value of `NO`, inserts into the `MERGE` table are not permitted and attempts to do so result in an error.
The following example shows how to create a `MERGE` table:
```
mysql> CREATE TABLE t1 (
-> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> message CHAR(20)) ENGINE=MyISAM;
mysql> CREATE TABLE t2 (
-> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> message CHAR(20)) ENGINE=MyISAM;
mysql> INSERT INTO t1 (message) VALUES ('Testing'),('table'),('t1');
mysql> INSERT INTO t2 (message) VALUES ('Testing'),('table'),('t2');
mysql> CREATE TABLE total (
-> a INT NOT NULL AUTO_INCREMENT,
-> message CHAR(20), INDEX(a))
-> ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
```
Column `a` is indexed as a `PRIMARY KEY` in the underlying `MyISAM` tables, but not in the `MERGE` table. There it is indexed but not as a `PRIMARY KEY` because a `MERGE` table cannot enforce uniqueness over the set of underlying tables. (Similarly, a column with a `UNIQUE` index in the underlying tables should be indexed in the `MERGE` table but not as a `UNIQUE` index.)
After creating the `MERGE` table, you can use it to issue queries that operate on the group of tables as a whole:
```
mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table |
| 3 | t1 |
| 1 | Testing |
| 2 | table |
| 3 | t2 |
+---+---------+
```
To remap a `MERGE` table to a different collection of `MyISAM` tables, you can use one of the following methods:
* `DROP` the `MERGE` table and re-create it.
* Use `ALTER TABLE *`tbl_name`* UNION=(...)` to change the list of underlying tables.
It is also possible to use `ALTER TABLE ... UNION=()` (that is, with an empty [`UNION`](union.html) clause) to remove all of the underlying tables. However, in this case, the table is effectively empty and inserts fail because there is no underlying table to take new rows. Such a table might be useful as a template for creating new `MERGE` tables with [`CREATE TABLE ... LIKE`](create-table-like.html).
The underlying table definitions and indexes must conform closely to the definition of the `MERGE` table. Conformance is checked when a table that is part of a `MERGE` table is opened, not when the `MERGE` table is created. If any table fails the conformance checks, the operation that triggered the opening of the table fails. This means that changes to the definitions of tables within a `MERGE` may cause a failure when the `MERGE` table is accessed. The conformance checks applied to each table are:
* The underlying table and the `MERGE` table must have the same number of columns.
* The column order in the underlying table and the `MERGE` table must match.
* Additionally, the specification for each corresponding column in the parent `MERGE` table and the underlying tables are compared and must satisfy these checks:
* The column type in the underlying table and the `MERGE` table must be equal.
* The column length in the underlying table and the `MERGE` table must be equal.
* The column of the underlying table and the `MERGE` table can be `NULL`.
* The underlying table must have at least as many indexes as the `MERGE` table. The underlying table may have more indexes than the `MERGE` table, but cannot have fewer.
Note
A known issue exists where indexes on the same columns must be in identical order, in both the `MERGE` table and the underlying `MyISAM` table. See Bug #33653.
Each index must satisfy these checks:
* The index type of the underlying table and the `MERGE` table must be the same.
* The number of index parts (that is, multiple columns within a compound index) in the index definition for the underlying table and the `MERGE` table must be the same.
* For each index part:
* Index part lengths must be equal.
* Index part types must be equal.
* Index part languages must be equal.
* Check whether index parts can be `NULL`.
If a `MERGE` table cannot be opened or used because of a problem with an underlying table, [`CHECK TABLE`](check-table.html) displays information about which table caused the problem.
### Additional Resources
* A forum dedicated to the `MERGE` storage engine is available at [https://forums.mysql.com/list.php?93](https://forums.mysql.com/list.php?93).
## 16.7 MERGE 存储引擎
[16.7.1 MERGE 表的优缺点](merge-table-advantages.html)
[16.7.2 合并表问题](merge-table-problems.html)
[](<>)[](<>)[](<>)[](<>)[](<>)
`合并`存储引擎,也称为`MRG_MyISAM`引擎,是相同的集合`MyISAM`可以作为一张桌子使用。“相同”意味着所有表都具有相同的列数据类型和索引信息。你不能合并`MyISAM`列以不同顺序列出的表,对应列中的数据类型不完全相同,或者索引的顺序不同。然而,任何或所有`MyISAM`表可以压缩[**myisampack**](myisampack.html).看[第 4.6.6 节,“myisampack - 生成压缩的只读 MyISAM 表”](myisampack.html).诸如此类的表之间的差异无关紧要:
- 对应列和索引的名称可以不同。
- 表、列和索引的注释可能不同。
- 表选项,例如`AVG_ROW_LENGTH`,`MAX_ROWS`, 要么`PACK_KEYS`可以不同。
一个替代品`合并`table 是一个分区表,它将单个表的分区存储在单独的文件中,并使某些操作能够更有效地执行。有关详细信息,请参阅[第 24 章,*分区*](partitioning.html).
当你创建一个`合并`表,MySQL 创建一个`.MRG`磁盘上包含底层证券名称的文件`MyISAM`应该作为一个表使用。表格的格式`合并`表存储在 MySQL 数据字典中。基础表不必与`合并`桌子。
您可以使用[`选择`](select.html),[`删除`](delete.html),[`更新`](update.html), 和[`插入`](insert.html)在`合并`表。你必须有[`选择`](privileges-provided.html#priv_select),[`删除`](privileges-provided.html#priv_delete), 和[`更新`](privileges-provided.html#priv_update)上的特权`MyISAM`您映射到的表`合并`桌子。
笔记
指某东西的用途`合并`表会带来以下安全问题:如果用户有权访问`MyISAM`桌子*`吨`*,该用户可以创建一个`合并`桌子*`米`*访问*`吨`*.但是,如果用户的权限*`吨`*随后被撤销,用户可以继续访问*`吨`*通过这样做*`米`*.
用于[`删除表`](drop-table.html)`合并`表只删除`合并`规格。基础表不受影响。
创建一个`合并`表,您必须指定一个`联合=(*`表列表`*)`指示哪个选项`MyISAM`要使用的表。您可以选择指定一个`插入方法`控制如何插入的选项`合并`表发生。使用值`第一的`要么`最后的`分别在第一个或最后一个基础表中进行插入。如果您指定否`插入方法`选项,或者如果您将其指定为`不`, 插入`合并`table 是不允许的,尝试这样做会导致错误。
下面的例子展示了如何创建一个`合并`桌子:
```
mysql> CREATE TABLE t1 (
-> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> message CHAR(20)) ENGINE=MyISAM;
mysql> CREATE TABLE t2 (
-> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> message CHAR(20)) ENGINE=MyISAM;
mysql> INSERT INTO t1 (message) VALUES ('Testing'),('table'),('t1');
mysql> INSERT INTO t2 (message) VALUES ('Testing'),('table'),('t2');
mysql> CREATE TABLE total (
-> a INT NOT NULL AUTO_INCREMENT,
-> message CHAR(20), INDEX(a))
-> ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
```
柱子`一种`被索引为`首要的关键`在底层`MyISAM`表,但不在`合并`桌子。在那里它被索引但不是作为`首要的关键`因为一个`合并`table 不能对一组基础表强制唯一性。(类似地,一列带有`独特`基础表中的索引应在`合并`表但不作为`独特`指数。)
创建后`合并`表,您可以使用它来发出对整个表组进行操作的查询:
```
mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table |
| 3 | t1 |
| 1 | Testing |
| 2 | table |
| 3 | t2 |
+---+---------+
```
重新映射一个`合并`表到不同的集合`MyISAM`表,您可以使用以下方法之一:
- `降低``合并`表并重新创建它。
- 采用`更改表 *`tbl_name`* 联合=(...)`更改基础表的列表。
也可以使用`更改表 ... UNION=()`(也就是说,有一个空的[`联盟`](union.html)子句)删除所有基础表。但是,在这种情况下,表实际上是空的并且插入失败,因为没有基础表来获取新行。这样的表可能可用作创建新表的模板`合并`表[`创建表...喜欢`](create-table-like.html).
基础表定义和索引必须与`合并`桌子。当表属于`合并`表被打开,而不是当`合并`表已创建。如果任何表未通过一致性检查,则触发打开表的操作将失败。这意味着更改一个内表的定义`合并`可能会导致失败时`合并`表被访问。应用于每个表的一致性检查是:
- 基础表和`合并`表必须具有相同的列数。
- 基础表中的列顺序和`合并`表必须匹配。
- 此外,父中每个对应列的规范`合并`表和基础表进行比较,并且必须满足以下检查:
- 基础表中的列类型和`合并`表必须相等。
- 基础表中的列长度和`合并`表必须相等。
- 基础表的列和`合并`表可以`空值`.
- 基础表的索引必须至少与`合并`桌子。基础表的索引可能比`合并`表,但不能少。
笔记
存在一个已知问题,即相同列上的索引必须以相同的顺序排列,在`合并`表和底层证券`MyISAM`桌子。请参阅错误 #33653。
每个索引必须满足以下检查:
- 基础表的索引类型和`合并`表必须相同。
- 基础表的索引定义中的索引部分(即复合索引中的多个列)的数量和`合并`表必须相同。
- 对于每个索引部分:
- 索引部分的长度必须相等。
- 索引部分类型必须相同。
- 索引部分语言必须相同。
- 检查索引部分是否可以`空值`.
如果一个`合并`由于基础表存在问题,无法打开或使用表,[`检查表`](check-table.html)显示有关哪个表导致问题的信息。
### 其他资源
- 一个专门的论坛`合并`存储引擎可在<https://forums.mysql.com/list.php?93>.
### 16.7.1 MERGE Table Advantages and Disadvantages
`MERGE` tables can help you solve the following problems:
* Easily manage a set of log tables. For example, you can put data from different months into separate tables, compress some of them with [**myisampack**](myisampack.html), and then create a `MERGE` table to use them as one.
* Obtain more speed. You can split a large read-only table based on some criteria, and then put individual tables on different disks. A `MERGE` table structured this way could be much faster than using a single large table.
* Perform more efficient searches. If you know exactly what you are looking for, you can search in just one of the underlying tables for some queries and use a `MERGE` table for others. You can even have many different `MERGE` tables that use overlapping sets of tables.
* Perform more efficient repairs. It is easier to repair individual smaller tables that are mapped to a `MERGE` table than to repair a single large table.
* Instantly map many tables as one. A `MERGE` table need not maintain an index of its own because it uses the indexes of the individual tables. As a result, `MERGE` table collections are *very* fast to create or remap. (You must still specify the index definitions when you create a `MERGE` table, even though no indexes are created.)
* If you have a set of tables from which you create a large table on demand, you can instead create a `MERGE` table from them on demand. This is much faster and saves a lot of disk space.
* Exceed the file size limit for the operating system. Each `MyISAM` table is bound by this limit, but a collection of `MyISAM` tables is not.
* You can create an alias or synonym for a `MyISAM` table by defining a `MERGE` table that maps to that single table. There should be no really notable performance impact from doing this (only a couple of indirect calls and `memcpy()` calls for each read).
The disadvantages of `MERGE` tables are:
* You can use only identical `MyISAM` tables for a `MERGE` table.
* Some `MyISAM` features are unavailable in `MERGE` tables. For example, you cannot create `FULLTEXT` indexes on `MERGE` tables. (You can create `FULLTEXT` indexes on the underlying `MyISAM` tables, but you cannot search the `MERGE` table with a full-text search.)
* If the `MERGE` table is nontemporary, all underlying `MyISAM` tables must be nontemporary. If the `MERGE` table is temporary, the `MyISAM` tables can be any mix of temporary and nontemporary.
* []() `MERGE` tables use more file descriptors than `MyISAM` tables. If 10 clients are using a `MERGE` table that maps to 10 tables, the server uses (10 × 10) + 10 file descriptors. (10 data file descriptors for each of the 10 clients, and 10 index file descriptors shared among the clients.)
* Index reads are slower. When you read an index, the `MERGE` storage engine needs to issue a read on all underlying tables to check which one most closely matches a given index value. To read the next index value, the `MERGE` storage engine needs to search the read buffers to find the next value. Only when one index buffer is used up does the storage engine need to read the next index block. This makes `MERGE` indexes much slower on [`eq_ref`](explain-output.html#jointype_eq_ref) searches, but not much slower on [`ref`](explain-output.html#jointype_ref) searches. For more information about [`eq_ref`](explain-output.html#jointype_eq_ref) and [`ref`](explain-output.html#jointype_ref), see [Section 13.8.2, “EXPLAIN Statement”](explain.html).
### 16.7.1 合并表的优缺点
`合并`表格可以帮助您解决以下问题:
- 轻松管理一组日志表。例如,您可以将不同月份的数据放入单独的表中,使用[**myisampack**](myisampack.html),然后创建一个`合并`表将它们合二为一。
- 获得更快的速度。您可以根据某些条件拆分大型只读表,然后将各个表放在不同的磁盘上。一种`合并`以这种方式构建的表可能比使用单个大表快得多。
- 执行更有效的搜索。如果您确切知道要查找的内容,则可以仅在其中一个基础表中搜索某些查询并使用`合并`给别人的表。你甚至可以有很多不同的`合并`使用重叠表集的表。
- 进行更有效的维修。更容易修复映射到`合并`表比修复单个大表。
- 立即将许多表映射为一个。一种`合并`table 不需要维护自己的索引,因为它使用各个表的索引。因此,`合并`表集合是*非常*快速创建或重新映射。(您仍然必须在创​​建索引时指定索引定义`合并`表,即使没有创建索引。)
- 如果您有一组表可以根据需要创建一个大表,则可以改为创建一个`合并`根据需要从他们那里获得表。这要快得多,并且可以节省大量磁盘空间。
- 超过操作系统的文件大小限制。每个`MyISAM`表受此限制,但集合`MyISAM`表不是。
- 您可以创建别名或同义词`MyISAM`通过定义一个表`合并`映射到该单个表的表。这样做应该不会对性能产生真正显着的影响(只有几个间接调用和`内存()`每次读取都调用)。
的缺点`合并`表是:
- 您只能使用相同的`MyISAM``合并`桌子。
- 一些`MyISAM`功能在`合并`表。例如,您不能创建`全文`索引`合并`表。(您可以创建`全文`基础指数`MyISAM`表,但您无法搜索`合并`带有全文搜索的表。)
- 如果`合并`表是非临时的,所有底层`MyISAM`表必须是非临时的。如果`合并`表是临时的,`MyISAM`表可以是临时表和非临时表的任意组合。
- [](<>) `合并`表使用的文件描述符多于`MyISAM`表。如果 10 个客户端正在使用`合并`映射到 10 个表的表,服务器使用 (10 × 10) + 10 个文件描述符。(10 个客户端中的每一个都有 10 个数据文件描述符,以及在客户端之间共享的 10 个索引文件描述符。)
- 索引读取速度较慢。当您阅读索引时,`合并`存储引擎需要对所有基础表进行读取,以检查哪一个与给定的索引值最匹配。要读取下一个索引值,`合并`存储引擎需要搜索读取缓冲区以找到下一个值。只有当一个索引缓冲区用完时,存储引擎才需要读取下一个索引块。这使得`合并`索引要慢得多[`eq_ref`](explain-output.html#jointype_eq_ref)搜索,但速度并不慢[`参考`](explain-output.html#jointype_ref)搜索。有关更多信息[`eq_ref`](explain-output.html#jointype_eq_ref)[`参考`](explain-output.html#jointype_ref), 看[第 13.8.2 节,“解释声明”](explain.html).
### 16.7.2 MERGE Table Problems
The following are known problems with `MERGE` tables:
* In versions of MySQL Server prior to 5.1.23, it was possible to create temporary merge tables with nontemporary child MyISAM tables.
From versions 5.1.23, MERGE children were locked through the parent table. If the parent was temporary, it was not locked and so the children were not locked either. Parallel use of the MyISAM tables corrupted them.
* If you use [`ALTER TABLE`](alter-table.html) to change a `MERGE` table to another storage engine, the mapping to the underlying tables is lost. Instead, the rows from the underlying `MyISAM` tables are copied into the altered table, which then uses the specified storage engine.
* The `INSERT_METHOD` table option for a `MERGE` table indicates which underlying `MyISAM` table to use for inserts into the `MERGE` table. However, use of the `AUTO_INCREMENT` table option for that `MyISAM` table has no effect for inserts into the `MERGE` table until at least one row has been inserted directly into the `MyISAM` table.
* A `MERGE` table cannot maintain uniqueness constraints over the entire table. When you perform an [`INSERT`](insert.html), the data goes into the first or last `MyISAM` table (as determined by the `INSERT_METHOD` option). MySQL ensures that unique key values remain unique within that `MyISAM` table, but not over all the underlying tables in the collection.
* Because the `MERGE` engine cannot enforce uniqueness over the set of underlying tables, [`REPLACE`](replace.html) does not work as expected. The two key facts are:
* [`REPLACE`](replace.html) can detect unique key violations only in the underlying table to which it is going to write (which is determined by the `INSERT_METHOD` option). This differs from violations in the `MERGE` table itself.
* If [`REPLACE`](replace.html) detects a unique key violation, it changes only the corresponding row in the underlying table it is writing to; that is, the first or last table, as determined by the `INSERT_METHOD` option.
Similar considerations apply for [`INSERT ... ON DUPLICATE KEY UPDATE`](insert-on-duplicate.html).
* `MERGE` tables do not support partitioning. That is, you cannot partition a `MERGE` table, nor can any of a `MERGE` table's underlying `MyISAM` tables be partitioned.
* You should not use [`ANALYZE TABLE`](analyze-table.html), [`REPAIR TABLE`](repair-table.html), [`OPTIMIZE TABLE`](optimize-table.html), [`ALTER TABLE`](alter-table.html), [`DROP TABLE`](drop-table.html), [`DELETE`](delete.html) without a `WHERE` clause, or [`TRUNCATE TABLE`](truncate-table.html) on any of the tables that are mapped into an open `MERGE` table. If you do so, the `MERGE` table may still refer to the original table and yield unexpected results. To work around this problem, ensure that no `MERGE` tables remain open by issuing a [`FLUSH TABLES`](flush.html#flush-tables) statement prior to performing any of the named operations.
The unexpected results include the possibility that the operation on the `MERGE` table reports table corruption. If this occurs after one of the named operations on the underlying `MyISAM` tables, the corruption message is spurious. To deal with this, issue a [`FLUSH TABLES`](flush.html#flush-tables) statement after modifying the `MyISAM` tables.
* [`DROP TABLE`](drop-table.html) on a table that is in use by a `MERGE` table does not work on Windows because the `MERGE` storage engine's table mapping is hidden from the upper layer of MySQL. Windows does not permit open files to be deleted, so you first must flush all `MERGE` tables (with [`FLUSH TABLES`](flush.html#flush-tables)) or drop the `MERGE` table before dropping the table.
* The definition of the `MyISAM` tables and the `MERGE` table are checked when the tables are accessed (for example, as part of a [`SELECT`](select.html) or [`INSERT`](insert.html) statement). The checks ensure that the definitions of the tables and the parent `MERGE` table definition match by comparing column order, types, sizes and associated indexes. If there is a difference between the tables, an error is returned and the statement fails. Because these checks take place when the tables are opened, any changes to the definition of a single table, including column changes, column ordering, and engine alterations cause the statement to fail.
* The order of indexes in the `MERGE` table and its underlying tables should be the same. If you use [`ALTER TABLE`](alter-table.html) to add a `UNIQUE` index to a table used in a `MERGE` table, and then use [`ALTER TABLE`](alter-table.html) to add a nonunique index on the `MERGE` table, the index ordering is different for the tables if there was already a nonunique index in the underlying table. (This happens because [`ALTER TABLE`](alter-table.html) puts `UNIQUE` indexes before nonunique indexes to facilitate rapid detection of duplicate keys.) Consequently, queries on tables with such indexes may return unexpected results.
* If you encounter an error message similar to ERROR 1017 (HY000): Can't find file: '*`tbl_name`*.MRG' (errno: 2), it generally indicates that some of the underlying tables do not use the `MyISAM` storage engine. Confirm that all of these tables are `MyISAM`.
* The maximum number of rows in a `MERGE` table is 2<sup>64</sup> (\~1.844E+19; the same as for a `MyISAM` table). It is not possible to merge multiple `MyISAM` tables into a single `MERGE` table that would have more than this number of rows.
* Use of underlying `MyISAM` tables of differing row formats with a parent `MERGE` table is currently known to fail. See Bug #32364.
* You cannot change the union list of a nontemporary `MERGE` table when [`LOCK TABLES`](lock-tables.html) is in effect. The following does *not* work:
```
CREATE TABLE m1 ... ENGINE=MRG_MYISAM ...;
LOCK TABLES t1 WRITE, t2 WRITE, m1 WRITE;
ALTER TABLE m1 ... UNION=(t1,t2) ...;
```
However, you can do this with a temporary `MERGE` table.
* You cannot create a `MERGE` table with `CREATE ... SELECT`, neither as a temporary `MERGE` table, nor as a nontemporary `MERGE` table. For example:
```
CREATE TABLE m1 ... ENGINE=MRG_MYISAM ... SELECT ...;
```
Attempts to do this result in an error: *`tbl_name`* is not `BASE TABLE`.
* In some cases, differing `PACK_KEYS` table option values among the `MERGE` and underlying tables cause unexpected results if the underlying tables contain `CHAR` or `BINARY` columns. As a workaround, use `ALTER TABLE` to ensure that all involved tables have the same `PACK_KEYS` value. (Bug #50646)
### 16.7.2 合并表问题
以下是已知问题`合并`表:
- 在 5.1.23 之前的 MySQL Server 版本中,可以使用非临时子 MyISAM 表创建临时合并表。
从版本 5.1.23 开始,MERGE 子项通过父表锁定。如果父母是临时的,它没有被锁定,所以孩子也没有被锁定。MyISAM 表的并行使用破坏了它们。
- 如果你使用[`更改表`](alter-table.html)改变一个`合并`表到另一个存储引擎,到基础表的映射会丢失。相反,来自底层证券的行`MyISAM`表被复制到更改后的表中,然后使用指定的存储引擎。
-`插入方法`表选项`合并`表显示哪个底层证券`MyISAM`用于插入的表`合并`桌子。然而,使用`自动递增`表选项`MyISAM`表对插入到`合并`直到至少有一行被直接插入到表中`MyISAM`桌子。
- 一种`合并`table 不能维护整个表的唯一性约束。当你执行一个[`插入`](insert.html), 数据进入第一个或最后一个`MyISAM`表(由`插入方法`选项)。MySQL 确保唯一键值在该范围内保持唯一`MyISAM`表,但不是集合中的所有基础表。
- 因为`合并`引擎无法对一组基础表强制唯一性,[`代替`](replace.html)没有按预期工作。两个关键事实是:
- [`代替`](replace.html)只能在要写入的基础表中检测唯一键违规(由`插入方法`选项)。这与违法行为不同`合并`表本身。
- 如果[`代替`](replace.html)检测到唯一键违规,它只更改它正在写入的基础表中的相应行;也就是说,第一个或最后一个表,由`插入方法`选项。
类似的考虑适用于[`插入 ... 在重复密钥更新时`](insert-on-duplicate.html).
- `合并`表不支持分区。也就是说,你不能对一个`合并`表,也不能任何一个`合并`表的底层`MyISAM`表被分区。
- 你不应该使用[`分析表`](analyze-table.html),[`维修台`](repair-table.html),[`优化表`](optimize-table.html),[`更改表`](alter-table.html),[`删除表`](drop-table.html),[`删除`](delete.html)没有`在哪里`条款,或[`截断表`](truncate-table.html)在映射到打开的任何表上`合并`桌子。如果您这样做,则`合并`table 可能仍然引用原始表并产生意外结果。要解决此问题,请确保没有`合并`通过发出一个表保持打开状态[`同花顺表`](flush.html#flush-tables)执行任何指定操作之前的语句。
意外结果包括对`合并`表报告表损坏。如果这发生在对底层证券的命名操作之一之后`MyISAM`表,损坏消息是虚假的。为了解决这个问题,发出一个[`同花顺表`](flush.html#flush-tables)修改后的声明`MyISAM`表。
- [`删除表`](drop-table.html)在一个正在使用的桌子上`合并`表在 Windows 上不起作用,因为`合并`存储引擎的表映射对 MySQL 上层隐藏。Windows 不允许删除打开的文件,因此您首先必须刷新所有文件`合并`表(与[`同花顺表`](flush.html#flush-tables)) 或删除`合并`删除表之前的表。
- 的定义`MyISAM`表和`合并`访问表时检查表(例如,作为[`选择`](select.html)要么[`插入`](insert.html)陈述)。检查确保表和父表的定义`合并`通过比较列顺序、类型、大小和相关索引来匹配表定义。如果表之间存在差异,则返回错误并且语句失败。因为这些检查是在打开表时进行的,所以对单个表定义的任何更改(包括列更改、列排序和引擎更改)都会导致语句失败。
- 索引中的顺序`合并`表和它的基础表应该是一样的。如果你使用[`更改表`](alter-table.html)添加一个`独特`在 a 中使用的表的索引`合并`表,然后使用[`更改表`](alter-table.html)`合并`表,如果基础表中已经存在非唯一索引,则表的索引顺序不同。(发生这种情况是因为[`更改表`](alter-table.html)看跌期权`独特`非唯一索引之前的索引,以便快速检测重复键。)因此,对具有此类索引的表的查询可能会返回意外结果。
- 如果遇到类似 ERROR 1017 (HY000): Can't find file: ' 的错误信息*`tbl_name`*.MRG' (errno: 2),一般表示部分基础表不使用`MyISAM`存储引擎。确认所有这些表`MyISAM`.
- a 中的最大行数`合并`表是 2<sup>64</sup>(~1.844E+19;和 a 一样`MyISAM`桌子)。无法合并多个`MyISAM`表成一个单一的`合并`行数超过此数量的表。
- 底层证券的使用`MyISAM`具有父级的不同行格式的表`合并`当前已知表失败。请参阅错误 #32364。
- 您不能更改非临时性的联合列表`合并`表什么时候[`锁定表`](lock-tables.html)生效。以下是*不是*工作:
```
CREATE TABLE m1 ... ENGINE=MRG_MYISAM ...;
LOCK TABLES t1 WRITE, t2 WRITE, m1 WRITE;
ALTER TABLE m1 ... UNION=(t1,t2) ...;
```
但是,您可以临时执行此操作`合并`桌子。
- 你不能创建一个`合并`表与`创建...选择`, 既不是临时的`合并`表,也不是非临时的`合并`桌子。例如:
```
CREATE TABLE m1 ... ENGINE=MRG_MYISAM ... SELECT ...;
```
尝试这样做会导致错误:*`tbl_name`*不是`基表`.
- 在某些情况下,不同`PACK_KEYS`表中的选项值`合并`如果基础表包含`字符`要么`二进制`列。作为一种解决方法,使用`更改表`确保所有涉及的表具有相同的`PACK_KEYS`价值。(错误 #50646)
### 16.2.1 MyISAM Startup Options
The following options to [**mysqld**](mysqld.html) can be used to change the behavior of `MyISAM` tables. For additional information, see [Section 5.1.7, “Server Command Options”](server-options.html).
[]()
**Table 16.3 MyISAM Option and Variable Reference**
| Name |Cmd-Line|Option File|System Var|Status Var|Var Scope|Dynamic|
|----------------------------------------------------------------------------------------------|--------|-----------|----------|----------|---------|-------|
| [bulk\_insert\_buffer\_size](server-system-variables.html#sysvar_bulk_insert_buffer_size) | Yes | Yes | Yes | | Both | Yes |
| [concurrent\_insert](server-system-variables.html#sysvar_concurrent_insert) | Yes | Yes | Yes | | Global | Yes |
| [delay\_key\_write](server-system-variables.html#sysvar_delay_key_write) | Yes | Yes | Yes | | Global | Yes |
| [have\_rtree\_keys](server-system-variables.html#sysvar_have_rtree_keys) | | | Yes | | Global | No |
| [key\_buffer\_size](server-system-variables.html#sysvar_key_buffer_size) | Yes | Yes | Yes | | Global | Yes |
| [log-isam](server-options.html#option_mysqld_log-isam) | Yes | Yes | | | | |
| [myisam-block-size](server-options.html#option_mysqld_myisam-block-size) | Yes | Yes | | | | |
| [myisam\_data\_pointer\_size](server-system-variables.html#sysvar_myisam_data_pointer_size) | Yes | Yes | Yes | | Global | Yes |
|[myisam\_max\_sort\_file\_size](server-system-variables.html#sysvar_myisam_max_sort_file_size)| Yes | Yes | Yes | | Global | Yes |
| [myisam\_mmap\_size](server-system-variables.html#sysvar_myisam_mmap_size) | Yes | Yes | Yes | | Global | No |
| [myisam\_recover\_options](server-system-variables.html#sysvar_myisam_recover_options) | Yes | Yes | Yes | | Global | No |
| [myisam\_repair\_threads](server-system-variables.html#sysvar_myisam_repair_threads) | Yes | Yes | Yes | | Both | Yes |
| [myisam\_sort\_buffer\_size](server-system-variables.html#sysvar_myisam_sort_buffer_size) | Yes | Yes | Yes | | Both | Yes |
| [myisam\_stats\_method](server-system-variables.html#sysvar_myisam_stats_method) | Yes | Yes | Yes | | Both | Yes |
| [myisam\_use\_mmap](server-system-variables.html#sysvar_myisam_use_mmap) | Yes | Yes | Yes | | Global | Yes |
| [tmp\_table\_size](server-system-variables.html#sysvar_tmp_table_size) | Yes | Yes | Yes | | Both | Yes |
The following system variables affect the behavior of `MyISAM` tables. For additional information, see [Section 5.1.8, “Server System Variables”](server-system-variables.html).
* [`bulk_insert_buffer_size`](server-system-variables.html#sysvar_bulk_insert_buffer_size)
[]()[]()
The size of the tree cache used in bulk insert optimization.
Note
This is a limit *per thread*!
* [`delay_key_write=ALL`](server-system-variables.html#sysvar_delay_key_write)
[]()[]()
Don't flush key buffers between writes for any `MyISAM` table.
Note
If you do this, you should not access `MyISAM` tables from another program (such as from another MySQL server or with [**myisamchk**](myisamchk.html)) when the tables are in use. Doing so risks index corruption. Using [`--external-locking`](server-options.html#option_mysqld_external-locking) does not eliminate this risk.
* [`myisam_max_sort_file_size`](server-system-variables.html#sysvar_myisam_max_sort_file_size)
[]()[]()
The maximum size of the temporary file that MySQL is permitted to use while re-creating a `MyISAM` index (during [`REPAIR TABLE`](repair-table.html), [`ALTER TABLE`](alter-table.html), or [`LOAD DATA`](load-data.html)). If the file size would be larger than this value, the index is created using the key cache instead, which is slower. The value is given in bytes.
* [`myisam_recover_options=*`mode`*`](server-system-variables.html#sysvar_myisam_recover_options)
[]()[]()
Set the mode for automatic recovery of crashed `MyISAM` tables.
* [`myisam_sort_buffer_size`](server-system-variables.html#sysvar_myisam_sort_buffer_size)
[]()[]()
Set the size of the buffer used when recovering tables.
Automatic recovery is activated if you start [**mysqld**](mysqld.html) with the [`myisam_recover_options`](server-system-variables.html#sysvar_myisam_recover_options) system variable set. In this case, when the server opens a `MyISAM` table, it checks whether the table is marked as crashed or whether the open count variable for the table is not 0 and you are running the server with external locking disabled. If either of these conditions is true, the following happens:
* The server checks the table for errors.
* If the server finds an error, it tries to do a fast table repair (with sorting and without re-creating the data file).
* If the repair fails because of an error in the data file (for example, a duplicate-key error), the server tries again, this time re-creating the data file.
* If the repair still fails, the server tries once more with the old repair option method (write row by row without sorting). This method should be able to repair any type of error and has low disk space requirements.
If the recovery wouldn't be able to recover all rows from previously completed statements and you didn't specify `FORCE` in the value of the [`myisam_recover_options`](server-system-variables.html#sysvar_myisam_recover_options) system variable, automatic repair aborts with an error message in the error log:
```
Error: Couldn't repair table: test.g00pages
```
If you specify `FORCE`, a warning like this is written instead:
```
Warning: Found 344 of 354 rows when repairing ./test/g00pages
```
If the automatic recovery value includes `BACKUP`, the recovery process creates files with names of the form `*`tbl_name-datetime`*.BAK`. You should have a **cron** script that automatically moves these files from the database directories to backup media.
### 16.2.1 MyISAM 启动选项
以下选项可[**mysqld**](mysqld.html)可以用来改变行为`MyISAM`表。有关其他信息,请参阅[第 5.1.7 节,“服务器命令选项”](server-options.html).
[](<>)
**表 16.3 MyISAM 选项和变量参考**
| 姓名 | 命令行 | 选项文件 | 系统变量 | 状态变量 | 变量范围 | 动态的 |
| --- | --- | ---- | ---- | ---- | ---- | --- |
| [块\_插入\_缓冲\_尺寸](server-system-variables.html#sysvar_bulk_insert_buffer_size) | 是的 | 是的 | 是的 | | 两个都 | 是的 |
| [同时\_插入](server-system-variables.html#sysvar_concurrent_insert) | 是的 | 是的 | 是的 | | 全球的 | 是的 |
| [延迟\_钥匙\_写](server-system-variables.html#sysvar_delay_key_write) | 是的 | 是的 | 是的 | | 全球的 | 是的 |
| [有\_rtree\_钥匙](server-system-variables.html#sysvar_have_rtree_keys) | | | 是的 | | 全球的 | 不 |
| [钥匙\_缓冲\_尺寸](server-system-variables.html#sysvar_key_buffer_size) | 是的 | 是的 | 是的 | | 全球的 | 是的 |
| [日志-isam](server-options.html#option_mysqld_log-isam) | 是的 | 是的 | | | | |
| [myisam 块大小](server-options.html#option_mysqld_myisam-block-size) | 是的 | 是的 | | | | |
| [米萨姆\_数据\_指针\_尺寸](server-system-variables.html#sysvar_myisam_data_pointer_size) | 是的 | 是的 | 是的 | | 全球的 | 是的 |
| [米萨姆\_最大限度\_种类\_文件\_尺寸](server-system-variables.html#sysvar_myisam_max_sort_file_size) | 是的 | 是的 | 是的 | | 全球的 | 是的 |
| [米萨姆\_地图\_尺寸](server-system-variables.html#sysvar_myisam_mmap_size) | 是的 | 是的 | 是的 | | 全球的 | 不 |
| [米萨姆\_恢复\_选项](server-system-variables.html#sysvar_myisam_recover_options) | 是的 | 是的 | 是的 | | 全球的 | 不 |
| [米萨姆\_维修\_线程](server-system-variables.html#sysvar_myisam_repair_threads) | 是的 | 是的 | 是的 | | 两个都 | 是的 |
| [米萨姆\_种类\_缓冲\_尺寸](server-system-variables.html#sysvar_myisam_sort_buffer_size) | 是的 | 是的 | 是的 | | 两个都 | 是的 |
| [米萨姆\_统计数据\_方法](server-system-variables.html#sysvar_myisam_stats_method) | 是的 | 是的 | 是的 | | 两个都 | 是的 |
| [米萨姆\_采用\_地图](server-system-variables.html#sysvar_myisam_use_mmap) | 是的 | 是的 | 是的 | | 全球的 | 是的 |
| [时间\_桌子\_尺寸](server-system-variables.html#sysvar_tmp_table_size) | 是的 | 是的 | 是的 | | 两个都 | 是的 |
以下系统变量会影响`MyISAM`表。有关其他信息,请参阅[第 5.1.8 节,“服务器系统变量”](server-system-variables.html).
- [`bulk_insert_buffer_size`](server-system-variables.html#sysvar_bulk_insert_buffer_size)
[](<>)[](<>)
批量插入优化中使用的树缓存的大小。
笔记
这是一个限制*每个线程*!
- [`delay_key_write=ALL`](server-system-variables.html#sysvar_delay_key_write)
[](<>)[](<>)
不要在任何写入之间刷新键缓冲区`MyISAM`桌子。
笔记
如果你这样做,你不应该访问`MyISAM`来自另一个程序的表(例如来自另一个 MySQL 服务器或使用[**迈萨姆奇克**](myisamchk.html)) 使用表时。这样做有索引损坏的风险。使用[`--外部锁定`](server-options.html#option_mysqld_external-locking)并不能消除这种风险。
- [`myisam_max_sort_file_size`](server-system-variables.html#sysvar_myisam_max_sort_file_size)
[](<>)[](<>)
MySQL 在重新创建时允许使用的临时文件的最大大小`MyISAM`指数(期间[`维修台`](repair-table.html),[`更改表`](alter-table.html), 要么[`加载数据`](load-data.html))。如果文件大小大于此值,则使用键缓存创建索引,这会更慢。该值以字节为单位。
- [`myisam_recover_options=*`模式`*`](server-system-variables.html#sysvar_myisam_recover_options)
[](<>)[](<>)
设置崩溃自动恢复模式`MyISAM`表。
- [`myisam_sort_buffer_size`](server-system-variables.html#sysvar_myisam_sort_buffer_size)
[](<>)[](<>)
设置恢复表时使用的缓冲区大小。
如果您启动自动恢复将被激活[**mysqld**](mysqld.html)与[`myisam_recover_options`](server-system-variables.html#sysvar_myisam_recover_options)系统变量集。在这种情况下,当服务器打开一个`MyISAM`表,它检查表是否被标记为崩溃或表的打开计数变量是否不为 0,并且您正在运行禁用外部锁定的服务器。如果其中任何一个条件为真,则会发生以下情况:
- 服务器检查表是否有错误。
- 如果服务器发现错误,它会尝试进行快速表修复(使用排序但不重新创建数据文件)。
- 如果由于数据文件中的错误(例如,重复密钥错误)而导致修复失败,则服务器会再次尝试,这次重新创建数据文件。
- 如果修复仍然失败,服务器会再次尝试使用旧的修复选项方法(逐行写入而不进行排序)。这种方法应该能够修复任何类型的错误并且对磁盘空间的要求很低。
如果恢复无法从以前完成的语句中恢复所有行并且您没有指定`力量`在价值[`myisam_recover_options`](server-system-variables.html#sysvar_myisam_recover_options)系统变量,自动修复中止并在错误日志中显示错误消息:
```
Error: Couldn't repair table: test.g00pages
```
如果您指定`力量`,而是写了这样的警告:
```
Warning: Found 344 of 354 rows when repairing ./test/g00pages
```
如果自动恢复值包括`备份`, 恢复过程创建文件的形式为`*`tbl_name-日期时间`*.BAK`.你应该有一个**cron**自动将这些文件从数据库目录移动到备份媒体的脚本。
## 16.2 The MyISAM Storage Engine
[16.2.1 MyISAM Startup Options](myisam-start.html)
[16.2.2 Space Needed for Keys](key-space.html)
[16.2.3 MyISAM Table Storage Formats](myisam-table-formats.html)
[16.2.4 MyISAM Table Problems](myisam-table-problems.html)
[]()[]()
`MyISAM` is based on the older (and no longer available) `ISAM` storage engine but has many useful extensions.
[]()
**Table 16.2 MyISAM Storage Engine Features**
| Feature | Support |
|-------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| **B-tree indexes** | Yes |
|**Backup/point-in-time recovery** (Implemented in the server, rather than in the storage engine.)| Yes |
| **Cluster database support** | No |
| **Clustered indexes** | No |
| **Compressed data** |Yes (Compressed MyISAM tables are supported only when using the compressed row format. Tables using the compressed row format with MyISAM are read only.)|
| **Data caches** | No |
| **Encrypted data** | Yes (Implemented in the server via encryption functions.) |
| **Foreign key support** | No |
| **Full-text search indexes** | Yes |
| **Geospatial data type support** | Yes |
| **Geospatial indexing support** | Yes |
| **Hash indexes** | No |
| **Index caches** | Yes |
| **Locking granularity** | Table |
| **MVCC** | No |
| **Replication support** (Implemented in the server, rather than in the storage engine.) | Yes |
| **Storage limits** | 256TB |
| **T-tree indexes** | No |
| **Transactions** | No |
| **Update statistics for data dictionary** | Yes |
Each `MyISAM` table is stored on disk in two files. The files have names that begin with the table name and have an extension to indicate the file type. The data file has an `.MYD` (`MYData`) extension. The index file has an `.MYI` (`MYIndex`) extension. The table definition is stored in the MySQL data dictionary.
To specify explicitly that you want a `MyISAM` table, indicate that with an `ENGINE` table option:
```
CREATE TABLE t (i INT) ENGINE = MYISAM;
```
In MySQL 8.0, it is normally necessary to use `ENGINE` to specify the `MyISAM` storage engine because `InnoDB` is the default engine.
You can check or repair `MyISAM` tables with the [**mysqlcheck**](mysqlcheck.html) client or [**myisamchk**](myisamchk.html) utility. You can also compress `MyISAM` tables with [**myisampack**](myisampack.html) to take up much less space. See [Section 4.5.3, “mysqlcheck — A Table Maintenance Program”](mysqlcheck.html), [Section 4.6.4, “myisamchk — MyISAM Table-Maintenance Utility”](myisamchk.html), and [Section 4.6.6, “myisampack — Generate Compressed, Read-Only MyISAM Tables”](myisampack.html).
In MySQL 8.0, the `MyISAM` storage engine provides no partitioning support. *Partitioned `MyISAM` tables created in previous versions of MySQL cannot be used in MySQL 8.0*. For more information, see [Section 24.6.2, “Partitioning Limitations Relating to Storage Engines”](partitioning-limitations-storage-engines.html). For help with upgrading such tables so that they can be used in MySQL 8.0, see [Section 2.11.4, “Changes in MySQL 8.0”](upgrading-from-previous-series.html).
`MyISAM` tables have the following characteristics:
* All data values are stored with the low byte first. This makes the data machine and operating system independent. The only requirements for binary portability are that the machine uses two's-complement signed integers and IEEE floating-point format. These requirements are widely used among mainstream machines. Binary compatibility might not be applicable to embedded systems, which sometimes have peculiar processors.
There is no significant speed penalty for storing data low byte first; the bytes in a table row normally are unaligned and it takes little more processing to read an unaligned byte in order than in reverse order. Also, the code in the server that fetches column values is not time critical compared to other code.
* All numeric key values are stored with the high byte first to permit better index compression.
* Large files (up to 63-bit file length) are supported on file systems and operating systems that support large files.
* There is a limit of (2<sup>32</sup>)<sup>2</sup> (1.844E+19) rows in a `MyISAM` table.
* The maximum number of indexes per `MyISAM` table is 64.
The maximum number of columns per index is 16.
* The maximum key length is 1000 bytes. This can also be changed by changing the source and recompiling. For the case of a key longer than 250 bytes, a larger key block size than the default of 1024 bytes is used.
* When rows are inserted in sorted order (as when you are using an `AUTO_INCREMENT` column), the index tree is split so that the high node only contains one key. This improves space utilization in the index tree.
* Internal handling of one `AUTO_INCREMENT` column per table is supported. `MyISAM` automatically updates this column for [`INSERT`](insert.html) and [`UPDATE`](update.html) operations. This makes `AUTO_INCREMENT` columns faster (at least 10%). Values at the top of the sequence are not reused after being deleted. (When an `AUTO_INCREMENT` column is defined as the last column of a multiple-column index, reuse of values deleted from the top of a sequence does occur.) The `AUTO_INCREMENT` value can be reset with [`ALTER TABLE`](alter-table.html) or [**myisamchk**](myisamchk.html).
* Dynamic-sized rows are much less fragmented when mixing deletes with updates and inserts. This is done by automatically combining adjacent deleted blocks and by extending blocks if the next block is deleted.
* `MyISAM` supports concurrent inserts: If a table has no free blocks in the middle of the data file, you can [`INSERT`](insert.html) new rows into it at the same time that other threads are reading from the table. A free block can occur as a result of deleting rows or an update of a dynamic length row with more data than its current contents. When all free blocks are used up (filled in), future inserts become concurrent again. See [Section 8.11.3, “Concurrent Inserts”](concurrent-inserts.html).
* You can put the data file and index file in different directories on different physical devices to get more speed with the `DATA DIRECTORY` and `INDEX DIRECTORY` table options to [`CREATE TABLE`](create-table.html). See [Section 13.1.20, “CREATE TABLE Statement”](create-table.html).
* [`BLOB`](blob.html) and [`TEXT`](blob.html) columns can be indexed.
* `NULL` values are permitted in indexed columns. This takes 0 to 1 bytes per key.
* Each character column can have a different character set. See [Chapter 10, *Character Sets, Collations, Unicode*](charset.html).
* There is a flag in the `MyISAM` index file that indicates whether the table was closed correctly. If [**mysqld**](mysqld.html) is started with the [`myisam_recover_options`](server-system-variables.html#sysvar_myisam_recover_options) system variable set, `MyISAM` tables are automatically checked when opened, and are repaired if the table wasn't closed properly.
* [**myisamchk**](myisamchk.html) marks tables as checked if you run it with the [`--update-state`](myisamchk-check-options.html#option_myisamchk_update-state) option. [**myisamchk --fast**](myisamchk.html) checks only those tables that don't have this mark.
* [**myisamchk --analyze**](myisamchk.html) stores statistics for portions of keys, as well as for entire keys.
* [**myisampack**](myisampack.html) can pack [`BLOB`](blob.html) and [`VARCHAR`](char.html) columns.
`MyISAM` also supports the following features:
* Support for a true [`VARCHAR`](char.html) type; a [`VARCHAR`](char.html) column starts with a length stored in one or two bytes.
* Tables with [`VARCHAR`](char.html) columns may have fixed or dynamic row length.
* The sum of the lengths of the [`VARCHAR`](char.html) and [`CHAR`](char.html) columns in a table may be up to 64KB.
* Arbitrary length `UNIQUE` constraints.
### Additional Resources
* A forum dedicated to the `MyISAM` storage engine is available at [https://forums.mysql.com/list.php?21](https://forums.mysql.com/list.php?21).
## 16.2 MyISAM 存储引擎
[16.2.1 MyISAM 启动选项](myisam-start.html)
[16.2.2 键所需空间](key-space.html)
[16.2.3 MyISAM 表存储格式](myisam-table-formats.html)
[16.2.4 MyISAM 表问题](myisam-table-problems.html)
[](<>)[](<>)
`MyISAM`基于旧的(不再可用)`是`存储引擎,但有许多有用的扩展。
[](<>)
**表 16.2 MyISAM 存储引擎功能**
| 特征 | 支持 |
| --- | --- |
| **B树索引** | 是的 |
| **备份/时间点恢复**(在服务器中实现,而不是在存储引擎中。) | 是的 |
| **集群数据库支持** | 不 |
| **聚集索引** | 不 |
| **压缩数据** | 是(仅当使用压缩行格式时才支持压缩的 MyISAM 表。使用带有 MyISAM 的压缩行格式的表是只读的。) |
| **数据缓存** | 不 |
| **加密数据** | 是(通过加密功能在服务器中实现。) |
| **外键支持** | 不 |
| **全文检索索引** | 是的 |
| **地理空间数据类型支持** | 是的 |
| **地理空间索引支持** | 是的 |
| **哈希索引** | 不 |
| **索引缓存** | 是的 |
| **锁定粒度** | 桌子 |
| **MVCC** | 不 |
| **复制支持**(在服务器中实现,而不是在存储引擎中。) | 是的 |
| **存储限制** | 256TB |
| **T-树索引** | 不 |
| **交易** | 不 |
| **更新数据字典的统计信息** | 是的 |
每个`MyISAM`表存储在磁盘上的两个文件中。这些文件的名称以表名开头,并具有指示文件类型的扩展名。数据文件有一个`.MYD`(`MYData`) 延期。索引文件有一个`。我的我`(`MYIndex`) 延期。表定义存储在 MySQL 数据字典中。
明确指定您想要一个`MyISAM`表,表明与`引擎`表选项:
```
CREATE TABLE t (i INT) ENGINE = MYISAM;
```
在 MySQL 8.0 中,通常需要使用`引擎`指定`MyISAM`存储引擎,因为`InnoDB`是默认引擎。
您可以检查或维修`MyISAM`表与[**mysql检查**](mysqlcheck.html)客户或[**迈萨姆奇克**](myisamchk.html)效用。你也可以压缩`MyISAM`[**myisampack**](myisampack.html)占用更少的空间。看[第 4.5.3 节,“mysqlcheck - 一个表维护程序”](mysqlcheck.html),[第 4.6.4 节,“myisamchk - MyISAM 表维护实用程序”](myisamchk.html), 和[第 4.6.6 节,“myisampack - 生成压缩的只读 MyISAM 表”](myisampack.html).
在 MySQL 8.0 中,`MyISAM`存储引擎不提供分区支持。*分区`MyISAM`在 MySQL 8.0 中不能使用在以前版本的 MySQL 中创建的表*.有关详细信息,请参阅[第 24.6.2 节,“与存储引擎相关的分区限制”](partitioning-limitations-storage-engines.html).有关升级此类表以便它们可以在 MySQL 8.0 中使用的帮助,请参阅[第 2.11.4 节,“MySQL 8.0 中的更改”](upgrading-from-previous-series.html).
`MyISAM`表具有以下特点:
- 所有数据值都以低字节优先存储。这使得数据机和操作系统独立。二进制可移植性的唯一要求是机器使用二进制补码有符号整数和 IEEE 浮点格式。这些要求在主流机器中被广泛使用。二进制兼容性可能不适用于有时具有特殊处理器的嵌入式系统。
首先存储数据低字节没有明显的速度损失;表行中的字节通常是未对齐的,按顺序读取未对齐字节所需的处理时间比按相反顺序读取的处理时间要多。此外,与其他代码相比,服务器中获取列值的代码不是时间关键的。
- 所有数字键值都以高字节优先存储,以允许更好的索引压缩。
- 支持大文件的文件系统和操作系统支持大文件(文件长度最大为 63 位)。
- 有一个限制(2<sup>32</sup>)<sup>2</sup>(1.844E+19) 行`MyISAM`桌子。
- 每个索引的最大数量`MyISAM`表是 64。
每个索引的最大列数为 16。
- 最大密钥长度为 1000 字节。这也可以通过更改源并重新编译来更改。对于长度超过 250 字节的密钥,使用比默认值 1024 字节更大的密钥块大小。
- 当按排序顺序插入行时(如您使用`自动递增`列),索引树被拆分,使得高节点只包含一个键。这提高了索引树中的空间利用率。
- 内部处理一`自动递增`支持每个表的列。`MyISAM`自动更新此列[`插入`](insert.html)[`更新`](update.html)操作。这使得`自动递增`列速度更快(至少 10%)。序列顶部的值在被删除后不会被重用。(当一个`自动递增`column 被定义为多列索引的最后一列,重复使用从序列顶部删除的值确实会发生。)`自动递增`值可以重置[`更改表`](alter-table.html)要么[**迈萨姆奇克**](myisamchk.html).
- 将删除与更新和插入混合使用时,动态大小的行碎片更少。这是通过自动组合相邻的已删除块并在下一个块被删除时扩展块来完成的。
- `MyISAM`支持并发插入:如果一个表在数据文件中间没有空闲块,你可以[`插入`](insert.html)在其他线程从表中读取的同时将新行写入其中。由于删除行或更新具有比当前内容更多的数据的动态长度行,可能会出现空闲块。当所有空闲块都用完(填充)时,未来的插入再次变为并发。看[第 8.11.3 节,“并发插入”](concurrent-inserts.html).
- 您可以将数据文件和索引文件放在不同物理设备上的不同目录中,以获得更快的速度`数据目录``索引目录`表选项[`创建表`](create-table.html).看[第 13.1.20 节,“CREATE TABLE 语句”](create-table.html).
- [`斑点`](blob.html)[`文本`](blob.html)列可以被索引。
- `空值`索引列中允许值。每个密钥需要 0 到 1 个字节。
- 每个字符列可以有不同的字符集。看[第 10 章,*字符集、排序规则、Unicode*](charset.html).
- 里面有一面旗帜`MyISAM`指示表是否正确关闭的索引文件。如果[**mysqld**](mysqld.html)开始于[`myisam_recover_options`](server-system-variables.html#sysvar_myisam_recover_options)系统变量集,`MyISAM`打开时会自动检查表,如果表未正确关闭,则会进行修复。
- [**迈萨姆奇克**](myisamchk.html)如果您使用[`--更新状态`](myisamchk-check-options.html#option_myisamchk_update-state)选项。[**myisamchk --fast**](myisamchk.html)只检查那些没有这个标记的表。
- [**myisamchk——分析**](myisamchk.html)存储部分键的统计信息,以及整个键的统计信息。
- [**myisampack**](myisampack.html)可以打包[`斑点`](blob.html)[`VARCHAR`](char.html)列。
`MyISAM`还支持以下功能:
- 支持真实的[`VARCHAR`](char.html)类型;一种[`VARCHAR`](char.html)列以存储在一个或两个字节中的长度开始。
- 表与[`VARCHAR`](char.html)列可能具有固定或动态的行长度。
- 长度的总和[`VARCHAR`](char.html)[`字符`](char.html)表中的列最多可达 64KB。
- 任意长度`独特`约束。
### 其他资源
- 一个专门的论坛`MyISAM`存储引擎可在<https://forums.mysql.com/list.php?21>.
#### 16.2.4.2 Problems from Tables Not Being Closed Properly
Each `MyISAM` index file (`.MYI` file) has a counter in the header that can be used to check whether a table has been closed properly. If you get the following warning from [`CHECK TABLE`](check-table.html) or [**myisamchk**](myisamchk.html), it means that this counter has gone out of sync:
```
clients are using or haven't closed the table properly
```
This warning doesn't necessarily mean that the table is corrupted, but you should at least check the table.
The counter works as follows:
* The first time a table is updated in MySQL, a counter in the header of the index files is incremented.
* The counter is not changed during further updates.
* When the last instance of a table is closed (because a [`FLUSH TABLES`](flush.html#flush-tables) operation was performed or because there is no room in the table cache), the counter is decremented if the table has been updated at any point.
* When you repair the table or check the table and it is found to be okay, the counter is reset to zero.
* To avoid problems with interaction with other processes that might check the table, the counter is not decremented on close if it was zero.
In other words, the counter can become incorrect only under these conditions:
* A `MyISAM` table is copied without first issuing [`LOCK TABLES`](lock-tables.html) and [`FLUSH TABLES`](flush.html#flush-tables).
* MySQL has crashed between an update and the final close. (The table may still be okay because MySQL always issues writes for everything between each statement.)
* A table was modified by [**myisamchk --recover**](myisamchk.html) or [**myisamchk --update-state**](myisamchk.html) at the same time that it was in use by [**mysqld**](mysqld.html).
* Multiple [**mysqld**](mysqld.html) servers are using the table and one server performed a [`REPAIR TABLE`](repair-table.html) or [`CHECK TABLE`](check-table.html) on the table while it was in use by another server. In this setup, it is safe to use [`CHECK TABLE`](check-table.html), although you might get the warning from other servers. However, [`REPAIR TABLE`](repair-table.html) should be avoided because when one server replaces the data file with a new one, this is not known to the other servers.
In general, it is a bad idea to share a data directory among multiple servers. See [Section 5.8, “Running Multiple MySQL Instances on One Machine”](multiple-servers.html), for additional discussion.
#### 16.2.4.2 表未正确关闭的问题
每个`MyISAM`索引文件(`。我的我`file) 在标题中有一个计数器,可用于检查表是否已正确关闭。如果您收到以下警告[`检查表`](check-table.html)要么[**迈萨姆奇克**](myisamchk.html),这意味着这个计数器已经不同步:
```
clients are using or haven't closed the table properly
```
此警告并不一定意味着表已损坏,但您至少应该检查表。
计数器的工作原理如下:
- 第一次在 MySQL 中更新表时,索引文件头中的计数器会递增。
- 在进一步更新期间不会更改计数器。
- 当表的最后一个实例关闭时(因为[`同花顺表`](flush.html#flush-tables)操作已执行或因为表缓存中没有空间),如果表已在任何时候更新,则计数器会递减。
- 当您修表或检查表并发现没有问题时,计数器将重置为零。
- 为避免与可能检查表的其他进程交互时出现问题,如果计数器为零,则计数器不会在关闭时递减。
换句话说,只有在以下情况下,计数器才会变得不正确:
- 一种`MyISAM`表被复制而不首先发布[`锁定表`](lock-tables.html)[`同花顺表`](flush.html#flush-tables).
- MySQL 在更新和最终关闭之间崩溃。(该表可能仍然没问题,因为 MySQL 总是为每个语句之间的所有内容发出写入。)
- 一个表被修改[**myisamchk --recover**](myisamchk.html)要么[**myisamchk --更新状态**](myisamchk.html)在它被使用的同时[**mysqld**](mysqld.html).
- 多种的[**mysqld**](mysqld.html)服务器正在使用该表,并且一台服务器执行了[`维修台`](repair-table.html)要么[`检查表`](check-table.html)在另一台服务器使用时放在桌子上。在此设置中,可以安全使用[`检查表`](check-table.html),尽管您可能会收到来自其他服务器的警告。然而,[`维修台`](repair-table.html)应该避免,因为当一台服务器用新的数据文件替换数据文件时,其他服务器不知道这一点。
通常,在多个服务器之间共享数据目录是一个坏主意。看[第 5.8 节,“在一台机器上运行多个 MySQL 实例”](multiple-servers.html), 以供进一步讨论。
### 16.2.3 MyISAM Table Storage Formats
[16.2.3.1 Static (Fixed-Length) Table Characteristics](static-format.html)
[16.2.3.2 Dynamic Table Characteristics](dynamic-format.html)
[16.2.3.3 Compressed Table Characteristics](compressed-format.html)
`MyISAM` supports three different storage formats. Two of them, fixed and dynamic format, are chosen automatically depending on the type of columns you are using. The third, compressed format, can be created only with the [**myisampack**](myisampack.html) utility (see [Section 4.6.6, “myisampack — Generate Compressed, Read-Only MyISAM Tables”](myisampack.html)).
When you use [`CREATE TABLE`](create-table.html) or [`ALTER TABLE`](alter-table.html) for a table that has no [`BLOB`](blob.html) or [`TEXT`](blob.html) columns, you can force the table format to `FIXED` or `DYNAMIC` with the `ROW_FORMAT` table option.
See [Section 13.1.20, “CREATE TABLE Statement”](create-table.html), for information about `ROW_FORMAT`.
You can decompress (unpack) compressed `MyISAM` tables using [**myisamchk**](myisamchk.html) [`--unpack`](myisamchk-repair-options.html#option_myisamchk_unpack); see [Section 4.6.4, “myisamchk — MyISAM Table-Maintenance Utility”](myisamchk.html), for more information.
### 16.2.3 MyISAM 表存储格式
[16.2.3.1 静态(固定长度)表特性](static-format.html)
[16.2.3.2 动态表特征](dynamic-format.html)
[16.2.3.3 压缩表特性](compressed-format.html)
`MyISAM`支持三种不同的存储格式。其中两种,固定格式和动态格式,会根据您使用的列类型自动选择。第三种,压缩格式,只能用[**myisampack**](myisampack.html)实用程序(见[第 4.6.6 节,“myisampack - 生成压缩的只读 MyISAM 表”](myisampack.html))。
当你使用[`创建表`](create-table.html)要么[`更改表`](alter-table.html)对于没有[`斑点`](blob.html)要么[`文本`](blob.html)列,您可以强制表格格式为`固定的`要么`动态的``ROW_FORMAT`表选项。
[第 13.1.20 节,“CREATE TABLE 语句”](create-table.html), 有关信息`ROW_FORMAT`.
可以解压(unpack)压缩`MyISAM`表使用[**迈萨姆奇克**](myisamchk.html) [`--解包`](myisamchk-repair-options.html#option_myisamchk_unpack);看[第 4.6.4 节,“myisamchk - MyISAM 表维护实用程序”](myisamchk.html), 了解更多信息。
### 16.2.4 MyISAM Table Problems
[16.2.4.1 Corrupted MyISAM Tables](corrupted-myisam-tables.html)
[16.2.4.2 Problems from Tables Not Being Closed Properly](myisam-table-close.html)
The file format that MySQL uses to store data has been extensively tested, but there are always circumstances that may cause database tables to become corrupted. The following discussion describes how this can happen and how to handle it.
### 16.2.4 MyISAM 表问题
[16.2.4.1 损坏的 MyISAM 表](corrupted-myisam-tables.html)
[16.2.4.2 表未正确关闭的问题](myisam-table-close.html)
MySQL 用于存储数据的文件格式已经过广泛的测试,但总有可能导致数据库表损坏的情况。以下讨论描述了这种情况如何发生以及如何处理它。
### 16.11.2 The Common Database Server Layer
A MySQL pluggable storage engine is the component in the MySQL database server that is responsible for performing the actual data I/O operations for a database as well as enabling and enforcing certain feature sets that target a specific application need. A major benefit of using specific storage engines is that you are only delivered the features needed for a particular application, and therefore you have less system overhead in the database, with the end result being more efficient and higher database performance. This is one of the reasons that MySQL has always been known to have such high performance, matching or beating proprietary monolithic databases in industry standard benchmarks.
From a technical perspective, what are some of the unique supporting infrastructure components that are in a storage engine? Some of the key feature differentiations include:
* *Concurrency*: Some applications have more granular lock requirements (such as row-level locks) than others. Choosing the right locking strategy can reduce overhead and therefore improve overall performance. This area also includes support for capabilities such as multi-version concurrency control or “snapshot” read.
* *Transaction Support*: Not every application needs transactions, but for those that do, there are very well defined requirements such as ACID compliance and more.
* *Referential Integrity*: The need to have the server enforce relational database referential integrity through DDL defined foreign keys.
* *Physical Storage*: This involves everything from the overall page size for tables and indexes as well as the format used for storing data to physical disk.
* *Index Support*: Different application scenarios tend to benefit from different index strategies. Each storage engine generally has its own indexing methods, although some (such as B-tree indexes) are common to nearly all engines.
* *Memory Caches*: Different applications respond better to some memory caching strategies than others, so although some memory caches are common to all storage engines (such as those used for user connections), others are uniquely defined only when a particular storage engine is put in play.
* *Performance Aids*: This includes multiple I/O threads for parallel operations, thread concurrency, database checkpointing, bulk insert handling, and more.
* *Miscellaneous Target Features*: This may include support for geospatial operations, security restrictions for certain data manipulation operations, and other similar features.
Each set of the pluggable storage engine infrastructure components are designed to offer a selective set of benefits for a particular application. Conversely, avoiding a set of component features helps reduce unnecessary overhead. It stands to reason that understanding a particular application's set of requirements and selecting the proper MySQL storage engine can have a dramatic impact on overall system efficiency and performance.
### 16.11.2 通用数据库服务器层
MySQL 可插拔存储引擎是 MySQL 数据库服务器中的组件,它负责为数据库执行实际的数据 I/O 操作,以及启用和执行针对特定应用程序需求的某些功能集。使用特定存储引擎的一个主要好处是您只获得特定应用程序所需的功能,因此您在数据库中的系统开销更少,最终结果是更高效和更高的数据库性能。这是 MySQL 一直以在行业标准基准测试中具有如此高性能、匹配或击败专有单体数据库而闻名的原因之一。
从技术角度来看,存储引擎中有哪些独特的支持基础架构组件?一些关键的功能差异包括:
- *并发*: 一些应用程序比其他应用程序有更细粒度的锁需求(例如行级锁)。选择正确的锁定策略可以减少开销,从而提高整体性能。该领域还包括对多版本并发控制或“快照”读取等功能的支持。
- *交易支持*:并非每个应用程序都需要事务,但对于那些需要事务的应用程序,有非常明确的要求,例如 ACID 合规性等等。
- *参照完整性*:需要让服务器通过 DDL 定义的外键强制关系数据库的引用完整性。
- *物理存储*:这涉及从表和索引的整体页面大小以及用于将数据存储到物理磁盘的格式的所有内容。
- *索引支持*:不同的应用场景往往受益于不同的索引策略。每个存储引擎通常都有自己的索引方法,尽管有些(例如 B-tree 索引)对几乎所有引擎都是通用的。
- *内存缓存*: 不同的应用程序对某些内存缓存策略的响应比其他应用程序更好,因此尽管某些内存缓存对所有存储引擎都是通用的(例如用于用户连接的那些),但其他应用程序仅在使用特定存储引擎时才唯一定义。
- *表演辅助*:这包括用于并行操作、线程并发、数据库检查点、批量插入处理等的多个 I/O 线程。
- *其他目标特征*:这可能包括对地理空间操作的支持、某些数据操作操作的安全限制以及其他类似功能。
每组可插拔存储引擎基础架构组件都旨在为特定应用程序提供一组选择性优势。相反,避免使用一组组件功能有助于减少不必要的开销。理所当然地,了解特定应用程序的一组需求并选择合适的 MySQL 存储引擎会对整体系统效率和性能产生巨大影响。
## 16.11 Overview of MySQL Storage Engine Architecture
[16.11.1 Pluggable Storage Engine Architecture](pluggable-storage.html)
[16.11.2 The Common Database Server Layer](pluggable-storage-common-layer.html)
The MySQL pluggable storage engine architecture enables a database professional to select a specialized storage engine for a particular application need while being completely shielded from the need to manage any specific application coding requirements. The MySQL server architecture isolates the application programmer and DBA from all of the low-level implementation details at the storage level, providing a consistent and easy application model and API. Thus, although there are different capabilities across different storage engines, the application is shielded from these differences.
The MySQL pluggable storage engine architecture is shown in [Figure 16.3, “MySQL Architecture with Pluggable Storage Engines”](pluggable-storage-overview.html#mysql-architecture-diagram).
[]()
**Figure 16.3 MySQL Architecture with Pluggable Storage Engines**
<img alt="MySQL architecture diagram showing connectors, interfaces, pluggable storage engines, the file system with files and logs." src="images/mysql-architecture.png" height="533" width="500" />
The pluggable storage engine architecture provides a standard set of management and support services that are common among all underlying storage engines. The storage engines themselves are the components of the database server that actually perform actions on the underlying data that is maintained at the physical server level.
This efficient and modular architecture provides huge benefits for those wishing to specifically target a particular application need—such as data warehousing, transaction processing, or high availability situations—while enjoying the advantage of utilizing a set of interfaces and services that are independent of any one storage engine.
The application programmer and DBA interact with the MySQL database through Connector APIs and service layers that are above the storage engines. If application changes bring about requirements that demand the underlying storage engine change, or that one or more storage engines be added to support new needs, no significant coding or process changes are required to make things work. The MySQL server architecture shields the application from the underlying complexity of the storage engine by presenting a consistent and easy-to-use API that applies across storage engines.
## 16.11 Overview of MySQL Storage Engine Architecture
[16.11.1 Pluggable Storage Engine Architecture](pluggable-storage.html)
[16.11.2 The Common Database Server Layer](pluggable-storage-common-layer.html)
The MySQL pluggable storage engine architecture enables a database professional to select a specialized storage engine for a particular application need while being completely shielded from the need to manage any specific application coding requirements. The MySQL server architecture isolates the application programmer and DBA from all of the low-level implementation details at the storage level, providing a consistent and easy application model and API. Thus, although there are different capabilities across different storage engines, the application is shielded from these differences.
The MySQL pluggable storage engine architecture is shown in[Figure 16.3, “MySQL Architecture with Pluggable Storage Engines”](pluggable-storage-overview.html#mysql-architecture-diagram).
[](<>)
**Figure 16.3 MySQL Architecture with Pluggable Storage Engines**
<img alt="MySQL architecture diagram showing connectors, interfaces, pluggable storage engines, the file system with files and logs." src="images/mysql-architecture.png" height="533" width="500" />
The pluggable storage engine architecture provides a standard set of management and support services that are common among all underlying storage engines. The storage engines themselves are the components of the database server that actually perform actions on the underlying data that is maintained at the physical server level.
This efficient and modular architecture provides huge benefits for those wishing to specifically target a particular application need—such as data warehousing, transaction processing, or high availability situations—while enjoying the advantage of utilizing a set of interfaces and services that are independent of any one storage engine.
The application programmer and DBA interact with the MySQL database through Connector APIs and service layers that are above the storage engines. If application changes bring about requirements that demand the underlying storage engine change, or that one or more storage engines be added to support new needs, no significant coding or process changes are required to make things work. The MySQL server architecture shields the application from the underlying complexity of the storage engine by presenting a consistent and easy-to-use API that applies across storage engines.
### 16.11.1 Pluggable Storage Engine Architecture
MySQL Server uses a pluggable storage engine architecture that enables storage engines to be loaded into and unloaded from a running MySQL server.
**Plugging in a Storage Engine**
Before a storage engine can be used, the storage engine plugin shared library must be loaded into MySQL using the [`INSTALL PLUGIN`](install-plugin.html) statement. For example, if the `EXAMPLE` engine plugin is named `example` and the shared library is named `ha_example.so`, you load it with the following statement:
```
INSTALL PLUGIN example SONAME 'ha_example.so';
```
To install a pluggable storage engine, the plugin file must be located in the MySQL plugin directory, and the user issuing the [`INSTALL PLUGIN`](install-plugin.html) statement must have [`INSERT`](privileges-provided.html#priv_insert) privilege for the `mysql.plugin` table.
The shared library must be located in the MySQL server plugin directory, the location of which is given by the [`plugin_dir`](server-system-variables.html#sysvar_plugin_dir) system variable.
**Unplugging a Storage Engine**
To unplug a storage engine, use the [`UNINSTALL PLUGIN`](uninstall-plugin.html) statement:
```
UNINSTALL PLUGIN example;
```
If you unplug a storage engine that is needed by existing tables, those tables become inaccessible, but are still present on disk (where applicable). Ensure that there are no tables using a storage engine before you unplug the storage engine.
### 16.11.1 可插拔存储引擎架构
MySQL 服务器使用可插拔的存储引擎架构,使存储引擎能够加载到正在运行的 MySQL 服务器中或从其中卸载。
**插入存储引擎**
在使用存储引擎之前,存储引擎插件共享库必须使用[`安装插件`](install-plugin.html)陈述。例如,如果`例子`引擎插件被命名`例子`并且共享库被命名`ha_example.so`,您使用以下语句加载它:
```
INSTALL PLUGIN example SONAME 'ha_example.so';
```
要安装可插拔存储引擎,插件文件必须位于 MySQL 插件目录中,并且用户发出[`安装插件`](install-plugin.html)声明必须有[`插入`](privileges-provided.html#priv_insert)的特权`mysql.plugin`桌子。
共享库必须位于 MySQL 服务器插件目录中,其位置由[`插件目录`](server-system-variables.html#sysvar_plugin_dir)系统变量。
**拔下存储引擎**
要拔下存储引擎,请使用[`卸载插件`](uninstall-plugin.html)陈述:
```
UNINSTALL PLUGIN example;
```
如果您拔下现有表所需的存储引擎,这些表将无法访问,但仍存在于磁盘上(如果适用)。在拔下存储引擎之前,请确保没有使用存储引擎的表。
### 16.4.2 CSV Limitations
The `CSV` storage engine does not support indexing.
The `CSV` storage engine does not support partitioning.
All tables that you create using the `CSV` storage engine must have the `NOT NULL` attribute on all columns.
### 16.4.2 CSV 限制
`CSV`存储引擎不支持索引。
`CSV`存储引擎不支持分区。
您使用`CSV`存储引擎必须具有`非空`所有列的属性。
### 16.4.1 Repairing and Checking CSV Tables
The `CSV` storage engine supports the [`CHECK TABLE`](check-table.html) and [`REPAIR TABLE`](repair-table.html) statements to verify and, if possible, repair a damaged `CSV` table.
When running the [`CHECK TABLE`](check-table.html) statement, the `CSV` file is checked for validity by looking for the correct field separators, escaped fields (matching or missing quotation marks), the correct number of fields compared to the table definition and the existence of a corresponding `CSV` metafile. The first invalid row discovered causes an error. Checking a valid table produces output like that shown here:
```
mysql> CHECK TABLE csvtest;
+--------------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+--------------+-------+----------+----------+
| test.csvtest | check | status | OK |
+--------------+-------+----------+----------+
```
A check on a corrupted table returns a fault such as
```
mysql> CHECK TABLE csvtest;
+--------------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+--------------+-------+----------+----------+
| test.csvtest | check | error | Corrupt |
+--------------+-------+----------+----------+
```
To repair a table, use [`REPAIR TABLE`](repair-table.html), which copies as many valid rows from the existing `CSV` data as possible, and then replaces the existing `CSV` file with the recovered rows. Any rows beyond the corrupted data are lost.
```
mysql> REPAIR TABLE csvtest;
+--------------+--------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+--------------+--------+----------+----------+
| test.csvtest | repair | status | OK |
+--------------+--------+----------+----------+
```
Warning
During repair, only the rows from the `CSV` file up to the first damaged row are copied to the new table. All other rows from the first damaged row to the end of the table are removed, even valid rows.
### 16.4.1 修复和检查 CSV 表
`CSV`存储引擎支持[`检查表`](check-table.html)[`维修台`](repair-table.html)声明以验证并在可能的情况下修复损坏的`CSV`桌子。
运行时[`检查表`](check-table.html)声明`CSV`通过查找正确的字段分隔符、转义字段(匹配或缺少引号)、与表定义相比的正确字段数以及是否存在相应的字段来检查文件的有效性`CSV`元文件。发现的第一个无效行会导致错误。检查有效表会产生如下所示的输出:
```
mysql> CHECK TABLE csvtest;
+--------------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+--------------+-------+----------+----------+
| test.csvtest | check | status | OK |
+--------------+-------+----------+----------+
```
检查损坏的表会返回错误,例如
```
mysql> CHECK TABLE csvtest;
+--------------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+--------------+-------+----------+----------+
| test.csvtest | check | error | Corrupt |
+--------------+-------+----------+----------+
```
要修复表,请使用[`维修台`](repair-table.html),它从现有的复制尽可能多的有效行`CSV`数据尽可能,然后替换现有的`CSV`文件与恢复的行。损坏数据之外的任何行都将丢失。
```
mysql> REPAIR TABLE csvtest;
+--------------+--------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+--------------+--------+----------+----------+
| test.csvtest | repair | status | OK |
+--------------+--------+----------+----------+
```
警告
在修复过程中,只有从`CSV`直到第一个损坏的行的文件都被复制到新表中。从第一个损坏的行到表末尾的所有其他行都将被删除,甚至是有效行。
#### 16.2.3.1 Static (Fixed-Length) Table Characteristics
Static format is the default for `MyISAM` tables. It is used when the table contains no variable-length columns ([`VARCHAR`](char.html), [`VARBINARY`](binary-varbinary.html), [`BLOB`](blob.html), or [`TEXT`](blob.html)). Each row is stored using a fixed number of bytes.
Of the three `MyISAM` storage formats, static format is the simplest and most secure (least subject to corruption). It is also the fastest of the on-disk formats due to the ease with which rows in the data file can be found on disk: To look up a row based on a row number in the index, multiply the row number by the row length to calculate the row position. Also, when scanning a table, it is very easy to read a constant number of rows with each disk read operation.
The security is evidenced if your computer crashes while the MySQL server is writing to a fixed-format `MyISAM` file. In this case, [**myisamchk**](myisamchk.html) can easily determine where each row starts and ends, so it can usually reclaim all rows except the partially written one. `MyISAM` table indexes can always be reconstructed based on the data rows.
Note
Fixed-length row format is available only for tables having no [`BLOB`](blob.html) or [`TEXT`](blob.html) columns. Creating a table having such columns with an explicit `ROW_FORMAT` clause does not raise an error or warning; the format specification is ignored.
Static-format tables have these characteristics:
* [`CHAR`](char.html) and [`VARCHAR`](char.html) columns are space-padded to the specified column width, although the column type is not altered. [`BINARY`](binary-varbinary.html) and [`VARBINARY`](binary-varbinary.html) columns are padded with `0x00` bytes to the column width.
* `NULL` columns require additional space in the row to record whether their values are `NULL`. Each `NULL` column takes one bit extra, rounded up to the nearest byte.
* Very quick.
* Easy to cache.
* Easy to reconstruct after a crash, because rows are located in fixed positions.
* Reorganization is unnecessary unless you delete a huge number of rows and want to return free disk space to the operating system. To do this, use [`OPTIMIZE TABLE`](optimize-table.html) or [**myisamchk -r**](myisamchk.html).
* Usually require more disk space than dynamic-format tables.
* The expected row length in bytes for static-sized rows is calculated using the following expression:
```
row length = 1
+ (sum of column lengths)
+ (number of NULL columns + delete_flag + 7)/8
+ (number of variable-length columns)
```
*`delete_flag`* is 1 for tables with static row format. Static tables use a bit in the row record for a flag that indicates whether the row has been deleted. *`delete_flag`* is 0 for dynamic tables because the flag is stored in the dynamic row header.
#### 16.2.3.1 Static (Fixed-Length) Table Characteristics
Static format is the default for`MyISAM`tables. It is used when the table contains no variable-length columns ([`VARCHAR`](char.html),[`VARBINARY`](binary-varbinary.html),[`BLOB`](blob.html), or[`TEXT`](blob.html)). Each row is stored using a fixed number of bytes.
Of the three`MyISAM`storage formats, static format is the simplest and most secure (least subject to corruption). It is also the fastest of the on-disk formats due to the ease with which rows in the data file can be found on disk: To look up a row based on a row number in the index, multiply the row number by the row length to calculate the row position. Also, when scanning a table, it is very easy to read a constant number of rows with each disk read operation.
The security is evidenced if your computer crashes while the MySQL server is writing to a fixed-format`MyISAM`file. In this case,[**myisamchk**](myisamchk.html)can easily determine where each row starts and ends, so it can usually reclaim all rows except the partially written one.`MyISAM`表索引总是可以根据数据行重建。
笔记
固定长度行格式仅适用于没有[`斑点`](blob.html)要么[`文本`](blob.html)列。创建具有此类列的表,其中包含显式`ROW_FORMAT`子句不会引发错误或警告;格式规范被忽略。
静态格式表具有以下特征:
- [`字符`](char.html)[`VARCHAR`](char.html)列被空格填充到指定的列宽,尽管列类型没有改变。[`二进制`](binary-varbinary.html)[`变量`](binary-varbinary.html)列填充`0x00`字节到列宽。
- `空值`列在行中需要额外的空间来记录它们的值是否`空值`.每个`空值`column 需要额外的一位,四舍五入到最接近的字节。
- 很快。
- 易于缓存。
- 崩溃后易于重建,因为行位于固定位置。
- 除非您删除大量行并希望将可用磁盘空间返还给操作系统,否则无需重新组织。为此,请使用[`优化表`](optimize-table.html)要么[**myisamchk -r**](myisamchk.html).
- 通常比动态格式表需要更多的磁盘空间。
- 使用以下表达式计算静态大小行的预期行长度(以字节为单位):
```
row length = 1
+ (sum of column lengths)
+ (number of NULL columns + delete_flag + 7)/8
+ (number of variable-length columns)
```
*`删除标志`*对于具有静态行格式的表,为 1。静态表在行记录中使用一个位作为标志,指示该行是否已被删除。*`删除标志`*动态表为 0,因为标志存储在动态行标题中。
## 16.1 Setting the Storage Engine
When you create a new table, you can specify which storage engine to use by adding an `ENGINE` table option to the [`CREATE TABLE`](create-table.html) statement:
```
-- ENGINE=INNODB not needed unless you have set a different
-- default storage engine.
CREATE TABLE t1 (i INT) ENGINE = INNODB;
-- Simple table definitions can be switched from one to another.
CREATE TABLE t2 (i INT) ENGINE = CSV;
CREATE TABLE t3 (i INT) ENGINE = MEMORY;
```
When you omit the `ENGINE` option, the default storage engine is used. The default engine is [`InnoDB`](innodb-storage-engine.html) in MySQL 8.0. You can specify the default engine by using the [`--default-storage-engine`](server-system-variables.html#sysvar_default_storage_engine) server startup option, or by setting the [`default-storage-engine`](server-system-variables.html#sysvar_default_storage_engine) option in the `my.cnf` configuration file.
You can set the default storage engine for the current session by setting the [`default_storage_engine`](server-system-variables.html#sysvar_default_storage_engine) variable:
```
SET default_storage_engine=NDBCLUSTER;
```
The storage engine for `TEMPORARY` tables created with [`CREATE TEMPORARY TABLE`](create-table.html) can be set separately from the engine for permanent tables by setting the [`default_tmp_storage_engine`](server-system-variables.html#sysvar_default_tmp_storage_engine), either at startup or at runtime.
To convert a table from one storage engine to another, use an [`ALTER TABLE`](alter-table.html) statement that indicates the new engine:
```
ALTER TABLE t ENGINE = InnoDB;
```
See [Section 13.1.20, “CREATE TABLE Statement”](create-table.html), and [Section 13.1.9, “ALTER TABLE Statement”](alter-table.html).
If you try to use a storage engine that is not compiled in or that is compiled in but deactivated, MySQL instead creates a table using the default storage engine. For example, in a replication setup, perhaps your source server uses `InnoDB` tables for maximum safety, but the replica servers use other storage engines for speed at the expense of durability or concurrency.
By default, a warning is generated whenever [`CREATE TABLE`](create-table.html) or [`ALTER TABLE`](alter-table.html) cannot use the default storage engine. To prevent confusing, unintended behavior if the desired engine is unavailable, enable the [`NO_ENGINE_SUBSTITUTION`](sql-mode.html#sqlmode_no_engine_substitution) SQL mode. If the desired engine is unavailable, this setting produces an error instead of a warning, and the table is not created or altered. See [Section 5.1.11, “Server SQL Modes”](sql-mode.html).
MySQL may store a table's index and data in one or more other files, depending on the storage engine. Table and column definitions are stored in the MySQL data dictionary. Individual storage engines create any additional files required for the tables that they manage. If a table name contains special characters, the names for the table files contain encoded versions of those characters as described in [Section 9.2.4, “Mapping of Identifiers to File Names”](identifier-mapping.html).
## 16.1 设置存储引擎
创建新表时,可以通过添加`引擎`表选项[`创建表`](create-table.html)陈述:
```
-- ENGINE=INNODB not needed unless you have set a different
-- default storage engine.
CREATE TABLE t1 (i INT) ENGINE = INNODB;
-- Simple table definitions can be switched from one to another.
CREATE TABLE t2 (i INT) ENGINE = CSV;
CREATE TABLE t3 (i INT) ENGINE = MEMORY;
```
当你省略`引擎`选项,使用默认存储引擎。默认引擎是[`InnoDB`](innodb-storage-engine.html)在 MySQL 8.0 中。您可以使用[`--默认存储引擎`](server-system-variables.html#sysvar_default_storage_engine)服务器启动选项,或通过设置[`默认存储引擎`](server-system-variables.html#sysvar_default_storage_engine)中的选项`我的.cnf`配置文件。
您可以通过设置当前会话的默认存储引擎[`default_storage_engine`](server-system-variables.html#sysvar_default_storage_engine)多变的:
```
SET default_storage_engine=NDBCLUSTER;
```
存储引擎`暂时的`创建的表[`创建临时表`](create-table.html)可以通过设置[`default_tmp_storage_engine`](server-system-variables.html#sysvar_default_tmp_storage_engine),无论是在启动时还是在运行时。
要将表从一个存储引擎转换为另一个,请使用[`更改表`](alter-table.html)表示新引擎的语句:
```
ALTER TABLE t ENGINE = InnoDB;
```
[第 13.1.20 节,“CREATE TABLE 语句”](create-table.html), 和[第 13.1.9 节,“ALTER TABLE 语句”](alter-table.html).
如果您尝试使用未编译或已编译但停用的存储引擎,MySQL 会使用默认存储引擎创建表。例如,在复制设置中,也许您的源服务器使用`InnoDB`表以获得最大的安全性,但副本服务器使用其他存储引擎以牺牲持久性或并发性来提高速度。
默认情况下,每当[`创建表`](create-table.html)要么[`更改表`](alter-table.html)无法使用默认存储引擎。为防止在所需引擎不可用时出现令人困惑的意外行为,请启用[`NO_ENGINE_SUBSTITUTION`](sql-mode.html#sqlmode_no_engine_substitution)SQL 模式。如果所需的引擎不可用,则此设置会产生错误而不是警告,并且不会创建或更改表。看[第 5.1.11 节,“服务器 SQL 模式”](sql-mode.html).
MySQL 可能会将表的索引和数据存储在一个或多个其他文件中,具体取决于存储引擎。表和列定义存储在 MySQL 数据字典中。各个存储引擎创建它们管理的表所需的任何附加文件。如果表名包含特殊字符,则表文件的名称包含这些字符的编码版本,如[第 9.2.4 节,“标识符到文件名的映射”](identifier-mapping.html).
## 16.10 Other Storage Engines
Other storage engines may be available from third parties and community members that have used the Custom Storage Engine interface.
Third party engines are not supported by MySQL. For further information, documentation, installation guides, bug reporting or for any help or assistance with these engines, please contact the developer of the engine directly.
For more information on developing a customer storage engine that can be used with the Pluggable Storage Engine Architecture, see [MySQL Internals: Writing a Custom Storage Engine](https://dev.mysql.com/doc/internals/en/custom-engine.html).
## 16.10 其他存储引擎
其他存储引擎可以从使用自定义存储引擎接口的第三方和社区成员处获得。
MySQL 不支持第三方引擎。有关更多信息、文档、安装指南、错误报告或有关这些引擎的任何帮助或帮助,请直接联系引擎的开发人员。
有关开发可与可插入存储引擎架构一起使用的客户存储引擎的更多信息,请参阅[MySQL 内部结构:编写自定义存储引擎](https://dev.mysql.com/doc/internals/en/custom-engine.html).
# Chapter 16 Alternative Storage Engines
**Table of Contents**
[16.1 Setting the Storage Engine](storage-engine-setting.html)[16.2 The MyISAM Storage Engine](myisam-storage-engine.html)[16.2.1 MyISAM Startup Options](myisam-start.html)[16.2.2 Space Needed for Keys](key-space.html)[16.2.3 MyISAM Table Storage Formats](myisam-table-formats.html)[16.2.4 MyISAM Table Problems](myisam-table-problems.html)[16.3 The MEMORY Storage Engine](memory-storage-engine.html)[16.4 The CSV Storage Engine](csv-storage-engine.html)[16.4.1 Repairing and Checking CSV Tables](se-csv-repair.html)[16.4.2 CSV Limitations](se-csv-limitations.html)[16.5 The ARCHIVE Storage Engine](archive-storage-engine.html)[16.6 The BLACKHOLE Storage Engine](blackhole-storage-engine.html)[16.7 The MERGE Storage Engine](merge-storage-engine.html)[16.7.1 MERGE Table Advantages and Disadvantages](merge-table-advantages.html)[16.7.2 MERGE Table Problems](merge-table-problems.html)[16.8 The FEDERATED Storage Engine](federated-storage-engine.html)[16.8.1 FEDERATED Storage Engine Overview](federated-description.html)[16.8.2 How to Create FEDERATED Tables](federated-create.html)[16.8.3 FEDERATED Storage Engine Notes and Tips](federated-usagenotes.html)[16.8.4 FEDERATED Storage Engine Resources](federated-storage-engine-resources.html)[16.9 The EXAMPLE Storage Engine](example-storage-engine.html)[16.10 Other Storage Engines](storage-engines-other.html)[16.11 Overview of MySQL Storage Engine Architecture](pluggable-storage-overview.html)[16.11.1 Pluggable Storage Engine Architecture](pluggable-storage.html)[16.11.2 The Common Database Server Layer](pluggable-storage-common-layer.html)
[]()[]()[]()[]()[]()[]()[]()[]()[]()[]()[]()[]()[]()[]()
Storage engines are MySQL components that handle the SQL operations for different table types. [`InnoDB`](innodb-storage-engine.html) is the default and most general-purpose storage engine, and Oracle recommends using it for tables except for specialized use cases. (The [`CREATE TABLE`](create-table.html) statement in MySQL 8.0 creates `InnoDB` tables by default.)
MySQL Server uses a pluggable storage engine architecture that enables storage engines to be loaded into and unloaded from a running MySQL server.
To determine which storage engines your server supports, use the [`SHOW ENGINES`](show-engines.html) statement. The value in the `Support` column indicates whether an engine can be used. A value of `YES`, `NO`, or `DEFAULT` indicates that an engine is available, not available, or available and currently set as the default storage engine.
```
mysql> SHOW ENGINES\G
*************************** 1. row ***************************
Engine: PERFORMANCE_SCHEMA
Support: YES
Comment: Performance Schema
Transactions: NO
XA: NO
Savepoints: NO
*************************** 2. row ***************************
Engine: InnoDB
Support: DEFAULT
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
*************************** 3. row ***************************
Engine: MRG_MYISAM
Support: YES
Comment: Collection of identical MyISAM tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 4. row ***************************
Engine: BLACKHOLE
Support: YES
Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
XA: NO
Savepoints: NO
*************************** 5. row ***************************
Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO
...
```
This chapter covers use cases for special-purpose MySQL storage engines. It does not cover the default [`InnoDB`](innodb-storage-engine.html) storage engine or the [`NDB`](mysql-cluster.html) storage engine which are covered in [Chapter 15, *The InnoDB Storage Engine*](innodb-storage-engine.html) and [Chapter 23, *MySQL NDB Cluster 8.0*](mysql-cluster.html). For advanced users, it also contains a description of the pluggable storage engine architecture (see [Section 16.11, “Overview of MySQL Storage Engine Architecture”](pluggable-storage-overview.html)).
For information about features offered in commercial MySQL Server binaries, see [*MySQL Editions*](https://www.mysql.com/products/), on the MySQL website. The storage engines available might depend on which edition of MySQL you are using.
For answers to commonly asked questions about MySQL storage engines, see [Section A.2, “MySQL 8.0 FAQ: Storage Engines”](faqs-storage-engines.html).
## MySQL 8.0 Supported Storage Engines
* [`InnoDB`](innodb-storage-engine.html): The default storage engine in MySQL 8.0. `InnoDB` is a transaction-safe (ACID compliant) storage engine for MySQL that has commit, rollback, and crash-recovery capabilities to protect user data. `InnoDB` row-level locking (without escalation to coarser granularity locks) and Oracle-style consistent nonlocking reads increase multi-user concurrency and performance. `InnoDB` stores user data in clustered indexes to reduce I/O for common queries based on primary keys. To maintain data integrity, `InnoDB` also supports `FOREIGN KEY` referential-integrity constraints. For more information about `InnoDB`, see [Chapter 15, *The InnoDB Storage Engine*](innodb-storage-engine.html).
* [`MyISAM`](myisam-storage-engine.html): These tables have a small footprint. [Table-level locking](glossary.html#glos_table_lock) limits the performance in read/write workloads, so it is often used in read-only or read-mostly workloads in Web and data warehousing configurations.
* [`Memory`](memory-storage-engine.html): Stores all data in RAM, for fast access in environments that require quick lookups of non-critical data. This engine was formerly known as the `HEAP` engine. Its use cases are decreasing; `InnoDB` with its buffer pool memory area provides a general-purpose and durable way to keep most or all data in memory, and `NDBCLUSTER` provides fast key-value lookups for huge distributed data sets.
* [`CSV`](csv-storage-engine.html): Its tables are really text files with comma-separated values. CSV tables let you import or dump data in CSV format, to exchange data with scripts and applications that read and write that same format. Because CSV tables are not indexed, you typically keep the data in `InnoDB` tables during normal operation, and only use CSV tables during the import or export stage.
* [`Archive`](archive-storage-engine.html): These compact, unindexed tables are intended for storing and retrieving large amounts of seldom-referenced historical, archived, or security audit information.
* [`Blackhole`](blackhole-storage-engine.html): The Blackhole storage engine accepts but does not store data, similar to the Unix `/dev/null` device. Queries always return an empty set. These tables can be used in replication configurations where DML statements are sent to replica servers, but the source server does not keep its own copy of the data.
* [`NDB`](mysql-cluster.html) (also known as [`NDBCLUSTER`](mysql-cluster.html)): This clustered database engine is particularly suited for applications that require the highest possible degree of uptime and availability.
* [`Merge`](merge-storage-engine.html): Enables a MySQL DBA or developer to logically group a series of identical `MyISAM` tables and reference them as one object. Good for VLDB environments such as data warehousing.
* [`Federated`](federated-storage-engine.html): Offers the ability to link separate MySQL servers to create one logical database from many physical servers. Very good for distributed or data mart environments.
* [`Example`](example-storage-engine.html): This engine serves as an example in the MySQL source code that illustrates how to begin writing new storage engines. It is primarily of interest to developers. The storage engine is a “stub” that does nothing. You can create tables with this engine, but no data can be stored in them or retrieved from them.
You are not restricted to using the same storage engine for an entire server or schema. You can specify the storage engine for any table. For example, an application might use mostly `InnoDB` tables, with one `CSV` table for exporting data to a spreadsheet and a few `MEMORY` tables for temporary workspaces.
**Choosing a Storage Engine**
The various storage engines provided with MySQL are designed with different use cases in mind. The following table provides an overview of some storage engines provided with MySQL, with clarifying notes following the table.
[]()
**Table 16.1 Storage Engines Feature Summary**
| Feature | MyISAM | Memory | InnoDB | Archive | NDB |
|--------------------------------------|------------|----------------|------------|------------|------------|
| B-tree indexes | Yes | Yes | Yes | No | No |
|Backup/point-in-time recovery (note 1)| Yes | Yes | Yes | Yes | Yes |
| Cluster database support | No | No | No | No | Yes |
| Clustered indexes | No | No | Yes | No | No |
| Compressed data |Yes (note 2)| No | Yes | Yes | No |
| Data caches | No | N/A | Yes | No | Yes |
| Encrypted data |Yes (note 3)| Yes (note 3) |Yes (note 4)|Yes (note 3)|Yes (note 3)|
| Foreign key support | No | No | Yes | No |Yes (note 5)|
| Full-text search indexes | Yes | No |Yes (note 6)| No | No |
| Geospatial data type support | Yes | No | Yes | Yes | Yes |
| Geospatial indexing support | Yes | No |Yes (note 7)| No | No |
| Hash indexes | No | Yes |No (note 8) | No | Yes |
| Index caches | Yes | N/A | Yes | No | Yes |
| Locking granularity | Table | Table | Row | Row | Row |
| MVCC | No | No | Yes | No | No |
| Replication support (note 1) | Yes |Limited (note 9)| Yes | Yes | Yes |
| Storage limits | 256TB | RAM | 64TB | None | 384EB |
| T-tree indexes | No | No | No | No | Yes |
| Transactions | No | No | Yes | No | Yes |
|Update statistics for data dictionary | Yes | Yes | Yes | Yes | Yes |
**Notes:**
1. Implemented in the server, rather than in the storage engine.
2. Compressed MyISAM tables are supported only when using the compressed row format. Tables using the compressed row format with MyISAM are read only.
3. Implemented in the server via encryption functions.
4. Implemented in the server via encryption functions; In MySQL 5.7 and later, data-at-rest encryption is supported.
5. Support for foreign keys is available in MySQL Cluster NDB 7.3 and later.
6. Support for FULLTEXT indexes is available in MySQL 5.6 and later.
7. Support for geospatial indexing is available in MySQL 5.7 and later.
8. InnoDB utilizes hash indexes internally for its Adaptive Hash Index feature.
9. See the discussion later in this section.
# 第 16 章 替代存储引擎
**目录**
[16.1 设置存储引擎](storage-engine-setting.html)[16.2 MyISAM 存储引擎](myisam-storage-engine.html)[16.2.1 MyISAM 启动选项](myisam-start.html)[16.2.2 键所需空间](key-space.html)[16.2.3 MyISAM 表存储格式](myisam-table-formats.html)[16.2.4 MyISAM 表问题](myisam-table-problems.html)[16.3 MEMORY存储引擎](memory-storage-engine.html)[16.4 CSV 存储引擎](csv-storage-engine.html)[16.4.1 修复和检查 CSV 表](se-csv-repair.html)[16.4.2 CSV 限制](se-csv-limitations.html)[16.5 ARCHIVE 存储引擎](archive-storage-engine.html)[16.6 黑洞存储引擎](blackhole-storage-engine.html)[16.7 MERGE存储引擎](merge-storage-engine.html)[16.7.1 MERGE 表的优缺点](merge-table-advantages.html)[16.7.2 合并表问题](merge-table-problems.html)[16.8 联合存储引擎](federated-storage-engine.html)[16.8.1 联邦存储引擎概述](federated-description.html)[16.8.2 如何创建 FEDERATED 表](federated-create.html)[16.8.3 联合存储引擎注意事项和提示](federated-usagenotes.html)[16.8.4 联合存储引擎资源](federated-storage-engine-resources.html)[16.9 示例存储引擎](example-storage-engine.html)[16.10 其他存储引擎](storage-engines-other.html)[16.11 MySQL存储引擎架构概述](pluggable-storage-overview.html)[16.11.1 可插拔存储引擎架构](pluggable-storage.html)[16.11.2 通用数据库服务器层](pluggable-storage-common-layer.html)
[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)
存储引擎是处理不同表类型的 SQL 操作的 MySQL 组件。[`InnoDB`](innodb-storage-engine.html)是默认且最通用的存储引擎,Oracle 建议将其用于表,但特殊用例除外。(这[`创建表`](create-table.html)MySQL 8.0 中的语句创建`InnoDB`默认情况下的表格。)
MySQL 服务器使用可插拔的存储引擎架构,使存储引擎能够加载到正在运行的 MySQL 服务器中或从其中卸载。
要确定您的服务器支持哪些存储引擎,请使用[`显示引擎`](show-engines.html)陈述。中的值`支持`列指示是否可以使用引擎。一个值`是的`,`不`, 要么`默认`表示引擎可用、不可用或可用且当前设置为默认存储引擎。
```
mysql> SHOW ENGINES\G
*************************** 1. row ***************************
Engine: PERFORMANCE_SCHEMA
Support: YES
Comment: Performance Schema
Transactions: NO
XA: NO
Savepoints: NO
*************************** 2. row ***************************
Engine: InnoDB
Support: DEFAULT
Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
XA: YES
Savepoints: YES
*************************** 3. row ***************************
Engine: MRG_MYISAM
Support: YES
Comment: Collection of identical MyISAM tables
Transactions: NO
XA: NO
Savepoints: NO
*************************** 4. row ***************************
Engine: BLACKHOLE
Support: YES
Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
XA: NO
Savepoints: NO
*************************** 5. row ***************************
Engine: MyISAM
Support: YES
Comment: MyISAM storage engine
Transactions: NO
XA: NO
Savepoints: NO
...
```
本章介绍专用 MySQL 存储引擎的用例。它不包括默认值[`InnoDB`](innodb-storage-engine.html)存储引擎或[`新开发银行`](mysql-cluster.html)涵盖的存储引擎[第 15 章,*InnoDB 存储引擎*](innodb-storage-engine.html)[第 23 章,*MySQL NDB 集群 8.0*](mysql-cluster.html).对于高级用户,它还包含对可插拔存储引擎架构的描述(参见[第 16.11 节,“MySQL 存储引擎架构概述”](pluggable-storage-overview.html))。
有关商业 MySQL 服务器二进制文件中提供的功能的信息,请参阅[*MySQL 版本*](https://www.mysql.com/products/),在 MySQL 网站上。可用的存储引擎可能取决于您使用的 MySQL 版本。
有关 MySQL 存储引擎的常见问题解答,请参阅[第 A.2 节,“MySQL 8.0 常见问题解答:存储引擎”](faqs-storage-engines.html).
## MySQL 8.0 支持的存储引擎
- [`InnoDB`](innodb-storage-engine.html): MySQL 8.0 中默认的存储引擎。`InnoDB`是用于 MySQL 的事务安全(符合 ACID)存储引擎,具有提交、回滚和崩溃恢复功能以保护用户数据。`InnoDB`行级锁定(不升级到更粗粒度的锁定)和 Oracle 风格的一致非锁定读取提高了多用户并发性和性能。`InnoDB`将用户数据存储在聚集索引中,以减少基于主键的常见查询的 I/O。为了保持数据完整性,`InnoDB`也支持`外键`参照完整性约束。有关更多信息`InnoDB`, 看[第 15 章,*InnoDB 存储引擎*](innodb-storage-engine.html).
- [`MyISAM`](myisam-storage-engine.html):这些表占用空间小。[表级锁定](glossary.html#glos_table_lock)限制了读/写工作负载的性能,因此它通常用于 Web 和数据仓库配置中的只读或以读取为主的工作负载。
- [`记忆`](memory-storage-engine.html):将所有数据存储在 RAM 中,以便在需要快速查找非关键数据的环境中快速访问。这台发动机以前被称为`堆`引擎。它的用例正在减少;`InnoDB`其缓冲池内存区域提供了一种通用且持久的方式来将大部分或所有数据保存在内存中,并且`NDBCLUSTER`为庞大的分布式数据集提供快速的键值查找。
- [`CSV`](csv-storage-engine.html): 它的表格实际上是带有逗号分隔值的文本文件。CSV 表允许您以 CSV 格式导入或转储数据,以便与读取和写入相同格式的脚本和应用程序交换数据。由于 CSV 表没有索引,因此您通常将数据保存在`InnoDB`在正常操作期间使用表,并且仅在导入或导出阶段使用 CSV 表。
- [`档案`](archive-storage-engine.html):这些紧凑的未索引表旨在存储和检索大量很少引用的历史、归档或安全审计信息。
- [`黑洞`](blackhole-storage-engine.html):黑洞存储引擎接受但不存储数据,类似于Unix`/dev/null`设备。查询总是返回一个空集。这些表可用于复制配置,其中 DML 语句被发送到副本服务器,但源服务器不保留自己的数据副本。
- [`新开发银行`](mysql-cluster.html)(也称为[`NDBCLUSTER`](mysql-cluster.html)):这种集群数据库引擎特别适用于需要尽可能高的正常运行时间和可用性的应用程序。
- [`合并`](merge-storage-engine.html):使 MySQL DBA 或开发人员能够在逻辑上对一系列相同的`MyISAM`表并将它们作为一个对象引用。适用于 VLDB 环境,例如数据仓库。
- [`联合的`](federated-storage-engine.html):提供链接不同的 MySQL 服务器以从多个物理服务器创建一个逻辑数据库的能力。非常适合分布式或数据集市环境。
- [`例子`](example-storage-engine.html):这个引擎作为 MySQL 源代码中的一个示例,说明了如何开始编写新的存储引擎。它主要是开发人员感兴趣的。存储引擎是一个什么都不做的“存根”。您可以使用此引擎创建表,但无法在其中存储或检索数据。
您不限于对整个服务器或架构使用相同的存储引擎。您可以为任何表指定存储引擎。例如,一个应用程序可能主要使用`InnoDB`表,有一个`CSV`用于将数据导出到电子表格的表格和一些`记忆`临时工作区的表。
**选择存储引擎**
MySQL 提供的各种存储引擎在设计时考虑了不同的用例。下表概述了 MySQL 提供的一些存储引擎,并在表后提供了澄清说明。
[](<>)
**表 16.1 存储引擎功能摘要**
| 特征 | MyISAM | 记忆 | InnoDB | 档案 | 新开发银行 |
| --- | ------ | --- | ------ | --- | ----- |
| B树索引 | 是的 | 是的 | 是的 | 不 | 不 |
| 备份/时间点恢复(注 1) | 是的 | 是的 | 是的 | 是的 | 是的 |
| 集群数据库支持 | 不 | 不 | 不 | 不 | 是的 |
| 聚集索引 | 不 | 不 | 是的 | 不 | 不 |
| 压缩数据 | 是(注2) | 不 | 是的 | 是的 | 不 |
| 数据缓存 | 不 | 不适用 | 是的 | 不 | 是的 |
| 加密数据 | 是(注 3) | 是(注 3) | 是(注 4) | 是(注 3) | 是(注 3) |
| 外键支持 | 不 | 不 | 是的 | 不 | 是(注 5) |
| 全文检索索引 | 是的 | 不 | 是(注 6) | 不 | 不 |
| 地理空间数据类型支持 | 是的 | 不 | 是的 | 是的 | 是的 |
| 地理空间索引支持 | 是的 | 不 | 是(注 7) | 不 | 不 |
| 哈希索引 | 不 | 是的 | 否(注 8) | 不 | 是的 |
| 索引缓存 | 是的 | 不适用 | 是的 | 不 | 是的 |
| 锁定粒度 | 桌子 | 桌子 | 排 | 排 | 排 |
| MVCC | 不 | 不 | 是的 | 不 | 不 |
| 复制支持(注 1) | 是的 | 有限(注 9) | 是的 | 是的 | 是的 |
| 存储限制 | 256TB | 内存 | 64TB | 没有 | 384EB |
| T-树索引 | 不 | 不 | 不 | 不 | 是的 |
| 交易 | 不 | 不 | 是的 | 不 | 是的 |
| 更新数据字典的统计信息 | 是的 | 是的 | 是的 | 是的 | 是的 |
**笔记:**
1. 在服务器中实现,而不是在存储引擎中。
2. 仅当使用压缩行格式时才支持压缩的 MyISAM 表。使用 MyISAM 压缩行格式的表是只读的。
3. 通过加密功能在服务器中实现。
4. 通过加密功能在服务器中实现;在 MySQL 5.7 及更高版本中,支持静态数据加密。
5. MySQL Cluster NDB 7.3 及更高版本中提供了对外键的支持。
6. MySQL 5.6 及更高版本提供对 FULLTEXT 索引的支持。
7. MySQL 5.7 及更高版本中提供了对地理空间索引的支持。
8. InnoDB 在内部使用哈希索引来实现其自适应哈希索引功能。
9. 请参阅本节后面的讨论。
# Chapter 7 Backup and Recovery
**Table of Contents**
[7.1 Backup and Recovery Types](backup-types.html)
[7.2 Database Backup Methods](backup-methods.html)
[7.3 Example Backup and Recovery Strategy](backup-strategy-example.html)
[7.3.1 Establishing a Backup Policy](backup-policy.html)
[7.3.2 Using Backups for Recovery](recovery-from-backups.html)
[7.3.3 Backup Strategy Summary](backup-strategy-summary.html)
[7.4 Using mysqldump for Backups](using-mysqldump.html)
[7.4.1 Dumping Data in SQL Format with mysqldump](mysqldump-sql-format.html)
[7.4.2 Reloading SQL-Format Backups](reloading-sql-format-dumps.html)
[7.4.3 Dumping Data in Delimited-Text Format with mysqldump](mysqldump-delimited-text.html)
[7.4.4 Reloading Delimited-Text Format Backups](reloading-delimited-text-dumps.html)
[7.4.5 mysqldump Tips](mysqldump-tips.html)
[7.5 Point-in-Time (Incremental) Recovery](point-in-time-recovery.html)
[7.5.1 Point-in-Time Recovery Using Binary Log](point-in-time-recovery-binlog.html)
[7.5.2 Point-in-Time Recovery Using Event Positions](point-in-time-recovery-positions.html)
[7.6 MyISAM Table Maintenance and Crash Recovery](myisam-table-maintenance.html)
[7.6.1 Using myisamchk for Crash Recovery](myisam-crash-recovery.html)
[7.6.2 How to Check MyISAM Tables for Errors](myisam-check.html)
[7.6.3 How to Repair MyISAM Tables](myisam-repair.html)
[7.6.4 MyISAM Table Optimization](myisam-optimization.html)
[7.6.5 Setting Up a MyISAM Table Maintenance Schedule](myisam-maintenance-schedule.html)
[]()[]()
It is important to back up your databases so that you can recover your data and be up and running again in case problems occur, such as system crashes, hardware failures, or users deleting data by mistake. Backups are also essential as a safeguard before upgrading a MySQL installation, and they can be used to transfer a MySQL installation to another system or to set up replica servers.
MySQL offers a variety of backup strategies from which you can choose the methods that best suit the requirements for your installation. This chapter discusses several backup and recovery topics with which you should be familiar:
* Types of backups: Logical versus physical, full versus incremental, and so forth.
* Methods for creating backups.
* Recovery methods, including point-in-time recovery.
* Backup scheduling, compression, and encryption.
* Table maintenance, to enable recovery of corrupt tables.
## Additional Resources
Resources related to backup or to maintaining data availability include the following:
* Customers of MySQL Enterprise Edition can use the MySQL Enterprise Backup product for backups. For an overview of the MySQL Enterprise Backup product, see [Section 30.2, “MySQL Enterprise Backup Overview”](mysql-enterprise-backup.html).
* A forum dedicated to backup issues is available at [https://forums.mysql.com/list.php?28](https://forums.mysql.com/list.php?28).
* Details for [**mysqldump**](mysqldump.html) can be found in [Chapter 4, *MySQL Programs*](programs.html).
* The syntax of the SQL statements described here is given in [Chapter 13, *SQL Statements*](sql-statements.html).
* For additional information about `InnoDB` backup procedures, see [Section 15.18.1, “InnoDB Backup”](innodb-backup.html).
* Replication enables you to maintain identical data on multiple servers. This has several benefits, such as enabling client query load to be distributed over servers, availability of data even if a given server is taken offline or fails, and the ability to make backups with no impact on the source by using a replica. See [Chapter 17, *Replication*](replication.html).
* MySQL InnoDB Cluster is a collection of products that work together to provide a high availability solution. A group of MySQL servers can be configured to create a cluster using MySQL Shell. The cluster of servers has a single source, called the primary, which acts as the read-write source. Multiple secondary servers are replicas of the source. A minimum of three servers are required to create a high availability cluster. A client application is connected to the primary via MySQL Router. If the primary fails, a secondary is automatically promoted to the role of primary, and MySQL Router routes requests to the new primary.
* NDB Cluster provides a high-availability, high-redundancy version of MySQL adapted for the distributed computing environment. See [Chapter 23, *MySQL NDB Cluster 8.0*](mysql-cluster.html), which provides information about MySQL NDB Cluster 8.0.
# 第 7 章 备份与恢复
**目录**
[7.1 备份和恢复类型](backup-types.html)
[7.2 数据库备份方法](backup-methods.html)
[7.3 示例备份和恢复策略](backup-strategy-example.html)
[7.3.1 建立备份策略](backup-policy.html)
[7.3.2 使用备份进行恢复](recovery-from-backups.html)
[7.3.3 备份策略总结](backup-strategy-summary.html)
[7.4 使用 mysqldump 进行备份](using-mysqldump.html)
[7.4.1 使用 mysqldump 以 SQL 格式转储数据](mysqldump-sql-format.html)
[7.4.2 重新加载 SQL 格式的备份](reloading-sql-format-dumps.html)
[7.4.3 使用 mysqldump 以分隔文本格式转储数据](mysqldump-delimited-text.html)
[7.4.4 重新加载分隔文本格式的备份](reloading-delimited-text-dumps.html)
[7.4.5 mysqldump 提示](mysqldump-tips.html)
[7.5 时间点(增量)恢复](point-in-time-recovery.html)
[7.5.1 使用二进制日志的时间点恢复](point-in-time-recovery-binlog.html)
[7.5.2 使用事件位置的时间点恢复](point-in-time-recovery-positions.html)
[7.6 MyISAM 表维护和崩溃恢复](myisam-table-maintenance.html)
[7.6.1 使用 myisamchk 进行崩溃恢复](myisam-crash-recovery.html)
[7.6.2 如何检查 MyISAM 表的错误](myisam-check.html)
[7.6.3 如何修复 MyISAM 表](myisam-repair.html)
[7.6.4 MyISAM 表优化](myisam-optimization.html)
[7.6.5 设置 MyISAM 表维护计划](myisam-maintenance-schedule.html)
[](<>)[](<>)
备份数据库很重要,这样您就可以恢复数据并在出现问题时重新启动并运行,例如系统崩溃、硬件故障或用户误删除数据。在升级 MySQL 安装之前,备份也是必不可少的保障,它们可用于将 MySQL 安装转移到另一个系统或设置副本服务器。
MySQL 提供了多种备份策略,您可以从中选择最适合您的安装要求的方法。本章讨论了您应该熟悉的几个备份和恢复主题:
- 备份类型:逻辑与物理、完整与增量等。
- 创建备份的方法。
- 恢复方法,包括时间点恢复。
- 备份调度、压缩和加密。
- 表维护,以启用损坏表的恢复。
## 其他资源
与备份或维护数据可用性相关的资源包括:
- MySQL Enterprise Edition 的客户可以使用 MySQL Enterprise Backup 产品进行备份。有关 MySQL Enterprise Backup 产品的概述,请参阅[第 30.2 节,“MySQL 企业备份概述”](mysql-enterprise-backup.html).
- 一个专门讨论备份问题的论坛可以在<https://forums.mysql.com/list.php?28>.
- 详细信息[**mysql转储**](mysqldump.html)可以在[第 4 章,*MySQL 程序*](programs.html).
- 此处描述的 SQL 语句的语法在[第 13 章,*SQL 语句*](sql-statements.html).
- 有关更多信息`InnoDB`备份程序,请参阅[第 15.18.1 节,“InnoDB 备份”](innodb-backup.html).
- 复制使您能够在多个服务器上维护相同的数据。这有几个好处,例如使客户端查询负载能够分布在服务器上,即使给定的服务器脱机或发生故障,数据的可用性,以及通过使用副本在不影响源的情况下进行备份的能力。看[第十七章,*复制*](replication.html).
- MySQL InnoDB Cluster 是一组产品,它们协同工作以提供高可用性解决方案。一组 MySQL 服务器可以配置为使用 MySQL Shell 创建集群。服务器集群有一个单一的源,称为主源,它充当读写源。多个辅助服务器是源的副本。创建高可用性集群至少需要三台服务器。客户端应用程序通过 MySQL 路由器连接到主应用程序。如果主节点失败,辅助节点会自动提升为主节点的角色,并且 MySQL 路由器将请求路由到新的主节点。
- NDB Cluster 提供了适用于分布式计算环境的高可用、高冗余版本的 MySQL。看[第 23 章,*MySQL NDB 集群 8.0*](mysql-cluster.html),它提供了有关 MySQL NDB Cluster 8.0 的信息。
## 7.2 Database Backup Methods
This section summarizes some general methods for making backups.
### Making a Hot Backup with MySQL Enterprise Backup
Customers of MySQL Enterprise Edition can use the [MySQL Enterprise Backup](glossary.html#glos_mysql_enterprise_backup) product to do [physical](glossary.html#glos_physical) backups of entire instances or selected databases, tables, or both. This product includes features for [incremental](glossary.html#glos_incremental_backup) and [compressed](glossary.html#glos_compressed_backup) backups. Backing up the physical database files makes restore much faster than logical techniques such as the `mysqldump` command. `InnoDB` tables are copied using a [hot backup](glossary.html#glos_hot_backup) mechanism. (Ideally, the `InnoDB` tables should represent a substantial majority of the data.) Tables from other storage engines are copied using a [warm backup](glossary.html#glos_warm_backup) mechanism. For an overview of the MySQL Enterprise Backup product, see [Section 30.2, “MySQL Enterprise Backup Overview”](mysql-enterprise-backup.html).
### Making Backups with mysqldump
The [**mysqldump**](mysqldump.html) program can make backups. It can back up all kinds of tables. (See [Section 7.4, “Using mysqldump for Backups”](using-mysqldump.html).)
For `InnoDB` tables, it is possible to perform an online backup that takes no locks on tables using the [`--single-transaction`](mysqldump.html#option_mysqldump_single-transaction) option to [**mysqldump**](mysqldump.html). See [Section 7.3.1, “Establishing a Backup Policy”](backup-policy.html).
### Making Backups by Copying Table Files
MyISAM tables can be backed up by copying table files (`*.MYD`, `*.MYI` files, and associated `*.sdi` files). To get a consistent backup, stop the server or lock and flush the relevant tables:
```
FLUSH TABLES tbl_list WITH READ LOCK;
```
You need only a read lock; this enables other clients to continue to query the tables while you are making a copy of the files in the database directory. The flush is needed to ensure that the all active index pages are written to disk before you start the backup. See [Section 13.3.6, “LOCK TABLES and UNLOCK TABLES Statements”](lock-tables.html), and [Section 13.7.8.3, “FLUSH Statement”](flush.html).
You can also create a binary backup simply by copying the table files, as long as the server isn't updating anything. (But note that table file copying methods do not work if your database contains `InnoDB` tables. Also, even if the server is not actively updating data, `InnoDB` may still have modified data cached in memory and not flushed to disk.)
For an example of this backup method, refer to the export and import example in [Section 13.2.5, “IMPORT TABLE Statement”](import-table.html).
### Making Delimited-Text File Backups
To create a text file containing a table's data, you can use [`SELECT * INTO OUTFILE '*`file_name`*' FROM *`tbl_name`*`](select-into.html). The file is created on the MySQL server host, not the client host. For this statement, the output file cannot already exist because permitting files to be overwritten constitutes a security risk. See [Section 13.2.10, “SELECT Statement”](select.html). This method works for any kind of data file, but saves only table data, not the table structure.
Another way to create text data files (along with files containing [`CREATE TABLE`](create-table.html) statements for the backed up tables) is to use [**mysqldump**](mysqldump.html) with the [`--tab`](mysqldump.html#option_mysqldump_tab) option. See [Section 7.4.3, “Dumping Data in Delimited-Text Format with mysqldump”](mysqldump-delimited-text.html).
To reload a delimited-text data file, use [`LOAD DATA`](load-data.html) or [**mysqlimport**](mysqlimport.html).
### Making Incremental Backups by Enabling the Binary Log
MySQL supports incremental backups using the binary log. The binary log files provide you with the information you need to replicate changes to the database that are made subsequent to the point at which you performed a backup. Therefore, to allow a server to be restored to a point-in-time, binary logging must be enabled on it, which is the default setting for MySQL 8.0 ; see [Section 5.4.4, “The Binary Log”](binary-log.html).
At the moment you want to make an incremental backup (containing all changes that happened since the last full or incremental backup), you should rotate the binary log by using [`FLUSH LOGS`](flush.html#flush-logs). This done, you need to copy to the backup location all binary logs which range from the one of the moment of the last full or incremental backup to the last but one. These binary logs are the incremental backup; at restore time, you apply them as explained in [Section 7.5, “Point-in-Time (Incremental) Recovery”](point-in-time-recovery.html). The next time you do a full backup, you should also rotate the binary log using [`FLUSH LOGS`](flush.html#flush-logs) or [**mysqldump --flush-logs**](mysqldump.html). See [Section 4.5.4, “mysqldump — A Database Backup Program”](mysqldump.html).
### Making Backups Using Replicas
If you have performance problems with a server while making backups, one strategy that can help is to set up replication and perform backups on the replica rather than on the source. See [Section 17.4.1, “Using Replication for Backups”](replication-solutions-backups.html).
If you are backing up a replica, you should back up its connection metadata repository and applier metadata repository (see [Section 17.2.4, “Relay Log and Replication Metadata Repositories”](replica-logs.html)) when you back up the replica's databases, regardless of the backup method you choose. This information is always needed to resume replication after you restore the replica's data. If your replica is replicating [`LOAD DATA`](load-data.html) statements, you should also back up any `SQL_LOAD-*` files that exist in the directory that the replica uses for this purpose. The replica needs these files to resume replication of any interrupted [`LOAD DATA`](load-data.html) operations. The location of this directory is the value of the system variable [`replica_load_tmpdir`](replication-options-replica.html#sysvar_replica_load_tmpdir) (from MySQL 8.0.26) or [`slave_load_tmpdir`](replication-options-replica.html#sysvar_slave_load_tmpdir) (before MySQL 8.0.26). If the server was not started with that variable set, the directory location is the value of the [`tmpdir`](server-system-variables.html#sysvar_tmpdir) system variable.
### Recovering Corrupt Tables
If you have to restore `MyISAM` tables that have become corrupt, try to recover them using [`REPAIR TABLE`](repair-table.html) or [**myisamchk -r**](myisamchk.html) first. That should work in 99.9% of all cases. If [**myisamchk**](myisamchk.html) fails, see [Section 7.6, “MyISAM Table Maintenance and Crash Recovery”](myisam-table-maintenance.html).
### Making Backups Using a File System Snapshot
If you are using a Veritas file system, you can make a backup like this:
1. From a client program, execute [`FLUSH TABLES WITH READ LOCK`](flush.html#flush-tables-with-read-lock).
2. From another shell, execute `mount vxfs snapshot`.
3. From the first client, execute [`UNLOCK TABLES`](lock-tables.html).
4. Copy files from the snapshot.
5. Unmount the snapshot.
Similar snapshot capabilities may be available in other file systems, such as LVM or ZFS.
## 7.2 数据库备份方法
本节总结了一些进行备份的一般方法。
### 使用 MySQL Enterprise Backup 进行热备份
MySQL企业版的客户可以使用[MySQL 企业备份](glossary.html#glos_mysql_enterprise_backup)要做的产品[身体的](glossary.html#glos_physical)整个实例或选定的数据库、表或两者的备份。该产品包括以下功能[增加的](glossary.html#glos_incremental_backup)[压缩的](glossary.html#glos_compressed_backup)备份。备份物理数据库文件使恢复比逻辑技术(如`mysql转储`命令。`InnoDB`使用 a 复制表[热备份](glossary.html#glos_hot_backup)机制。(理想情况下,`InnoDB`表应该代表大部分数据。)来自其他存储引擎的表使用[热备份](glossary.html#glos_warm_backup)机制。有关 MySQL Enterprise Backup 产品的概述,请参阅[第 30.2 节,“MySQL 企业备份概述”](mysql-enterprise-backup.html).
### 使用 mysqldump 进行备份
[**mysql转储**](mysqldump.html)程序可以进行备份。它可以备份各种表。(看[第 7.4 节,“使用 mysqldump 进行备份”](using-mysqldump.html).)
为了`InnoDB`表,可以使用不锁定表执行联机备份[`--单笔交易`](mysqldump.html#option_mysqldump_single-transaction)选项[**mysql转储**](mysqldump.html).看[第 7.3.1 节,“建立备份策略”](backup-policy.html).
### 通过复制表文件进行备份
MyISAM 表可以通过复制表文件(`*.MYD`,`*。我的我`文件和相关联的`*.sdi`文件)。要获得一致的备份,请停止服务器或锁定并刷新相关表:
```
FLUSH TABLES tbl_list WITH READ LOCK;
```
你只需要一个读锁;这使其他客户端能够在您复制数据库目录中的文件时继续查询表。需要刷新以确保在开始备份之前将所有活动索引页写入磁盘。看[第 13.3.6 节,“LOCK TABLES 和 UNLOCK TABLES 语句”](lock-tables.html), 和[第 13.7.8.3 节,“FLUSH 语句”](flush.html).
只要服务器不更新任何内容,您也可以简单地通过复制表文件来创建二进制备份。(但请注意,如果您的数据库包含表文件复制方法不起作用`InnoDB`表。此外,即使服务器没有主动更新数据,`InnoDB`可能仍然有修改过的数据缓存在内存中并且没有刷新到磁盘。)
有关此备份方法的示例,请参阅中的导出和导入示例[第 13.2.5 节,“IMPORT TABLE 语句”](import-table.html).
### 制作分隔文本文件备份
要创建包含表数据的文本文件,您可以使用[`选择 * 进入文件 '*`文件名`*' 从 *`tbl_name`*`](select-into.html).该文件是在 MySQL 服务器主机上创建的,而不是在客户端主机上创建的。对于此语句,输出文件不可能已经存在,因为允许覆盖文件会构成安全风险。看[第 13.2.10 节,“SELECT 语句”](select.html).此方法适用于任何类型的数据文件,但只保存表数据,而不保存表结构。
创建文本数据文件的另一种方法(以及包含[`创建表`](create-table.html)备份表的语句)是使用[**mysql转储**](mysqldump.html)[`- 标签`](mysqldump.html#option_mysqldump_tab)选项。看[第 7.4.3 节,“使用 mysqldump 以分隔文本格式转储数据”](mysqldump-delimited-text.html).
要重新加载分隔文本数据文件,请使用[`加载数据`](load-data.html)要么[**mysql导入**](mysqlimport.html).
### 通过启用二进制日志进行增量备份
MySQL 支持使用二进制日志进行增量备份。二进制日志文件为您提供了在执行备份之后将更改复制到数据库所需的信息。因此,要让服务器恢复到某个时间点,必须在其上启用二进制日志记录,这是 MySQL 8.0 的默认设置;看[第 5.4.4 节,“二进制日志”](binary-log.html).
在您想要进行增量备份(包含自上次完整或增量备份以来发生的所有更改)的那一刻,您应该使用旋转二进制日志[`刷新日志`](flush.html#flush-logs).完成后,您需要将所有二进制日志复制到备份位置,范围从最后一次完整或增量备份到最后一个。这些二进制日志是增量备份;在恢复时,您按照中的说明应用它们[第 7.5 节,“时间点(增量)恢复”](point-in-time-recovery.html).下次进行完整备份时,还应该使用轮换二进制日志[`刷新日志`](flush.html#flush-logs)要么[**mysqldump --flush-logs**](mysqldump.html).看[第 4.5.4 节,“mysqldump - 数据库备份程序”](mysqldump.html).
### 使用副本进行备份
如果您在进行备份时遇到服务器性能问题,一种可以提供帮助的策略是设置复制并在副本而不是源上执行备份。看[第 17.4.1 节,“使用复制进行备份”](replication-solutions-backups.html).
如果要备份副本,则应备份其连接元数据存储库和应用程序元数据存储库(请参阅[第 17.2.4 节,“中继日志和复制元数据存储库”](replica-logs.html)) 当您备份副本的数据库时,无论您选择哪种备份方法。恢复副本的数据后,始终需要此信息来恢复复制。如果您的副本正在复制[`加载数据`](load-data.html)声明,您还应该备份任何`SQL_LOAD-*`副本用于此目的的目录中存在的文件。副本需要这些文件来恢复任何中断的复制[`加载数据`](load-data.html)操作。这个目录的位置就是系统变量的值[`replica_load_tmpdir`](replication-options-replica.html#sysvar_replica_load_tmpdir)(来自 MySQL 8.0.26)或[`slave_load_tmpdir`](replication-options-replica.html#sysvar_slave_load_tmpdir)(在 MySQL 8.0.26 之前)。如果服务器未使用该变量集启动,则目录位置是[`临时目录`](server-system-variables.html#sysvar_tmpdir)系统变量。
### 恢复损坏的表
如果必须恢复`MyISAM`已损坏的表,请尝试使用[`维修台`](repair-table.html)要么[**myisamchk -r**](myisamchk.html)第一的。这应该适用于所有情况的 99.9%。如果[**迈萨姆奇克**](myisamchk.html)失败,见[第 7.6 节,“MyISAM 表维护和崩溃恢复”](myisam-table-maintenance.html).
### 使用文件系统快照进行备份
如果您使用的是 Veritas 文件系统,则可以像这样进行备份:
1. 从客户端程序,执行[`带读锁的刷新表`](flush.html#flush-tables-with-read-lock).
2. 从另一个shell,执行`挂载 vxfs 快照`.
3. 从第一个客户端,执行[`解锁桌子`](lock-tables.html).
4. 从快照复制文件。
5. 卸载快照。
类似的快照功能可能在其他文件系统中可用,例如 LVM 或 ZFS。
### 7.3.1 Establishing a Backup Policy
To be useful, backups must be scheduled regularly. A full backup (a snapshot of the data at a point in time) can be done in MySQL with several tools. For example, [MySQL Enterprise Backup](mysql-enterprise-backup.html) can perform a [physical backup](glossary.html#glos_physical_backup) of an entire instance, with optimizations to minimize overhead and avoid disruption when backing up `InnoDB` data files; [**mysqldump**](mysqldump.html) provides online [logical backup](glossary.html#glos_logical_backup). This discussion uses [**mysqldump**](mysqldump.html).
Assume that we make a full backup of all our `InnoDB` tables in all databases using the following command on Sunday at 1 p.m., when load is low:
```
$> mysqldump --all-databases --master-data --single-transaction > backup_sunday_1_PM.sql
```
The resulting `.sql` file produced by [**mysqldump**](mysqldump.html) contains a set of SQL [`INSERT`](insert.html) statements that can be used to reload the dumped tables at a later time.
This backup operation acquires a global read lock on all tables at the beginning of the dump (using [`FLUSH TABLES WITH READ LOCK`](flush.html#flush-tables-with-read-lock)). As soon as this lock has been acquired, the binary log coordinates are read and the lock is released. If long updating statements are running when the [`FLUSH`](flush.html) statement is issued, the backup operation may stall until those statements finish. After that, the dump becomes lock-free and does not disturb reads and writes on the tables.
It was assumed earlier that the tables to back up are `InnoDB` tables, so [`--single-transaction`](mysqldump.html#option_mysqldump_single-transaction) uses a consistent read and guarantees that data seen by [**mysqldump**](mysqldump.html) does not change. (Changes made by other clients to `InnoDB` tables are not seen by the [**mysqldump**](mysqldump.html) process.) If the backup operation includes nontransactional tables, consistency requires that they do not change during the backup. For example, for the `MyISAM` tables in the `mysql` database, there must be no administrative changes to MySQL accounts during the backup.
Full backups are necessary, but it is not always convenient to create them. They produce large backup files and take time to generate. They are not optimal in the sense that each successive full backup includes all data, even that part that has not changed since the previous full backup. It is more efficient to make an initial full backup, and then to make incremental backups. The incremental backups are smaller and take less time to produce. The tradeoff is that, at recovery time, you cannot restore your data just by reloading the full backup. You must also process the incremental backups to recover the incremental changes.
To make incremental backups, we need to save the incremental changes. In MySQL, these changes are represented in the binary log, so the MySQL server should always be started with the [`--log-bin`](replication-options-binary-log.html#option_mysqld_log-bin) option to enable that log. With binary logging enabled, the server writes each data change into a file while it updates data. Looking at the data directory of a MySQL server that has been running for some days, we find these MySQL binary log files:
```
-rw-rw---- 1 guilhem guilhem 1277324 Nov 10 23:59 gbichot2-bin.000001
-rw-rw---- 1 guilhem guilhem 4 Nov 10 23:59 gbichot2-bin.000002
-rw-rw---- 1 guilhem guilhem 79 Nov 11 11:06 gbichot2-bin.000003
-rw-rw---- 1 guilhem guilhem 508 Nov 11 11:08 gbichot2-bin.000004
-rw-rw---- 1 guilhem guilhem 220047446 Nov 12 16:47 gbichot2-bin.000005
-rw-rw---- 1 guilhem guilhem 998412 Nov 14 10:08 gbichot2-bin.000006
-rw-rw---- 1 guilhem guilhem 361 Nov 14 10:07 gbichot2-bin.index
```
Each time it restarts, the MySQL server creates a new binary log file using the next number in the sequence. While the server is running, you can also tell it to close the current binary log file and begin a new one manually by issuing a [`FLUSH LOGS`](flush.html#flush-logs) SQL statement or with a [**mysqladmin flush-logs**](mysqladmin.html) command. [**mysqldump**](mysqldump.html) also has an option to flush the logs. The `.index` file in the data directory contains the list of all MySQL binary logs in the directory.
The MySQL binary logs are important for recovery because they form the set of incremental backups. If you make sure to flush the logs when you make your full backup, the binary log files created afterward contain all the data changes made since the backup. Let's modify the previous [**mysqldump**](mysqldump.html) command a bit so that it flushes the MySQL binary logs at the moment of the full backup, and so that the dump file contains the name of the new current binary log:
```
$> mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases > backup_sunday_1_PM.sql
```
After executing this command, the data directory contains a new binary log file, `gbichot2-bin.000007`, because the [`--flush-logs`](mysqldump.html#option_mysqldump_flush-logs) option causes the server to flush its logs. The [`--master-data`](mysqldump.html#option_mysqldump_master-data) option causes [**mysqldump**](mysqldump.html) to write binary log information to its output, so the resulting `.sql` dump file includes these lines:
```
-- Position to start replication or point-in-time recovery from
-- CHANGE MASTER TO MASTER_LOG_FILE='gbichot2-bin.000007',MASTER_LOG_POS=4;
```
Because the [**mysqldump**](mysqldump.html) command made a full backup, those lines mean two things:
* The dump file contains all changes made before any changes written to the `gbichot2-bin.000007` binary log file or higher.
* All data changes logged after the backup are not present in the dump file, but are present in the `gbichot2-bin.000007` binary log file or higher.
On Monday at 1 p.m., we can create an incremental backup by flushing the logs to begin a new binary log file. For example, executing a [**mysqladmin flush-logs**](mysqladmin.html) command creates `gbichot2-bin.000008`. All changes between the Sunday 1 p.m. full backup and Monday 1 p.m. are written in `gbichot2-bin.000007`. This incremental backup is important, so it is a good idea to copy it to a safe place. (For example, back it up on tape or DVD, or copy it to another machine.) On Tuesday at 1 p.m., execute another [**mysqladmin flush-logs**](mysqladmin.html) command. All changes between Monday 1 p.m. and Tuesday 1 p.m. are written in `gbichot2-bin.000008` (which also should be copied somewhere safe).
The MySQL binary logs take up disk space. To free up space, purge them from time to time. One way to do this is by deleting the binary logs that are no longer needed, such as when we make a full backup:
```
$> mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases --delete-master-logs > backup_sunday_1_PM.sql
```
Note
Deleting the MySQL binary logs with [**mysqldump --delete-master-logs**](mysqldump.html) can be dangerous if your server is a replication source server, because replicas might not yet fully have processed the contents of the binary log. The description for the [`PURGE BINARY LOGS`](purge-binary-logs.html) statement explains what should be verified before deleting the MySQL binary logs. See [Section 13.4.1.1, “PURGE BINARY LOGS Statement”](purge-binary-logs.html).
### 7.3.1 制定备份策略
为了有用,必须定期安排备份。可以使用多种工具在 MySQL 中完成完整备份(某个时间点的数据快照)。例如,[MySQL 企业备份](mysql-enterprise-backup.html)可以执行一个[物理备份](glossary.html#glos_physical_backup)整个实例的优化,以最大限度地减少开销并避免备份时中断`InnoDB`数据文件;[**mysql转储**](mysqldump.html)在线提供[逻辑备份](glossary.html#glos_logical_backup).本次讨论使用[**mysql转储**](mysqldump.html).
假设我们对我们所有的`InnoDB`周日下午 1 点,当负载较低时,使用以下命令在所有数据库中的表:
```
$> mysqldump --all-databases --master-data --single-transaction > backup_sunday_1_PM.sql
```
所结果的`.sql`文件由[**mysql转储**](mysqldump.html)包含一组 SQL[`插入`](insert.html)可用于稍后重新加载转储表的语句。
此备份操作在转储开始时获取所有表的全局读锁(使用[`带读锁的刷新表`](flush.html#flush-tables-with-read-lock))。一旦获得了这个锁,就会读取二进制日志坐标并释放锁。如果在运行长更新语句时[`冲洗`](flush.html)发出语句,备份操作可能会停止,直到这些语句完成。之后,转储变为无锁并且不会干扰对表的读取和写入。
之前假设要备份的表是`InnoDB`表,所以[`--单笔交易`](mysqldump.html#option_mysqldump_single-transaction)使用一致的读取并保证所看到的数据[**mysql转储**](mysqldump.html)不改变。(其他客户对`InnoDB`表不被看到[**mysql转储**](mysqldump.html)过程。)如果备份操作包括非事务性表,一致性要求它们在备份期间不改变。例如,对于`MyISAM`中的表`mysql`数据库,备份期间不得对 MySQL 帐户进行管理更改。
完全备份是必要的,但创建它们并不总是很方便。它们会生成大型备份文件并需要时间来生成。它们不是最优的,因为每个连续的完整备份都包含所有数据,甚至包括自上次完整备份以来未更改的部分。进行初始完整备份,然后进行增量备份更有效。增量备份更小,生成时间更短。权衡是,在恢复时,您不能仅通过重新加载完整备份来恢复数据。您还必须处理增量备份以恢复增量更改。
要进行增量备份,我们需要保存增量更改。在 MySQL 中,这些更改在二进制日志中表示,因此 MySQL 服务器应始终以[`--log-bin`](replication-options-binary-log.html#option_mysqld_log-bin)启用该日志的选项。启用二进制日志记录后,服务器在更新数据时将每个数据更改写入文件。查看已经运行了几天的 MySQL 服务器的数据目录,我们发现了这些 MySQL 二进制日志文件:
```
-rw-rw---- 1 guilhem guilhem 1277324 Nov 10 23:59 gbichot2-bin.000001
-rw-rw---- 1 guilhem guilhem 4 Nov 10 23:59 gbichot2-bin.000002
-rw-rw---- 1 guilhem guilhem 79 Nov 11 11:06 gbichot2-bin.000003
-rw-rw---- 1 guilhem guilhem 508 Nov 11 11:08 gbichot2-bin.000004
-rw-rw---- 1 guilhem guilhem 220047446 Nov 12 16:47 gbichot2-bin.000005
-rw-rw---- 1 guilhem guilhem 998412 Nov 14 10:08 gbichot2-bin.000006
-rw-rw---- 1 guilhem guilhem 361 Nov 14 10:07 gbichot2-bin.index
```
每次重新启动时,MySQL 服务器都会使用序列中的下一个数字创建一个新的二进制日志文件。在服务器运行时,您还可以通过发出[`刷新日志`](flush.html#flush-logs)SQL 语句或带有[**mysqladmin 刷新日志**](mysqladmin.html)命令。[**mysql转储**](mysqldump.html)还可以选择刷新日志。这`。指数`数据目录中的文件包含目录中所有 MySQL 二进制日志的列表。
MySQL 二进制日志对于恢复很重要,因为它们形成了一组增量备份。如果您确保在进行完整备份时刷新日志,则之后创建的二进制日志文件包含自备份以来所做的所有数据更改。让我们修改以前的[**mysql转储**](mysqldump.html)命令一点,以便它在完全备份时刷新 MySQL 二进制日志,并且转储文件包含新的当前二进制日志的名称:
```
$> mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases > backup_sunday_1_PM.sql
```
执行此命令后,数据目录包含一个新的二进制日志文件,`gbihot2-bin.000007`,因为[`--刷新日志`](mysqldump.html#option_mysqldump_flush-logs)选项导致服务器刷新其日志。这[`- 主要的数据`](mysqldump.html#option_mysqldump_master-data)选项原因[**mysql转储**](mysqldump.html)将二进制日志信息写入其输出,因此结果`.sql`转储文件包括以下几行:
```
-- Position to start replication or point-in-time recovery from
-- CHANGE MASTER TO MASTER_LOG_FILE='gbichot2-bin.000007',MASTER_LOG_POS=4;
```
因为[**mysql转储**](mysqldump.html)命令进行了完整备份,这些行意味着两件事:
- 转储文件包含在写入任何更改之前所做的所有更改`gbihot2-bin.000007`二进制日志文件或更高版本。
- 备份后记录的所有数据更改都不存在于转储文件中,但存在于`gbihot2-bin.000007`二进制日志文件或更高版本。
周一下午 1 点,我们可以通过刷新日志来创建增量备份,以开始一个新的二进制日志文件。例如,执行一个[**mysqladmin 刷新日志**](mysqladmin.html)命令创建`gbihot2-bin.000008`.周日下午 1 点之间的所有变化。完整备份和星期一下午 1 点。写在`gbihot2-bin.000007`.这种增量备份很重要,因此最好将其复制到安全的地方。(例如,将其备份到磁带或 DVD 上,或将其复制到另一台机器上。)周二下午 1 点,执行另一个[**mysqladmin 刷新日志**](mysqladmin.html)命令。周一下午 1 点之间的所有变化。和周二下午 1 点。写在`gbihot2-bin.000008`(也应该复制到安全的地方)。
MySQL 二进制日志占用磁盘空间。要释放空间,请不时清除它们。一种方法是删除不再需要的二进制日志,例如当我们进行完整备份时:
```
$> mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases --delete-master-logs > backup_sunday_1_PM.sql
```
笔记
删除 MySQL 二进制日志[**mysqldump --delete-master-logs**](mysqldump.html)如果您的服务器是复制源服务器,则可能很危险,因为副本可能尚未完全处理二进制日志的内容。的描述[`清除二进制日志`](purge-binary-logs.html)声明解释了在删除 MySQL 二进制日志之前应该验证的内容。看[第 13.4.1.1 节,“PURGE BINARY LOGS 语句”](purge-binary-logs.html).
## 7.3 Example Backup and Recovery Strategy
[7.3.1 Establishing a Backup Policy](backup-policy.html)
[7.3.2 Using Backups for Recovery](recovery-from-backups.html)
[7.3.3 Backup Strategy Summary](backup-strategy-summary.html)
This section discusses a procedure for performing backups that enables you to recover data after several types of crashes:
* Operating system crash
* Power failure
* File system crash
* Hardware problem (hard drive, motherboard, and so forth)
The example commands do not include options such as [`--user`](connection-options.html#option_general_user) and [`--password`](connection-options.html#option_general_password) for the [**mysqldump**](mysqldump.html) and [**mysql**](mysql.html) client programs. You should include such options as necessary to enable client programs to connect to the MySQL server.
Assume that data is stored in the `InnoDB` storage engine, which has support for transactions and automatic crash recovery. Assume also that the MySQL server is under load at the time of the crash. If it were not, no recovery would ever be needed.
For cases of operating system crashes or power failures, we can assume that MySQL's disk data is available after a restart. The `InnoDB` data files might not contain consistent data due to the crash, but `InnoDB` reads its logs and finds in them the list of pending committed and noncommitted transactions that have not been flushed to the data files. `InnoDB` automatically rolls back those transactions that were not committed, and flushes to its data files those that were committed. Information about this recovery process is conveyed to the user through the MySQL error log. The following is an example log excerpt:
```
InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections
```
For the cases of file system crashes or hardware problems, we can assume that the MySQL disk data is *not* available after a restart. This means that MySQL fails to start successfully because some blocks of disk data are no longer readable. In this case, it is necessary to reformat the disk, install a new one, or otherwise correct the underlying problem. Then it is necessary to recover our MySQL data from backups, which means that backups must already have been made. To make sure that is the case, design and implement a backup policy.
## 7.3 示例备份和恢复策略
[7.3.1 建立备份策略](backup-policy.html)
[7.3.2 使用备份进行恢复](recovery-from-backups.html)
[7.3.3 备份策略总结](backup-strategy-summary.html)
本节讨论执行备份的过程,使您能够在几种类型的崩溃后恢复数据:
- 操作系统崩溃
- 电源(检测)失败
- 文件系统崩溃
- 硬件问题(硬盘驱动器、主板等)
示例命令不包括诸如[`- 用户`](connection-options.html#option_general_user)和[`- 密码`](connection-options.html#option_general_password)为了[**mysql转储**](mysqldump.html)和[**mysql**](mysql.html)客户端程序。您应该包括必要的选项,以使客户端程序能够连接到 MySQL 服务器。
假设数据存储在`InnoDB`存储引擎,支持事务和自动崩溃恢复。还假设 MySQL 服务器在崩溃时处于负载状态。如果不是这样,就永远不需要恢复。
对于操作系统崩溃或断电的情况,我们可以假设 MySQL 的磁盘数据在重启后可用。这`InnoDB`由于崩溃,数据文件可能不包含一致的数据,但`InnoDB`读取其日志并在其中找到尚未刷新到数据文件的待处理已提交和未提交事务的列表。`InnoDB`自动回滚那些未提交的事务,并将那些已提交的事务刷新到其数据文件中。有关此恢复过程的信息通过 MySQL 错误日志传达给用户。以下是示例日志摘录:
```
InnoDB: Database was not shut down normally.
InnoDB: Starting recovery from log files...
InnoDB: Starting log scan based on checkpoint at
InnoDB: log sequence number 0 13674004
InnoDB: Doing recovery: scanned up to log sequence number 0 13739520
InnoDB: Doing recovery: scanned up to log sequence number 0 13805056
InnoDB: Doing recovery: scanned up to log sequence number 0 13870592
InnoDB: Doing recovery: scanned up to log sequence number 0 13936128
...
InnoDB: Doing recovery: scanned up to log sequence number 0 20555264
InnoDB: Doing recovery: scanned up to log sequence number 0 20620800
InnoDB: Doing recovery: scanned up to log sequence number 0 20664692
InnoDB: 1 uncommitted transaction(s) which must be rolled back
InnoDB: Starting rollback of uncommitted transactions
InnoDB: Rolling back trx no 16745
InnoDB: Rolling back of trx no 16745 completed
InnoDB: Rollback of uncommitted transactions completed
InnoDB: Starting an apply batch of log records to the database...
InnoDB: Apply batch completed
InnoDB: Started
mysqld: ready for connections
```
对于文件系统崩溃或硬件问题的情况,我们可以假设 MySQL 磁盘数据是*不是*重启后可用。这意味着 MySQL 无法成功启动,因为某些磁盘数据块不再可读。在这种情况下,必须重新格式化磁盘、安装新磁盘或以其他方式纠正根本问题。然后有必要从备份中恢复我们的 MySQL 数据,这意味着必须已经进行了备份。为确保确实如此,请设计并实施备份策略。
### 7.3.3 Backup Strategy Summary
In case of an operating system crash or power failure, `InnoDB` itself does all the job of recovering data. But to make sure that you can sleep well, observe the following guidelines:
* Always tun the MySQL server with binary logging enabled (that is the default setting for MySQL 8.0). If you have such safe media, this technique can also be good for disk load balancing (which results in a performance improvement).
* Make periodic full backups, using the [**mysqldump**](mysqldump.html) command shown earlier in [Section 7.3.1, “Establishing a Backup Policy”](backup-policy.html), that makes an online, nonblocking backup.
* Make periodic incremental backups by flushing the logs with [`FLUSH LOGS`](flush.html#flush-logs) or [**mysqladmin flush-logs**](mysqladmin.html).
### 7.3.3 备份策略总结
在操作系统崩溃或电源故障的情况下,`InnoDB`它本身完成了恢复数据的所有工作。但为了确保您能睡得好,请遵守以下准则:
- 始终在启用二进制日志记录的情况下调整 MySQL 服务器(这是 MySQL 8.0 的默认设置)。如果你有这样安全的媒体,这种技术也可以很好地用于磁盘负载平衡(从而提高性能)。
- 使用[**mysql转储**](mysqldump.html)前面显示的命令[第 7.3.1 节,“建立备份策略”](backup-policy.html),这将进行在线、非阻塞备份。
- 通过刷新日志进行定期增量备份[`刷新日志`](flush.html#flush-logs)要么[**mysqladmin 刷新日志**](mysqladmin.html).
## 7.1 Backup and Recovery Types
This section describes the characteristics of different types of backups.
### Physical (Raw) Versus Logical Backups
Physical backups consist of raw copies of the directories and files that store database contents. This type of backup is suitable for large, important databases that need to be recovered quickly when problems occur.
Logical backups save information represented as logical database structure ([`CREATE DATABASE`](create-database.html), [`CREATE TABLE`](create-table.html) statements) and content ([`INSERT`](insert.html) statements or delimited-text files). This type of backup is suitable for smaller amounts of data where you might edit the data values or table structure, or recreate the data on a different machine architecture.
Physical backup methods have these characteristics:
* The backup consists of exact copies of database directories and files. Typically this is a copy of all or part of the MySQL data directory.
* Physical backup methods are faster than logical because they involve only file copying without conversion.
* Output is more compact than for logical backup.
* Because backup speed and compactness are important for busy, important databases, the MySQL Enterprise Backup product performs physical backups. For an overview of the MySQL Enterprise Backup product, see [Section 30.2, “MySQL Enterprise Backup Overview”](mysql-enterprise-backup.html).
* Backup and restore granularity ranges from the level of the entire data directory down to the level of individual files. This may or may not provide for table-level granularity, depending on storage engine. For example, `InnoDB` tables can each be in a separate file, or share file storage with other `InnoDB` tables; each `MyISAM` table corresponds uniquely to a set of files.
* In addition to databases, the backup can include any related files such as log or configuration files.
* Data from `MEMORY` tables is tricky to back up this way because their contents are not stored on disk. (The MySQL Enterprise Backup product has a feature where you can retrieve data from `MEMORY` tables during a backup.)
* Backups are portable only to other machines that have identical or similar hardware characteristics.
* Backups can be performed while the MySQL server is not running. If the server is running, it is necessary to perform appropriate locking so that the server does not change database contents during the backup. MySQL Enterprise Backup does this locking automatically for tables that require it.
* Physical backup tools include the **mysqlbackup** of MySQL Enterprise Backup for `InnoDB` or any other tables, or file system-level commands (such as **cp**, **scp**, **tar**, **rsync**) for `MyISAM` tables.
* For restore:
* MySQL Enterprise Backup restores `InnoDB` and other tables that it backed up.
* [**ndb\_restore**](mysql-cluster-programs-ndb-restore.html) restores [`NDB`](mysql-cluster.html) tables.
* Files copied at the file system level can be copied back to their original locations with file system commands.
Logical backup methods have these characteristics:
* The backup is done by querying the MySQL server to obtain database structure and content information.
* Backup is slower than physical methods because the server must access database information and convert it to logical format. If the output is written on the client side, the server must also send it to the backup program.
* Output is larger than for physical backup, particularly when saved in text format.
* Backup and restore granularity is available at the server level (all databases), database level (all tables in a particular database), or table level. This is true regardless of storage engine.
* The backup does not include log or configuration files, or other database-related files that are not part of databases.
* Backups stored in logical format are machine independent and highly portable.
* Logical backups are performed with the MySQL server running. The server is not taken offline.
* Logical backup tools include the [**mysqldump**](mysqldump.html) program and the [`SELECT ... INTO OUTFILE`](select.html) statement. These work for any storage engine, even `MEMORY`.
* To restore logical backups, SQL-format dump files can be processed using the [**mysql**](mysql.html) client. To load delimited-text files, use the [`LOAD DATA`](load-data.html) statement or the [**mysqlimport**](mysqlimport.html) client.
### Online Versus Offline Backups
Online backups take place while the MySQL server is running so that the database information can be obtained from the server. Offline backups take place while the server is stopped. This distinction can also be described as “hot” versus “cold” backups; a “warm” backup is one where the server remains running but locked against modifying data while you access database files externally.
Online backup methods have these characteristics:
* The backup is less intrusive to other clients, which can connect to the MySQL server during the backup and may be able to access data depending on what operations they need to perform.
* Care must be taken to impose appropriate locking so that data modifications do not take place that would compromise backup integrity. The MySQL Enterprise Backup product does such locking automatically.
Offline backup methods have these characteristics:
* Clients can be affected adversely because the server is unavailable during backup. For that reason, such backups are often taken from a replica that can be taken offline without harming availability.
* The backup procedure is simpler because there is no possibility of interference from client activity.
A similar distinction between online and offline applies for recovery operations, and similar characteristics apply. However, it is more likely for clients to be affected by online recovery than by online backup because recovery requires stronger locking. During backup, clients might be able to read data while it is being backed up. Recovery modifies data and does not just read it, so clients must be prevented from accessing data while it is being restored.
### Local Versus Remote Backups
A local backup is performed on the same host where the MySQL server runs, whereas a remote backup is done from a different host. For some types of backups, the backup can be initiated from a remote host even if the output is written locally on the server. host.
* [**mysqldump**](mysqldump.html) can connect to local or remote servers. For SQL output (`CREATE` and [`INSERT`](insert.html) statements), local or remote dumps can be done and generate output on the client. For delimited-text output (with the [`--tab`](mysqldump.html#option_mysqldump_tab) option), data files are created on the server host.
* [`SELECT ... INTO OUTFILE`](select-into.html) can be initiated from a local or remote client host, but the output file is created on the server host.
* Physical backup methods typically are initiated locally on the MySQL server host so that the server can be taken offline, although the destination for copied files might be remote.
### Snapshot Backups
Some file system implementations enable “snapshots” to be taken. These provide logical copies of the file system at a given point in time, without requiring a physical copy of the entire file system. (For example, the implementation may use copy-on-write techniques so that only parts of the file system modified after the snapshot time need be copied.) MySQL itself does not provide the capability for taking file system snapshots. It is available through third-party solutions such as Veritas, LVM, or ZFS.
### Full Versus Incremental Backups
A full backup includes all data managed by a MySQL server at a given point in time. An incremental backup consists of the changes made to the data during a given time span (from one point in time to another). MySQL has different ways to perform full backups, such as those described earlier in this section. Incremental backups are made possible by enabling the server's binary log, which the server uses to record data changes.
### Full Versus Point-in-Time (Incremental) Recovery
A full recovery restores all data from a full backup. This restores the server instance to the state that it had when the backup was made. If that state is not sufficiently current, a full recovery can be followed by recovery of incremental backups made since the full backup, to bring the server to a more up-to-date state.
Incremental recovery is recovery of changes made during a given time span. This is also called point-in-time recovery because it makes a server's state current up to a given time. Point-in-time recovery is based on the binary log and typically follows a full recovery from the backup files that restores the server to its state when the backup was made. Then the data changes written in the binary log files are applied as incremental recovery to redo data modifications and bring the server up to the desired point in time.
### Table Maintenance
Data integrity can be compromised if tables become corrupt. For [`InnoDB`](innodb-storage-engine.html) tables, this is not a typical issue. For programs to check [`MyISAM`](myisam-storage-engine.html) tables and repair them if problems are found, see [Section 7.6, “MyISAM Table Maintenance and Crash Recovery”](myisam-table-maintenance.html).
### Backup Scheduling, Compression, and Encryption
Backup scheduling is valuable for automating backup procedures. Compression of backup output reduces space requirements, and encryption of the output provides better security against unauthorized access of backed-up data. MySQL itself does not provide these capabilities. The MySQL Enterprise Backup product can compress `InnoDB` backups, and compression or encryption of backup output can be achieved using file system utilities. Other third-party solutions may be available.
## 7.1 备份和恢复类型
本节介绍不同类型备份的特征。
### 物理(原始)与逻辑备份
物理备份由存储数据库内容的目录和文件的原始副本组成。这种类型的备份适用于出现问题时需要快速恢复的大型重要数据库。
逻辑备份将信息保存为逻辑数据库结构 ([`创建数据库`](create-database.html),[`创建表`](create-table.html)声明)和内容([`插入`](insert.html)语句或分隔文本文件)。这种类型的备份适用于少量数据,您可以在其中编辑数据值或表结构,或在不同的机器架构上重新创建数据。
物理备份方法具有以下特点:
- 备份由数据库目录和文件的精确副本组成。通常这是 MySQL 数据目录的全部或部分的副本。
- 物理备份方法比逻辑备份方法更快,因为它们只涉及文件复制而不进行转换。
- 输出比逻辑备份更紧凑。
- 因为备份速度和紧凑性对于繁忙的重要数据库很重要,所以 MySQL Enterprise Backup 产品执行物理备份。有关 MySQL Enterprise Backup 产品的概述,请参阅[第 30.2 节,“MySQL 企业备份概述”](mysql-enterprise-backup.html).
- 备份和恢复的粒度范围从整个数据目录的级别到单个文件的级别。这可能会或可能不会提供表级粒度,具体取决于存储引擎。例如,`InnoDB`每个表都可以在一个单独的文件中,或与其他表共享文件存储`InnoDB`表格;每个`MyISAM`表唯一地对应于一组文件。
- 除了数据库之外,备份还可以包括任何相关文件,例如日志或配置文件。
- 数据来自`记忆`以这种方式备份表很棘手,因为它们的内容不存储在磁盘上。(MySQL Enterprise Backup 产品具有一项功能,您可以从中检索数据`记忆`备份期间的表。)
- 备份只能移植到具有相同或相似硬件特征的其他机器上。
- 可以在 MySQL 服务器未运行时执行备份。如果服务器正在运行,则需要执行适当的锁定,以使服务器在备份期间不会更改数据库内容。MySQL Enterprise Backup 自动为需要它的表执行此锁定。
- 物理备份工具包括**mysql备份**MySQL 企业备份的`InnoDB`或任何其他表,或文件系统级命令(例如**cp**,**scp**,**柏油**,**rsync**) 为了`MyISAM`表。
- 对于还原:
- MySQL 企业备份恢复`InnoDB`以及它备份的其他表。
- [**数据库\_恢复**](mysql-cluster-programs-ndb-restore.html)恢复[`新开发银行`](mysql-cluster.html)表。
- 在文件系统级别复制的文件可以使用文件系统命令复制回其原始位置。
逻辑备份方法具有以下特点:
- 备份是通过查询 MySQL 服务器来获取数据库结构和内容信息来完成的。
- 备份比物理方法慢,因为服务器必须访问数据库信息并将其转换为逻辑格式。如果输出是在客户端写入的,服务器也必须将其发送到备份程序。
- 输出大于物理备份,尤其是以文本格式保存时。
- 备份和还原粒度可在服务器级别(所有数据库)、数据库级别(特定数据库中的所有表)或表级别使用。无论存储引擎如何,都是如此。
- 备份不包括日志或配置文件,或不属于数据库的其他与数据库相关的文件。
- 以逻辑格式存储的备份独立于机器且高度可移植。
- 逻辑备份是在 MySQL 服务器运行的情况下执行的。服务器未脱机。
- 逻辑备份工具包括[**mysql转储**](mysqldump.html)程序和[`选择...进入文件`](select.html)陈述。这些适用于任何存储引擎,甚至`记忆`.
- 要恢复逻辑备份,可以使用 SQL 格式的转储文件处理[**mysql**](mysql.html)客户。要加载分隔文本文件,请使用[`加载数据`](load-data.html)声明或[**mysql导入**](mysqlimport.html)客户。
### 在线与离线备份
在 MySQL 服务器运行时进行在线备份,以便可以从服务器获取数据库信息。离线备份在服务器停止时进行。这种区别也可以描述为“热”备份与“冷”备份;“热”备份是服务器保持运行但在您从外部访问数据库文件时锁定以防止修改数据的备份。
在线备份方式具有以下特点:
- 备份对其他客户端的干扰较小,它们可以在备份期间连接到 MySQL 服务器,并且可能能够根据需要执行的操作访问数据。
- 必须注意施加适当的锁定,以免发生会损害备份完整性的数据修改。MySQL Enterprise Backup 产品会自动执行此类锁定。
离线备份方式具有以下特点:
- 由于服务器在备份期间不可用,客户端可能会受到不利影响。因此,此类备份通常取自可以脱机而不会损害可用性的副本。
- 备份过程更简单,因为不会受到客户端活动的干扰。
在线和离线之间的类似区别适用于恢复操作,并且类似的特征也适用。但是,与在线备份相比,客户端更可能受到在线恢复的影响,因为恢复需要更强的锁定。在备份期间,客户端可能能够在备份时读取数据。恢复会修改数据而不仅仅是读取数据,因此必须防止客户端在恢复数据时访问数据。
### 本地与远程备份
本地备份是在 MySQL 服务器运行的同一主机上执行的,而远程备份是从不同的主机上完成的。对于某些类型的备份,即使输出是本地写入服务器上的,也可以从远程主机启动备份。主持人。
- [**mysql转储**](mysqldump.html)可以连接到本地或远程服务器。对于 SQL 输出 (`创建`[`插入`](insert.html)语句),本地或远程转储可以完成并在客户端生成输出。对于分隔文本输出(使用[`- 标签`](mysqldump.html#option_mysqldump_tab)选项),在服务器主机上创建数据文件。
- [`选择...进入文件`](select-into.html)可以从本地或远程客户端主机启动,但输出文件是在服务器主机上创建的。
- 物理备份方法通常在 MySQL 服务器主机上本地启动,以便服务器可以脱机,尽管复制文件的目标可能是远程的。
### 快照备份
一些文件系统实现可以拍摄“快照”。它们在给定时间点提供文件系统的逻辑副本,而不需要整个文件系统的物理副本。(例如,实现可以使用写时复制技术,以便只复制在快照时间之后修改的部分文件系统。) MySQL 本身不提供获取文件系统快照的能力。它可通过第三方解决方案获得,例如 Veritas、LVM 或 ZFS。
### 完整备份与增量备份
完整备份包括 MySQL 服务器在给定时间点管理的所有数据。增量备份包括在给定时间跨度(从一个时间点到另一个时间点)内对数据所做的更改。MySQL 有不同的方法来执行完整备份,例如本节前面描述的那些。通过启用服务器的二进制日志来实现增量备份,服务器使用它来记录数据更改。
### 完全与时间点(增量)恢复
完全恢复从完全备份中恢复所有数据。这会将服务器实例恢复到进行备份时的状态。如果该状态不够最新,则可以在完全恢复之后恢复自完全备份以来所做的增量备份,以使服务器处于更新状态。
增量恢复是恢复在给定时间跨度内所做的更改。这也称为时间点恢复,因为它使服务器的状态在给定时间之前保持最新状态。时间点恢复基于二进制日志,通常在从备份文件完全恢复之后,将服务器恢复到备份时的状态。然后将写入二进制日志文件中的数据更改作为增量恢复应用,以重做数据修改并将服务器恢复到所需的时间点。
### 表维护
如果表损坏,数据完整性可能会受到影响。为了[`InnoDB`](innodb-storage-engine.html)表,这不是一个典型的问题。用于检查的程序[`MyISAM`](myisam-storage-engine.html)表并在发现问题时修复它们,请参阅[第 7.6 节,“MyISAM 表维护和崩溃恢复”](myisam-table-maintenance.html).
### 备份计划、压缩和加密
备份计划对于自动化备份过程很有价值。备份输出的压缩减少了空间需求,输出加密提供了更好的安全性,防止未经授权访问备份数据。MySQL 本身不提供这些功能。MySQL Enterprise Backup 产品可以压缩`InnoDB`备份,以及备份输出的压缩或加密可以使用文件系统实用程序来实现。其他第三方解决方案可能可用。
### 7.6.2 How to Check MyISAM Tables for Errors
[]()[]()[]()
To check a `MyISAM` table, use the following commands:
* [**myisamchk *`tbl_name`***](myisamchk.html)
This finds 99.99% of all errors. What it cannot find is corruption that involves *only* the data file (which is very unusual). If you want to check a table, you should normally run [**myisamchk**](myisamchk.html) without options or with the `-s` (silent) option.
* [**myisamchk -m *`tbl_name`***](myisamchk.html)
This finds 99.999% of all errors. It first checks all index entries for errors and then reads through all rows. It calculates a checksum for all key values in the rows and verifies that the checksum matches the checksum for the keys in the index tree.
* [**myisamchk -e *`tbl_name`***](myisamchk.html)
This does a complete and thorough check of all data (`-e` means “extended check”). It does a check-read of every key for each row to verify that they indeed point to the correct row. This may take a long time for a large table that has many indexes. Normally, [**myisamchk**](myisamchk.html) stops after the first error it finds. If you want to obtain more information, you can add the `-v` (verbose) option. This causes [**myisamchk**](myisamchk.html) to keep going, up through a maximum of 20 errors.
* [**myisamchk -e -i *`tbl_name`***](myisamchk.html)
This is like the previous command, but the `-i` option tells [**myisamchk**](myisamchk.html) to print additional statistical information.
In most cases, a simple [**myisamchk**](myisamchk.html) command with no arguments other than the table name is sufficient to check a table.
### 7.6.2 如何检查 MyISAM 表是否有错误
[](<>)[](<>)[](<>)
检查一个`MyISAM`表,使用以下命令:
- [**迈萨姆奇克*`tbl_name`***](myisamchk.html)
这会发现所有错误的 99.99%。它找不到的是涉及*只要*数据文件(这是非常不寻常的)。如果要检查表格,通常应该运行[**迈萨姆奇克**](myisamchk.html)没有选项或有`-s`(静音)选项。
- [**myisamchk -m*`tbl_name`***](myisamchk.html)
这可以找到所有错误的 99.999%。它首先检查所有索引条目是否有错误,然后读取所有行。它计算行中所有键值的校验和,并验证校验和是否与索引树中键的校验和匹配。
- [**myisamchk -e*`tbl_name`***](myisamchk.html)
这会对所有数据进行全面彻底的检查(`-e`意思是“扩展检查”)。它对每一行的每个键进行检查读取,以验证它们确实指向正确的行。对于具有许多索引的大表,这可能需要很长时间。一般,[**迈萨姆奇克**](myisamchk.html)在发现第一个错误后停止。如果您想获取更多信息,可以添加`-v`(详细)选项。这引起[**迈萨姆奇克**](myisamchk.html)继续前进,最多通过 20 个错误。
- [**myisamchk -e -i*`tbl_name`***](myisamchk.html)
这与前面的命令类似,但`-一世`选项告诉[**迈萨姆奇克**](myisamchk.html)打印附加统计信息。
大多数情况下,一个简单的[**迈萨姆奇克**](myisamchk.html)除了表名之外没有参数的命令足以检查表。
### 7.6.1 Using myisamchk for Crash Recovery
[]()[]()[]()[]()
This section describes how to check for and deal with data corruption in MySQL databases. If your tables become corrupted frequently, you should try to find the reason why. See [Section B.3.3.3, “What to Do If MySQL Keeps Crashing”](crashing.html).
For an explanation of how `MyISAM` tables can become corrupted, see [Section 16.2.4, “MyISAM Table Problems”](myisam-table-problems.html).
If you run [**mysqld**](mysqld.html) with external locking disabled (which is the default), you cannot reliably use [**myisamchk**](myisamchk.html) to check a table when [**mysqld**](mysqld.html) is using the same table. If you can be certain that no one can access the tables using [**mysqld**](mysqld.html) while you run [**myisamchk**](myisamchk.html), you only have to execute [**mysqladmin flush-tables**](mysqladmin.html) before you start checking the tables. If you cannot guarantee this, you must stop [**mysqld**](mysqld.html) while you check the tables. If you run [**myisamchk**](myisamchk.html) to check tables that [**mysqld**](mysqld.html) is updating at the same time, you may get a warning that a table is corrupt even when it is not.
If the server is run with external locking enabled, you can use [**myisamchk**](myisamchk.html) to check tables at any time. In this case, if the server tries to update a table that [**myisamchk**](myisamchk.html) is using, the server waits for [**myisamchk**](myisamchk.html) to finish before it continues.
If you use [**myisamchk**](myisamchk.html) to repair or optimize tables, you *must* always ensure that the [**mysqld**](mysqld.html) server is not using the table (this also applies if external locking is disabled). If you do not stop [**mysqld**](mysqld.html), you should at least do a [**mysqladmin flush-tables**](mysqladmin.html) before you run [**myisamchk**](myisamchk.html). Your tables *may become corrupted* if the server and [**myisamchk**](myisamchk.html) access the tables simultaneously.
When performing crash recovery, it is important to understand that each `MyISAM` table *`tbl_name`* in a database corresponds to the three files in the database directory shown in the following table.
| File | Purpose |
|------------------|----------|
|`*`tbl_name`*.MYD`|Data file |
|`*`tbl_name`*.MYI`|Index file|
Each of these three file types is subject to corruption in various ways, but problems occur most often in data files and index files.
[**myisamchk**](myisamchk.html) works by creating a copy of the `.MYD` data file row by row. It ends the repair stage by removing the old `.MYD` file and renaming the new file to the original file name. If you use [`--quick`](myisamchk-repair-options.html#option_myisamchk_quick), [**myisamchk**](myisamchk.html) does not create a temporary `.MYD` file, but instead assumes that the `.MYD` file is correct and generates only a new index file without touching the `.MYD` file. This is safe, because [**myisamchk**](myisamchk.html) automatically detects whether the `.MYD` file is corrupt and aborts the repair if it is. You can also specify the [`--quick`](myisamchk-repair-options.html#option_myisamchk_quick) option twice to [**myisamchk**](myisamchk.html). In this case, [**myisamchk**](myisamchk.html) does not abort on some errors (such as duplicate-key errors) but instead tries to resolve them by modifying the `.MYD` file. Normally the use of two [`--quick`](myisamchk-repair-options.html#option_myisamchk_quick) options is useful only if you have too little free disk space to perform a normal repair. In this case, you should at least make a backup of the table before running [**myisamchk**](myisamchk.html).
### 7.6.1 使用 myisamchk 进行崩溃恢复
[](<>)[](<>)[](<>)[](<>)
本节介绍如何检查和处理 MySQL 数据库中的数据损坏。如果您的表经常损坏,您应该尝试找出原因。看[第 B.3.3.3 节,“如果 MySQL 不断崩溃怎么办”](crashing.html).
有关如何解释`MyISAM`表可能会损坏,请参阅[第 16.2.4 节,“MyISAM 表问题”](myisam-table-problems.html).
如果你跑[**mysqld**](mysqld.html)禁用外部锁定(这是默认设置),您不能可靠地使用[**迈萨姆奇克**](myisamchk.html)检查表时[**mysqld**](mysqld.html)正在使用同一张桌子。如果您可以确定没有人可以使用[**mysqld**](mysqld.html)当你跑步时[**迈萨姆奇克**](myisamchk.html), 你只需要执行[**mysqladmin 刷新表**](mysqladmin.html)在您开始检查表格之前。如果你不能保证这一点,你必须停止[**mysqld**](mysqld.html)当您检查表格时。如果你跑[**迈萨姆奇克**](myisamchk.html)检查表[**mysqld**](mysqld.html)同时更新时,您可能会收到警告说表已损坏,即使它没有损坏。
如果服务器在启用外部锁定的情况下运行,您可以使用[**迈萨姆奇克**](myisamchk.html)随时查看表格。在这种情况下,如果服务器尝试更新一个表[**迈萨姆奇克**](myisamchk.html)正在使用,服务器等待[**迈萨姆奇克**](myisamchk.html)在它继续之前完成。
如果你使用[**迈萨姆奇克**](myisamchk.html)要修复或优化表,您*必须*始终确保[**mysqld**](mysqld.html)服务器未使用该表(如果禁用了外部锁定,这也适用)。如果你不停[**mysqld**](mysqld.html),你至少应该做一个[**mysqladmin 刷新表**](mysqladmin.html)在你跑步之前[**迈萨姆奇克**](myisamchk.html).你的桌子*可能会损坏*如果服务器和[**迈萨姆奇克**](myisamchk.html)同时访问表。
在执行崩溃恢复时,重要的是要了解每个`MyISAM`桌子*`tbl_name`*在一个数据库中对应于下表所示数据库目录中的三个文件。
| 文件 | 目的 |
| --- | --- |
| `*`tbl_name`*.MYD` | 数据文件 |
| `*`tbl_name`*。我的我` | 索引文件 |
这三种文件类型中的每一种都以各种方式受到损坏,但问题最常发生在数据文件和索引文件中。
[**迈萨姆奇克**](myisamchk.html)通过创建副本来工作`.MYD`数据文件逐行。它通过移除旧的来结束修复阶段`.MYD`文件并将新文件重命名为原始文件名。如果你使用[`- 快的`](myisamchk-repair-options.html#option_myisamchk_quick),[**迈萨姆奇克**](myisamchk.html)不创建临时`.MYD`文件,而是假设`.MYD`文件是正确的并且只生成一个新的索引文件而不接触`.MYD`文件。这是安全的,因为[**迈萨姆奇克**](myisamchk.html)自动检测是否`.MYD`文件已损坏,如果是,则中止修复。您还可以指定[`- 快的`](myisamchk-repair-options.html#option_myisamchk_quick)选项两次[**迈萨姆奇克**](myisamchk.html).在这种情况下,[**迈萨姆奇克**](myisamchk.html)不会中止某些错误(例如重复键错误),而是尝试通过修改`.MYD`文件。通常使用两个[`- 快的`](myisamchk-repair-options.html#option_myisamchk_quick)仅当可用磁盘空间太少而无法执行正常修复时,选项才有用。在这种情况下,您至少应该在运行之前对表进行备份[**迈萨姆奇克**](myisamchk.html).
### 7.6.5 Setting Up a MyISAM Table Maintenance Schedule
[]()[]()
It is a good idea to perform table checks on a regular basis rather than waiting for problems to occur. One way to check and repair `MyISAM` tables is with the [`CHECK TABLE`](check-table.html) and [`REPAIR TABLE`](repair-table.html) statements. See [Section 13.7.3, “Table Maintenance Statements”](table-maintenance-statements.html).
Another way to check tables is to use [**myisamchk**](myisamchk.html). For maintenance purposes, you can use [**myisamchk -s**](myisamchk.html). The `-s` option (short for [`--silent`](myisamchk-general-options.html#option_myisamchk_silent)) causes [**myisamchk**](myisamchk.html) to run in silent mode, printing messages only when errors occur.
[]()
It is also a good idea to enable automatic `MyISAM` table checking. For example, whenever the machine has done a restart in the middle of an update, you usually need to check each table that could have been affected before it is used further. (These are “expected crashed tables.”) To cause the server to check `MyISAM` tables automatically, start it with the [`myisam_recover_options`](server-system-variables.html#sysvar_myisam_recover_options) system variable set. See [Section 5.1.8, “Server System Variables”](server-system-variables.html).
You should also check your tables regularly during normal system operation. For example, you can run a **cron** job to check important tables once a week, using a line like this in a `crontab` file:
```
35 0 * * 0 /path/to/myisamchk --fast --silent /path/to/datadir/*/*.MYI
```
This prints out information about crashed tables so that you can examine and repair them as necessary.
To start with, execute [**myisamchk -s**](myisamchk.html) each night on all tables that have been updated during the last 24 hours. As you see that problems occur infrequently, you can back off the checking frequency to once a week or so.
[]()
Normally, MySQL tables need little maintenance. If you are performing many updates to `MyISAM` tables with dynamic-sized rows (tables with [`VARCHAR`](char.html), [`BLOB`](blob.html), or [`TEXT`](blob.html) columns) or have tables with many deleted rows you may want to defragment/reclaim space from the tables from time to time. You can do this by using [`OPTIMIZE TABLE`](optimize-table.html) on the tables in question. Alternatively, if you can stop the [**mysqld**](mysqld.html) server for a while, change location into the data directory and use this command while the server is stopped:
```
$> myisamchk -r -s --sort-index --myisam_sort_buffer_size=16M */*.MYI
```
### 7.6.5 设置 MyISAM 表维护计划
[](<>)[](<>)
定期执行表检查而不是等待问题发生是个好主意。检查和维修的一种方法`MyISAM`表与[`检查表`](check-table.html)[`维修台`](repair-table.html)陈述。看[第 13.7.3 节,“表维护语句”](table-maintenance-statements.html).
检查表的另一种方法是使用[**迈萨姆奇克**](myisamchk.html).出于维护目的,您可以使用[**myisamchk -s**](myisamchk.html).这`-s`选项(简称[`- 无声`](myisamchk-general-options.html#option_myisamchk_silent)) 原因[**迈萨姆奇克**](myisamchk.html)以静默模式运行,仅在发生错误时打印消息。
[](<>)
启用自动也是一个好主意`MyISAM`表检查。例如,每当机器在更新过程中重新启动时,您通常需要在进一步使用之前检查每个可能受到影响的表。(这些是“预期的崩溃表”。)使服务器检查`MyISAM`表自动启动它[`myisam_recover_options`](server-system-variables.html#sysvar_myisam_recover_options)系统变量集。看[第 5.1.8 节,“服务器系统变量”](server-system-variables.html).
您还应该在系统正常运行期间定期检查您的表格。例如,您可以运行**cron**每周检查一次重要表的工作,在`crontab`文件:
```
35 0 * * 0 /path/to/myisamchk --fast --silent /path/to/datadir/*/*.MYI
```
这会打印出有关崩溃表的信息,以便您可以根据需要检查和修复它们。
首先,执行[**myisamchk -s**](myisamchk.html)每晚在过去 24 小时内更新的所有表格上。当您看到问题很少发生时,您可以将检查频率降低到每周一次左右。
[](<>)
通常,MySQL 表几乎不需要维护。如果您正在执行许多更新`MyISAM`具有动态大小行的表(具有[`VARCHAR`](char.html),[`斑点`](blob.html), 要么[`文本`](blob.html)列)或具有许多已删除行的表,您可能希望不时对表进行碎片整理/回收空间。您可以使用[`优化表`](optimize-table.html)在有问题的桌子上。或者,如果您可以停止[**mysqld**](mysqld.html)服务器一段时间,将位置更改为数据目录并在服务器停止时使用此命令:
```
$> myisamchk -r -s --sort-index --myisam_sort_buffer_size=16M */*.MYI
```
### 7.6.4 MyISAM Table Optimization
[]()[]()
To coalesce fragmented rows and eliminate wasted space that results from deleting or updating rows, run [**myisamchk**](myisamchk.html) in recovery mode:
```
$> myisamchk -r tbl_name
```
You can optimize a table in the same way by using the [`OPTIMIZE TABLE`](optimize-table.html) SQL statement. [`OPTIMIZE TABLE`](optimize-table.html) does a table repair and a key analysis, and also sorts the index tree so that key lookups are faster. There is also no possibility of unwanted interaction between a utility and the server, because the server does all the work when you use [`OPTIMIZE TABLE`](optimize-table.html). See [Section 13.7.3.4, “OPTIMIZE TABLE Statement”](optimize-table.html).
[**myisamchk**](myisamchk.html) has a number of other options that you can use to improve the performance of a table:
* [`--analyze`](myisamchk-other-options.html#option_myisamchk_analyze) or `-a`: Perform key distribution analysis. This improves join performance by enabling the join optimizer to better choose the order in which to join the tables and which indexes it should use.
* [`--sort-index`](myisamchk-other-options.html#option_myisamchk_sort-index) or `-S`: Sort the index blocks. This optimizes seeks and makes table scans that use indexes faster.
* [`--sort-records=*`index_num`*`](myisamchk-other-options.html#option_myisamchk_sort-records) or `-R *`index_num`*`: Sort data rows according to a given index. This makes your data much more localized and may speed up range-based [`SELECT`](select.html) and `ORDER BY` operations that use this index.
For a full description of all available options, see [Section 4.6.4, “myisamchk — MyISAM Table-Maintenance Utility”](myisamchk.html).
### 7.6.4 MyISAM 表优化
[](<>)[](<>)
要合并碎片行并消除因删除或更新行而造成的空间浪费,请运行[**迈萨姆奇克**](myisamchk.html)在恢复模式下:
```
$> myisamchk -r tbl_name
```
您可以使用相同的方式优化表[`优化表`](optimize-table.html)SQL 语句。[`优化表`](optimize-table.html)进行表修复和键分析,并对索引树进行排序,以便键查找更快。实用程序和服务器之间也不会发生不必要的交互,因为服务器会在您使用时完成所有工作[`优化表`](optimize-table.html).看[第 13.7.3.4 节,“优化 TABLE 语句”](optimize-table.html).
[**迈萨姆奇克**](myisamchk.html)有许多其他选项可用于提高表的性能:
- [`- 分析`](myisamchk-other-options.html#option_myisamchk_analyze)要么`-一种`:执行密钥分布分析。这通过使连接优化器能够更好地选择连接表的顺序和它应该使用的索引来提高连接性能。
- [`--排序索引`](myisamchk-other-options.html#option_myisamchk_sort-index)要么`-S`:对索引块进行排序。这优化了查找并使使用索引的表扫描更快。
- [`--排序记录=*`index_num`*`](myisamchk-other-options.html#option_myisamchk_sort-records)要么`-R *`index_num`*`:根据给定的索引对数据行进行排序。这使您的数据更加本地化,​​并且可以加快基于范围的[`选择`](select.html)`订购方式`使用此索引的操作。
有关所有可用选项的完整说明,请参阅[第 4.6.4 节,“myisamchk - MyISAM 表维护实用程序”](myisamchk.html).
### 7.6.3 How to Repair MyISAM Tables
[]()[]()
The discussion in this section describes how to use [**myisamchk**](myisamchk.html) on `MyISAM` tables (extensions `.MYI` and `.MYD`).
You can also use the [`CHECK TABLE`](check-table.html) and [`REPAIR TABLE`](repair-table.html) statements to check and repair `MyISAM` tables. See [Section 13.7.3.2, “CHECK TABLE Statement”](check-table.html), and [Section 13.7.3.5, “REPAIR TABLE Statement”](repair-table.html).
Symptoms of corrupted tables include queries that abort unexpectedly and observable errors such as these:
* Can't find file `*`tbl_name`*.MYI` (Errcode: *`nnn`*)
* Unexpected end of file
* Record file is crashed
* Got error *`nnn`* from table handler
To get more information about the error, run [**perror**](perror.html) *`nnn`*, where *`nnn`* is the error number. The following example shows how to use [**perror**](perror.html) to find the meanings for the most common error numbers that indicate a problem with a table:
```
$> perror 126 127 132 134 135 136 141 144 145
MySQL error code 126 = Index file is crashed
MySQL error code 127 = Record-file is crashed
MySQL error code 132 = Old database file
MySQL error code 134 = Record was already deleted (or record file crashed)
MySQL error code 135 = No more room in record file
MySQL error code 136 = No more room in index file
MySQL error code 141 = Duplicate unique key or constraint on write or update
MySQL error code 144 = Table is crashed and last repair failed
MySQL error code 145 = Table was marked as crashed and should be repaired
```
Note that error 135 (no more room in record file) and error 136 (no more room in index file) are not errors that can be fixed by a simple repair. In this case, you must use [`ALTER TABLE`](alter-table.html) to increase the `MAX_ROWS` and `AVG_ROW_LENGTH` table option values:
```
ALTER TABLE tbl_name MAX_ROWS=xxx AVG_ROW_LENGTH=yyy;
```
If you do not know the current table option values, use [`SHOW CREATE TABLE`](show-create-table.html).
For the other errors, you must repair your tables. [**myisamchk**](myisamchk.html) can usually detect and fix most problems that occur.
The repair process involves up to three stages, described here. Before you begin, you should change location to the database directory and check the permissions of the table files. On Unix, make sure that they are readable by the user that [**mysqld**](mysqld.html) runs as (and to you, because you need to access the files you are checking). If it turns out you need to modify files, they must also be writable by you.
This section is for the cases where a table check fails (such as those described in [Section 7.6.2, “How to Check MyISAM Tables for Errors”](myisam-check.html)), or you want to use the extended features that [**myisamchk**](myisamchk.html) provides.
The [**myisamchk**](myisamchk.html) options used for table maintenance with are described in [Section 4.6.4, “myisamchk — MyISAM Table-Maintenance Utility”](myisamchk.html). [**myisamchk**](myisamchk.html) also has variables that you can set to control memory allocation that may improve performance. See [Section 4.6.4.6, “myisamchk Memory Usage”](myisamchk-memory.html).
If you are going to repair a table from the command line, you must first stop the [**mysqld**](mysqld.html) server. Note that when you do [**mysqladmin shutdown**](mysqladmin.html) on a remote server, the [**mysqld**](mysqld.html) server is still available for a while after [**mysqladmin**](mysqladmin.html) returns, until all statement-processing has stopped and all index changes have been flushed to disk.
**Stage 1: Checking your tables**
Run [**myisamchk \*.MYI**](myisamchk.html) or [**myisamchk -e \*.MYI**](myisamchk.html) if you have more time. Use the `-s` (silent) option to suppress unnecessary information.
If the [**mysqld**](mysqld.html) server is stopped, you should use the [`--update-state`](myisamchk-check-options.html#option_myisamchk_update-state) option to tell [**myisamchk**](myisamchk.html) to mark the table as “checked.”
You have to repair only those tables for which [**myisamchk**](myisamchk.html) announces an error. For such tables, proceed to Stage 2.
If you get unexpected errors when checking (such as `out of memory` errors), or if [**myisamchk**](myisamchk.html) crashes, go to Stage 3.
**Stage 2: Easy safe repair**
First, try [**myisamchk -r -q *`tbl_name`***](myisamchk.html) (`-r -q` means “quick recovery mode”). This attempts to repair the index file without touching the data file. If the data file contains everything that it should and the delete links point at the correct locations within the data file, this should work, and the table is fixed. Start repairing the next table. Otherwise, use the following procedure:
1. Make a backup of the data file before continuing.
2. Use [**myisamchk -r *`tbl_name`***](myisamchk.html) (`-r` means “recovery mode”). This removes incorrect rows and deleted rows from the data file and reconstructs the index file.
3. If the preceding step fails, use [**myisamchk --safe-recover *`tbl_name`***](myisamchk.html). Safe recovery mode uses an old recovery method that handles a few cases that regular recovery mode does not (but is slower).
Note
If you want a repair operation to go much faster, you should set the values of the [`sort_buffer_size`](server-system-variables.html#sysvar_sort_buffer_size) and [`key_buffer_size`](server-system-variables.html#sysvar_key_buffer_size) variables each to about 25% of your available memory when running [**myisamchk**](myisamchk.html).
If you get unexpected errors when repairing (such as `out of memory` errors), or if [**myisamchk**](myisamchk.html) crashes, go to Stage 3.
**Stage 3: Difficult repair**
You should reach this stage only if the first 16KB block in the index file is destroyed or contains incorrect information, or if the index file is missing. In this case, it is necessary to create a new index file. Do so as follows:
1. Move the data file to a safe place.
2. Use the table description file to create new (empty) data and index files:
```
$> mysql db_name
```
```
mysql> SET autocommit=1;
mysql> TRUNCATE TABLE tbl_name;
mysql> quit
```
3. Copy the old data file back onto the newly created data file. (Do not just move the old file back onto the new file. You want to retain a copy in case something goes wrong.)
Important
If you are using replication, you should stop it prior to performing the above procedure, since it involves file system operations, and these are not logged by MySQL.
Go back to Stage 2. [**myisamchk -r -q**](myisamchk.html) should work. (This should not be an endless loop.)
You can also use the `REPAIR TABLE *`tbl_name`* USE_FRM` SQL statement, which performs the whole procedure automatically. There is also no possibility of unwanted interaction between a utility and the server, because the server does all the work when you use [`REPAIR TABLE`](repair-table.html). See [Section 13.7.3.5, “REPAIR TABLE Statement”](repair-table.html).
### 7.6.3 如何修复 MyISAM 表
[](<>)[](<>)
本节中的讨论描述了如何使用[**迈萨姆奇克**](myisamchk.html)`MyISAM`表(扩展`。我的我``.MYD`)。
您还可以使用[`检查表`](check-table.html)[`维修台`](repair-table.html)检查和维修的声明`MyISAM`表。看[第 13.7.3.2 节,“CHECK TABLE 语句”](check-table.html), 和[第 13.7.3.5 节,“REPAIR TABLE 语句”](repair-table.html).
损坏表的症状包括意外中止的查询和可观察到的错误,例如:
- 找不到文件`*`tbl_name`*。我的我`(错误代码:*`nnn`*)
- 文件意外结束
- 记录文件崩溃
- 出现错误*`nnn`*从表处理程序
要获取有关错误的更多信息,请运行[**错误**](perror.html) *`nnn`*, 在哪里*`nnn`*是错误号。下面的例子展示了如何使用[**错误**](perror.html)查找表示表格问题的最常见错误编号的含义:
```
$> perror 126 127 132 134 135 136 141 144 145
MySQL error code 126 = Index file is crashed
MySQL error code 127 = Record-file is crashed
MySQL error code 132 = Old database file
MySQL error code 134 = Record was already deleted (or record file crashed)
MySQL error code 135 = No more room in record file
MySQL error code 136 = No more room in index file
MySQL error code 141 = Duplicate unique key or constraint on write or update
MySQL error code 144 = Table is crashed and last repair failed
MySQL error code 145 = Table was marked as crashed and should be repaired
```
请注意,错误 135(记录文件中没有更多空间)和错误 136(索引文件中没有更多空间)不是可以通过简单修复来修复的错误。在这种情况下,您必须使用[`更改表`](alter-table.html)增加`MAX_ROWS``AVG_ROW_LENGTH`表选项值:
```
ALTER TABLE tbl_name MAX_ROWS=xxx AVG_ROW_LENGTH=yyy;
```
如果您不知道当前表选项值,请使用[`显示创建表`](show-create-table.html).
对于其他错误,您必须修复您的表。[**迈萨姆奇克**](myisamchk.html)通常可以检测并修复发生的大多数问题。
修复过程涉及多达三个阶段,如下所述。在开始之前,您应该将位置更改为数据库目录并检查表文件的权限。在 Unix 上,确保它们可以被用户读取[**mysqld**](mysqld.html)运行为(对你来说,因为你需要访问你正在检查的文件)。如果事实证明您需要修改文件,它们也必须是您可写的。
本节适用于表检查失败的情况(例如在[第 7.6.2 节,“如何检查 MyISAM 表的错误”](myisam-check.html)),或者您想使用扩展功能[**迈萨姆奇克**](myisamchk.html)提供。
[**迈萨姆奇克**](myisamchk.html)用于表维护的选项在[第 4.6.4 节,“myisamchk - MyISAM 表维护实用程序”](myisamchk.html).[**迈萨姆奇克**](myisamchk.html)还可以设置一些变量来控制内存分配,从而提高性能。看[第 4.6.4.6 节,“myisamchk 内存使用”](myisamchk-memory.html).
如果要从命令行修复表,必须先停止[**mysqld**](mysqld.html)服务器。请注意,当你这样做[**mysqladmin 关闭**](mysqladmin.html)在远程服务器上,[**mysqld**](mysqld.html)服务器在一段时间后仍然可用[**mysql管理员**](mysqladmin.html)返回,直到所有语句处理停止并且所有索引更改都已刷新到磁盘。
**第 1 阶段:检查您的表格**
跑步[**迈萨姆奇克\*。我的我**](myisamchk.html)要么[**myisamchk -e\*。我的我**](myisamchk.html)如果你有更多的时间。使用`-s`(静默)选项以抑制不必要的信息。
如果[**mysqld**](mysqld.html)服务器已停止,您应该使用[`--更新状态`](myisamchk-check-options.html#option_myisamchk_update-state)告诉的选项[**迈萨姆奇克**](myisamchk.html)将表格标记为“已检查”。
你只需要修复那些表[**迈萨姆奇克**](myisamchk.html)宣布错误。对于此类表格,请进入第 2 阶段。
如果您在检查时遇到意外错误(例如`记不清`错误),或者如果[**迈萨姆奇克**](myisamchk.html)崩溃,进入第 3 阶段。
**第 2 阶段:轻松安全维修**
第一次尝试[**myisamchk -r -q*`tbl_name`***](myisamchk.html)(`-r -q`表示“快速恢复模式”)。这会尝试在不接触数据文件的情况下修复索引文件。如果数据文件包含它应该包含的所有内容并且删除链接指向数据文件中的正确位置,那么这应该可以工作,并且表是固定的。开始修理下一张桌子。否则,请使用以下过程:
1. 在继续之前备份数据文件。
2. 采用[**myisamchk -r*`tbl_name`***](myisamchk.html)(`-r`表示“恢复模式”)。这会从数据文件中删除不正确的行和已删除的行并重建索引文件。
3. 如果上一步失败,请使用[**myisamchk --安全恢复*`tbl_name`***](myisamchk.html).安全恢复模式使用一种旧的恢复方法,可以处理一些常规恢复模式不能处理的情况(但速度较慢)。
笔记
如果您希望修复操作进行得更快,您应该设置[`排序缓冲区大小`](server-system-variables.html#sysvar_sort_buffer_size)和[`key_buffer_size`](server-system-variables.html#sysvar_key_buffer_size)运行时每个变量占可用内存的 25% 左右[**迈萨姆奇克**](myisamchk.html).
如果您在修复时遇到意外错误(例如`内存不足`错误),或者如果[**myisamchk**](myisamchk.html)坠机,进入第三阶段。
**第三阶段:修复困难**
只有当索引文件中的第一个16KB块被破坏或包含不正确的信息,或者索引文件丢失时,才应达到此阶段。在这种情况下,有必要创建一个新的索引文件。按以下步骤进行:
1. 将数据文件移到安全的地方。
2. 使用表格描述文件创建新(空)数据和索引文件:
```
$> mysql db_name
```
```
mysql> SET autocommit=1;
mysql> TRUNCATE TABLE tbl_name;
mysql> quit
```
3. 将旧数据文件复制回新创建的数据文件。(不要只是将旧文件移回新文件。你要保留一份副本,以防出现问题。)
重要的
如果您使用的是复制,您应该在执行上述过程之前停止它,因为它涉及文件系统操作,MySQL不会记录这些操作。
回到第二阶段。[**通过简单修复**](myisamchk.html)应该有用。(这不应该是一个无休止的循环。)
你也可以使用`修理台*`tbl\_名称`*使用`SQL语句,自动执行整个过程。在实用程序和服务器之间也不存在不必要的交互,因为当您使用时,服务器会完成所有工作[`修理台`](repair-table.html)看见[第13.7.3.5节,“维修表声明”](repair-table.html).
## 7.6 MyISAM Table Maintenance and Crash Recovery
[7.6.1 Using myisamchk for Crash Recovery](myisam-crash-recovery.html)
[7.6.2 How to Check MyISAM Tables for Errors](myisam-check.html)
[7.6.3 How to Repair MyISAM Tables](myisam-repair.html)
[7.6.4 MyISAM Table Optimization](myisam-optimization.html)
[7.6.5 Setting Up a MyISAM Table Maintenance Schedule](myisam-maintenance-schedule.html)
This section discusses how to use [**myisamchk**](myisamchk.html) to check or repair `MyISAM` tables (tables that have `.MYD` and `.MYI` files for storing data and indexes). For general [**myisamchk**](myisamchk.html) background, see [Section 4.6.4, “myisamchk — MyISAM Table-Maintenance Utility”](myisamchk.html). Other table-repair information can be found at [Section 2.11.13, “Rebuilding or Repairing Tables or Indexes”](rebuilding-tables.html).
You can use [**myisamchk**](myisamchk.html) to check, repair, or optimize database tables. The following sections describe how to perform these operations and how to set up a table maintenance schedule. For information about using [**myisamchk**](myisamchk.html) to get information about your tables, see [Section 4.6.4.5, “Obtaining Table Information with myisamchk”](myisamchk-table-info.html).
Even though table repair with [**myisamchk**](myisamchk.html) is quite secure, it is always a good idea to make a backup *before* doing a repair or any maintenance operation that could make a lot of changes to a table.
[**myisamchk**](myisamchk.html) operations that affect indexes can cause `MyISAM` `FULLTEXT` indexes to be rebuilt with full-text parameters that are incompatible with the values used by the MySQL server. To avoid this problem, follow the guidelines in [Section 4.6.4.1, “myisamchk General Options”](myisamchk-general-options.html).
`MyISAM` table maintenance can also be done using the SQL statements that perform operations similar to what [**myisamchk**](myisamchk.html) can do:
* To check `MyISAM` tables, use [`CHECK TABLE`](check-table.html).
* To repair `MyISAM` tables, use [`REPAIR TABLE`](repair-table.html).
* To optimize `MyISAM` tables, use [`OPTIMIZE TABLE`](optimize-table.html).
* To analyze `MyISAM` tables, use [`ANALYZE TABLE`](analyze-table.html).
For additional information about these statements, see [Section 13.7.3, “Table Maintenance Statements”](table-maintenance-statements.html).
These statements can be used directly or by means of the [**mysqlcheck**](mysqlcheck.html) client program. One advantage of these statements over [**myisamchk**](myisamchk.html) is that the server does all the work. With [**myisamchk**](myisamchk.html), you must make sure that the server does not use the tables at the same time so that there is no unwanted interaction between [**myisamchk**](myisamchk.html) and the server.
## 7.6 MyISAM 表维护和崩溃恢复
[7.6.1 使用 myisamchk 进行崩溃恢复](myisam-crash-recovery.html)
[7.6.2 如何检查 MyISAM 表的错误](myisam-check.html)
[7.6.3 如何修复 MyISAM 表](myisam-repair.html)
[7.6.4 MyISAM 表优化](myisam-optimization.html)
[7.6.5 设置 MyISAM 表维护计划](myisam-maintenance-schedule.html)
本节讨论如何使用[**迈萨姆奇克**](myisamchk.html)检查或修理`MyISAM`表(具有`.MYD``。我的我`用于存储数据和索引的文件)。对于一般[**迈萨姆奇克**](myisamchk.html)背景,见[第 4.6.4 节,“myisamchk - MyISAM 表维护实用程序”](myisamchk.html).其他表修复信息可在以下位置找到[第 2.11.13 节,“重建或修复表或索引”](rebuilding-tables.html).
您可以使用[**迈萨姆奇克**](myisamchk.html)检查、修复或优化数据库表。以下部分描述了如何执行这些操作以及如何设置表维护计划。有关使用的信息[**迈萨姆奇克**](myisamchk.html)要获取有关您的表的信息,请参阅[第 4.6.4.5 节,“使用 myisamchk 获取表信息”](myisamchk-table-info.html).
即使表修复与[**迈萨姆奇克**](myisamchk.html)非常安全,备份总是一个好主意*前*进行可能对表进行大量更改的维修或任何维护操作。
[**迈萨姆奇克**](myisamchk.html)影响索引的操作可能导致`MyISAM` `全文`使用与 MySQL 服务器使用的值不兼容的全文参数重建索引。为避免此问题,请遵循[第 4.6.4.1 节,“myisamchk 常规选项”](myisamchk-general-options.html).
`MyISAM`也可以使用执行类似于以下操作的 SQL 语句来完成表维护[**迈萨姆奇克**](myisamchk.html)可以做:
- 去检查`MyISAM`表,使用[`检查表`](check-table.html).
- 修复`MyISAM`表,使用[`维修台`](repair-table.html).
- 优化`MyISAM`表,使用[`优化表`](optimize-table.html).
- 分析`MyISAM`表,使用[`分析表`](analyze-table.html).
有关这些声明的更多信息,请参阅[第 13.7.3 节,“表维护语句”](table-maintenance-statements.html).
这些语句可以直接使用,也可以通过[**mysql检查**](mysqlcheck.html)客户端程序。这些陈述的一个优点是[**迈萨姆奇克**](myisamchk.html)是服务器完成所有工作。和[**迈萨姆奇克**](myisamchk.html),你必须确保服务器不会同时使用这些表,这样就不会出现不需要的交互[**迈萨姆奇克**](myisamchk.html)和服务器。
#### 7.4.5.1 Making a Copy of a Database
```
$> mysqldump db1 > dump.sql
$> mysqladmin create db2
$> mysql db2 < dump.sql
```
Do not use [`--databases`](mysqldump.html#option_mysqldump_databases) on the [**mysqldump**](mysqldump.html) command line because that causes `USE db1` to be included in the dump file, which overrides the effect of naming `db2` on the [**mysql**](mysql.html) command line.
#### 7.4.5.1 制作数据库副本
```
$> mysqldump db1 > dump.sql
$> mysqladmin create db2
$> mysql db2 < dump.sql
```
不使用[`--数据库`](mysqldump.html#option_mysqldump_databases)[**mysql转储**](mysqldump.html)命令行,因为这会导致`使用 db1`被包含在转储文件中,它覆盖了命名的效果`数据库2`[**mysql**](mysql.html)命令行。
#### 7.4.5.2 Copy a Database from one Server to Another
On Server 1:
```
$> mysqldump --databases db1 > dump.sql
```
Copy the dump file from Server 1 to Server 2.
On Server 2:
```
$> mysql < dump.sql
```
Use of [`--databases`](mysqldump.html#option_mysqldump_databases) with the [**mysqldump**](mysqldump.html) command line causes the dump file to include [`CREATE DATABASE`](create-database.html) and [`USE`](use.html) statements that create the database if it does exist and make it the default database for the reloaded data.
Alternatively, you can omit [`--databases`](mysqldump.html#option_mysqldump_databases) from the [**mysqldump**](mysqldump.html) command. Then you need to create the database on Server 2 (if necessary) and specify it as the default database when you reload the dump file.
On Server 1:
```
$> mysqldump db1 > dump.sql
```
On Server 2:
```
$> mysqladmin create db1
$> mysql db1 < dump.sql
```
You can specify a different database name in this case, so omitting [`--databases`](mysqldump.html#option_mysqldump_databases) from the [**mysqldump**](mysqldump.html) command enables you to dump data from one database and load it into another.
#### 7.4.5.2 将数据库从一台服务器复制到另一台服务器
在服务器 1 上:
```
$> mysqldump --databases db1 > dump.sql
```
将转储文件从服务器 1 复制到服务器 2。
在服务器 2 上:
```
$> mysql < dump.sql
```
用于[`--数据库`](mysqldump.html#option_mysqldump_databases)[**mysql转储**](mysqldump.html)命令行使转储文件包含[`创建数据库`](create-database.html)[`采用`](use.html)如果数据库确实存在,则创建数据库并使其成为重新加载数据的默认数据库的语句。
或者,您可以省略[`--数据库`](mysqldump.html#option_mysqldump_databases)来自[**mysql转储**](mysqldump.html)命令。然后您需要在服务器 2 上创建数据库(如果需要),并在重新加载转储文件时将其指定为默认数据库。
在服务器 1 上:
```
$> mysqldump db1 > dump.sql
```
在服务器 2 上:
```
$> mysqladmin create db1
$> mysql db1 < dump.sql
```
在这种情况下,您可以指定不同的数据库名称,因此省略[`--数据库`](mysqldump.html#option_mysqldump_databases)来自[**mysql转储**](mysqldump.html)命令使您能够从一个数据库中转储数据并将其加载到另一个数据库中。
#### 7.4.5.4 Dumping Table Definitions and Content Separately
The [`--no-data`](mysqldump.html#option_mysqldump_no-data) option tells [**mysqldump**](mysqldump.html) not to dump table data, resulting in the dump file containing only statements to create the tables. Conversely, the [`--no-create-info`](mysqldump.html#option_mysqldump_no-create-info) option tells [**mysqldump**](mysqldump.html) to suppress `CREATE` statements from the output, so that the dump file contains only table data.
For example, to dump table definitions and data separately for the `test` database, use these commands:
```
$> mysqldump --no-data test > dump-defs.sql
$> mysqldump --no-create-info test > dump-data.sql
```
For a definition-only dump, add the [`--routines`](mysqldump.html#option_mysqldump_routines) and [`--events`](mysqldump.html#option_mysqldump_events) options to also include stored routine and event definitions:
```
$> mysqldump --no-data --routines --events test > dump-defs.sql
```
#### 7.4.5.4 分别转储表定义和内容
[`- 没有数据`](mysqldump.html#option_mysqldump_no-data)选项告诉[**mysql转储**](mysqldump.html)不转储表数据,导致转储文件仅包含创建表的语句。相反,[`--no-create-info`](mysqldump.html#option_mysqldump_no-create-info)选项告诉[**mysql转储**](mysqldump.html)压制`创建`输出中的语句,以便转储文件仅包含表数据。
例如,要单独转储表定义和数据`测试`数据库,请使用以下命令:
```
$> mysqldump --no-data test > dump-defs.sql
$> mysqldump --no-create-info test > dump-data.sql
```
对于仅定义转储,添加[`--例程`](mysqldump.html#option_mysqldump_routines)[`--事件`](mysqldump.html#option_mysqldump_events)还包括存储的例程和事件定义的选项:
```
$> mysqldump --no-data --routines --events test > dump-defs.sql
```
### 7.4.3 Dumping Data in Delimited-Text Format with mysqldump
This section describes how to use [**mysqldump**](mysqldump.html) to create delimited-text dump files. For information about reloading such dump files, see [Section 7.4.4, “Reloading Delimited-Text Format Backups”](reloading-delimited-text-dumps.html).
If you invoke [**mysqldump**](mysqldump.html) with the [`--tab=*`dir_name`*`](mysqldump.html#option_mysqldump_tab) option, it uses *`dir_name`* as the output directory and dumps tables individually in that directory using two files for each table. The table name is the base name for these files. For a table named `t1`, the files are named `t1.sql` and `t1.txt`. The `.sql` file contains a [`CREATE TABLE`](create-table.html) statement for the table. The `.txt` file contains the table data, one line per table row.
The following command dumps the contents of the `db1` database to files in the `/tmp` database:
```
$> mysqldump --tab=/tmp db1
```
The `.txt` files containing table data are written by the server, so they are owned by the system account used for running the server. The server uses [`SELECT ... INTO OUTFILE`](select-into.html) to write the files, so you must have the [`FILE`](privileges-provided.html#priv_file) privilege to perform this operation, and an error occurs if a given `.txt` file already exists.
The server sends the `CREATE` definitions for dumped tables to [**mysqldump**](mysqldump.html), which writes them to `.sql` files. These files therefore are owned by the user who executes [**mysqldump**](mysqldump.html).
It is best that [`--tab`](mysqldump.html#option_mysqldump_tab) be used only for dumping a local server. If you use it with a remote server, the [`--tab`](mysqldump.html#option_mysqldump_tab) directory must exist on both the local and remote hosts, and the `.txt` files are written by the server in the remote directory (on the server host), whereas the `.sql` files are written by [**mysqldump**](mysqldump.html) in the local directory (on the client host).
For [**mysqldump --tab**](mysqldump.html), the server by default writes table data to `.txt` files one line per row with tabs between column values, no quotation marks around column values, and newline as the line terminator. (These are the same defaults as for [`SELECT ... INTO OUTFILE`](select-into.html).)
To enable data files to be written using a different format, [**mysqldump**](mysqldump.html) supports these options:
* [`--fields-terminated-by=*`str`*`](mysqldump.html#option_mysqldump_fields)
The string for separating column values (default: tab).
* [`--fields-enclosed-by=*`char`*`](mysqldump.html#option_mysqldump_fields)
The character within which to enclose column values (default: no character).
* [`--fields-optionally-enclosed-by=*`char`*`](mysqldump.html#option_mysqldump_fields)
The character within which to enclose non-numeric column values (default: no character).
* [`--fields-escaped-by=*`char`*`](mysqldump.html#option_mysqldump_fields)
The character for escaping special characters (default: no escaping).
* [`--lines-terminated-by=*`str`*`](mysqldump.html#option_mysqldump_lines-terminated-by)
The line-termination string (default: newline).
Depending on the value you specify for any of these options, it might be necessary on the command line to quote or escape the value appropriately for your command interpreter. Alternatively, specify the value using hex notation. Suppose that you want [**mysqldump**](mysqldump.html) to quote column values within double quotation marks. To do so, specify double quote as the value for the [`--fields-enclosed-by`](mysqldump.html#option_mysqldump_fields) option. But this character is often special to command interpreters and must be treated specially. For example, on Unix, you can quote the double quote like this:
```
--fields-enclosed-by='"'
```
On any platform, you can specify the value in hex:
```
--fields-enclosed-by=0x22
```
It is common to use several of the data-formatting options together. For example, to dump tables in comma-separated values format with lines terminated by carriage-return/newline pairs (`\r\n`), use this command (enter it on a single line):
```
$> mysqldump --tab=/tmp --fields-terminated-by=,
--fields-enclosed-by='"' --lines-terminated-by=0x0d0a db1
```
Should you use any of the data-formatting options to dump table data, you need to specify the same format when you reload data files later, to ensure proper interpretation of the file contents.
### 7.4.3 使用 mysqldump 以分隔文本格式转储数据
本节介绍如何使用[**mysql转储**](mysqldump.html)创建分隔文本转储文件。有关重新加载此类转储文件的信息,请参阅[第 7.4.4 节,“重新加载分隔文本格式的备份”](reloading-delimited-text-dumps.html).
如果你调用[**mysql转储**](mysqldump.html)[`--tab=*`目录名`*`](mysqldump.html#option_mysqldump_tab)选项,它使用*`目录名`*作为输出目录,并使用每个表的两个文件在该目录中单独转储表。表名是这些文件的基本名称。对于名为`t1`, 文件被命名`t1.sql``t1.txt`.这`.sql`文件包含一个[`创建表`](create-table.html)表的声明。这`。文本文件`文件包含表数据,每行一行。
以下命令转储文件的内容`db1`数据库中的文件`/tmp`数据库:
```
$> mysqldump --tab=/tmp db1
```
`。文本文件`包含表数据的文件由服务器写入,因此它们归用于运行服务器的系统帐户所有。服务器使用[`选择...进入文件`](select-into.html)写文件,所以你必须有[`文件`](privileges-provided.html#priv_file)执行此操作的权限,如果给定`。文本文件`文件已存在。
服务器发送`创建`转储表的定义[**mysql转储**](mysqldump.html), 将它们写入`.sql`文件。因此,这些文件归执行的用户所有[**mysql转储**](mysqldump.html).
最好是[`- 标签`](mysqldump.html#option_mysqldump_tab)仅用于转储本地服务器。如果将它与远程服务器一起使用,则[`- 标签`](mysqldump.html#option_mysqldump_tab)目录必须同时存在于本地和远程主机上,并且`。文本文件`文件由服务器写入远程目录(在服务器主机上),而`.sql`文件由[**mysql转储**](mysqldump.html)在本地目录中(在客户端主机上)。
为了[**mysqldump --选项卡**](mysqldump.html),服务器默认将表数据写入`。文本文件`文件每行一行,列值之间有制表符,列值周围没有引号,换行符作为行终止符。(这些默认值与[`选择...进入文件`](select-into.html).)
要使数据文件能够使用不同的格式写入,[**mysql转储**](mysqldump.html)支持这些选项:
- [`--fields-terminated-by=*`字符串`*`](mysqldump.html#option_mysqldump_fields)
用于分隔列值的字符串(默认值:tab)。
- [`--fields-enclosed-by=*`字符`*`](mysqldump.html#option_mysqldump_fields)
包含列值的字符(默认值:无字符)。
- [`--fields-optional-enclosed-by=*`字符`*`](mysqldump.html#option_mysqldump_fields)
包含非数字列值的字符(默认值:无字符)。
- [`--fields-escaped-by=*`字符`*`](mysqldump.html#option_mysqldump_fields)
转义特殊字符的字符(默认:不转义)。
- [`--lines-terminated-by=*`字符串`*`](mysqldump.html#option_mysqldump_lines-terminated-by)
行终止字符串(默认值:换行符)。
根据您为这些选项中的任何一个指定的值,可能需要在命令行上为您的命令解释器适当地引用或转义该值。或者,使用十六进制表示法指定值。假设你想要[**mysql转储**](mysqldump.html)在双引号内引用列值。为此,请将双引号指定为[`--fields-enclosed-by`](mysqldump.html#option_mysqldump_fields)选项。但是这个字符对于命令解释器来说通常是特殊的,必须特殊对待。例如,在 Unix 上,您可以像这样引用双引号:
```
--fields-enclosed-by='"'
```
在任何平台上,您都可以指定十六进制值:
```
--fields-enclosed-by=0x22
```
一起使用几个数据格式选项是很常见的。例如,以逗号分隔值格式转储表格,其中行以回车符/换行符对终止 (`\r\n`),使用此命令(在一行中输入):
```
$> mysqldump --tab=/tmp --fields-terminated-by=,
--fields-enclosed-by='"' --lines-terminated-by=0x0d0a db1
```
如果您使用任何数据格式选项来转储表数据,则需要在稍后重新加载数据文件时指定相同的格式,以确保正确解释文件内容。
### 7.4.1 Dumping Data in SQL Format with mysqldump
This section describes how to use [**mysqldump**](mysqldump.html) to create SQL-format dump files. For information about reloading such dump files, see [Section 7.4.2, “Reloading SQL-Format Backups”](reloading-sql-format-dumps.html).
By default, [**mysqldump**](mysqldump.html) writes information as SQL statements to the standard output. You can save the output in a file:
```
$> mysqldump [arguments] > file_name
```
To dump all databases, invoke [**mysqldump**](mysqldump.html) with the [`--all-databases`](mysqldump.html#option_mysqldump_all-databases) option:
```
$> mysqldump --all-databases > dump.sql
```
To dump only specific databases, name them on the command line and use the [`--databases`](mysqldump.html#option_mysqldump_databases) option:
```
$> mysqldump --databases db1 db2 db3 > dump.sql
```
The [`--databases`](mysqldump.html#option_mysqldump_databases) option causes all names on the command line to be treated as database names. Without this option, [**mysqldump**](mysqldump.html) treats the first name as a database name and those following as table names.
With [`--all-databases`](mysqldump.html#option_mysqldump_all-databases) or [`--databases`](mysqldump.html#option_mysqldump_databases), [**mysqldump**](mysqldump.html) writes [`CREATE DATABASE`](create-database.html) and [`USE`](use.html) statements prior to the dump output for each database. This ensures that when the dump file is reloaded, it creates each database if it does not exist and makes it the default database so database contents are loaded into the same database from which they came. If you want to cause the dump file to force a drop of each database before recreating it, use the [`--add-drop-database`](mysqldump.html#option_mysqldump_add-drop-database) option as well. In this case, [**mysqldump**](mysqldump.html) writes a [`DROP DATABASE`](drop-database.html) statement preceding each [`CREATE DATABASE`](create-database.html) statement.
To dump a single database, name it on the command line:
```
$> mysqldump --databases test > dump.sql
```
In the single-database case, it is permissible to omit the [`--databases`](mysqldump.html#option_mysqldump_databases) option:
```
$> mysqldump test > dump.sql
```
The difference between the two preceding commands is that without [`--databases`](mysqldump.html#option_mysqldump_databases), the dump output contains no [`CREATE DATABASE`](create-database.html) or [`USE`](use.html) statements. This has several implications:
* When you reload the dump file, you must specify a default database name so that the server knows which database to reload.
* For reloading, you can specify a database name different from the original name, which enables you to reload the data into a different database.
* If the database to be reloaded does not exist, you must create it first.
* Because the output contains no [`CREATE DATABASE`](create-database.html) statement, the [`--add-drop-database`](mysqldump.html#option_mysqldump_add-drop-database) option has no effect. If you use it, it produces no [`DROP DATABASE`](drop-database.html) statement.
To dump only specific tables from a database, name them on the command line following the database name:
```
$> mysqldump test t1 t3 t7 > dump.sql
```
By default, if GTIDs are in use on the server where you create the dump file ([`gtid_mode=ON`](replication-options-gtids.html#sysvar_gtid_mode)), [**mysqldump**](mysqldump.html) includes a `SET @@GLOBAL.gtid_purged` statement in the output to add the GTIDs from the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) set on the source server to the [`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged) set on the target server. If you are dumping only specific databases or tables, it is important to note that the value that is included by [**mysqldump**](mysqldump.html) includes the GTIDs of all transactions in the [`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed) set on the source server, even those that changed suppressed parts of the database, or other databases on the server that were not included in the partial dump. If you only replay one partial dump file on the target server, the extra GTIDs do not cause any problems with the future operation of that server. However, if you replay a second dump file on the target server that contains the same GTIDs (for example, another partial dump from the same source server), any `SET @@GLOBAL.gtid_purged` statement in the second dump file fails. To avoid this issue, either set the [**mysqldump**](mysqldump.html) option `--set-gtid-purged` to `OFF` or `COMMENTED` to output the second dump file without an active `SET @@GLOBAL.gtid_purged` statement, or remove the statement manually before replaying the dump file.
### 7.4.1 使用 mysqldump 以 SQL 格式转储数据
本节介绍如何使用[**mysql转储**](mysqldump.html)创建 SQL 格式的转储文件。有关重新加载此类转储文件的信息,请参阅[第 7.4.2 节,“重新加载 SQL 格式的备份”](reloading-sql-format-dumps.html).
默认,[**mysql转储**](mysqldump.html)将信息作为 SQL 语句写入标准输出。您可以将输出保存在文件中:
```
$> mysqldump [arguments] > file_name
```
要转储所有数据库,请调用[**mysql转储**](mysqldump.html)[`--所有数据库`](mysqldump.html#option_mysqldump_all-databases)选项:
```
$> mysqldump --all-databases > dump.sql
```
要仅转储特定数据库,请在命令行上命名它们并使用[`--数据库`](mysqldump.html#option_mysqldump_databases)选项:
```
$> mysqldump --databases db1 db2 db3 > dump.sql
```
[`--数据库`](mysqldump.html#option_mysqldump_databases)选项导致命令行上的所有名称都被视为数据库名称。没有这个选项,[**mysql转储**](mysqldump.html)将第一个名称视为数据库名称,将后面的名称视为表名称。
[`--所有数据库`](mysqldump.html#option_mysqldump_all-databases)要么[`--数据库`](mysqldump.html#option_mysqldump_databases),[**mysql转储**](mysqldump.html)[`创建数据库`](create-database.html)[`采用`](use.html)每个数据库的转储输出之前的语句。这确保了在重新加载转储文件时,它会创建每个数据库(如果它不存在)并使其成为默认数据库,以便将数据库内容加载到它们来自的同一数据库中。如果要使转储文件在重新创建之前强制删除每个数据库,请使用[`--add-drop-database`](mysqldump.html#option_mysqldump_add-drop-database)选项也是如此。在这种情况下,[**mysql转储**](mysqldump.html)写一个[`删除数据库`](drop-database.html)每个前面的声明[`创建数据库`](create-database.html)陈述。
要转储单个数据库,请在命令行上为其命名:
```
$> mysqldump --databases test > dump.sql
```
在单数据库情况下,可以省略[`--数据库`](mysqldump.html#option_mysqldump_databases)选项:
```
$> mysqldump test > dump.sql
```
前面两个命令的区别在于没有[`--数据库`](mysqldump.html#option_mysqldump_databases),转储输出不包含[`创建数据库`](create-database.html)要么[`采用`](use.html)陈述。这有几个含义:
- 重新加载转储文件时,必须指定默认数据库名称,以便服务器知道要重新加载哪个数据库。
- 对于重新加载,您可以指定与原始名称不同的数据库名称,这样您就可以将数据重新加载到不同的数据库中。
- 如果要重新加载的数据库不存在,则必须先创建它。
- 因为输出不包含[`创建数据库`](create-database.html)声明[`--add-drop-database`](mysqldump.html#option_mysqldump_add-drop-database)选项无效。如果你使用它,它不会产生[`删除数据库`](drop-database.html)陈述。
要仅转储数据库中的特定表,请在数据库名称后面的命令行中命名它们:
```
$> mysqldump test t1 t3 t7 > dump.sql
```
默认情况下,如果在您创建转储文件的服务器上使用 GTID ([`gtid_mode=ON`](replication-options-gtids.html#sysvar_gtid_mode)),[**mysql转储**](mysqldump.html)包括一个`SET @@GLOBAL.gtid_purged`输出中的语句以添加来自[`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed)在源服务器上设置为[`gtid_purged`](replication-options-gtids.html#sysvar_gtid_purged)在目标服务器上设置。如果您只转储特定的数据库或表,请务必注意包含的值[**mysql转储**](mysqldump.html)包括所有交易的 GTID[`gtid_executed`](replication-options-gtids.html#sysvar_gtid_executed)在源服务器上设置,即使更改了数据库的抑制部分,或服务器上未包含在部分转储中的其他数据库。如果您只在目标服务器上重放一个部分转储文件,则额外的 GTID 不会对该服务器的未来操作造成任何问题。但是,如果您在目标服务器上重放包含相同 GTID 的第二个转储文件(例如,来自同一源服务器的另一个部分转储),则任何`SET @@GLOBAL.gtid_purged`第二个转储文件中的语句失败。为避免此问题,请设置[**mysql转储**](mysqldump.html)选项`--set-gtid-purge``离开`要么`已评论`在没有活动的情况下输出第二个转储文件`SET @@GLOBAL.gtid_purged`语句,或在重播转储文件之前手动删除该语句。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册