You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用UPDATE语句更新Room数据库变量时进度值丢失问题排查

问题分析与解决方案

问题核心

跨设备分片传输文件时,每次迭代从Room数据库读取当前progressDownload值,加上本次传输的transport.count后更新回数据库,但部分更新未被持久化,导致进度条无法达到100%。

原因诊断

这是典型的并发竞态条件:多个协程/线程同时读取数据库中的旧进度值,各自计算累加后执行更新,后执行的更新会覆盖先执行的,导致中间的传输字节数丢失。

代码问题展示

Dao层代码

@Query("UPDATE FileItem SET progressDownload = :value WHERE uuid = :uuid")
suspend fun updateProgressDownload(uuid: String, value: Long)

Repository实现

override suspend fun updateProgressDownload(uuid: String, value: Long) {
    fileDao.updateProgressDownload(uuid, value)
}

ViewModel逻辑

val currentValueDataBase = roomRepository.getItemByUuid(it)?.progressDownload
val addANewValueToThePrevious = currentValueDataBase?.plus(transport.count)
if (addANewValueToThePrevious != null) {
   roomRepository.updateProgressDownload(it, addANewValueToThePrevious)
}

日志现象

日志显示多次进度更新操作中,部分累加后的进度值未被正确写入数据库,最终存储的进度值低于文件总大小对应的100%数值。

解决方案

方案1:数据库端原子更新(推荐)

直接在SQL语句中完成累加操作,利用数据库的原子性保证更新不丢失:

  1. 修改Dao层方法:
@Query("UPDATE FileItem SET progressDownload = progressDownload + :value WHERE uuid = :uuid")
suspend fun incrementProgressDownload(uuid: String, value: Long)
  1. 更新Repository实现:
override suspend fun incrementProgressDownload(uuid: String, value: Long) {
    fileDao.incrementProgressDownload(uuid, value)
}
  1. 简化ViewModel逻辑:
roomRepository.incrementProgressDownload(it, transport.count)

这种方式将累加操作放在数据库层面执行,单个UPDATE语句是原子的,完全避免竞态问题。

方案2:协程互斥锁控制

如果业务逻辑必须先读取值再处理,可以用Mutex保证同一时间只有一个协程执行读写操作:

  1. 在Repository中添加互斥锁:
private val progressUpdateMutex = Mutex()

override suspend fun updateProgressDownload(uuid: String, addValue: Long) {
    progressUpdateMutex.withLock {
        val currentProgress = fileDao.getItemByUuid(uuid)?.progressDownload ?: 0L
        fileDao.updateProgressDownload(uuid, currentProgress + addValue)
    }
}
  1. ViewModel中直接调用该方法即可,无需自行计算:
roomRepository.updateProgressDownload(it, transport.count)

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:33:23