c# - 解决数据库竞争条件的最佳方法
问题描述
我有一个保存电影字幕的应用程序。我需要防止出现 2 个字幕重叠的情况。首先,我将定义什么是重叠字幕。假设字幕类有 MovieId、EntryTime、ExistTime 和 Text。EntryTime 是一个数字,表示在电影中显示字幕的时间(以毫秒为单位),而 ExistTime 是在电影中消失的时间。如果我们有 2 个标题如下
var caption1 = new Caption(){MovieId = 1, EntryTime = 100, ExistTime =200}
var caption2 = new Caption(){MovieId = 1, EntryTime = 120, ExistTime =220}
它们是重叠的,但以下标题不是
var caption3 = new Caption(){MovieId = 1, EntryTime = 400, ExistTime =450}
var caption4 = new Caption(){MovieId = 2, EntryTime = 425, ExistTime =470}
所有电影的所有字幕都保存在同一个数据库中,数据库中有同一个表。
为了避免插入重叠的标题,我首先尝试在我的服务器代码中加锁。此代码专门检查标题的 EntryTime 和 EndTime 并且不检查重叠场景,但此检查应支持重叠情况
lock (insertCaptionLocker)
{
var captionExists = dbCaptions.Captions.Any(x =>
x.MovieId == caption.MovieId && x.EntryTime == caption.EntryTime &&
x.ExitTime == caption.ExitTime);
if (!captionExists)
{
dbCaptions.Captions.InsertOnSubmit(caption);
}
dbCaptions.SubmitChanges();
}
我对这段代码有一些问题:
- 它并不总是一个关键部分 - 大多数时候允许超过 1 个线程进入此代码应该是可以的。仅当我们有 2 个线程(或更多)尝试更新具有重叠时间的相同 MovieId 时,我们才会遇到问题。
- 如果我们有超过 1 个服务器与负载平衡器连接,它将无法工作。
我认为解决方案应该以某种方式来自数据库,但我不知道该使用什么。任何帮助将不胜感激。
解决方案
一个观察:
您的条件仅检查给定 MovieId 是否已经存在具有相同 EntryTime 和 ExistTime 的字幕,它不会检查它们是否重叠。
对于非重叠,您应该检查类似这样的内容,检查每对的开始和结束时间:
var non_overlapping = dbCaptions.Captions.Any(x =>
x.MovieId == caption.MovieId &&( x.EntryTime < caption.EntryTime && x.ExitTime < caption.EntryTime || x.EntryTime > caption.EntryTime && caption.ExitTime < x.EntryTime )
这对将不重叠,因此您可以插入它们。使用您的方法,您将获得完全相同的标题,但不是所有重叠的标题,ypu 还可以定义一个范围并检查您的元组(x.EntryTime ,x.ExitTime)
是否在range(caption.EntryTime ,caption.ExitTime)
.
推荐阅读
- moving-average - 移动平均线只显示到最后一个ticker.id close
- robotframework - 阅读直到在机器人框架中使用不断变化的提示
- r - 如何在 GGPlot 中插入调色板?
- python - 从 SFTP 服务器解析 CSV 太慢,如何提高效率?
- node.js - React-Router 可以直接指向使用 Express 定义的路由而不是渲染组件吗?
- machine-learning - 在 sklearn 中运行管道时出现 PicklingError
- reactjs - 在 React Native Navigation 中处理页面转换
- docker - ansible docker_compose 网络
- node.js - Electron: How to import or include CSS installed using npm package manager in our index.html?
- git - git pull 后如何获取未提交的文件?