在这种情况下,我需要更新一些表行,将没有出现在外部数据源中的行标记为禁用(即更新active=0)。直截了当的解决方案是对事务进行BEGIN,将每一行UPDATE转换为active=0,然后扫描远程数据,对应该是active=1的每个条目执行UPDATE以将其放回。我有大约1k行,所以这应该是一个相对快速的操作,即使存在很多效率低下的查询解析。
然而,这些数据往往根本不会改变。因此,在大多数情况下,事务的净影响将为零变化。如果数据库引擎将解决整个问题,则检测什么都没有改变,而不是因此而改变任何东西,这将是理想的。但是,如果每次都要遍历并实际更新每一行,我宁愿找到另一种解决方案。
发布于 2019-08-26 17:10:46
这是一个演示。我在一行中创建了一个只有一个简单整数的表。
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注意Changed: 0。
查看日志写入,它也没有改变:
mysql> show status like 'innodb_log_write_requests';
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| Innodb_log_write_requests | 5432153 |
+---------------------------+---------+发布于 2019-08-26 20:21:39
我认为已经有了很大的结论,您的非操作有磁盘I/O。让我们来讨论眼前的任务:
与实际修改数据库不同,您能否在内存中保留可能被禁用的项的列表?完成扫描后,如果有任何要禁用的,则继续禁用单个UPDATE ... WHERE id IN (...)中的所有
另一个话题..。如果你真的这么做
BEGIN;
UPDATE a=0; -- for all rows
COMMIT;
-- all are disabled briefly
BEGIN;
UPDATE a=1 WHERE id = ... -- one row at a time
COMMIT;然后你就有了一个窗口,所有的东西都被禁用了。你可能不想那样。
https://stackoverflow.com/questions/57661889
复制相似问题