2013-07-13 5 views
1

Я написал многопоточное приложение, которое каждый поток вызывает процедуру sql-сервера. Мне нужно защитить строку от получения более одного потока. Я хочу, чтобы каждая строка принимала его только одним потоком. Я использовал этот код:Как я могу запустить процедуру по времени?

CREATE PROCEDURE GetRow 
    @ThreadID int 
AS 
BEGIN 

    DECLARE @rowID int; 
    SELECT TOP (1) @rowID=[ID] FROM [TestTable] WHERE [ThreadID] = 0 (AND some other parameters) 

    IF @rowID is not NULL 
    BEGIN 
     UPDATE TOP (1) [TestTable] SET [CallCount] = [CallCount]+1,[ThreadID] = @ThreadID WHERE [ID] = @rowID 

    --some other codes 

    END 
END 

как я сказал, что я запускаю приложение, а затем мое приложение создает 10 потоков, и я устанавливаю threadid для принятия строки только одним потоком, но я видел, что строка, вызываемая более чем 1 потоком и около 4-5 потоков, получает один строка .. как я могу сделать это наилучшим образом, я решил это с помощью этого кода, я не хотел бы иметь два одинаковых места, где в выборе и обновлении:

CREATE PROCEDURE GetRow 
    @ThreadID int 
AS 
BEGIN 

    DECLARE @rowID int; 

    UPDATE TOP (1) [TestTable] SET [CallCount] = [CallCount]+1,[ThreadID] = @ThreadID WHERE [ThreadID] = 0 (AND some other parameters) 


    SELECT TOP (1) @rowID=[ID] FROM [TestTable] WHERE [ThreadID] = @ThreadID (AND some other parameters) 

    IF @rowID is not NULL 
    BEGIN 

    --some other codes 

    END 
END 

Как я могу сделать это с помощью верхнего кода? и должен ли я сначала обновить, а затем выбрать, как указано выше, для его исправления?

+1

Что вы пытаетесь достичь? Я попытался понять, но я не понял ... – jazzytomato

+0

@ Томас Харатик извините, я действительно пытаюсь это объяснить .. Я не хочу выбирать специальную строку в более чем одном потоке .. Я написал процедуру обновления столбца theardid of row to don't позволяют другим потокам выбирать его, но в Sametime другие потоки выбирают его. –

ответ

2

Если вы используете SQL Server 2005 или более поздней версии, вы можете быть в состоянии combine the UPDATE and SELECT с использованием нового OUTPUT clause.

Однако я бы предложил создать резервную копию и подумать о вашей схеме базы данных, и действительно ли она соответствует вашей проблеме - особенно при многопоточности!

У меня создается впечатление, что вы хотите посчитать вызовы из каждой темы. Было бы лучше иметь каждый вызов INSERT строки в простой таблице ThreadCallCount, которая просто имеет один столбец ThreadID. Каждый вызов - это новая строка. Позже вы можете Sum() этой таблицы ThreadID, чтобы получить общее количество вызовов в потоке. Это было бы простым и легким в обеспечении безопасности потоковой передачи.

Похоже, что есть некоторые другие данные, которые вы пытаетесь извлечь, и неясно, как и когда он хранится. Но подобный анализ - и многое другое, более простые таблицы - может вам помочь.

В целом: Не чувствуйте, что вам нужно сжать все это на одном столе. С многопоточным он поможет разбить вещи на более мелкие кусочки. Не стесняйтесь использовать больше таблиц, каждая из которых имеет единую четкую цель. SQL Server предназначен для безопасного и эффективного управления транзакциями строк, поэтому старайтесь максимально использовать это.

+0

tanx много для объяснения, и я использовал 'sql server 2008 r2', я дал вам upvote, и мне нравится ваш метод вставки для подсчета вызовов, поэтому у меня нет лучшего ответа, чем у вас, и я принял ваш ответ, а tanx снова ребята (вы и кодер) –

+1

Большой совет Грег. Id добавляет только это [sp_getAppLock] (http://msdn.microsoft.com/en-us/library/ms189823.aspx) также является полезным методом сериализации вызова хранимой процедуры. Если хранимая процедура громоздка, иногда ее лучше просто заставить другие потоки ждать :) –

1

Я бы порекомендовал запись безопасный код вместо этого это хранится процедура.

Вы не упомянули язык кодирования, в C# один способ обернуть код, который вызывает эту хранимую процедуру внутри lock блока:

using System.Threading 
... 

public class ClassName { 

    object syncLock = new object(); 
    ... 

    SomeFunction(){ 

     lock(syncLock){ 

      // For example, com could be SqlCommand object that calls stored procedure 
      int updatedRowCount = com.ExecuteNonQuery(); 
      ... 
     } 
    } 

} 
+0

tanx я дал вам upvote, но действительно мне нравится его решать в sql, а не C# –

+0

Я согласен с Coder в том, что было бы желательно обрабатывать безопасность потоков в C# (или что вы используете). Однако, если вы предпочитаете делать это на уровне SQL - или _have_, потому что по какой-либо причине вы не можете полагаться на код приложения для реализации безопасности потоков, я опубликовал ответ в этом ключе. –

Смежные вопросы