解决数据库竞争条件的最佳方法

时间:2018-07-12 10:12:53

标签: c# sql-server multithreading race-condition

我有一个用于保存电影字幕的应用程序。 我需要防止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重叠时间进行更新时,我们才遇到问题。
  2. 如果我们的负载均衡器连接了多于一台服务器,则将无法正常工作。

我认为解决方案应该以某种方式来自数据库,但是我没有什么用。 任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

观察:

您的条件仅检查对于给定的MovieId,是否已经存在具有相同EntryTime和ExistTime的字幕,而不检查它们是否重叠。

对于非重叠,您应该检查类似这样的内容,检查开始位置和 每对结束时间:

(x.EntryTime ,x.ExitTime)

这对将不重叠,因此您可以插入它们。 使用您的方法,您只会得到完全相同的标题,但并非所有重叠的标题,ypu coul还会定义范围并检查元组range(caption.EntryTime ,caption.ExitTime)是否在Get-ADPrincipalGroupMembership <USERNAME> | Select Name | Export-CSV -path c:\path\filename.csv -NoTypeInformation 中。