【问题标题】:mysql : understanding innodb log operationsmysql : 了解 innodb 日志操作
【发布时间】:2022-01-02 17:17:29
【问题描述】:

在将更改写入 innodb 存储引擎中的二进制日志时,我试图了解这 3 个变量

sync_binlog

innodb_flush_log_at_trx_commit

innodb_flush_log_at_timeout

在这里阅读了几次文档后,我对这些变量的理解是什么

sync_binlog

0  -> Operating system decides when to write log to disk(whenever it has free time)
1  -> after every commit changes written to disk(safest)
N  -> after N commits changes written to disk

innodb_flush_log_at_trx_commit

0 -> written and flushed to disk once per second
1 -> written and flushed after every commit(safest)
2 -> written after every commit and flushed to disk once per second

innodb_flush_log_at_timeout

after N seconds of delay logs are written to file

所以作为一个实验,这是我想要实现的目标

1)在提交 5 个事务之前,不应将任何事务写入日志

2) 提交 5 个事务后,我希望 innodb 等待 10 秒,然后将这些事务写入日志

所以我将变量设置如下

SET @@GLOBAL.sync_binlog=5;                          #Don't write anything until 5 commits have been done?
SET @@GLOBAL.innodb_flush_log_at_trx_commit=0;       #Maybe? because logs are written every second regardless if they are commited or not?
SET @@GLOBAL.innodb_flush_log_at_timeout=10;         #After 5 commit's wait for 10 seconds before writing the transaction's to disk?

如您所见,我到处都放了问号,因为我不知道自己在做什么。 而且这些设置不起作用。每次提交后,我都会立即在日志中看到更改更新

基本上我有一个测试表

CREATE TABLE Test(TestCol INT);

我将 5 个事务的[auto commit is on] 作为 5 个插入语句发出

INSERT INTO Test VALUES(1);
INSERT INTO Test VALUES(2);
INSERT INTO Test VALUES(3);
INSERT INTO Test VALUES(4);
INSERT INTO Test VALUES(5);

我想要的是,如果我插入值让我们说只有 1 到 4,那么我不想看到日志文件中的任何更改,但是一旦我插入 5 以及总共 5 个事务然后我想要让 innodb 在将这些事务写入日志之前等待 10 秒,这样我就有足够的时间打开 我的文件资源管理器并运行

mysqlbinlog --verbose --base64-output=DECODE-ROWS binlog.000001

查看我的日志文件中的更改

但即使我只插入一个值并打开我的日志文件,我也会立即看到该插入。

我的目标甚至可能吗?有人能解释一下这些变量是如何工作的吗?如果可能的话,还有一个替代解决方案可以解决我的问题吗?

任何澄清将不胜感激

【问题讨论】:

    标签: mysql transactions innodb mysqlbinlog


    【解决方案1】:

    sync_binlog 仅控制文件何时同步到磁盘。当您提交事务时,事务仍会立即写入逻辑文件,它们只是由操作系统缓冲。如果您使用程序(例如 mysqlbinlog)读取同一文件,则会读取所有内容,包括操作系统缓冲区中的内容。操作系统会自动将缓冲区与磁盘上的内容合并。

    我不知道有什么方法可以让 MySQL 在提交时延迟写入二进制日志。有一个 binlog 缓冲区,但它用于在事务提交之前累积更改。一旦你提交,它应该立即写入binlog,因为其他会话可能也想写入binlog,并且提交应该按照提交时间的顺序写入。

    同样,对 innodb 重做日志的写入是连续的。您命名的刷新选项仅控制文件同步到磁盘的时间。与此同时,对日志文件的写入仍在发生,但可能会被操作系统缓冲。操作系统可能会选择在 innodb 强制同步之前刷新缓冲的 I/O。

    我不认为你可以做你想做的事。我不知道您为什么要这样做,因为它会破坏耐用性。假设您可以让 InnoDB 在提交 5 个事务之前不将事务保存到重做日志。如果您提交其中 4 个事务并突然崩溃,那么您将丢失这 4 个事务。


    你的评论:

    https://bugs.mysql.com/bug.php?id=69309有更多解释:

    N 秒写入并刷新一次日志。 innodb_flush_log_at_timeout 在 MySQL 5.6.6 中引入。它允许之间的超时时间 冲洗量增加,以减少冲洗并避免影响 二进制日志组提交的性能。在 MySQL 5.6.6 之前,刷新 频率是每秒一次。默认设置为 innodb_flush_log_at_timeout 也是每秒一次。

    错误日志声称此解释将添加到文档中,但我猜它从未出现过。

    如果您的事务率太高以至于同步日志文件成为瓶颈,听起来这个选项是为了降低持久性。见https://dev.mysql.com/worklog/task/?id=5223

    在我看来,如果您的事务率如此之高以至于无法跟上每秒一次的 fsync,那么您需要考虑如何重新设计您的架构。即使您延长 fsync 之间的间隔,也会给您的数据带来风险,并且您不能永远延长它。您需要更好的策略来管理不断增长的交易率。通常这意味着将数据库拆分为“分片”,以便每个事务写入多个服务器之一。

    【讨论】:

    • 但是 flush_log_at_timeout 变量是干什么用的。他们已经明确提到它会引入延迟以减少 I/O?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-02
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多