FLUSH TABLE rt_table
FLUSH TABLE 强制将实时表的RAM块内容刷新到磁盘。
实时表的RAM块会在正常关闭时自动刷新到磁盘,或者每隔rt_flush_period秒周期性刷新。
执行 FLUSH TABLE 命令不仅会强制将RAM块内容写入磁盘,还会触发二进制日志文件的清理。
- SQL
- JSON
POST /sql?mode=raw -d "FLUSH TABLE rt"Query OK, 0 rows affected (0.05 sec)[
{
"total": 0,
"error": "",
"warning": ""
}
]FLUSH TABLE rt;随着时间的推移,RT 表可能会碎片化为多个磁盘块和/或被删除但未清除的数据污染,从而影响搜索性能。在这些情况下,需要进行优化。本质上,优化过程会合并磁盘块(N 路合并),并移除之前使用 DELETE 语句删除的文档。
从 Manticore 4 开始,此过程默认自动执行。但是,您也可以使用以下命令手动启动表压缩。
OPTIMIZE TABLE table_name [OPTION opt_name = opt_value [,...]]
OPTIMIZE 语句会将 RT 表添加到优化队列中,该队列将在后台线程中处理。
- SQL
- JSON
OPTIMIZE TABLE rt;POST /sql?mode=raw -d "OPTIMIZE TABLE rt"默认情况下,OPTIMIZE 会将 RT 表的磁盘块合并到小于或等于逻辑 CPU 核心数乘以 2 的数量。
但是,如果表具有带有 KNN 索引的属性,则此阈值不同。在这种情况下,它设置为物理 CPU 核心数除以 2,以提高 KNN 搜索性能。
您还可以使用 cutoff 选项手动控制优化的磁盘块数量。
其他选项包括:
- 服务器设置 optimize_cutoff 用于覆盖默认阈值
- 每表设置 optimize_cutoff
- SQL
- JSON
OPTIMIZE TABLE rt OPTION cutoff=4;POST /sql?mode=raw -d "OPTIMIZE TABLE rt OPTION cutoff=4"使用 OPTION sync=1(默认为 0)时,命令将在优化过程完成后才返回。如果连接中断,优化将在服务器上继续运行。
- SQL
- JSON
OPTIMIZE TABLE rt OPTION sync=1;POST /sql?mode=raw -d "OPTIMIZE TABLE rt OPTION sync=1"优化可能是一个漫长且 I/O 强度高的过程。OPTIMIZE 语句会将任务添加到后台工作池中。您可以使用 parallel_chunk_merges 控制并行运行的任务数量,使用 merge_chunks_per_job 控制每个任务合并的块数。优化工作线程可以被 I/O 限流,您可以使用 rt_merge_iops 和 rt_merge_maxiosize 指令分别控制每秒最大 I/O 数和最大 I/O 大小。
在优化期间,正在优化的 RT 表几乎始终在线,并且可用于搜索和更新。当一对磁盘块成功合并时,表会被短暂锁定,以允许重命名旧文件和新文件并更新表头。
只要 auto_optimize 未被禁用,表就会自动优化。
如果您遇到意外的 SST 或希望集群中所有节点的表二进制相同,您需要:
- 禁用 auto_optimize。
- 手动优化表:
在其中一个节点上,从集群中删除表:
- SQL
- JSON
ALTER CLUSTER mycluster DROP myindex;POST /sql?mode=raw -d "ALTER CLUSTER mycluster DROP myindex"- SQL
- JSON
OPTIMIZE TABLE myindex;POST /sql?mode=raw -d "OPTIMIZE TABLE myindex"优化表:
将表重新添加到集群中:
- SQL
- JSON
ALTER CLUSTER mycluster ADD myindex;POST /sql?mode=raw -d "ALTER CLUSTER mycluster ADD myindex"当表重新添加到集群中时,优化过程创建的新文件将被复制到集群中的其他节点。 其他节点上对表的任何本地更改都将丢失。
表数据修改(插入、替换、删除、更新)应:
- 延迟,或
- 指向正在运行优化过程的节点。
请注意,当表不在集群中时,插入/替换/删除/更新命令应不带集群名称前缀引用它(对于 SQL 语句或 HTTP JSON 请求中的集群属性),否则它们将失败。 一旦表重新添加到集群中,您必须恢复对表的写入操作并再次包含集群名称前缀,否则它们将失败。
在过程中,搜索操作在任何节点上都可以正常使用。
Manticore 在实时表的刷新和合并过程中提供隔离,防止任何更改影响正在运行的查询。
例如,在表压缩期间,一对磁盘块会被合并并产生一个新的块。在某个时刻,会创建表的新版本,新块替换了原始的这一对块。这一过程是无缝进行的,因此使用原始块的长时间运行的查询将继续看到旧版本的表,而新的查询将看到包含合并后块的新版本。
同样适用于刷新 RAM 块的情况,此时合适的 RAM 段会被合并成新的磁盘块,而参与的 RAM 块段则被放弃。在此操作期间,Manticore 对操作开始前启动的查询提供隔离。
此外,这些操作对替换和更新是透明的。如果您更新属于正在与另一个块合并的磁盘块中的文档的属性,更新将应用于该块和合并后生成的新块。如果在合并期间删除文档,该文档将同时在原始块和合并后生成的新块中被删除,新块要么将该文档标记为已删除,要么如果删除发生在合并过程的早期,则根本不会包含该文档。
“冻结”表在你想制作物理副本或备份时很有用。它会将表文件标记为已冻结,并显示这些文件的存放位置。冻结后,你可以安全地将这些文件复制到其他地方。被冻结的表仍然可以继续添加新文档,直到达到 rt_mem_limit,但这些新数据只会留在内存中,在表解冻之前不会写入磁盘。如果表超过了 rt_mem_limit,所有更改都会暂停,直到表被解冻。如果守护进程意外停止,任何未保存的数据都会从 binlog 中恢复。
“锁定”表适用于逻辑备份。它不会停止内部维护任务,例如磁盘块合并操作或将 RAM 块写入磁盘。它只会阻止写入操作。这意味着你不能向已锁定的表中插入、替换或更新数据。这对 mysqldump 之类的工具很有帮助,因为锁定可以确保数据在逻辑上保持一致。比如说,如果在转储期间替换了一条文档记录,在没有锁的情况下,旧版本可能已经出现在转储里,而新版本也可能随后出现,而且两者的文档 ID 相同。锁定表可以避免这种情况。
FREEZE tbl1[, tbl2, ...]
FREEZE 会让一个实时/普通表为安全的 备份 做好准备。具体来说,它会:
- 停用表压缩。如果表当前正在压缩,
FREEZE会优雅地中断它。 - 将当前 RAM 块转移为磁盘块。
- 刷新属性。
- 禁用可能修改磁盘文件的隐式操作。
- 增加表的锁定计数器。
- 显示与该表关联的实际文件列表。
如果表已经处于冻结(锁定)状态,FREEZE 会:
- 增加表的锁定计数器。
- 显示与该表关联的实际文件列表。
内置工具 manticore-backup 使用 FREEZE 来确保数据一致性。如果你想创建自己的备份方案,或者出于其他原因需要冻结表,也可以照做。只需按以下步骤执行:
- 冻结一张表(或几张)。
- 捕获
FREEZE命令的输出,并备份指定的文件。 - 完成后对表执行
UNFREEZE。
- Example
FREEZE t;+-------------------+---------------------------------+
| file | normalized |
+-------------------+---------------------------------+
| data/t/t.0.spa | /work/anytest/data/t/t.0.spa |
| data/t/t.0.spd | /work/anytest/data/t/t.0.spd |
| data/t/t.0.spds | /work/anytest/data/t/t.0.spds |
| data/t/t.0.spe | /work/anytest/data/t/t.0.spe |
| data/t/t.0.sph | /work/anytest/data/t/t.0.sph |
| data/t/t.0.sphi | /work/anytest/data/t/t.0.sphi |
| data/t/t.0.spi | /work/anytest/data/t/t.0.spi |
| data/t/t.0.spm | /work/anytest/data/t/t.0.spm |
| data/t/t.0.spp | /work/anytest/data/t/t.0.spp |
| data/t/t.0.spt | /work/anytest/data/t/t.0.spt |
| data/t/t.meta | /work/anytest/data/t/t.meta |
| data/t/t.ram | /work/anytest/data/t/t.ram |
| data/t/t.settings | /work/anytest/data/t/t.settings |
+-------------------+---------------------------------+
13 rows in set (0.01 sec)file 列表示运行中的实例在 data_dir 内对应的表文件路径。normalized 列显示这些文件的绝对路径。要备份表,只需直接复制提供的文件,无需额外准备。
当表被冻结时,你不能执行 UPDATE 查询;它们会一直等待到表解冻为止。
另外,在表被冻结期间,DELETE 和 REPLACE 查询也有一些限制:
- 如果
DELETE作用于当前 RAM 块中的文档,则允许执行。 - 如果
DELETE影响的是磁盘块中的文档,但该文档之前已经被删除,则允许执行。 - 如果
DELETE会修改实际的磁盘块,则会等待直到表被解冻。
手动对冻结表的 RAM 块执行 FLUSH 会返回“success”,但实际上不会发生真正的保存。
冻结表上的 DROP/TRUNCATE 是允许的,因为这些操作不是隐式的。我们假设如果你要截断或删除一张表,就不需要为它做备份;因此,它本来就不应该被冻结。
向冻结表执行 INSERT 是支持的,但有上限:新数据会像平常一样先存入 RAM,直到达到 rt_mem_limit;之后新的插入会等待,直到表解冻。
如果你在有冻结表的情况下关闭守护进程,它的行为会像经历了一次非正常关机(例如 kill -9):新插入的数据不会被保存到磁盘上的 RAM 块中,重启后会从二进制日志中恢复(如果有的话),否则就会丢失(如果禁用了二进制日志)。
UNFREEZE tbl1[, tbl2, ...]
UNFREEZE 命令会减少表的锁定计数器;当它降到零时,会重新激活此前被阻塞的操作,并恢复内部压缩服务。任何正在等待表解冻的操作也会恢复并正常完成。
- Example
UNFREEZE tbl;你可以使用 SHOW table_name STATUS 来检查表是否被冻结。
锁定计数器会在表状态的 locked 列中显示。值为零表示表未被冻结,而非零值表示当前活动锁的数量。每一次显式的 FREEZE 命令,以及每一次隐式锁定(例如表属于一个集群,而复制流程将其选为副本的 donor)都会增加这个计数器。每一次 UNFREEZE 命令都会减少该计数器,最终降到零。
- Example
SHOW TABLE `foo` STATUS LIKE 'locked';+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| locked | 2 |
+---------------+-------+
1 row in set (0,00 sec)lock tables tbl1 read[, tbl2 read, ...]
你可以在 SQL 客户端会话中显式锁定表,以便与其他会话协调访问,或者在你需要独占访问时阻止其他会话修改数据。一个会话只能为自己锁定或解锁表,不能代替其他会话进行锁定或解锁。锁只能在通过 MySQL 协议连接的 SQL 会话中使用。表被锁定时,任何协议都不能修改其数据(SQL / HTTP / binary)。锁也不适用于属于复制集群的表。
Manticore 只支持 读(共享) 锁,不支持 写(独占) 锁。
当会话请求读锁时,Manticore 会:
- 检查连接是否使用 MySQL 协议。
- 检查该表是否可以被锁定。它必须是本地的实时表或 percolate 表,并且不能属于复制集群。
- 自动释放该会话已经持有的任何锁。
- 等待该表上所有正在进行的 insert、replace、update 或 delete 操作完成。
- 增加表的读锁计数器(参见 SHOW LOCKS)。
任何修改语句(DML),例如 INSERT、REPLACE、UPDATE、DELETE 和 TRUNCATE,都会先检查表是否被读锁锁定。如果是,语句会因 table is locked 错误而失败。DDL 语句(例如 CREATE、ALTER、DROP)不受读锁阻止。
- Example
--------------
LOCK TABLES tbl READ
--------------
Query OK, 0 rows affected (0.000 sec)
--------------
LOCK TABLES tbl READ, tbl2 WRITE
--------------
Query OK, 0 rows affected, 1 warning (0.000 sec)
--------------
SHOW WARNINGS
--------------
+---------+------+--------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------+
| warning | 1000 | Write lock is not implemented. |
+---------+------+--------------------------------+
1 row in set (0.000 sec)UNLOCK TABLES 命令会显式释放当前 SQL 会话持有的任何表锁。
如果客户端会话的连接终止,无论是正常还是异常,守护进程都会隐式释放该会话持有的所有 表锁。如果客户端重新连接,这些锁就不再生效。
- Example
UNLOCK TABLES;SHOW LOCKS 命令会列出当前所有已锁定或已冻结的表。
每一行都会显示表类型、表名、锁的类型,以及表示该锁被应用了多少次的计数器。
锁类型 可以是:
read— 表受读锁保护。修改语句会失败,直到锁被释放。freeze— 表处于冻结状态。这会阻止任何会将数据写入磁盘的操作,直到表被解冻。
- Example
SHOW LOCKS;+-----------+------+-----------+-----------------+
| Type | Name | Lock Type | Additional Info |
+-----------+------+-----------+-----------------+
| rt | a | read | Count: 1 |
| percolate | bar | freeze | Count: 3 |
| rt | foo | freeze | Count: 2 |
+-----------+------+-----------+-----------------+
3 rows in set (0,01 sec)