MySQL8-中文参考-七十五-

48 阅读1小时+

MySQL8 中文参考(七十五)

原文:docs.oracle.com/javase/tutorial/reallybigindex.html

原文:dev.mysql.com/doc/refman/8.0/en/innodb-memcached-porting-memcached.html

17.20.6.2 调整 memcached 应用以适配 InnoDB memcached 插件

在将现有的memcached应用程序调整为使用daemon_memcached插件时,请考虑 MySQL 和InnoDB表的这些方面:

  • 如果键值长于几个字节,最好在InnoDB表的主键上使用数值自增列,并在包含memcached键值的列上创建唯一的二级索引可能更有效。这是因为如果主键值按排序顺序添加(就像使用自增值一样),InnoDB在大规模插入时表现最佳。主键值包含在二级索引中,如果主键是长字符串值,则会占用不必要的空间。

  • 如果您使用memcached存储多种不同类别的信息,请考虑为每种数据类型设置单独的InnoDB表。在innodb_memcache.containers表中定义额外的表标识符,并使用@@*table_id*.*key*的表示法来存储和检索来自不同表的项目。物理上划分不同类型的信息允许您调整每个表的特性,以实现最佳的空间利用率、性能和可靠性。例如,您可以为保存博客文章的表启用压缩,但不为保存缩略图图像的表启用。您可能更频繁地备份一个表,因为它包含关键数据。您可能在经常用于生成报告的表上创建额外的二级索引。

  • 最好为与daemon_memcached插件一起使用的表定义一个稳定的表定义,并永久保留这些表。对innodb_memcache.containers表的更改将在下次查询innodb_memcache.containers表时生效。容器表中的条目在启动时被处理,并且在使用@@表示法请求未识别的表标识符(由containers.name定义)时会被查询。因此,只要使用相关的表标识符,新条目就会立即可见,但对现有条目的更改需要在生效之前重新启动服务器。

  • 当您使用默认的innodb_only缓存策略时,对add()set()incr()等的调用可能会成功,但仍会触发调试消息,如while expecting 'STORED', got unexpected response 'NOT_STORED。调试消息的出现是因为新值和更新值直接发送到InnoDB表,而不保存在内存缓存中,这是由于innodb_only缓存策略导致的。

原文:dev.mysql.com/doc/refman/8.0/en/innodb-memcached-tuning.html

17.20.6.3 调整 InnoDB memcached 插件性能

因为使用InnoDBmemcached结合涉及将所有数据写入磁盘,无论是立即还是稍后,所以原始性能预计会比单独使用memcached略慢。在使用InnoDBmemcached插件时,将memcached操作的调整目标集中在实现比等效 SQL 操作更好的性能上。

基准测试表明,使用memcached接口的查询和 DML 操作(插入、更新和删除)比传统 SQL 更快。DML 操作通常会看到更大的改进。因此,首先考虑调整写入密集型应用程序以使用memcached接口。还要考虑优先适应使用快速、轻量级机制但缺乏可靠性的写入密集型应用程序。

调整 SQL 查询

最适合简单GET请求的查询类型是具有单个子句或WHERE子句中一组AND条件的查询:

SQL:
SELECT col FROM tbl WHERE key = 'key_value';

memcached:
get key_value

SQL:
SELECT col FROM tbl WHERE col1 = val1 and col2 = val2 and col3 = val3;

memcached:
# Since you must always know these 3 values to look up the key,
# combine them into a unique string and use that as the key
# for all ADD, SET, and GET operations.
key_value = val1 + ":" + val2 + ":" + val3
get key_value

SQL:
SELECT 'key exists!' FROM tbl
  WHERE EXISTS (SELECT col1 FROM tbl WHERE KEY = 'key_value') LIMIT 1;

memcached:
# Test for existence of key by asking for its value and checking if the call succeeds,
# ignoring the value itself. For existence checking, you typically only store a very
# short value such as "1".
get key_value
利用系统内存

为了获得最佳性能,请在配置为典型数据库服务器的机器上部署daemon_memcached插件,其中大部分系统 RAM 专用于InnoDB缓冲池,通过innodb_buffer_pool_size配置选项。对于具有多千兆字节缓冲池的系统,考虑提高innodb_buffer_pool_instances的值,以获得大多数操作涉及已缓存在内存中的数据时的最大吞吐量。

减少冗余 I/O

InnoDB有许多设置选项,让您在发生崩溃时可以选择高可靠性,同时在高写入工作负载期间减少 I/O 开销。例如,考虑将innodb_doublewrite设置为0,将innodb_flush_log_at_trx_commit设置为2。使用不同的innodb_flush_method设置来衡量性能。

若要减少或调整表操作的 I/O 的其他方法,请参阅第 10.5.8 节,“优化 InnoDB 磁盘 I/O”。

减少事务开销

daemon_memcached_r_batch_sizedaemon_memcached_w_batch_size的默认值为 1,旨在获得最大的结果可靠性和存储或更新数据的安全性。

根据应用程序的类型,您可能会增加这两个设置中的一个或两个,以减少频繁提交操作的开销。在繁忙的系统上,您可能会增加daemon_memcached_r_batch_size的值,知道通过 SQL 对数据的更改可能不会立即对memcached可见(也就是说,直到处理了*Nget操作)。在处理每个写操作都必须可靠存储的数据时,将daemon_memcached_w_batch_size设置为1。在处理仅用于统计分析的大量更新时,可以增加该设置,其中在意外退出时丢失最后N*次更新是可以接受的风险。

例如,想象一个监视穿过繁忙桥梁的交通的系统,每天记录大约 10 万辆车辆的数据。如果应用程序计算不同类型的车辆以分析交通模式,将daemon_memcached_w_batch_size1更改为100可以将提交操作的 I/O 开销减少 99%。在发生故障时,最多会丢失 100 条记录,这可能是可以接受的误差范围。如果应用程序执行每辆车的自动收费,您将把daemon_memcached_w_batch_size设置为1,以确保每个收费记录立即保存到磁盘。

由于InnoDB在磁盘上组织memcached键值的方式,如果要创建大量键,则在应用程序中按键值对数据项进行排序并按排序顺序add它们可能比以任意顺序创建键更快。

memslap命令是常规memcached分发的一部分,但不包括在daemon_memcached插件中,可用于对不同配置进行基准测试。它还可用于生成样本键值对,以在您自己的基准测试中使用。

原文:dev.mysql.com/doc/refman/8.0/en/innodb-memcached-txn.html

17.20.6.4 控制 InnoDB memcached 插件的事务行为

与传统的memcached不同,daemon_memcached插件允许您控制通过addsetincr等调用生成的数据值的耐久性。默认情况下,通过memcached接口写入的数据会存储到磁盘,并且调用get会从磁盘返回最新的值。尽管默认行为并不提供最佳的原始性能,但与InnoDB表的 SQL 接口相比,仍然快速。

随着您使用daemon_memcached插件的经验增加,您可以考虑放宽非关键数据类的耐久性设置,以便在发生故障时可能会丢失一些更新的值,或者返回略有过时的数据。

提交频率

耐久性和原始性能之间的一个权衡是新数据和更改数据的提交频率。如果数据很关键,应立即提交,以便在意外退出或故障时安全。如果数据不那么关键,例如在意外退出后重置的计数器或您可以承受丢失的日志数据,您可能更喜欢更少的提交频率可用的更高原始吞吐量。

memcached操作在底层InnoDB表中插入、更新或删除数据时,如果daemon_memcached_w_batch_size=1,更改可能会立即提交到InnoDB表中,或者稍后一段时间(如果daemon_memcached_w_batch_size的值大于 1)。在任何情况下,更改都无法回滚。如果您增加daemon_memcached_w_batch_size的值以避免在繁忙时期产生高 I/O 开销,当工作负载减少时,提交可能变得不频繁。作为一项安全措施,后台线程会定期自动提交通过memcached API 进行的更改。这个间隔由innodb_api_bk_commit_interval配置选项控制,默认设置为5秒。

memcached操作在底层InnoDB表中插入或更新数据时,由于新值仍然保留在内存缓存中,即使尚未在 MySQL 端提交,其他memcached请求立即可以看到更改的数据。

事务隔离

当 memcached 操作(如 getincr)导致基础 InnoDB 表上的查询或 DML 操作时,您可以控制操作是否看到表中最新写入的数据,仅看到已提交的数据,或事务隔离级别的其他变化。使用 innodb_api_trx_level 配置选项来控制此功能。此选项指定的数字值对应于隔离级别,如 REPEATABLE READ。有关其他设置的信息,请参阅 innodb_api_trx_level 选项的描述。

严格的隔离级别确保您检索的数据不会被回滚或突然更改,导致后续查询返回不同的值。然而,严格的隔离级别需要更大的锁定开销,可能会导致等待。对于不使用长时间事务的 NoSQL 风格应用程序,通常可以使用默认隔离级别或切换到较不严格的隔禅级别。

禁用 memcached 的 DML 操作的行锁。

memcached 请求通过 daemon_memcached 插件导致对 InnoDB 表的查询或 DML 操作时,可以使用 innodb_api_disable_rowlock 选项来禁用行锁。默认情况下,innodb_api_disable_rowlock 设置为 OFF,这意味着 memcached 请求行锁用于 getset 操作。当 innodb_api_disable_rowlock 设置为 ON 时,memcached 请求表锁而不是行锁。

innodb_api_disable_rowlock 选项不是动态的。必须在启动时在 mysqld 命令行上指定,或在 MySQL 配置文件中输入。

允许或禁止 DDL。

默认情况下,可以在 daemon_memcached 插件使用的表上执行 DDL 操作,如 ALTER TABLE。为避免这些表用于高吞吐量应用程序时潜在的减速,启用 innodb_api_enable_mdl 来禁用这些表上的 DDL 操作。当通过 memcached 和 SQL 访问相同的表时,此选项不太合适,因为它会阻止对表进行 CREATE INDEX 语句的操作,这对运行报表查询可能很重要。

将数据存储在磁盘、内存中,或两者兼而有之。

innodb_memcache.cache_policies 表指定是否将通过 memcached 接口写入的数据存储到磁盘(innodb_only,默认);仅存��在内存中,如传统的 memcachedcache_only);或两者兼而有之(caching)。

使用caching设置,如果memcached在内存中找不到一个键,它会在InnoDB表中搜索该值。在caching设置下返回的get调用的值可能已经过时,如果这些值在InnoDB表中更新但尚未从内存缓存中过期。

缓存策略可以独立设置为getset(包括incrdecr)、deleteflush操作。

例如,您可以允许getset操作同时查询或更新表和memcached内存缓存(使用caching设置),同时使deleteflush或两者仅在内存副本上操作(使用cache_only设置)。这样,删除或刷新项目仅会使项目从缓存中过期,并且下次请求项目时将从InnoDB表中返回最新值。

mysql> SELECT * FROM innodb_memcache.cache_policies;
+--------------+-------------+-------------+---------------+--------------+
| policy_name  | get_policy  | set_policy  | delete_policy | flush_policy |
+--------------+-------------+-------------+---------------+--------------+
| cache_policy | innodb_only | innodb_only | innodb_only   | innodb_only  |
+--------------+-------------+-------------+---------------+--------------+

mysql> UPDATE innodb_memcache.cache_policies SET set_policy = 'caching'
       WHERE policy_name = 'cache_policy';

innodb_memcache.cache_policies的值只在启动时读取。在更改此表中的值后,卸载并重新安装daemon_memcached插件以确保更改生效。

mysql> UNINSTALL PLUGIN daemon_memcached;

mysql> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";

原文:dev.mysql.com/doc/refman/8.0/en/innodb-memcached-dml.html

17.20.6.5 将 DML 语句调整为 memcached 操作

基准测试表明,daemon_memcached 插件加速了 DML 操作(插入、更新和删除)比加速查询更多。因此,考虑将初始开发工作重点放在写入密集型且 I/O 限制的应用程序上,并寻找机会在新的写入密集型应用程序中使用带有 daemon_memcached 插件的 MySQL。

单行 DML 语句是最容易转换为 memcached 操作的语句类型。INSERT 变为 addUPDATE 变为 setincrdecr,而 DELETE 变为 delete。这些操作通过 memcached 接口发出时,保证只影响一行,因为 key 在表内是唯一的。

在以下的 SQL 示例中,t1 指的是基于 innodb_memcache.containers 表中配置的 memcached 操作所使用的表。key 指的是列在 key_columns 下列出的列,val 指的是列在 value_columns 下列出的列。

INSERT INTO t1 (key,val) VALUES (*some_key*,*some_value*);
SELECT val FROM t1 WHERE key = *some_key*;
UPDATE t1 SET val = *new_value* WHERE key = *some_key*;
UPDATE t1 SET val = val + x WHERE key = *some_key*;
DELETE FROM t1 WHERE key = *some_key*;

下面的 TRUNCATE TABLEDELETE 语句,用于从表中删除所有行,对应于 flush_all 操作,其中 t1 被配置为 memcached 操作的表,就像前面的示例中一样。

TRUNCATE TABLE t1;
DELETE FROM t1;

原文:dev.mysql.com/doc/refman/8.0/en/innodb-memcached-ddl.html

17.20.6.6 在底层 InnoDB 表上执行 DML 和 DDL 语句

您可以通过标准 SQL 接口访问底层的InnoDB表(默认为test.demo_test)。但是,存在一些限制:

  • 当查询通过memcached接口访问的表时,请记住memcached操作可以配置为定期提交,而不是在每次写操作后立即提交。此行为由daemon_memcached_w_batch_size选项控制。如果此选项设置为大于1的值,请使用READ UNCOMMITTED查询以查找刚刚插入的行。

    mysql> SET SESSSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    
    mysql> SELECT * FROM demo_test;
    +------+------+------+------+-----------+------+------+------+------+------+------+
    | cx   | cy   | c1   | cz   | c2        | ca   | CB   | c3   | cu   | c4   | C5   |
    +------+------+------+------+-----------+------+------+------+------+------+------+
    | NULL | NULL | a11  | NULL | 123456789 | NULL | NULL |   10 | NULL |    3 | NULL |
    +------+------+------+------+-----------+------+------+------+------+------+------+
    
  • 当使用 SQL 修改通过memcached接口访问的表时,您可以配置memcached操作定期启动新事务,而不是每次读操作都启动事务。此行为由daemon_memcached_r_batch_size选项控制。如果此选项设置为大于1的值,则使用 SQL 对表进行的更改不会立即对memcached操作可见。

  • 对于事务中的所有操作,InnoDB表都会被 IS(意向共享)或 IX(意向排他)锁定。如果您将daemon_memcached_r_batch_sizedaemon_memcached_w_batch_size从默认值1大幅增加,那么表在每个操作之间很可能被锁定,从而阻止对表的 DDL 语句的执行。

17.20.7 InnoDB memcached 插件和复制

原文:dev.mysql.com/doc/refman/8.0/en/innodb-memcached-replication.html

因为daemon_memcached插件支持 MySQL 的二进制日志,源服务器通过memcached接口可以进行备份复制,平衡读取工作负载,并实现高可用性。所有memcached命令都支持二进制日志记录。

您无需在副本服务器上设置daemon_memcached插件。此配置的主要优势是增加源端的写入吞吐量。复制机制的速度不受影响。

以下各节显示了在使用daemon_memcached插件进行 MySQL 复制时如何使用二进制日志功能。假定您已完成第 17.20.3 节“设置 InnoDB memcached 插件”中描述的设置。

启用 InnoDB memcached 二进制日志

  1. 要在 MySQL 的二进制日志中使用daemon_memcached插件,请在源服务器上启用innodb_api_enable_binlog配置选项。此选项只能在服务器启动时设置。您还必须在源服务器上使用--log-bin选项启用 MySQL 的二进制日志。您可以将这些选项添加到 MySQL 配置文件中,或者在mysqld命令行中添加。

    mysqld ... --log-bin -–innodb_api_enable_binlog=1
    
  2. 配置源服务器和副本服务器,如第 19.1.2 节“基于二进制日志文件位置的复制设置”中所述。

  3. 使用mysqldump创建源数据快照,并将快照同步到副本服务器。

    source $> mysqldump --all-databases --lock-all-tables > dbdump.db
    replica $> mysql < dbdump.db
    
  4. 在源服务器上,执行SHOW MASTER STATUS以获取源二进制日志坐标。

    mysql> SHOW MASTER STATUS;
    
  5. 在副本服务器上,使用CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(MySQL 8.0.23 之前)设置使用源二进制日志坐标的副本服务器。

    mysql> CHANGE MASTER TO
           MASTER_HOST='localhost',
           MASTER_USER='root',
           MASTER_PASSWORD='',
           MASTER_PORT = 13000,
           MASTER_LOG_FILE='0.000001,
           MASTER_LOG_POS=114;
    
    Or from MySQL 8.0.23:
    mysql> CHANGE REPLICATION SOURCE TO
           SOURCE_HOST='localhost',
           SOURCE_USER='root',
           SOURCE_PASSWORD='',
           SOURCE_PORT = 13000,
           SOURCE_LOG_FILE='0.000001,
           SOURCE_LOG_POS=114;
    
  6. 启动副本。

    mysql> START SLAVE;
    Or from MySQL 8.0.22:
    mysql> START REPLICA;
    

    如果错误日志输出类似于以下内容,则副本已准备好进行复制。

    2013-09-24T13:04:38.639684Z 49 [Note] Replication I/O thread: connected to
    source 'root@localhost:13000', replication started in log '0.000001'
    at position 114
    

测试 InnoDB memcached 复制配置

该示例演示了如何使用memcached和 telnet 测试InnoDB memcached复制配置,以插入、更新和删除数据。使用 MySQL 客户端验证源服务器和副本服务器上的结果。

该示例使用了innodb_memcached_config.sql配置脚本在daemon_memcached插件的初始设置期间创建的demo_test表。demo_test表包含一个示例记录。

  1. 使用set命令插入一个具有键test1、标志值10、过期值0、cas 值 1 和值t1的记录。

    telnet 127.0.0.1 11211
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    set test1 10 0 1
    t1
    STORED
    
  2. 在源服务器上,检查记录是否插入到demo_test表中。假设demo_test表之前未被修改,应该有两条记录。一个具有键AA的示例记录,以及刚刚插入的具有键test1的记录。c1列映射到键,c2列映射到值,c3列映射到标志值,c4列映射到 cas 值,c5列映射到过期时间。过期时间设置为 0,因为未使用。

    mysql> SELECT * FROM test.demo_test;
    +-------+--------------+------+------+------+
    | c1    | c2           | c3   | c4   | c5   |
    +-------+--------------+------+------+------+
    | AA    | HELLO, HELLO |    8 |    0 |    0 |
    | test1 | t1           |   10 |    1 |    0 |
    +-------+--------------+------+------+------+
    
  3. 检查验证相同记录是否被复制到副本服务器。

    mysql> SELECT * FROM test.demo_test;
    +-------+--------------+------+------+------+
    | c1    | c2           | c3   | c4   | c5   |
    +-------+--------------+------+------+------+
    | AA    | HELLO, HELLO |    8 |    0 |    0 |
    | test1 | t1           |   10 |    1 |    0 |
    +-------+--------------+------+------+------+
    
  4. 使用set命令将键更新为new的值。

    telnet 127.0.0.1 11211
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    set test1 10 0 2
    new
    STORED
    

    更新被复制到副本服务器(注意cas值也被更新)。

    mysql> SELECT * FROM test.demo_test;
    +-------+--------------+------+------+------+
    | c1    | c2           | c3   | c4   | c5   |
    +-------+--------------+------+------+------+
    | AA    | HELLO, HELLO |    8 |    0 |    0 |
    | test1 | new          |   10 |    2 |    0 |
    +-------+--------------+------+------+------+
    
  5. 使用delete命令删除test1记录。

    telnet 127.0.0.1 11211
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    delete test1
    DELETED
    

    delete操作被复制到副本时,副本上的test1记录也被删除。

    mysql> SELECT * FROM test.demo_test;
    +----+--------------+------+------+------+
    | c1 | c2           | c3   | c4   | c5   |
    +----+--------------+------+------+------+
    | AA | HELLO, HELLO |    8 |    0 |    0 |
    +----+--------------+------+------+------+
    
  6. 使用flush_all命令从表中删除所有行。

    telnet 127.0.0.1 11211
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    flush_all
    OK
    
    mysql> SELECT * FROM test.demo_test;
    Empty set (0.00 sec)
    
  7. 使用 telnet 连接到源服务器并输入两条新记录。

    telnet 127.0.0.1 11211
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'
    set test2 10 0 4
    again
    STORED
    set test3 10 0 5
    again1
    STORED
    
  8. 确认两条记录是否被复制到副本服务器。

    mysql> SELECT * FROM test.demo_test;
    +-------+--------------+------+------+------+
    | c1    | c2           | c3   | c4   | c5   |
    +-------+--------------+------+------+------+
    | test2 | again        |   10 |    4 |    0 |
    | test3 | again1       |   10 |    5 |    0 |
    +-------+--------------+------+------+------+
    
  9. 使用flush_all命令从表中删除所有行。

    telnet 127.0.0.1 11211
    Trying 127.0.0.1...
    Connected to 127.0.0.1.
    Escape character is '^]'.
    flush_all
    OK
    
  10. 检查确保flush_all操作在副本服务器上被复制。

    mysql> SELECT * FROM test.demo_test;
    Empty set (0.00 sec)
    

InnoDB memcached二进制日志注释

二进制日志格式:

  • 大多数memcached操作都映射到 DML 语句(类似于插入、删除、更新)。由于 MySQL 服务器没有实际的 SQL 语句在处理,所有memcached命令(除了flush_all)使用基于行的复制(RBR)日志记录,这与任何服务器binlog_format设置无关。

  • memcachedflush_all命令映射到 MySQL 5.7 及更早版本的TRUNCATE TABLE命令。由于 DDL 命令只能使用基于语句的日志记录,flush_all命令通过发送TRUNCATE TABLE语句来复制。在 MySQL 8.0 及更高版本中,flush_all映射到DELETE,但仍通过发送TRUNCATE TABLE语句来复制。

事务:

  • 事务的概念通常不是memcached应用的一部分。为了性能考虑,daemon_memcached_r_batch_sizedaemon_memcached_w_batch_size用于控制读取和写入事务的批处理大小。这些设置不影响复制。在底层InnoDB表上的每个 SQL 操作在成功完成后被复制。

  • daemon_memcached_w_batch_size的默认值为1,这意味着每个memcached写操作立即提交。这个默认设置会产生一定的性能开销,以避免在源服务器和副本服务器上可见的数据不一致。复制的记录在副本服务器上始终立即可用。如果将daemon_memcached_w_batch_size设置为大于1的值,则通过memcached插入或更新的记录在源服务器上不会立即可见;在提交之前在源服务器上查看记录,请发出SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

17.20.8 InnoDB memcached 插件内部

原文:dev.mysql.com/doc/refman/8.0/en/innodb-memcached-internals.html

InnoDB memcached 插件的 InnoDB API

InnoDB memcached引擎通过InnoDB API 访问InnoDB,其中大部分直接采用自嵌入式InnoDBInnoDB API 函数作为回调函数传递给InnoDB memcached引擎。 InnoDB API 函数直接访问InnoDB表,大多数是 DML 操作,除了TRUNCATE TABLE

memcached命令通过InnoDB memcached API 实现。以下表格概述了如何将memcached命令映射到 DML 或 DDL 操作。

表 17.27 memcached 命令及相关的 DML 或 DDL 操作

memcached 命令DML 或 DDL 操作
get读取/获取命令
set一次搜索,然后是INSERTUPDATE(取决于键是否存在)
add一次搜索,然后是INSERTUPDATE
replace一次搜索,然后是UPDATE
append一次搜索,然后是UPDATE(在UPDATE之前将数据追加到结果中)
prepend一次搜索,然后是UPDATE(在UPDATE之前将数据前置到结果中)
incr一次搜索,然后是UPDATE
decr一次搜索,然后是UPDATE
delete一次搜索,然后是DELETE
flush_allTRUNCATE TABLE(DDL)
memcached 命令DML 或 DDL 操作

InnoDB memcached 插件配置表

本节描述了daemon_memcached插件使用的配置表。 cache_policies表,config_options表和containers表由innodb_memcached_config.sql配置脚本在innodb_memcache数据库中创建。

mysql> USE innodb_memcache;
Database changed
mysql> SHOW TABLES;
+---------------------------+
| Tables_in_innodb_memcache |
+---------------------------+
| cache_policies            |
| config_options            |
| containers                |
+---------------------------+

cache_policies 表

cache_policies表定义了InnoDB memcached安装的缓存策略。您可以在单个缓存策略中为getsetdeleteflush操作指定单独的策略。所有操作的默认设置为innodb_only

  • innodb_only: 使用InnoDB作为数据存储。

  • cache_only: 使用memcached引擎作为数据存储。

  • caching: 同时使用InnoDBmemcached引擎作为数据存储。在这种情况下,如果memcached在内存中找不到键,则会在InnoDB表中搜索该值。

  • disable: 禁用缓存。

表 17.28 cache_policies 列

描述
policy_name缓存策略的名称。默认缓存策略名称为cache_policy
get_policyget 操作的缓存策略。有效值为innodb_onlycache_onlycachingdisabled。默认设置为innodb_only
set_policyset 操作的缓存策略。有效值为innodb_onlycache_onlycachingdisabled。默认设置为innodb_only
delete_policy删除操作的缓存策略。有效值为innodb_onlycache_onlycachingdisabled。默认设置为innodb_only
flush_policy刷新操作的缓存策略。有效值为innodb_onlycache_onlycachingdisabled。默认设置为innodb_only

config_options 表

config_options表存储可以使用 SQL 在运行时更改的与memcached相关的设置。支持的配置选项是separatortable_map_delimiter

表 17.29 config_options 列

描述

| Name | memcached相关配置选项的名称。config_options表支持以下配置选项:

  • separator:用于将长字符串的值分隔为单独的值的分隔符,当定义了多个value_columns时。默认情况下,分隔符是&#124;字符。例如,如果您将col1, col2定义为值列,并将&#124;定义为分隔符,则可以发出以下memcached命令将值分别插入到col1col2中:

    set keyx 10 0 19
    valuecolx&#124;valuecoly
    

    valuecol1x存储在col1中,valuecoly存储在col2中。

  • table_map_delimiter:在使用@@符号访问特定表中的键时,用于分隔模式名称和表名称的字符。例如,@@t1.some_key@@t2.some_key具有相同的键值,但存储在不同的表中。

|

Value分配给与memcached相关的配置选项的值。

containers 表

containers表是三个配置表中最重要的一个。用于存储memcached值的每个InnoDB表必须在containers表中有一个条目。该条目提供了InnoDB表列和容器表列之间的映射,这对于memcachedInnoDB表一起工作是必需的。

containers表包含test.demo_test表的默认条目,该表是由innodb_memcached_config.sql配置脚本创建的。要使用daemon_memcached插件与自己的InnoDB表,必须在containers表中创建一个条目。

表 17.30 containers 列

描述
name分配给容器的名称。如果没有使用@@符号按名称请求InnoDB表,则daemon_memcached插件将使用具有containers.name值为defaultInnoDB表。如果没有这样的条目,则按name(升序)字母顺序排列的containers表中的第一个条目确定默认的InnoDB表。
db_schema包含InnoDB表的数据库的名称。这是一个必填值。
db_table存储memcached值的InnoDB表的名称。这是一个必填值。
key_columns包含memcached操作查找键值的InnoDB表中的列。这是一个必填值。
value_columns存储memcached数据的InnoDB表列(一个或多个)。可以使用innodb_memcached.config_options表中指定的分隔符字符指定多个列。默认情况下,分隔符是一个竖线字符(“”)。要指定多个列,请使用定义的分隔符字符分隔它们。例如:`col1col2col3`。这是一个必需的值。
flags用作memcached标志(与主值一起存储和检索的用户定义的数值)的InnoDB表列。如果memcached值映射到多个列,则标志值可以用作某些操作(如incrprepend)的列指定符,以便在指定列上执行操作。例如,如果你已将value_columns映射到三个InnoDB表列,并且只想要增量操作在一个列上执行,请使用flags列指定该列。如果你不使用flags列,请设置值为0以指示未使用。
cas_column存储比较和交换(cas)值的InnoDB表列。cas_column值与memcached如何将请求哈希到不同服务器并在内存中缓存数据有关。由于InnoDB memcached插件与单个memcached守护程序紧密集成,并且内存缓存机制由 MySQL 和 InnoDB 缓冲池处理,因此很少需要此列。如果你不使用此列,请设置值为0以指示未使用。
expire_time_column存储过期值的InnoDB表列。expire_time_column值与memcached如何将请求哈希到不同服务器并在内存中缓存数据有关。由于InnoDB memcached插件与单个memcached守护程序紧密集成,并且内存缓存机制由 MySQL 和 InnoDB 缓冲池处理,因此很少需要此列。如果你不使用此列,请设置值为0以指示未使用。最大过期时间定义为INT_MAX32或 2147483647 秒(约 68 年)。
unique_idx_name_on_key索引在关键列上的名称。它必须是一个唯一索引。它可以是主键或次要索引。最好使用InnoDB表的主键。使用主键可以避免在使用次要索引时进行查找。你不能为memcached查找创建一个覆盖索引;如果你尝试在键和值列上定义一个复合次要索引,InnoDB会返回错误。
容器表列约束
  • 您必须为db_schemadb_namekey_columnsvalue_columnsunique_idx_name_on_key提供值。如果未使用,将flagscas_columnexpire_time_column设置为0。如果未这样做,可能会导致设置失败。

  • key_columns: memcached键的最大限制为 250 个字符,由memcached强制执行。映射键必须是非空的CHARVARCHAR类型。

  • value_columns: 必须映射到CHARVARCHARBLOB列。没有长度限制,值可以为 NULL。

  • cas_column: cas值是 64 位整数。必须映射到至少 8 字节的BIGINT。如果您不使用此列,请设置值为0以指示未使用。

  • expiration_time_column: 必须映射到至少 4 字节的INTEGER。过期时间定义为 Unix 时间的 32 位整数(自 1970 年 1 月 1 日以来的秒数作为 32 位值),或从当前时间开始的秒数。对于后者,秒数不得超过 606024*30(30 天内的秒数)。如果客户端发送的数字较大,则服务器将其视为真实的 Unix 时间值,而不是从当前时间的偏移量。如果不使用此列,请设置值为0以指示未使用。

  • flags: 必须映射到至少 32 位的INTEGER,可以为 NULL。如果您不使用此列,请设置值为0以指示未使用。

在插件加载时执行预检查以强制执行列约束。如果发现不匹配,插件将不加载。

多值列映射
  • 在插件初始化期间,当InnoDB memcached配置为containers表中定义的信息时,将验证containers.value_columns中定义的每个映射列与映射的InnoDB表。如果映射了多个InnoDB表列,则会检查以确保每个列存在且为正确类型。

  • 在运行时,对于memcached插入操作,如果有比映射列数更多的分隔值,则仅取映射值的数量。例如,如果有六个映射列,并且提供了七个分隔值,则仅取前六个分隔值。第七个分隔值将被忽略。

  • 如果分隔值少于映射的列数,未填充的列将被设置为 NULL。如果无法将未填充的列设置为 NULL,则插入操作将失败。

  • 如果一个表的列数多于映射值,额外的列不会影响结果。

demo_test 示例表

innodb_memcached_config.sql 配置脚本在 test 数据库中创建了一个 demo_test 表,可用于在安装InnoDB memcached 插件后立即验证安装。

innodb_memcached_config.sql 配置脚本还在 innodb_memcache.containers 表中为 demo_test 表创建了一个条目。

mysql> SELECT * FROM innodb_memcache.containers\G
*************************** 1\. row ***************************
                  name: aaa
             db_schema: test
              db_table: demo_test
           key_columns: c1
         value_columns: c2
                 flags: c3
            cas_column: c4
    expire_time_column: c5
unique_idx_name_on_key: PRIMARY 
mysql> SELECT * FROM test.demo_test;
+----+------------------+------+------+------+
| c1 | c2               | c3   | c4   | c5   |
+----+------------------+------+------+------+
| AA | HELLO, HELLO     |    8 |    0 |    0 |
+----+------------------+------+------+------+

17.20.9 解决 InnoDB memcached 插件问题

原文:dev.mysql.com/doc/refman/8.0/en/innodb-memcached-troubleshoot.html

本节描述了在使用InnoDB memcached插件时可能遇到的问题。

  • 如果在 MySQL 错误日志中遇到以下错误,则服务器可能无法启动:

    设置打开文件数的限制失败。尝试以 root 用户身份运行或请求较小的 maxconns 值。

    错误消息来自memcached守护程序。一个解决方案是提高操作系统打开文件数的限制。检查和增加打开文件限制的命令因操作系统而异。以下示例显示了 Linux 和 macOS 的命令:

    # Linux
    $> ulimit -n
    1024
    $> ulimit -n 4096
    $> ulimit -n
    4096
    
    # macOS
    $> ulimit -n
    256
    $> ulimit -n 4096
    $> ulimit -n
    4096
    

    另一种解决方案是减少允许memcached守护程序的并发连接数。为此,在 MySQL 配置文件中的daemon_memcached_option配置参数中编码-c memcached选项。-c选项的默认值为 1024。

    [mysqld]
    ...
    loose-daemon_memcached_option='-c 64'
    
  • 要解决memcached守护程序无法存储或检索InnoDB表数据的问题,请在 MySQL 配置文件的daemon_memcached_option配置参数中编码-vvv memcached选项。检查 MySQL 错误日志以获取与memcached操作相关的调试输出。

    [mysqld]
    ...
    loose-daemon_memcached_option='-vvv'
    
  • 如果指定用于保存memcached值的列的数据类型错误,例如数字类型而不是字符串类型,则尝试存储键值对将失败,而不会显示特定的错误代码或消息。

  • 如果daemon_memcached插件导致 MySQL 服务器启动问题,您可以在故障排除时通过在 MySQL 配置文件的[mysqld]组下添加以下行来临时禁用daemon_memcached插件:

    daemon_memcached=OFF
    

    例如,如果在运行innodb_memcached_config.sql配置脚本设置必要的数据库和表之前运行INSTALL PLUGIN语句,则服务器可能会意外退出并无法启动。如果在innodb_memcache.containers表中错误配置条目,服务器也可能无法启动。

    要卸载 MySQL 实例的memcached插件,请发出以下语句:

    mysql> UNINSTALL PLUGIN daemon_memcached;
    
  • 如果在同一台机器上运行多个 MySQL 实例,并且每个实例都启用了daemon_memcached插件,请使用daemon_memcached_option配置参数为每个daemon_memcached插件指定一个独特的memcached端口。

  • 如果一个 SQL 语句无法找到InnoDB表或在表中找不到数据,但memcached API 调用检索到了预期的数据,那么可能是在innodb_memcache.containers表中缺少了InnoDB表的条目,或者您可能没有通过使用@@*table_id*标记发出getset请求来切换到正确的InnoDB表。如果您在之后没有重新启动 MySQL 服务器的情况下更改了innodb_memcache.containers表中的现有条目,也可能会出现这个问题。自由形式的存储机制足够灵活,即使守护程序正在使用将值存储在单列中的test.demo_test表,您对存储或检索多列值(如col1|col2|col3)的请求可能仍然有效。

  • 在为daemon_memcached插件定义自己的InnoDB表时,如果表中的列被定义为NOT NULL,请确保在将表的记录插入innodb_memcache.containers表时为NOT NULL列提供值。如果innodb_memcache.containers记录的INSERT语句包含的分隔值少于映射列的数量,未填充的列将被设置为NULL。尝试将NULL值插入NOT NULL列会导致INSERT失败,这可能只有在重新初始化daemon_memcached插件以应用对innodb_memcache.containers表的更改后才会显现。

  • 如果innodb_memcached.containers表的cas_columnexpire_time_column字段设置为NULL,则在尝试加载memcached插件时会返回以下错误:

    InnoDB_Memcached: column 6 in the entry for config table 'containers' in
    database 'innodb_memcache' has an invalid NULL value.
    

    memcached插件拒绝在cas_columnexpire_time_column列中使用NULL。当这些列未使用时,将这些列的值设置为0

  • 随着memcached键和值的长度增加,您可能会遇到大小和长度限制。

    • 当键超过 250 字节时,memcached操作会返回错误。这是memcached中当前的固定限制。

    • 如果值的大小超过 768 字节、3072 字节或半个innodb_page_size值,可能会遇到InnoDB表限制。这些限制主要适用于如果您打算在值列上创建索引以使用 SQL 运行生成报表的查询时。有关详细信息,请参见第 17.22 节,“InnoDB 限制”。

    • 键-值组合的最大大小为 1 MB。

  • 如果在不同版本的 MySQL 服务器之间共享配置文件,并且使用daemon_memcached插件的最新配置选项可能会导致在旧的 MySQL 版本上启动错误。为避免兼容性问题,请在选项名称前使用loose前缀。例如,使用loose-daemon_memcached_option='-c 64'而不是daemon_memcached_option='-c 64'

  • 没有限制或检查来验证字符集设置。memcached以字节形式存储和检索键和值,因此不受字符集的影响。但是,您必须确保memcached客户端和 MySQL 表使用相同的字符集。

  • memcached连接被阻止访问包含索引虚拟列的表。访问索引虚拟列需要回调到服务器,但memcached连接无法访问服务器代码。

17.21 InnoDB 故障排除

原文:dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting.html

17.21.1 故障排除 InnoDB I/O 问题

17.21.2 故障排除恢复失败

17.21.3 强制 InnoDB 恢复

17.21.4 故障排除 InnoDB 数据字典操作

17.21.5 InnoDB 错误处理

以下一般准则适用于故障排除 InnoDB 问题:

  • 当操作失败或怀疑存在 bug 时,请查看 MySQL 服务器错误日志(参见 7.4.2 “错误日志”)。服务器错误消息参考 提供了一些常见的 InnoDB 特定错误的故障排除信息。

  • 如果故障与死锁有关,请启用 innodb_print_all_deadlocks 选项运行,以便将每个死锁的详细信息打印到 MySQL 服务器错误日志中。有关死锁的信息,请参见 17.7.5 “InnoDB 中的死锁”。

  • 如果问题与 InnoDB 数据字典有关,请参见 17.21.4 “故障排除 InnoDB 数据字典操作”。

  • 在故障排除时,通常最好从命令提示符下运行 MySQL 服务器,而不是通过 mysqld_safe 或作为 Windows 服务运行。然后您可以看到 mysqld 打印到控制台的内容,从而更好地了解发生了什么。在 Windows 上,使用 --console 选项启动 mysqld,将输出定向到控制台窗口。

  • 启用 InnoDB Monitors 以获取有关问题的信息(参见 17.17 “InnoDB Monitors”)。如果问题与性能有关,或者服务器似乎挂起,您应该启用标准 Monitor 以打印有关 InnoDB 内部状态的信息。如果问题与锁有关,请启用 Lock Monitor。如果问题与表创建、表空间或数据字典操作有关,请参考 InnoDB 信息模式系统表 来检查 InnoDB 内部数据字典的内容。

    InnoDB 在以下情况下临时启用标准 InnoDB Monitor 输出:

    • 一个长时间的信号量等待

    • InnoDB在缓冲池中找不到空闲块。

    • 缓冲池超过67%被锁堆或自适应哈希索引占用。

  • 如果你怀疑某个表损坏,运行CHECK TABLE命令检查该表。

17.21.1 解决 InnoDB I/O 问题

原文:dev.mysql.com/doc/refman/8.0/en/error-creating-innodb.html

处理InnoDB I/O 问题的故障排除步骤取决于问题发生的时间:MySQL 服务器启动期间,或者在正常操作期间,当 DML 或 DDL 语句由于文件系统级别的问题而失败时。

初始化问题

如果InnoDB在尝试初始化其表空间或日志文件时出现问题,请删除InnoDB创建的所有文件:所有ibdata文件和所有重做日志文件(MySQL 8.0.30 及更高版本中的#ib_redo*N*文件或早期版本中的ib_logfile文件)。如果您创建了任何InnoDB表,还要从 MySQL 数据库目录中删除任何.ibd文件。然后尝试重新初始化InnoDB。为了进行最简单的故障排除,请从命令提示符启动 MySQL 服务器,以便查看发生了什么。

运行时问题

如果InnoDB在文件操作期间打印操作系统错误,通常问题有以下解决方案之一:

  • 确保InnoDB数据文件目录和InnoDB日志目录存在。

  • 确保mysqld有权限在这些目录中创建文件。

  • 确保mysqld可以读取正确的my.cnfmy.ini选项文件,以便它以您指定的选项启动。

  • 确保磁盘未满,并且未超出任何磁盘配额。

  • 确保您为子目录和数据文件指定的名称不冲突。

  • 仔细检查innodb_data_home_dirinnodb_data_file_path值的语法。特别是,在innodb_data_file_path选项中的任何MAX值都是一个硬限制,超过该限制会导致致命错误。

17.21.2 故障恢复失败的故障排除

原文:dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting-recovery.html

从 MySQL 8.0.26 开始,在重做日志恢复完成并且数据字典动态元数据(srv_dict_metadata)转移到数据字典表(dict_table_t)对象之前,不允许进行检查点和推进检查点 LSN。如果在恢复期间或恢复后(但在数据字典动态元数据转移到数据字典表对象之前)重做日志空间不足,可能需要进行innodb_force_recovery重启,至少从SRV_FORCE_NO_IBUF_MERGE设置开始,或者在失败的情况下,从SRV_FORCE_NO_LOG_REDO设置开始。如果在这种情况下innodb_force_recovery重启失败,可能需要从备份中恢复。(Bug #32200595)

17.21.3 强制 InnoDB 恢复

原文:dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html

为了调查数据库页面损坏,您可以使用 SELECT ... INTO OUTFILE 从数据库中导出表。通常,以这种方式获得的大部分数据是完整的。严重的损坏可能会导致 SELECT * FROM *tbl_name* 语句或 InnoDB 后台操作意外退出或断言,甚至导致 InnoDB 回滚恢复崩溃。在这种情况下,您可以使用 innodb_force_recovery 选项来强制 InnoDB 存储引擎启动,同时阻止后台操作运行,以便您可以导出表。例如,您可以在重新启动服务器之前将以下行添加到您的选项文件的 [mysqld] 部分中:

[mysqld]
innodb_force_recovery = 1

有关使用选项文件的信息,请参见 Section 6.2.2.2, “Using Option Files”。

警告

仅在紧急情况下将 innodb_force_recovery 设置为大于 0 的值,以便您可以启动 InnoDB 并导出表。在这样做之前,请确保您有数据库的备份副本,以防需要重新创建它。值为 4 或更大可能会永久损坏数据文件。仅在成功在数据库的单独物理副本上测试设置后,才在生产服务器实例上使用大于 4 的 innodb_force_recovery 设置。在强制 InnoDB 恢复时,您应始终从 innodb_force_recovery=1 开始,并根据需要逐渐增加值。

innodb_force_recovery 默认为 0(正常启动,无需强制恢复)。innodb_force_recovery 允许的非零值为 1 到 6。较大的值包含较小值的功能。例如,值为 3 包含值为 1 和 2 的所有功能。

如果您能够使用值为 3 或更低的 innodb_force_recovery 导出表,那么您相对安全,只有一些损坏的单个页面上的数据丢失。值为 4 或更大被认为是危险的,因为数据文件可能会永久损坏。值为 6 被认为是极端的,因为数据库页面处于过时状态,这反过来可能会在 B 树 和其他数据库结构中引入更多损坏。

作为安全措施,当innodb_force_recovery大于 0 时,InnoDB会阻止INSERTUPDATEDELETE操作。设置为 4 或更高的innodb_force_recovery值会将InnoDB置于只读模式。

  • 1 (SRV_FORCE_IGNORE_CORRUPT)

    让服务器即使检测到损坏的页面也能继续运行。尝试使SELECT * FROM * tbl_name *跳过损坏的索引记录和页面,有助于导出表格。

  • 2 (SRV_FORCE_NO_BACKGROUND)

    阻止主线程和任何清理线程运行。如果在清理操作期间发生意外退出,此恢复值将阻止它。

  • 3 (SRV_FORCE_NO_TRX_UNDO)

    在崩溃恢复后不运行事务回滚。

  • 4 (SRV_FORCE_NO_IBUF_MERGE)

    阻止插入缓冲区合并操作。如果这些操作可能导致崩溃,则不执行。不计算表的统计信息。这个值可能会永久损坏数据文件。使用此值后,准备好删除并重新创建所有辅助索引。将InnoDB设置为只读。

  • 5 (SRV_FORCE_NO_UNDO_LOG_SCAN)

    在启动数据库时不查看撤销日志:InnoDB将即使是不完整的事务也视为已提交。这个值可能会永久损坏数据文件。将InnoDB设置为只读。

  • 6 (SRV_FORCE_NO_LOG_REDO)

    在恢复过程中不执行重做日志的前进。这个值可能会永久损坏数据文件。将数据库页面留在过时状态,这可能会导致 B 树和其他数据库结构出现更多损坏。将InnoDB设置为只读。

您可以从表中SELECT以导出它们。当innodb_force_recovery值为 3 或更低时,可以DROPCREATE表。当innodb_force_recovery值大于 3 时,也支持DROP TABLE。当innodb_force_recovery值大于 4 时,不允许DROP TABLE

如果您知道某个表在回滚时导致意外退出,您可以将其删除。如果遇到由于失败的大规模导入或ALTER TABLE导致的无限回滚,您可以终止mysqld进程,并将innodb_force_recovery设置为3,以在没有回滚的情况下启动数据库,然后DROP掉导致无限回滚的表。

如果表数据中的损坏阻止您转储整个表内容,带有ORDER BY *primary_key* DESC子句的查询可能能够转储受损部分之后的表部分。

如果需要较高的innodb_force_recovery值才能启动InnoDB,可能存在损坏的数据结构,可能导致复杂查询(包含WHEREORDER BY或其他子句的查询)失败。在这种情况下,您可能只能运行基本的SELECT * FROM t查询。

17.21.4 InnoDB 数据字典操作故障排除

原文:dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting-datadict.html

表定义信息存储在 InnoDB 数据字典中。如果移动数据文件,字典数据可能变得不一致。

如果数据字典损坏或一致性问题阻止您启动InnoDB,请参阅第 17.21.3 节,“强制 InnoDB 恢复”以获取有关手动恢复的信息。

无法打开数据文件

启用innodb_file_per_table(默认情况下),如果缺少 file-per-table 表空间文件(.ibd文件),则可能在启动时出现以下消息:

[ERROR] InnoDB: Operating system error number 2 in a file operation.
[ERROR] InnoDB: The error means the system cannot find the path specified.
[ERROR] InnoDB: Cannot open datafile for read-only: './test/t1.ibd' OS error: 71
[Warning] InnoDB: Ignoring tablespace `test/t1` because it could not be opened.

要解决这些消息,请发出DROP TABLE语句,以从数据字典中删除有关缺失表的数据。

恢复孤立的 file-per-table ibd 文件

该过程描述了如何将孤立的 file-per-table.ibd文件恢复到另一个 MySQL 实例。如果系统表空间丢失或无法恢复,并且您想要在新的 MySQL 实例上恢复.ibd文件备份,则可以使用此过程。

该过程不支持 general tablespace.ibd文件。

该过程假定您只有.ibd文件备份,您正在恢复到最初创建孤立的.ibd文件的 MySQL 版本,并且.ibd文件备份是干净的。有关创建干净备份的信息,请参阅第 17.6.1.4 节,“移动或复制 InnoDB 表”。

第 17.6.1.3 节,“导入 InnoDB 表”中概述的表导入限制适用于此过程。

  1. 在新的 MySQL 实例中,在同名数据库中重新创建表。

    mysql> CREATE DATABASE sakila;
    
    mysql> USE sakila;
    
    mysql> CREATE TABLE actor (
             actor_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
             first_name VARCHAR(45) NOT NULL,
             last_name VARCHAR(45) NOT NULL,
             last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
             PRIMARY KEY  (actor_id),
             KEY idx_actor_last_name (last_name)
           )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
  2. 丢弃新创建表的表空间。

    mysql> ALTER TABLE sakila.actor DISCARD TABLESPACE;
    
  3. 将孤立的.ibd文件从备份目录复制到新的数据库目录。

    $> cp /backup_directory/actor.ibd *path/to/mysql-5.7/data*/sakila/
    
  4. 确保.ibd文件具有必要的文件权限。

  5. 导入孤立的.ibd文件。会发出警告,指示InnoDB正在尝试在没有模式验证的情况下导入文件。

    mysql> ALTER TABLE sakila.actor IMPORT TABLESPACE; SHOW WARNINGS;
    Query OK, 0 rows affected, 1 warning (0.15 sec)
    
    Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory)
    Error opening './sakila/actor.cfg', will attempt to import
    without schema verification
    
  6. 查询表以验证.ibd文件是否成功恢复。

    mysql> SELECT COUNT(*) FROM sakila.actor;
    +----------+
    | count(*) |
    +----------+
    |      200 |
    +----------+
    

17.21.5 InnoDB 错误处理

原文:dev.mysql.com/doc/refman/8.0/en/innodb-error-handling.html

以下项目描述了InnoDB如何执行错误处理。InnoDB有时只回滚失败的语句,有时会回滚整个事务。

  • 如果在表空间中耗尽文件空间,则会发生 MySQL Table is full错误,并且InnoDB会回滚 SQL 语句。

  • 事务死锁会导致InnoDB回滚整个事务。发生这种情况时,请重试整个事务。

    锁等待超时会导致InnoDB回滚当前语句(等待锁并遇到超时的语句)。要使整个事务回滚,请启动服务器时启用--innodb-rollback-on-timeout。如果使用默认行为,请重试语句,或者如果启用了--innodb-rollback-on-timeout,则重试整个事务。

    在繁忙服务器上,死锁和锁等待超时是正常的,应用程序需要意识到它们可能发生,并通过重试来处理。通过在事务期间对数据进行第一次更改和提交之间尽可能少地进行工作,可以减少发生这些情况的可能性,从而锁定的时间最短,影响的行数最少。有时将工作分割到不同的事务中可能是实用和有帮助的。

  • 如果发生重复键错误,则回滚 SQL 语句,如果在语句中未指定IGNORE选项。

  • 行过长错误会回滚 SQL 语句。

  • 其他错误大多由 MySQL 代码层(在InnoDB存储引擎层之上)检测到,并回滚相应的 SQL 语句。在回滚单个 SQL 语句时不会释放锁。

在隐式回滚期间,以及在执行显式ROLLBACK SQL 语句期间,SHOW PROCESSLIST在相关连接的State列中显示Rolling back

17.22 InnoDB 限制

译文:dev.mysql.com/doc/refman/8.0/en/innodb-limits.html

本节描述了 InnoDB 表、索引、表空间以及 InnoDB 存储引擎的其他方面的限制。

  • 一张表最多可以包含 1017 列。虚拟生成列也包括在此限制内。

  • 一张表最多可以包含 64 个次要索引。

  • 对于使用 DYNAMICCOMPRESSED 行格式的 InnoDB 表,索引键前缀长度限制为 3072 字节。

    对于使用 REDUNDANTCOMPACT 行格式的 InnoDB 表,索引键前缀长度限制为 767 字节。例如,假设在 TEXTVARCHAR 列上使用了超过 191 个字符的 列前缀 索引,在 utf8mb4 字符集和每个字符最大 4 个字节的情况下,可能会达到这个限制。

    尝试使用超过限制的索引键前缀长度将返回错误。

    如果通过在创建 MySQL 实例时指定 innodb_page_size 选项将 InnoDB 页大小 降低为 8KB 或 4KB,那么基于 16KB 页大小的 3072 字节限制,索引键的最大长度将按比例降低。也就是说,当页大小为 8KB 时,最大索引键长度为 1536 字节,当页大小为 4KB 时,最大索引键长度为 768 字节。

    适用于索引键前缀的限制也适用于完整列索引键。

  • 最多允许为多列索引设置 16 列。超过限制将返回错误。

    ERROR 1070 (42000): Too many key parts specified; max 16 parts allowed
    
  • 行的最大大小,不包括存储在页外的任何可变长度列,对于 4KB、8KB、16KB 和 32KB 的页大小略小于半页。例如,默认的 innodb_page_size 为 16KB 时,最大行大小约为 8000 字节。然而,对于 64KB 的 InnoDB 页大小,最大行大小约为 16000 字节。LONGBLOBLONGTEXT 列必须小于 4GB,包括 BLOBTEXT 列在内的总行大小必须小于 4GB。

    如果一行长度小于半页,所有内容都存储在页面内。如果超过半页,变长列将选择外部离页存储,直到行适合半页为止,如第 17.11.2 节,“文件空间管理”中所述。

  • 尽管InnoDB内部支持大于 65535 字节的行大小,但 MySQL 本身对所有列的组合大小施加了 65535 的行大小限制。请参见第 10.4.7 节,“表列数和行大小限制”。

  • 在一些较旧的操作系统上,文件大小必须小于 2GB。这不是InnoDB的限制。如果您需要一个大的系统表空间,请使用多个较小的数据文件进行配置,而不是一个大的数据文件,或者将表数据分布在每个表一个文件和通用表空间数据文件中。

  • InnoDB日志文件的组合最大大小为 512GB。

  • 最小表空间大小略大于 10MB。最大表空间大小取决于InnoDB页面大小。

    表 17.31 InnoDB 最大表空间大小

    InnoDB 页面大小最大表空间大小
    4KB16TB
    8KB32TB
    16KB64TB
    32KB128TB
    64KB256TB

    最大表空间大小也是表的最大大小。

  • 一个InnoDB实例支持最多 2³²(4294967296)个表空间,其中少数表空间保留用于撤销和临时表。

  • 共享表空间支持最多 2³²(4294967296)个表。

  • 表空间文件的路径,包括文件名,在 Windows 上不能超过MAX_PATH限制。在 Windows 10 之前,MAX_PATH限制为 260 个字符。从 Windows 10,版本 1607 开始,MAX_PATH限制已从常见的 Win32 文件和目录函数中移除,但您必须启用新的行为。

  • 有关并发读写事务相关的限制,请参见第 17.6.6 节,“撤销日志”。

17.23 InnoDB 限制和限制

原文:dev.mysql.com/doc/refman/8.0/en/innodb-restrictions-limitations.html

本节描述了 InnoDB 存储引擎的限制和限制。

  • 不能创建具有与内部 InnoDB 列名匹配的列名的表(包括 DB_ROW_IDDB_TRX_IDDB_ROLL_PTR)。此限制适用于任何大小写形式中的名称使用。

    mysql> CREATE TABLE t1 (c1 INT, db_row_id INT) ENGINE=INNODB;
    ERROR 1166 (42000): Incorrect column name 'db_row_id'
    
  • SHOW TABLE STATUS 对于 InnoDB 表不提供准确的统计信息,除了表保留的物理大小。行计数仅是 SQL 优化中使用的粗略估计。

  • InnoDB 不会保留表中行的内部计数,因为并发事务可能在同一时间“看到”不同数量的行。因此,SELECT COUNT(*) 语句仅计算当前事务可见的行数。

    有关 InnoDB 如何处理 SELECT COUNT(*) 语句的信息,请参阅 第 14.19.1 节,“聚合函数描述” 中的 COUNT() 描述。

  • ROW_FORMAT=COMPRESSED 不支持大于 16KB 的页面大小。

  • 使用特定 InnoDB 页面大小(innodb_page_size)的 MySQL 实例不能使用来自使用不同页面大小的实例的数据文件或日志文件。

  • 有关使用 可传输表空间 功能导入表的限制,请参见 表导入限制。

  • 有关在线 DDL 的限制,请参见 第 17.12.8 节,“在线 DDL 限制”。

  • 有关一般表空间的限制,请参见 一般表空间限制。

  • 有关数据静态加密的限制,请参见 加密限制。

第十八章 备选存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/storage-engines.html

目录

18.1 设置存储引擎

18.2 MyISAM 存储引擎

18.2.1 MyISAM 启动选项

18.2.2 键所需的空间

18.2.3 MyISAM 表存储格式

18.2.4 MyISAM 表问题

18.3 MEMORY 存储引擎

18.4 CSV 存储引擎

18.4.1 修复和检查 CSV 表

18.4.2 CSV 限制

18.5 ARCHIVE 存储引擎

18.6 BLACKHOLE 存储引擎

18.7 MERGE 存储引擎

18.7.1 MERGE 表优缺点

18.7.2 MERGE 表问题

18.8 FEDERATED 存储引擎

18.8.1 FEDERATED 存储引擎概述

18.8.2 如何创建 FEDERATED 表

18.8.3 FEDERATED 存储引擎注意事项和提示

18.8.4 FEDERATED 存储引擎资源

18.9 EXAMPLE 存储引擎

18.10 其他存储引擎

18.11 MySQL 存储引擎架构概述

18.11.1 可插拔存储引擎架构

18.11.2 通用数据库服务器层

存储引擎是 MySQL 组件,用于处理不同表类型的 SQL 操作。InnoDB 是默认和最通用的存储引擎,Oracle 建议除了专用用例外,都使用它来创建表。(在 MySQL 8.0 中,CREATE TABLE 语句默认创建 InnoDB 表。)

MySQL 服务器使用可插拔存储引擎架构,允许存储引擎在运行中加载和卸载。

要确定服务器支持哪些存储引擎,请使用 SHOW ENGINES 语句。Support 列中的值指示引擎是否可用。YESNODEFAULT 的值表示引擎可用、不可用或可用且当前设置为默认存储引擎。

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 存储引擎或 NDB 存储引擎,这些在 Chapter 17, The InnoDB Storage Engine 和 Chapter 25, MySQL NDB Cluster 8.0 中有介绍。对于高级用户,它还包含了可插拔存储引擎架构的描述(请参见 Section 18.11, “Overview of MySQL Storage Engine Architecture”)。

有关商业 MySQL Server 二进制版本提供的功能信息,请访问 MySQL 网站上的MySQL Editions。可用的存储引擎可能取决于您使用的 MySQL 版本。

关于 MySQL 存储引擎常见问题的答案,请参见 Section A.2, “MySQL 8.0 FAQ: Storage Engines”。

MySQL 8.0 支持的存储引擎

  • InnoDB:MySQL 8.0 中的默认存储引擎。InnoDB 是 MySQL 的事务安全(ACID 兼容)存储引擎,具有提交、回滚和崩溃恢复功能,以保护用户数据。InnoDB 行级锁定(不升级为更粗粒度的锁)和 Oracle 风格的一致性非锁定读取增加了多用户并发性和性能。InnoDB 将用户数据存储在聚集索引中,以减少基于主键的常见查询的 I/O。为了保持数据完整性,InnoDB 还支持 FOREIGN KEY 外键完整性约束。有关 InnoDB 的更多信息,请参见 Chapter 17, The InnoDB Storage Engine

  • MyISAM:这些表占用空间小。表级锁定 限制了读/写工作负载的性能,因此通常用于 Web 和数据仓库配置中的只读或读多写少的工作负载。

  • Memory:将所有数据存储在 RAM 中,用于快速访问需要快速查找非关键数据的环境。这个引擎以前被称为 HEAP 引擎。它的使用案例正在减少;InnoDB 通过其缓冲池内存区提供了一种通用且耐用的方式来将大部分或全部数据保存在内存中,而 NDBCLUSTER 为庞大的分布式数据集提供了快速的键值查找。

  • CSV:它的表实际上是带有逗号分隔值的文本文件。CSV 表允许你以 CSV 格式导入或导出数据,与读写相同格式的脚本和应用程序交换数据。因为 CSV 表没有索引,通常在正常操作期间将数据保存在InnoDB表中,仅在导入或导出阶段使用 CSV 表。

  • 归档:这些紧凑的、无索引的表用于存储和检索大量很少被引用的历史、归档或安全审计信息。

  • 黑洞:黑洞存储引擎接受但不存储数据,类似于 Unix 的/dev/null设备。查询总是返回一个空集。这些表可以在复制配置中使用,其中 DML 语句被发送到副本服务器,但源服务器不保留自己的数据副本。

  • NDB(也称为NDBCLUSTER):这个集群数据库引擎特别适用于需要最高可用性和可用性的应用程序。

  • 合并:使 MySQL DBA 或开发人员可以逻辑地将一系列相同的MyISAM表分组,并将它们引用为一个对象。适用于数据仓库等 VLDB 环境。

  • 联合:提供了将不同的 MySQL 服务器链接起来,从许多物理服务器创建一个逻辑数据库的能力。非常适合分布式或数据仓库环境。

  • 示例:这个引擎在 MySQL 源代码中作为一个示例,展示了如何开始编写新的存储引擎。主要是为开发人员感兴趣。这个存储引擎是一个“存根”,什么也不做。你可以用这个引擎创建表,但不能在其中存储或检索数据。

你不必限制整个服务器或模式使用相同的存储引擎。你可以为任何表指定存储引擎。例如,一个应用程序可能主要使用InnoDB表,其中一个CSV表用于将数据导出到电子表格,以及一些MEMORY表用于临时工作空间。

选择存储引擎

MySQL 提供的各种存储引擎是针对不同用例设计的。以下表格提供了一些 MySQL 提供的存储引擎的概述,表格后面跟着澄清说明。

表 18.1 存储引擎特性摘要

特性MyISAMMemoryInnoDBArchiveNDB
B-tree 索引
备份/时间点恢复(注 1)
集群数据库支持
聚集索引
压缩数据是(注 2)
数据缓存不适用
加密数据是(注 3)是(注 3)是(注 4)是(注 3)是(注 5)
外键支持
全文搜索索引是(注 6)
地理空间数据类型支持
地理空间索引支持是(注 7)
哈希索引否(注 8)
索引缓存不适用
锁定粒度
MVCC
复制支持(注 1)有限(注 9)
存储限制256TBRAM64TB384EB
T 树索引
事务
更新数据字典的统计信息
特性MyISAMMemoryInnoDBArchiveNDB

注:

1. 在服务器端实现,而不是在存储引擎中。

2. 仅当使用压缩行格式时,支持压缩的 MyISAM 表。使用压缩行格式的 MyISAM 表是只读的。

3. 通过加密函数在服务器端实现。

4. 通过加密函数在服务器端实现;在 MySQL 5.7 及更高版本中,支持数据静态加密。

5. 通过加密函数在服务器端实现;NDB 8.0.22 起支持加密的 NDB 备份;NDB 8.0.29 及更高版本支持透明的 NDB 文件系统加密。

6. MySQL 5.6 及更高版本支持全文索引。

7. MySQL 5.7 及更高版本支持地理空间索引。

8. InnoDB 在内部利用哈希索引来实现其自适应哈希索引功能。

9. 请参见本节后面的讨论。

18.1 设置存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/storage-engine-setting.html

当您创建新表时,可以通过在CREATE TABLE语句中添加ENGINE表选项来指定要使用的存储引擎:

-- 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;

当您省略ENGINE选项时,将使用默认存储引擎。在 MySQL 8.0 中,默认引擎是InnoDB。您可以通过使用--default-storage-engine服务器启动选项或通过在my.cnf配置文件中设置default-storage-engine选项来指定默认引擎。

您可以通过设置default_storage_engine变量为当前会话设置默认存储引擎:

SET default_storage_engine=NDBCLUSTER;

使用CREATE TEMPORARY TABLE创建的TEMPORARY表的存储引擎可以通过在启动时或运行时设置default_tmp_storage_engine来单独设置,与永久表的引擎不同。

要将表从一种存储引擎转换为另一种,使用指示新引擎的ALTER TABLE语句:

ALTER TABLE t ENGINE = InnoDB;

参见第 15.1.20 节,“CREATE TABLE Statement”和第 15.1.9 节,“ALTER TABLE Statement”。

如果您尝试使用未编译或已编译但已停用的存储引擎,MySQL 会使用默认存储引擎创建表。例如,在复制设置中,也许您的源服务器使用InnoDB表以获得最大安全性,但副本服务器使用其他存储引擎以换取速度而牺牲耐久性或并发性。

默认情况下,当CREATE TABLEALTER TABLE无法使用默认存储引擎时会生成警告。为了防止混淆和意外行为,如果所需引擎不可用,请启用NO_ENGINE_SUBSTITUTION SQL 模式。如果所需引擎不可用,此设置会产生错误而不是警告,并且表不会被创建或更改。参见第 7.1.11 节,“服务器 SQL 模式”。

MySQL 可能会根据存储引擎的不同,将表的索引和数据存储在一个或多个其他文件中。表和列的定义存储在 MySQL 数据字典中。各个存储引擎会为其管理的表创建所需的任何额外文件。如果表名包含特殊字符,则表文件的名称会包含这些字符的编码版本,如 Section 11.2.4,“标识符映射到文件名”中所述。

18.2 MyISAM 存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/myisam-storage-engine.html

18.2.1 MyISAM 启动选项

18.2.2 键所需的空间

18.2.3 MyISAM 表存储格式

18.2.4 MyISAM 表问题

MyISAM基于旧的(不再可用)ISAM存储引擎,但具有许多有用的扩展。

表 18.2 MyISAM 存储引擎特性

功能支持
B 树索引
备份/时间点恢复(在服务器中实现,而不是在存储引擎中。)
集群数据库支持
聚集索引
压缩数据是(仅在使用压缩行格式时支持压缩的 MyISAM 表。使用压缩行格式和 MyISAM 的表是只读的。)
数据缓存
加密数据是(通过加密函数在服务器中实现。)
外键支持
全文搜索索引
地理空间数据类型支持
地理空间索引支持
哈希索引
索引缓存
锁定粒度
MVCC
复制支持(在服务器中实现,而不是在存储引擎中。)
存储限制256TB
T 树索引
事务
更新数据字典的统计信息
功能支持

每个MyISAM表在磁盘上以两个文件存储。这些文件的名称以表名开头,并具有指示文件类型的扩展名。数据文件具有.MYDMYData)扩展名。索引文件具有.MYIMYIndex)扩展名。表定义存储在 MySQL 数据字典中。

要明确指定要使用MyISAM表,可以使用ENGINE表选项指示:

CREATE TABLE t (i INT) ENGINE = MYISAM;

在 MySQL 8.0 中,通常需要使用ENGINE来指定MyISAM存储引擎,因为InnoDB是默认引擎。

您可以使用mysqlcheck客户端或myisamchk实用程序检查或修复MyISAM表。您还可以使用myisampack压缩MyISAM表,以占用更少的空间。请参阅 Section 6.5.3, “mysqlcheck — A Table Maintenance Program”,Section 6.6.4, “myisamchk — MyISAM Table-Maintenance Utility”和 Section 6.6.6, “myisampack — Generate Compressed, Read-Only MyISAM Tables”。

在 MySQL 8.0 中,MyISAM存储引擎不提供分区支持。在以前的 MySQL 版本中创建的分区MyISAM表无法在 MySQL 8.0 中使用。有关更多信息,请参见第 26.6.2 节,“与存储引擎相关的分区限制”。有关升级这些表以便在 MySQL 8.0 中使用的帮助,请参见第 3.5 节,“MySQL 8.0 中的更改”。

MyISAM表具有以下特点:

  • 所有数据值都以低字节优先存储。这使得数据与机器和操作系统无关。对于二进制可移植性的唯一要求是机器使用二进制补码有符号整数和 IEEE 浮点格式。这些要求在主流机器中被广泛使用。二进制兼容性可能不适用于有时具有特殊处理器的嵌入式系统。

    以低字节优先存储数据不会带来显著的速度惩罚;表行中的字节通常是不对齐的,读取不对齐字节按顺序比按相反顺序需要更少的处理。此外,服务器中提取列值的代码与其他代码相比并不是时间关键。

  • 所有数值键值都以高字节优先存储,以便更好地压缩索引。

  • 支持大文件(最多 63 位文件长度)的文件系统和操作系统。

  • MyISAM表中最多有(2³²)²(1.844E+19)行。

  • 每个MyISAM表的最大索引数为 64。

    每个索引的最大列数为 16。

  • 最大键长度为 1000 字节。这可以通过更改源代码并重新编译来改变。对于长度超过 250 字节的键,使用比默认的 1024 字节更大的键块大小。

  • 当按排序顺序插入行时(例如使用AUTO_INCREMENT列时),索引树会分裂,使高节点仅包含一个键。这提高了索引树的空间利用率。

  • 每个表支持一个AUTO_INCREMENT列的内部处理。MyISAM自动更新此列的INSERTUPDATE操作。这使得AUTO_INCREMENT列更快(至少快 10%)。在删除后,顺序顶部的值不会被重用。(当AUTO_INCREMENT列被定义为多列索引的最后一列时,从顺序顶部删除的值会被重用。)AUTO_INCREMENT值可以通过ALTER TABLEmyisamchk重置。

  • 在混合删除、更新和插入时,动态大小的行碎片化较少。这是通过自动组合相邻的已删除块和在下一个块被删除时扩展块来完成的。

  • MyISAM支持并发插入:如果表在数据文件中间没有空闲块,您可以在其他线程从表中读取数据的同时向其插入新行。空闲块可能是由于删除行或更新动态长度行而导致的,其数据超过当前内容。当所有空闲块都被使用完(填满)时,未来的插入操作再次变得并发。参见 Section 10.11.3, “Concurrent Inserts”。

  • 将数据文件和索引文件放在不同的目录中,放在不同的物理设备上,可以通过DATA DIRECTORYINDEX DIRECTORY表选项来加快速度,CREATE TABLE。参见 Section 15.1.20, “CREATE TABLE Statement”。

  • BLOBTEXT列可以建立索引。

  • 索引列中允许存在NULL值。每个键占用 0 到 1 个字节。

  • 每个字符列可以有不同的字符集。参见 Chapter 12, Character Sets, Collations, Unicode

  • MyISAM索引文件中有一个标志,指示表是否正确关闭。如果使用myisam_recover_options系统变量启动mysqld,则在打开时会自动检查MyISAM表,并在表未正确关闭时进行修复。

  • myisamchk如果使用--update-state选项运行,则会标记表为已检查。myisamchk --fast仅检查那些没有此标记的表。

  • myisamchk --analyze存储部分键的统计信息,以及整个键的统计信息。

  • myisampack可以压缩BLOBVARCHAR列。

MyISAM还支持以下功能:

  • 支持真正的VARCHAR类型;VARCHAR列以一个或两个字节存储的长度开始。

  • 带有VARCHAR列的表可能具有固定或动态行长度。

  • 表中VARCHARCHAR列的长度之和可以达到 64KB。

  • 任意长度的UNIQUE约束。

附加资源

18.2.1 MyISAM 启动选项

原文:dev.mysql.com/doc/refman/8.0/en/myisam-start.html

下列选项可用于更改MyISAM表的行为。有关更多信息,请参见mysqld的第 7.1.7 节,“服务器命令选项”。

表 18.3 MyISAM 选项和变量参考

名称命令行选项文件系统变量状态变量变量范围动态
bulk_insert_buffer_size两者
concurrent_insert全局
delay_key_write全局
have_rtree_keys全局
key_buffer_size全局
log-isam
myisam-block-size
myisam_data_pointer_size全局
myisam_max_sort_file_size全局
myisam_mmap_size全局
myisam_recover_options全局
myisam_repair_threads两者
myisam_sort_buffer_size两者
myisam_stats_method两者
myisam_use_mmap全局
tmp_table_size两者
名称命令行选项文件系统变量状态变量变量范围动态

下列系统变量影响MyISAM表的行为。有关更多信息,请参见第 7.1.8 节,“服务器系统变量”。

  • bulk_insert_buffer_size

    用于批量插入优化中使用的树缓存大小。

    这是每个线程的限制!

  • delay_key_write=ALL

    在任何MyISAM表的写入之间不要刷新键缓冲区。

    如果这样做,您不应该从另一个程序(例如从另一个 MySQL 服务器或使用myisamchk)访问MyISAM表格,当表格正在使用时。这样做会导致索引损坏。使用--external-locking并不能消除这种风险。

  • myisam_max_sort_file_size

    MySQL 在重新创建MyISAM索引时允许使用的临时文件的最大大小(在REPAIR TABLEALTER TABLELOAD DATA期间)。如果文件大小大于此值,则使用键缓存而不是创建索引,这会更慢。该值以字节为单位给出。

  • myisam_recover_options=*mode*

    设置自动恢复崩溃的MyISAM表的模式。

  • myisam_sort_buffer_size

    设置在恢复表格时使用的缓冲区的大小。

如果您使用设置了myisam_recover_options系统变量的值启动mysqld,则自动恢复将被激活。在这种情况下,当服务器打开MyISAM表时,它会检查表是否标记为崩溃,或者表的打开计数变量不为 0 且您正在以禁用外部锁定的方式运行服务器。如果这两个条件中的任何一个为真,则会发生以下情况:

  • 服务器检查表格是否有错误。

  • 如果服务器发现错误,则尝试进行快速表修复(带排序但不重新创建数据文件)。

  • 如果由于数据文件中的错误(例如重复键错误)而导致修复失败,则服务器会再次尝试,这次重新创建数据文��。

  • 如果修复仍然失败,服务器会再次尝试使用旧的修复选项方法(逐行写入而不排序)。这种方法应该能够修复任何类型的错误,并且对磁盘空间要求低。

如果恢复无法从先前完成的语句中恢复所有行,并且您没有在myisam_recover_options系统变量的值中指定FORCE,则自动修复将在错误日志中中止并显示错误消息:

Error: Couldn't repair table: test.g00pages

如果您指定了FORCE,则会写入类似于以下的警告:

Warning: Found 344 of 354 rows when repairing ./test/g00pages

如果自动恢复值包括BACKUP,则恢复过程会创建形如*tbl_name-datetime*.BAK的文件。您应该有一个cron脚本,自动将这些文件从数据库目录移动到备份介质。

18.2.2 键所需的空间

原文:dev.mysql.com/doc/refman/8.0/en/key-space.html

MyISAM 表使用 B 树索引。您可以粗略计算索引文件的大小为 (key_length+4)/0.67,对所有键求和。这是最坏情况下的情况,当所有键按排序顺序插入时,表中没有任何压缩键。

字符串索引是空间压缩的。如果第一个索引部分是字符串,则也进行前缀压缩。空间压缩使索引文件比最坏情况下的数字小,如果字符串列有很多尾随空格或是一个VARCHAR 列,没有始终使用到完整长度。前缀压缩用于以字符串开头的键。前缀压缩有助于处理具有相同前缀的许多字符串。

MyISAM 表中,您还可以通过在创建表时指定 PACK_KEYS=1 表选项来对数字进行前缀压缩。数字以高字节优先存储,因此当您有许多整数键具有相同前缀时,这很有帮助。

18.2.3 MyISAM 表存储格式

原文:dev.mysql.com/doc/refman/8.0/en/myisam-table-formats.html

18.2.3.1 静态(固定长度)表特性

18.2.3.2 动态表特性

18.2.3.3 压缩表特性

MyISAM支持三种不同的存储格式。其中两种,固定和动态格式,根据你使用的列类型自动选择。第三种,压缩格式,只能使用myisampack实用程序创建(参见第 6.6.6 节,“myisampack — 生成压缩的只读 MyISAM 表”)。

当你使用CREATE TABLEALTER TABLE创建没有BLOBTEXT列的表时,可以使用ROW_FORMAT表选项强制表格式为FIXEDDYNAMIC

查看第 15.1.20 节,“CREATE TABLE 语句”,了解ROW_FORMAT的信息。

你可以使用myisamchk--unpack选项来解压缩MyISAM表;查看第 6.6.4 节,“myisamchk — MyISAM 表维护实用程序”获取更多信息。

原文:dev.mysql.com/doc/refman/8.0/en/static-format.html

18.2.3.1 静态(固定长度)表特性

静态格式是MyISAM表的默认格式。当表中不包含可变长度列(VARCHARVARBINARYBLOBTEXT)时使用。每行使用固定字节数存储。

在三种MyISAM存储格式中,静态格式是最简单和最安全(最不容易损坏)的。由于在磁盘上很容易找到数据文件中的行,它也是磁盘上最快的格式:根据索引中的行号查找行时,将行号乘以行长度以计算行位置。此外,在扫描表时,每次磁盘读取操作都可以很容易地读取恒定数量的行。

如果在 MySQL 服务器写入固定格式的MyISAM文件时计算机崩溃,安全性得到证明。在这种情况下,myisamchk可以轻松确定每行的起始和结束位置,因此通常可以回收除部分写入的行之外的所有行。MyISAM表索引始终可以根据数据行重建。

注意

仅适用于没有BLOBTEXT列的表的固定长度行格式。创建具有此类列的表并使用显式的ROW_FORMAT子句不会引发错误或警告;格式规范将被忽略。

静态格式表具有以下特点:

  • CHARVARCHAR列会被填充到指定的列宽,尽管列类型不会改变。BINARYVARBINARY列会用0x00字节填充到列宽。

  • NULL列需要额外的空间来记录它们的值是否为NULL。每个NULL列额外占用一位,向最近的字节取整。

  • 非常快速。

  • 易于缓存。

  • 在崩溃后易于重建,因为行位于固定位置。

  • 除非删除大量行并希望将空闲磁盘空间返回给操作系统,否则不需要重新组织。要执行此操作,请使用OPTIMIZE TABLEmyisamchk -r

  • 通常需要比动态格式表更多的磁盘空间。

  • 静态大小行的预期行长度(以字节为单位)通过以下表达式计算:

    row length = 1
                 + (*sum of column lengths*)
                 + (*number of NULL columns* + *delete_flag* + 7)/8
                 + (*number of variable-length columns*)
    

    delete_flag 在静态行格式的表中为 1。静态表在行记录中使用一个位来表示行是否已被删除。对于动态表,delete_flag 为 0,因为标志位存储在动态行头中。

原文:dev.mysql.com/doc/refman/8.0/en/dynamic-format.html

18.2.3.2 动态表特性

如果MyISAM表包含任何可变长度列(VARCHARVARBINARYBLOBTEXT),或者表是使用ROW_FORMAT=DYNAMIC表选项创建的,则使用动态存储格式。

动态格式比静态格式稍微复杂,因为每行都有一个标头,指示其长度。当由于更新而使行变长时,行可能会变得碎片化(存储在非连续的片段中)。

您可以使用OPTIMIZE TABLEmyisamchk -r来对表进行碎片整理。如果您在一个表中频繁访问或更改固定长度列,并且该表还包含一些可变长度列,那么将可变长度列移动到其他表中以避免碎片化可能是一个好主意。

动态格式表具有以下特点:

  • 所有字符串列都是动态的,除了长度小于四的列。

  • 每行前面都有一个位图,指示哪些列包含空字符串(对于字符串列)或零(对于数值列)。这不包括包含NULL值的列。如果字符串列在去除尾随空格后长度为零,或者数值列的值为零,则在位图中标记并不保存到磁盘。非空字符串保存为长度字节加上字符串内容。

  • NULL列需要额外的空间来记录它们的值是否为NULL。每个NULL列额外占用一位,向上取整到最近的字节。

  • 比固定长度表通常需要更少的磁盘空间。

  • 每行只使用所需的空间。但是,如果一行变得更大,它将被分成所需的碎片,导致行碎片化。例如,如果更新了一行的信息,使行长度增加,那么该行将变得碎片化。在这种情况下,您可能需要定期运行OPTIMIZE TABLEmyisamchk -r来提高性能。使用myisamchk -ei获取表统计信息。

  • 在崩溃后更难重建比静态格式表,因为行可能会分成许多片段,而且链接(片段)可能丢失。

  • 动态大小行的预期行长度使用以下表达式计算:

    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 -ed来查找链接的数量。所有链接可以通过OPTIMIZE TABLEmyisamchk -r来移除。

原文:dev.mysql.com/doc/refman/8.0/en/compressed-format.html

18.2.3.3 压缩表特性

压缩存储格式是使用myisampack工具生成的只读格式。压缩表可以使用myisamchk解压缩。

压缩表具有以下特性:

  • 压缩表占用非常少的磁盘空间。这最小化了磁盘使用,对于使用慢速磁盘(如 CD-ROM)很有帮助。

  • 每行都单独压缩,因此几乎没有访问开销。每行的标头占用一到三个字节,取决于表中最大的行。每列的压缩方式不同。通常每列都有不同的哈夫曼树。一些压缩类型包括:

    • 后缀空间压缩。

    • 前缀空间压缩。

    • 值为零的数字使用一位存储。

    • 如果整数列中的值范围较小,则使用可能的最小类型存储该列。例如,一个BIGINT列(八个字节)可以存储为一个TINYINT列(一个字节),如果其所有值都在 -128127 的范围内。

    • 如果一列只有一小组可能的值,数据类型将转换为ENUM

    • 一列可以使用前述压缩类型的任意组合。

  • 可用于固定长度或动态长度行。

注意

虽然压缩表是只读的,因此您不能更新或添加表中的行,但 DDL(数据定义语言)操作仍然有效。例如,您仍然可以使用DROP删除表,使用TRUNCATE TABLE清空表。

18.2.4 MyISAM 表格问题

原文:dev.mysql.com/doc/refman/8.0/en/myisam-table-problems.html

18.2.4.1 损坏的 MyISAM 表格

18.2.4.2 未正确关闭表格导致的问题

MySQL 用于存储数据的文件格式经过了广泛测试,但总会有一些情况可能导致数据库表损坏。以下讨论描述了这种情况可能发生的原因以及如何处理。

原文:dev.mysql.com/doc/refman/8.0/en/corrupted-myisam-tables.html

18.2.4.1 损坏的 MyISAM 表

即使MyISAM表格式非常可靠(由 SQL 语句对表所做的所有更改都在语句返回之前写入),如果发生以下任何事件,仍然可能出现损坏的表:

  • mysqld进程在写入过程中被终止。

  • 发生意外的计算机关闭(例如,计算机被关闭)。

  • 硬件故障。

  • 您正在使用外部程序(例如myisamchk)同时修改服务器正在修改的表。

  • MySQL 或MyISAM代码中的软件错误。

损坏表的典型症状包括:

  • 从表中选择数据时出现以下错误:

    Incorrect key file for table: '...'. Try to repair it
    
  • 查询在表中找不到行或返回不完整的结果。

您可以使用CHECK TABLE语句检查MyISAM表的健康状况,并使用REPAIR TABLE修复损坏的MyISAM表。当mysqld未运行时,您还可以使用myisamchk命令检查或修复表。请参阅第 15.7.3.2 节,“CHECK TABLE Statement”,第 15.7.3.5 节,“REPAIR TABLE Statement”,以及第 6.6.4 节,“myisamchk — MyISAM 表维护实用程序”。

如果您的表经常损坏,您应该尝试确定为什么会发生这种情况。最重要的是要知道表是否因意外服务器退出而损坏。您可以通过查看错误日志中最近的重新启动的 mysqld消息来轻松验证这一点。如果有这样的消息,那么表损坏很可能是服务器死机的结果。否则,损坏可能发生在正常操作期间。这是一个错误。您应该尝试创建一个可重现的测试用例来演示问题。请参阅第 B.3.3.3 节,“如果 MySQL 一直崩溃该怎么办”,以及第 7.9 节,“调试 MySQL”。

原文:dev.mysql.com/doc/refman/8.0/en/myisam-table-close.html

18.2.4.2 未正确关闭表导致的问题

每个MyISAM索引文件(.MYI文件)的头部都有一个计数器,可用于检查表是否已正确关闭。如果您从CHECK TABLEmyisamchk收到以下警告,则表示该计数器已经不同步:

clients are using or haven't closed the table properly

此警告并不一定意味着表已损坏,但您至少应该检查表。

该计数器的工作方式如下:

  • 在 MySQL 中第一次更新表时,索引文件头部的计数器会递增。

  • 在进一步更新期间,计数器不会更改。

  • 当表的最后一个实例关闭时(因为执行了FLUSH TABLES操作或因为表缓存中没有空间),如果表在任何时候已更新,则计数器会递减。

  • 当修复表或检查表并发现表正常时,计数器将被重置为零。

  • 为避免与可能检查表的其他进程交互的问题,如果计数器为零,则在关闭时不会减少。

换句话说,只有在以下情况下计数器才会变得不正确:

  • 一个MyISAM表在未首先执行LOCK TABLESFLUSH TABLES的情况下被复制。

  • MySQL 在更新和最终关闭之间崩溃。(表可能仍然正常,因为 MySQL 总是在每个语句之间为所有内容发出写入。)

  • 一个表在被myisamchk --recovermyisamchk --update-state修改时,同时被mysqld使用。

  • 多个mysqld服务器正在使用该表,其中一个服务器在另一个服务器使用该表时执行了REPAIR TABLECHECK TABLE。在这种设置中,使用CHECK TABLE是安全的,尽管您可能会收到其他服务器的警告。但是,应避免使用REPAIR TABLE,因为当一个服务器用新文件替换数据文件时,其他服务器不知道这一点。

    一般来说,将数据目录共享给多台服务器是一个不好的主意。参见第 7.8 节,“在一台机器上运行多个 MySQL 实例”,进行进一步讨论。

18.3 MEMORY 存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/memory-storage-engine.html

MEMORY 存储引擎(以前称为 HEAP)创建内容存储在内存中的特殊用途表。由于数据容易受到崩溃、硬件问题或停电的影响,只能将这些表用作临时工作区或从其他表中提取数据的只读缓存。

表 18.4 MEMORY 存储引擎特性

特性支持
B 树索引
备份/时间点恢复(在服务器中实现,而不是在存储引擎中。)
集群数据库支持
聚集索引
压缩数据
数据缓存不适用
加密数据是(通过加密函数在服务器中实现。)
外键支持
全文搜索索引
地理空间数据类型支持
地理空间索引支持
哈希索引
索引缓存不适用
锁定粒度
MVCC
复制支持(在服务器中实现,而不是在存储引擎中。)有限(请参见本节后面的讨论。)
存储限制RAM
T 树索引
事务
更新数据字典统计信息
特性支持
  • 何时使用 MEMORY 或 NDB 集群

  • 分区

  • 性能特性

  • MEMORY 表的特点

  • MEMORY 表的 DDL 操作

  • 索引

  • 用户创建和临时表

  • 加载数据

  • MEMORY 表和复制

  • 管理内存使用

  • 其他资源

何时使用 MEMORY 或 NDB 集群

寻求部署使用 MEMORY 存储引擎处理重要、高可用或频繁更新数据的应用程序的开发人员应考虑 NDB Cluster 是否更合适。MEMORY 引擎的典型用例包括以下特点:

  • 涉及瞬态、非关键数据的操作,如会话管理或缓存。当 MySQL 服务器停止或重新启动时,MEMORY 表中的数据将丢失。

  • 内存存储以实现快速访问和低延迟。数据量完全可以放入内存,而不会导致操作系统交换虚拟内存页。

  • 读取为主或只读数据访问模式(有限更新)。

NDB Cluster 提供与 MEMORY 引擎相同的功能,性能水平更高,并提供 MEMORY 不支持的其他功能:

  • 行级锁定和多线程操作可减少客户端之间的低争用。

  • 即使包含写操作的语句混合,也具有可伸缩性。

  • 可选的磁盘支持操作以实现数据持久性。

  • 无共享架构和无单点故障的多主机操作,实现 99.999%的可用性。

  • 跨节点自动数据分布;应用程序开发人员无需设计自定义分片或分区解决方案。

  • 支持变长数据类型(包括BLOBTEXT),MEMORY 不支持。

分区

MEMORY 表不支持分区。

性能特征

MEMORY 性能受限于单线程执行和处理更新时的表锁定开销所导致的争用。当负载增加时,特别是包含写操作的语句混合时,这限制了可伸缩性。

尽管 MEMORY 表采用内存处理,但在繁忙服务器上,对于通用查询或读写工作负载,它们不一定比InnoDB表更快。特别是,执行更新涉及的表锁定可能会减慢多个会话中对 MEMORY 表的并发使用。

根据在 MEMORY 表上执行的查询类型,您可以创建索引作为默认哈希数据结构(用于基于唯一键查找单个值)或通用的 B 树数据结构(用于涉及等式、不等式或范围运算符(如小于或大于)的所有查询)。以下部分说明了创建这两种索引的语法。一个常见的性能问题是在 B 树索引更有效的工作负载中使用默认哈希索引。

MEMORY 表的特点

MEMORY 存储引擎不在磁盘上创建任何文件。表定义存储在 MySQL 数据字典中。

MEMORY 表具有以下特点:

  • MEMORY 表的空间是以小块分配的。表使用 100% 的动态哈希插入。不需要溢出区域或额外的键空间。不需要额外的空间用于空闲列表。删除的行被放入一个链表中,在你向表中插入新数据时被重用。MEMORY 表也没有通常与哈希表中的删除加插入相关的问题。

  • MEMORY 表使用固定长度的行存储格式。可变长度类型如 VARCHAR 使用固定长度存储。

  • MEMORY 表不能包含 BLOBTEXT 列。

  • MEMORY 包括对 AUTO_INCREMENT 列的支持。

  • 非临时的 MEMORY 表在所有客户端之间共享,就像任何其他非临时表一样。

MEMORY 表的 DDL 操作

要创建一个 MEMORY 表,在 CREATE TABLE 语句中指定 ENGINE=MEMORY 子句。

CREATE TABLE t (i INT) ENGINE = MEMORY;

如引擎名称所示,MEMORY 表存储在内存中。它们默认使用哈希索引,使得单值查找非常快速,并且非常适用于创建临时表。然而,当服务器关闭时,所有存储在 MEMORY 表中的行都会丢失。表本身会继续存在,因为它们的定义存储在 MySQL 数据字典中,但在服务器重新启动时它们是空的。

这个例子展示了如何创建、使用和移除一个 MEMORY 表:

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;

MEMORY 表的最大大小受 max_heap_table_size 系统变量限制,默认值为 16MB。要为 MEMORY 表强制不同的大小限制,改变这个变量的值。对于 CREATE TABLE,或随后的 ALTER TABLETRUNCATE TABLE,生效的值将用于表的生命周期。服务器重新启动也会将现有 MEMORY 表的最大大小设置为全局 max_heap_table_size 值。你可��像本节后面描述的那样为单个表设置大小。

索引

MEMORY 存储引擎支持 HASHBTREE 索引。你可以通过添加 USING 子句来指定给定索引使用的其中一个,如下所示:

CREATE TABLE lookup
    (id INT, INDEX USING HASH (id))
    ENGINE = MEMORY;
CREATE TABLE lookup
    (id INT, INDEX USING BTREE (id))
    ENGINE = MEMORY;

关于 B 树和哈希索引的一般特性,请参阅 第 10.3.1 节,“MySQL 如何使用索引”。

MEMORY 表每个表最多可以有 64 个索引,每个索引最多有 16 列,最大键长度为 3072 字节。

如果MEMORY表的哈希索引具有高度的键重复(许多包含相同值的索引条目),那么影响键值的表更新和所有删除操作将显着变慢。这种减速程度与重复程度成正比(或者与索引基数成反比)。您可以使用BTREE索引来避免这个问题。

MEMORY表可以具有非唯一键。(这是哈希索引实现的一个不常见的特性。)

索引的列可以包含NULL值。

用户创建的临时表

MEMORY表内容存储在内存中,这是MEMORY表与服务器在处理查询时动态创建的内部临时表共享的属性。然而,这两种类型的表在以下方面有所不同:MEMORY表不受存储转换的影响,而内部临时表受到影响:

  • 如果内部临时表变得太大,服务器会自动将其转换为磁盘存储,如第 10.4.4 节,“MySQL 中的内部临时表使用”所述。

  • 用户创建的MEMORY表永远不会转换为磁盘表。

加载数据

在 MySQL 服务器启动时填充MEMORY表,您可以使用init_file系统变量。例如,您可以将诸如INSERT INTO ... SELECTLOAD DATA之类的语句放入文件中,从持久数据源加载表,并使用init_file命名文件。请参见第 7.1.8 节,“服务器系统变量”和第 15.2.9 节,“LOAD DATA 语句”。

MEMORY 表和复制

当复制源服务器关闭并重新启动时,其MEMORY表变为空。为了将此效果复制到副本,源在启动后第一次使用给定的MEMORY表时,它会记录一个事件,通知副本必须通过向二进制日志写入该表的DELETE或(从 MySQL 8.0.22 开始)TRUNCATE TABLE语句来清空该表。当副本服务器关闭并重新启动时,其MEMORY表也变为空,并且它会向自己的二进制日志写入一个DELETE或(从 MySQL 8.0.22 开始)TRUNCATE TABLE语句,这些语句会传递给任何下游副本。

当您在复制拓扑中使用MEMORY表时,在某些情况下,源表和副本表可能会有所不同。有关处理这些情况以防止过时读取或错误的信息,请参阅 Section 19.5.1.21,“复制和 MEMORY 表”。

管理内存使用

服务器需要足够的内存来同时维护所有正在使用的MEMORY表。

如果您从MEMORY表中删除单个行,则不会回收内存。只有在删除整个表时才会回收内存。先前用于已删除行的内存将在同一表中为新行重新使用。当您不再需要其内容时,要释放MEMORY表使用的所有内存,请执行DELETETRUNCATE TABLE以删除所有行,或使用DROP TABLE完全删除表。要释放已删除行使用的内存,请使用ALTER TABLE ENGINE=MEMORY强制表重建。

MEMORY表中,一个行所需的内存通过以下表达式计算:

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()表示一个向上取整的因子,使行长度成为char指针大小的精确倍数。在 32 位机器上,sizeof(char*)为 4,在 64 位机器上为 8。

如前所述,max_heap_table_size系统变量设置了MEMORY表的最大大小限制。要控制各个表的最大大小,需在创建每个表之前设置此变量的会话值。(除非您打算将该值用于所有客户端创建的MEMORY表,否则不要更改全局max_heap_table_size值。)以下示例创建了两个MEMORY表,分别具有 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值。

您还可以在CREATE TABLE语句中为MEMORY表指定MAX_ROWS表选项,以提供关于您计划在其中存储的行数的提示。这不会使表增长超过max_heap_table_size值,该值仍然作为最大表大小的约束。为了能够灵活使用MAX_ROWS,请将max_heap_table_size设置至少与您希望每个MEMORY表能够增长的值一样高。

附加资源

一个专门致力于MEMORY存储引擎的论坛可在forums.mysql.com/list.php?92找到。

18.4 CSV 存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/csv-storage-engine.html

18.4.1 修复和检查 CSV 表

18.4.2 CSV 限制

CSV存储引擎使用逗号分隔值格式将数据存储在文本文件中。

CSV存储引擎始终编译到 MySQL 服务器中。

要查看CSV引擎的源代码,请查看 MySQL 源代码分发中的storage/csv目录。

当你创建一个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表还会创建一个相应的元文件,用于存储表的状态和表中存在的行数。该文件的名称与表名相同,扩展名为CSM

如果你检查执行上述语句创建的数据库目录中的test.CSV文件,其内容应该如下所示:

"1","record one"
"2","record two"

这种格式可以被电子表格应用程序(如 Microsoft Excel)读取,甚至写入。

18.4.1 修复和检查 CSV 表格

原文:dev.mysql.com/doc/refman/8.0/en/se-csv-repair.html

CSV存储引擎支持CHECK TABLEREPAIR TABLE语句,用于验证并且在可能的情况下修复损坏的CSV表格。

运行CHECK TABLE语句时,会通过查找正确的字段分隔符、转义字段(匹配或缺失的引号)、与表定义相比的正确字段数量以及相应的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语句,它会尽可能从现有的CSV数据中复制尽可能多的有效行,然后用恢复的行替换现有的CSV文件。任何在损坏数据之后的行都会丢失。

mysql> REPAIR TABLE csvtest;
+--------------+--------+----------+----------+
| Table        | Op     | Msg_type | Msg_text |
+--------------+--------+----------+----------+
| test.csvtest | repair | status   | OK       |
+--------------+--------+----------+----------+

警告

在修复过程中,只有从CSV文件中第一个损坏行之前的行会被复制到新表中。从第一个损坏行到表格末尾的所有其他行都会被移除,即使是有效行也会被移除。

18.4.2 CSV 限制

原文:dev.mysql.com/doc/refman/8.0/en/se-csv-limitations.html

CSV存储引擎不支持索引。

CSV存储引擎不支持分区。

使用CSV存储引擎创建的所有表必须在所有列上具有NOT NULL属性。

18.5 ARCHIVE 存储引擎

原文:dev.mysql.com/doc/refman/8.0/en/archive-storage-engine.html

ARCHIVE 存储引擎生成专用表,以非常小的占用空间存储大量未索引的数据。

表 18.5 ARCHIVE 存储引擎特性

功能支持
B-树索引
备份/时间点恢复(在服务器中实现,而不是在存储引擎中。)
集群数据库支持
集群索引
压缩数据
数据缓存
加密数据是(通过加密函数在服务器中实现。)
外键支持
全文搜索索引
地理空间数据类型支持
地理空间索引支持
哈希索引
索引缓存
锁定粒度
MVCC
复制支持(在服务器中实现,而不是在存储引擎中。)
存储限制
T-树索引
事务
数据字典的更新统计信息
功能支持

ARCHIVE 存储引擎包含在 MySQL 二进制发行版中。如果您从源代码构建 MySQL,可以通过使用 -DWITH_ARCHIVE_STORAGE_ENGINE 选项在 CMake 中启用此存储引擎。

要查看 ARCHIVE 引擎的源代码,请查看 MySQL 源代码分发中的 storage/archive 目录。

您可以使用 SHOW ENGINES 语句检查 ARCHIVE 存储引擎是否可用。

创建 ARCHIVE 表时,存储引擎会创建以表名开头的文件。数据文件的扩展名为 .ARZ。在优化操作期间可能会出现 .ARN 文件。

ARCHIVE 引擎支持 INSERT, REPLACE, 和 SELECT,但不支持 DELETEUPDATE。它支持 ORDER BY 操作,BLOB 列,以及空间数据类型(参见 第 13.4.1 节,“空间数据类型”)。不支持地理空间参考系统。ARCHIVE 引擎使用行级锁定。

ARCHIVE 引擎支持 AUTO_INCREMENT 列属性。AUTO_INCREMENT 列可以有唯一或非唯一索引。在任何其他列上创建索引会导致错误。ARCHIVE 引擎还支持 CREATE TABLE 语句中的 AUTO_INCREMENT 表选项,用于指定新表的初始序列值或重置现有表的序列值。

ARCHIVE 不支持将值插入到小于当前最大列值的 AUTO_INCREMENT 列中。尝试这样做会导致 ER_DUP_KEY 错误。

如果未请求,ARCHIVE 引擎会忽略 BLOB 列,并在读取时跳过它们。

ARCHIVE 存储引擎不支持分区。

存储: 行在插入时会被压缩。ARCHIVE 引擎使用 zlib 无损数据压缩(参见 www.zlib.net/)。您可以使用 OPTIMIZE TABLE 来分析表并将其打包成更小的格式(关于使用 OPTIMIZE TABLE 的原因,请参见本节后面)。该引擎还支持 CHECK TABLE。有几种类型的插入操作被使用:

  • INSERT 语句只是将行推送到压缩缓冲区中,并在必要时刷新该缓冲区。对缓冲区的插入受到锁的保护。SELECT 强制刷新发生。

  • 仅在批量插入完成后才能看到,除非同时发生其他插入操作,此时可能部分可见。SELECT 永远不会导致批量插入的刷新,除非在加载时发生正常插入。

检索:在检索时,行会按需解压缩;没有行缓存。SELECT 操作执行完整的表扫描:当发生 SELECT 时,它会找出当前有多少行并读取这些行。SELECT 作为一致性读取执行。请注意,插入期间大量的 SELECT 语句可能会降低压缩效果,除非只使用批量插入。为了获得更好的压缩效果,您可以使用 OPTIMIZE TABLEREPAIR TABLESHOW TABLE STATUS 报告的 ARCHIVE 表中的行数始终是准确的。请参阅 Section 15.7.3.4, “OPTIMIZE TABLE Statement”,Section 15.7.3.5, “REPAIR TABLE Statement” 和 Section 15.7.7.38, “SHOW TABLE STATUS Statement”。

其他资源