Mysql 没有净影响的事务是否会触及磁盘上的数据库?
在这种情况下,我需要更新一些表行,将没有出现在外部数据源中的表行标记为禁用(即更新Mysql 没有净影响的事务是否会触及磁盘上的数据库?,mysql,mariadb,Mysql,Mariadb,在这种情况下,我需要更新一些表行,将没有出现在外部数据源中的表行标记为禁用(即更新active=0)。直接的解决方案是开始事务,将每一行更新为active=0,然后扫描远程数据,对每个应为active=1的条目执行更新,将其放回。我有大约1k行,所以这应该是一个相对快速的操作,即使有很多低效的查询解析 然而,这些数据通常根本不会改变。因此,在大多数情况下,交易的净影响为零变化。如果数据库引擎能够解决整个问题,检测到没有任何变化,并且不会因此而改变任何东西,那将是理想的。然而,如果它要通过并实际更
active=0
)。直接的解决方案是开始
事务,将每一行更新为active=0
,然后扫描远程数据,对每个应为active=1
的条目执行更新
,将其放回。我有大约1k行,所以这应该是一个相对快速的操作,即使有很多低效的查询解析
然而,这些数据通常根本不会改变。因此,在大多数情况下,交易的净影响为零变化。如果数据库引擎能够解决整个问题,检测到没有任何变化,并且不会因此而改变任何东西,那将是理想的。然而,如果它要通过并实际更新每一行,每次,我宁愿找到另一个解决方案。这里是一个演示。我创建了一个表,其中一行只有一个简单的整数
mysql> create table t ( i int );
mysql> insert into t set i = 42;
我检查当前的日志写入次数
mysql> show status like 'innodb_log_write_requests';
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| Innodb_log_write_requests | 5432152 |
+---------------------------+---------+
然后使用更新更改行中的值,并确认它导致日志写入:
mysql> update t set i = 43;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> show status like 'innodb_log_write_requests';
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| Innodb_log_write_requests | 5432153 |
+---------------------------+---------+
接下来,进行一次没有净效果的更新
mysql> update t set i = 43;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
注意已更改:0
查看日志写入,它也保持不变:
mysql> show status like 'innodb_log_write_requests';
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| Innodb_log_write_requests | 5432153 |
+---------------------------+---------+
我认为基本上已经得出结论,您的no-op存在磁盘I/O。让我们讨论一下手头的任务:
您是否可以在内存中保留可能被禁用的项的列表,而不是实际修改数据库?完成扫描后,如果有任何要禁用的,则在一次更新中继续禁用所有。。。其中id位于(…)
关于另一个话题。。。如果你真的这么做了
BEGIN;
UPDATE a=0; -- for all rows
COMMIT;
-- all are disabled briefly
BEGIN;
UPDATE a=1 WHERE id = ... -- one row at a time
COMMIT;
然后你有一个窗口,所有的东西都被禁用了。您可能不希望这样。开始的时候是启动事务,MySQL在您提交后不会更改表/索引文件。。这意味着事务中的所有更新/插入都会立即刷新到磁盘。@RaymondNijland,如果InnoDB修改的页面超出缓冲池的容量,您认为InnoDB如何处理未提交的事务?“如果InnoDB修改的页面超出缓冲池的容量,您认为InnoDB如何处理未提交的事务?”WAL(预写日志)这是一个磁盘文件。。。是的@BillKarwin mine的评论简化了很多…如果WAL在日志文件的开头写了换行符,它必须开始将修改过的页面刷新到磁盘,刷新到表空间中,即使这些修改过的页面仍然未提交。根据您扫描远程数据和准备更新的方式,跟踪更新可能会更容易。一旦所有更新都启动了事务,请执行所有更新并提交。如果没有任何更新,就什么也不做。聪明的做法是查看日志写入请求,以确定我是否访问了磁盘。我刚刚进一步确认,在事务中取消的一对更新不会更改write requests变量。InnoDB是一个复杂的引擎@JamesK,因为InnoDB也可以这样做,在这些情况下,它也可能会执行“意外的”磁盘I/O。。我想说的是,在(可能是分离的)SSD上配置这些重做日志,以保持非常高的性能。@RaymondNijland您是否曾经将重做日志移动到单独的存储设备上,并使其产生很大的不同?我认为情况并非如此。如果在重做写入时性能受到限制,那么将其移动到另一个设备只会带来轻微的改善,因为在这一点上,写入很可能会一直增加,直到它们使单独的存储设备饱和。在缓冲池很冷的情况下,所有/大多数查询也需要访问磁盘,事实上,我注意到将重做日志分离到另一个磁盘的差异(很小)。。在RDMS中,磁盘IOPS不可用性能可能损失的临界点也很重要,因为在同一时间/qeuries正在运行多少事务。为什么要浪费磁盘IOPS来记录日志?我认为这是一个意见问题。。但是现在冷缓冲池已经不是什么稀奇的事情了,因为当需要重新启动时,可以在更现代的MySQL版本中转储和重新加载缓冲池。。。。当您完全在SSD/SSHD(混合)上运行,并且没有使用硬盘7200/10000/15000 rpm时,差异中的硬件因素较少甚至不明显。忘了提一下。。