如果在父节点上运行TransactionBlock会发生什么



代码:

public func emailExists(email: String, exists: @escaping ((Bool) -> Void)) {

let safeEmail = DatabaseManager.safeEmail(emailAddress: email)

database.child(safeEmail).runTransactionBlock ({ (currentData: MutableData) -> TransactionResult in

guard currentData.value as? [String: Any] != nil else {
print("   Email doesn't exist")

database.child(safeEmail).setValue([ *SomeData* ])

exists(false)
return TransactionResult.success(withValue: currentData)
}

exists(true)
return TransactionResult.success(withValue: currentData)

})
}

如果我在主父节点上运行TransactionBlock,这会锁定整个数据库,直到事务完成(或不完成)?如果多个用户同时调用此函数,那么实现此功能会是个坏主意吗?

Firebase实时数据库中的事务并不是真正锁定节点,而是比较和设置操作。

当您在节点上运行事务时,客户端会调用您的回调,并使用其对该节点值的当前猜测(通常是第一次null)。然后告诉它整个节点的新值应该变成什么。

客户端将这两个值(当前值和新值)发送到服务器,服务器检查当前值是否与客户端猜测的值相同。如果它是相同的,它会将结果写入数据库。如果它不相同(通常不会是第一次),它会告诉客户端写入被拒绝,并为其提供数据库中节点的实际值。然后,客户端使用当前值的更新猜测来调用回调。

这种情况一直重复,直到服务器能够提交新值(因为当前值未修改),或者直到尝试次数用完。


在数据库节点中运行更高级别的事务意味着:

  1. 您正在从数据库中请求更多数据
  2. 对数据进行冲突写入(称为争用)的可能性更大

建议在数据库中尽可能低地运行事务,实际上,将数据移动/复制到更低的数据库中以实现这一点是很常见的。

在JSON结构中运行过高的事务可能会导致争用问题,这种情况通常只有在系统上有足够的并发用户时才会发生,因此最好尽早防止这种情况发生。

相关内容

  • 没有找到相关文章

最新更新