OPTIMIZE TABLE 似乎“锁定”表(innodb)

cla*_*rkk 1 mysql innodb mysql-5.7

在大表上执行期间,OPTIMIZE TABLE该过程似乎“锁定”了表。您可以采取一些措施来加快该过程或防止它“锁定”表吗?

执行时应用程序/服务超时OPTIMIZE TABLE

mysql 5.7.36

我的cnf

[mysqld]

# GENERAL #
user                           = mysql
port                           = 3306
default_storage_engine         = InnoDB
pid-file                       = /var/run/mysqld/mysqld.pid
socket                         = /var/run/mysqld/mysqld.sock

# SAFETY #
max_allowed_packet             = 16M
max_connect_errors             = 1000000
skip_name_resolve
sql_mode                       = STRICT_ALL_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO
sysdate_is_now                 = 1
symbolic_links                 = 0

# DATA STORAGE #
datadir                        = /var/lib/mysql/

# BINARY LOGGING #
server_id                      = 1
log_bin                        = /var/lib/mysql/mysql-bin
expire_logs_days               = 10
sync_binlog                    = 1
log_bin_trust_function_creators= 1
binlog_format                  = ROW
master_verify_checksum         = 1

# REPLICATION #
gtid_mode                      = ON
enforce_gtid_consistency

# CACHES AND LIMITS #
tmp_table_size                 = 64M
max_heap_table_size            = 64M
query_cache_type               = 0
query_cache_size               = 0
max_connections                = 500
thread_cache_size              = 50
open_files_limit               = 65535
table_definition_cache         = 4096
table_open_cache               = 4096

# INNODB #
innodb_flush_method                 = O_DIRECT
innodb_log_files_in_group           = 2
innodb_log_file_size                = 512M
innodb_log_buffer_size              = 64M
innodb_flush_log_at_trx_commit      = 1
innodb_file_per_table               = 1
innodb_buffer_pool_size             = 40G
innodb_buffer_pool_instances        = 12
innodb_autoinc_lock_mode            = 2

# LOGGING #
log_error                      = /var/lib/mysql/mysql-error.log
log_queries_not_using_indexes  = 1
slow_query_log                 = 1
slow_query_log_file            = /var/lib/mysql/mysql-slow.log
long_query_time                = 1
Run Code Online (Sandbox Code Playgroud)

小智 6

里克·詹姆斯的答案是非常错误和误导的,所以我觉得有必要提供一个不同的答案。

不锁表执行该语句的要求请参考https://dev.mysql.com/doc/refman/5.7/en/optimize-table.html 。从该页面:

OPTIMIZE TABLE 对常规和分区InnoDB 表使用在线 DDL,从而减少并发 DML 操作的停机时间。OPTIMIZE TABLE 触发的表重建就地完成。仅在操作的准备阶段和提交阶段短暂地使用独占表锁。在准备阶段,元数据将被更新并创建中间表。在提交阶段,表元数据更改被提交。

OPTIMIZE TABLE 在以下条件下使用表复制方法重建表:

当 old_alter_table 系统变量启用时。

当使用 --skip-new 选项启动服务器时。

对于包含 FULLTEXT 索引的 InnoDB 表,不支持使用联机 DDL 的 OPTIMIZE TABLE。而是使用表复制方法。

我可以确认,使用正确的配置(例如默认的 AWS MySQL 5.7 Aurora 配置)可以OPTIMIZE TABLE在没有明显表锁的情况下执行。

最后,很容易找到有效的使用案例OPTIMIZE TABLE- 我们最近刚刚遇到一个错误,导致 cron 作业无法删除旧数据,修复后该表有数百 GB 的已分配和未使用空间,为此我们必须向我们的云数据库提供商付费。OPTIMIZE TABLE删除所有分配的未使用空间。