表中数据的大量更新 - 最佳方法?

时间:2017-02-19 15:33:42

标签: mysql database-design

我有类似下面的查询:

go get golang.org/x/tools/cmd/guru

我担心MySQL可能会查看整个表并在整个数据集上设置锁定以进行更新。因此,如果这个单个UPDATE语句发生在数百万个客户身上,并且f_SumAssetCosts甚至只需要很短的时间来处理,那么整个过程可能会锁定表整整几秒,可能是几分钟。在高事务系统中,这是不可取的,客户行可能会经常读取/更新。

首先,当整个操作正在运行时,MySQL会在整个表上放置一个锁(对于UPDATE / DELETE)吗?

其次,只是为了确认我的知识,即使在UPDATE期间从这个表中选择是否仍然可以?我假设UPDATE语句尚未提交"已提交"它的更改,所以任何SELECT运行期间将返回最后的已知提交值?它不能正确锁定读取并等待UPDATE完成?

我正在考虑将SELECT Id FROM客户中的整个操作分解为临时表,然后将光标循环到表上,以便运行一个UPDATE ...调用而不执行任何大量锁定(如果我对上面的巨大锁定的假设是正确的)。

1 个答案:

答案 0 :(得分:1)

如果您担心两者功能的成本以及正在进行的事务和锁定,那么您可能希望批量执行此操作。如果该值当前为NULL而新值不是,那么这很容易:

UPDATE customers 
    SET AssetsTotal = f_SumAssetCosts(c.Id)
    WHERE AssetsTotal IS NOT NULL
    LIMIT 1000;  -- or whatever

这将每次更新一小部分客户,限制锁定以及表格不可用的时间段。

如果值未以NULL开始,则会变得棘手。在这种情况下,您可以将其设置为NULL。 。 。有点贵但比功能调用便宜。

根据具体要求,还有其他方法:

  • 添加一列以指定列是否已更新。
  • 重新生成整个表,使用truncate并重新插入/重命名重新生成表。
  • 在另一个表中执行所有计算,使用join将其带入,并从另一个表中删除。

注意事项是:

  • 是否所有更新都必须同时出现?
  • 什么是交易负载?
  • 功能有多贵?