Howto:清理 mysql InnoDB 存储引擎?

发布于 2024-09-27 12:09:24 字数 73 浏览 3 评论 0 原文

是否可以清理 mysql innodb 存储引擎,使其不存储已删除表中的数据?

或者我每次都必须重建一个新的数据库?

Is it possible to clean a mysql innodb storage engine so it is not storing data from deleted tables?

Or do I have to rebuild a fresh database every time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

携君以终年 2024-10-04 12:09:24

这是关于 InnoDB 的更完整的答案。这是一个有点漫长的过程,但值得付出努力。

请记住,/var/lib/mysql/ibdata1 是 InnoDB 基础架构中最繁忙的文件。它通常包含六种类型的信息:

  • 表数据
  • 表索引
  • MVCC(多版本并发控制) 数据
    • 回滚段
    • 撤消空格
  • 表元数据(数据字典)
  • 双写缓冲区(后台写入以防止依赖操作系统缓存)
  • 插入缓冲区(管理对非唯一二级索引的更改)
  • 请参阅 ibdata1 的图示

InnoDB 架构

InnoDB Architecture

许多人创建多个 ibdata 文件,希望获得更好的磁盘空间管理和性能,但是这种信念是错误的。

我可以运行 OPTIMIZE TABLE

不幸的是,运行 OPTIMIZE TABLE 针对存储在共享表空间文件 ibdata1 中的 InnoDB 表执行两件事:

  • 表的数据和索引在 ibdata1 内连续
  • 使 code>ibdata1 会增长,因为连续的数据和索引页附加ibdata1

但是,您可以将表数据和表索引与 ibdata1 分离code> 并独立管理它们。

我可以运行 OPTIMIZE TABLE <代码>innodb_file_per_table

假设您要添加 innodb_file_per_table/etc/my.cnf (my.ini)。然后你可以运行 OPTIMIZE TABLE 在所有 InnoDB 表上?

好消息:当您运行使用 rel="noreferrer">innodb_file_per_table 启用,这将为该表生成一个 .ibd 文件。例如,如果表 mydb.mytable 的数据目录为 /var/lib/mysql,它将生成以下内容:

  • /var/lib/mysql/ mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

.ibd 将包含该表的数据页和索引页。伟大的。

坏消息:您所做的只是从 ibdata 中提取 mydb.mytable 的数据页和索引页。每个表的数据字典条目(包括mydb.mytable)仍然保留在数据字典中(请参阅ibdata1 的图形表示)。 此时您不能简单地删除 ibdata1!!!请注意,ibdata1 根本没有缩小。

InnoDB 基础设施清理

要一劳永逸地缩小 ibdata1,您必须执行以下操作:

  1. 将所有数据库转储(例如,使用 mysqldump)到 .sql< /code> 文本文件(下面使用SQLData.sql

  2. 删除所有数据库(mysqlinformation_schema 除外)CAVEAT< /strong> :作为预防措施,请运行此脚本以绝对确保您拥有所有用户授权:

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/。
    chown -R mysql:mysql /var/lib/mysql_grants
    

  3. 登录 mysql 并运行SET GLOBAL innodb_fast_shutdown = 0;(这将完全刷新ib_logfile0中的所有剩余事务更改和 ib_logfile1)

  4. 关闭 MySQL

  5. 将以下行添加到 /etc/my.cnf (或 my.ini 在 Windows 上)

    <前><代码>[mysqld]
    innodb_file_per_table
    innodb_flush_method=O_DIRECT
    innodb_log_file_size=1G
    innodb_buffer_pool_size=4G

    (旁注:无论您设置什么 innodb_buffer_pool_size,请确保 innodb_log_file_sizeinnodb_buffer_pool_size 的 25%。

    另外:innodb_flush_method=O_DIRECT 在 Windows 上不可用)

  6. 删除 ibdata*ib_logfile*,或者,您可以删除 中的所有文件夹/var/lib/mysql/var/lib/mysql/mysql 除外。

  7. 启动 MySQL(这将重新创建 ibdata1 [默认情况下为 10MB] 以及 ib_logfile0ib_logfile1,各 1G)。

  8. 导入SQLData.sql

现在,ibdata1仍然会增长,但只包含表元数据,因为每个InnoDB表将存在于 ibdata1 之外。 ibdata1 将不再包含其他表的 InnoDB 数据和索引。

例如,假设您有一个名为 mydb.mytable 的 InnoDB 表。如果您查看/var/lib/mysql/mydb,您将看到代表该表的两个文件:

  • mytable.frm(存储引擎标头)
  • mytable.ibd (表数据和索引)

使用/etc/my.cnf中的innodb_file_per_table选项,您可以运行OPTIMIZE TABLE mydb.mytable 文件 /var/lib/mysql/mydb/mytable.ibd 实际上会缩小。

在我作为 MySQL DBA 的职业生涯中,我曾多次这样做过。事实上,我第一次这样做时,我将 50GB ibdata1 文件缩小到只有 500MB!

尝试一下。如果您对此还有其他疑问,请询问。相信我;这无论是在短期还是长期都将发挥作用。

警告

在步骤 6 中,如果 mysql 由于 mysql 架构开始被删除而无法重新启动,请返回步骤 2。您创建了 mysql 架构的物理副本。您可以按如下方式恢复:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

返回步骤 6 并继续

UPDATE 2013-06-04 11:13 EDT

关于设置 innodb_log_file_sizeinnodb_buffer_pool_size 在第 5 步中,这是相当老派的一揽子规则。

早在2006年7月3日,Percona 有一篇不错的文章 为什么要选择合适的innodb_log_file_size。后来,2008 年 11 月 21 日,Percona 又发表了另一篇关于如何根据峰值工作负载保持一小时的更改来计算适当的大小

此后,我在 DBA StackExchange 中撰写了有关计算日志大小的帖子,并在其中引用了这两篇 Percona 文章。

就个人而言,我仍然会采用 25% 规则进行初始设置。然后,由于在生产中随着时间的推移可以更准确地确定工作负载,您可以调整日志大小< /a> 在维护周期内仅需几分钟。

Here is a more complete answer with regard to InnoDB. It is a bit of a lengthy process, but can be worth the effort.

Keep in mind that /var/lib/mysql/ibdata1 is the busiest file in the InnoDB infrastructure. It normally houses six types of information:

InnoDB Architecture

InnoDB Architecture

Many people create multiple ibdata files hoping for better disk-space management and performance, however that belief is mistaken.

Can I run OPTIMIZE TABLE ?

Unfortunately, running OPTIMIZE TABLE against an InnoDB table stored in the shared table-space file ibdata1 does two things:

  • Makes the table’s data and indexes contiguous inside ibdata1
  • Makes ibdata1 grow because the contiguous data and index pages are appended to ibdata1

You can however, segregate Table Data and Table Indexes from ibdata1 and manage them independently.

Can I run OPTIMIZE TABLE with innodb_file_per_table ?

Suppose you were to add innodb_file_per_table to /etc/my.cnf (my.ini). Can you then just run OPTIMIZE TABLE on all the InnoDB Tables?

Good News : When you run OPTIMIZE TABLE with innodb_file_per_table enabled, this will produce a .ibd file for that table. For example, if you have table mydb.mytable witha datadir of /var/lib/mysql, it will produce the following:

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

The .ibd will contain the Data Pages and Index Pages for that table. Great.

Bad News : All you have done is extract the Data Pages and Index Pages of mydb.mytable from living in ibdata. The data dictionary entry for every table, including mydb.mytable, still remains in the data dictionary (See the Pictorial Representation of ibdata1). YOU CANNOT JUST SIMPLY DELETE ibdata1 AT THIS POINT !!! Please note that ibdata1 has not shrunk at all.

InnoDB Infrastructure Cleanup

To shrink ibdata1 once and for all you must do the following:

  1. Dump (e.g., with mysqldump) all databases into a .sql text file (SQLData.sql is used below)

  2. Drop all databases (except for mysql and information_schema) CAVEAT : As a precaution, please run this script to make absolutely sure you have all user grants in place:

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
    
  3. Login to mysql and run SET GLOBAL innodb_fast_shutdown = 0; (This will completely flush all remaining transactional changes from ib_logfile0 and ib_logfile1)

  4. Shutdown MySQL

  5. Add the following lines to /etc/my.cnf (or my.ini on Windows)

    [mysqld]
    innodb_file_per_table
    innodb_flush_method=O_DIRECT
    innodb_log_file_size=1G
    innodb_buffer_pool_size=4G
    

    (Sidenote: Whatever your set for innodb_buffer_pool_size, make sure innodb_log_file_size is 25% of innodb_buffer_pool_size.

    Also: innodb_flush_method=O_DIRECT is not available on Windows)

  6. Delete ibdata* and ib_logfile*, Optionally, you can remove all folders in /var/lib/mysql, except /var/lib/mysql/mysql.

  7. Start MySQL (This will recreate ibdata1 [10MB by default] and ib_logfile0 and ib_logfile1 at 1G each).

  8. Import SQLData.sql

Now, ibdata1 will still grow but only contain table metadata because each InnoDB table will exist outside of ibdata1. ibdata1 will no longer contain InnoDB data and indexes for other tables.

For example, suppose you have an InnoDB table named mydb.mytable. If you look in /var/lib/mysql/mydb, you will see two files representing the table:

  • mytable.frm (Storage Engine Header)
  • mytable.ibd (Table Data and Indexes)

With the innodb_file_per_table option in /etc/my.cnf, you can run OPTIMIZE TABLE mydb.mytable and the file /var/lib/mysql/mydb/mytable.ibd will actually shrink.

I have done this many times in my career as a MySQL DBA. In fact, the first time I did this, I shrank a 50GB ibdata1 file down to only 500MB!

Give it a try. If you have further questions on this, just ask. Trust me; this will work in the short term as well as over the long haul.

CAVEAT

At Step 6, if mysql cannot restart because of the mysql schema begin dropped, look back at Step 2. You made the physical copy of the mysql schema. You can restore it as follows:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

Go back to Step 6 and continue

UPDATE 2013-06-04 11:13 EDT

With regard to setting innodb_log_file_size to 25% of innodb_buffer_pool_size in Step 5, that's blanket rule is rather old school.

Back on July 03, 2006, Percona had a nice article why to choose a proper innodb_log_file_size. Later, on Nov 21, 2008, Percona followed up with another article on how to calculate the proper size based on peak workload keeping one hour's worth of changes.

I have since written posts in the DBA StackExchange about calculating the log size and where I referenced those two Percona articles.

Personally, I would still go with the 25% rule for an initial setup. Then, as the workload can more accurate be determined over time in production, you could resize the logs during a maintenance cycle in just minutes.

白芷 2024-10-04 12:09:24

InnoDB引擎不存储已删除的数据。当您插入和删除行时,未使用的空间将在 InnoDB 存储文件中分配。随着时间的推移,总体空间不会减少,但随着时间的推移,“删除和释放”的空间将被数据库服务器自动重用。

您可以通过手动重新组织表来进一步调整和管理引擎使用的空间。为此,请使用 mysqldump 转储受影响表中的数据,删除这些表,重新启动 mysql 服务,然后从转储文件重新创建表。

The InnoDB engine does not store deleted data. As you insert and delete rows, unused space is left allocated within the InnoDB storage files. Over time, the overall space will not decrease, but over time the 'deleted and freed' space will be automatically reused by the DB server.

You can further tune and manage the space used by the engine through an manual re-org of the tables. To do this, dump the data in the affected tables using mysqldump, drop the tables, restart the mysql service, and then recreate the tables from the dump files.

惟欲睡 2024-10-04 12:09:24

我按照本指南进行完全重置(以 root 身份):

mysqldump --all-databases --single-transaction | gzip -c > /tmp/mysql.all.sql.gz
service mysql stop
mv /var/lib/mysql /var/lib/mysql.old; mkdir -m700 /var/lib/mysql; chown mysql:mysql /var/lib/mysql

mysql_install_db                # mysql 5.5
mysqld --initialize-insecure    # mysql 5.7

service mysql start
zcat /tmp/mysql.all.sql.gz | mysql
service mysql restart

I follow this guide for a complete reset (as root):

mysqldump --all-databases --single-transaction | gzip -c > /tmp/mysql.all.sql.gz
service mysql stop
mv /var/lib/mysql /var/lib/mysql.old; mkdir -m700 /var/lib/mysql; chown mysql:mysql /var/lib/mysql

mysql_install_db                # mysql 5.5
mysqld --initialize-insecure    # mysql 5.7

service mysql start
zcat /tmp/mysql.all.sql.gz | mysql
service mysql restart
傲鸠 2024-10-04 12:09:24

似乎没有人提到 innodb_undo_log_truncate 设置可能产生的影响。

看看我的答案 如何收缩/清除MySQL 中的 ibdata1 文件

What nobody seems to mention is the impact innodb_undo_log_truncate setting can have.

Take a look at my answer at How to shrink/purge ibdata1 file in MySQL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文