Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 没有净影响的事务是否会触及磁盘上的数据库?_Mysql_Mariadb - Fatal编程技术网

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时,差异中的硬件因素较少甚至不明显。忘了提一下。。