简体   繁体   中英

How can i run once on time procedure?

I wrote multi-threads application that every single thread call a sql server procedure.. i need to protect a row from getting by more than one thread i want every row take it only with by one thread i used this code:

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

as i said i run application and then my application create 10 threads and i set threadid for taking a row by only one thread but i saw that a row called by more than 1 thread and about 4-5 threads get one row.. how could i do this the best way, i solved it by this code by i don`t like to have two same where in select and update:

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

how can i do this with top code? and should i update first and then select like above code for fix it?

If you're using SQL Server 2005 or newer you may be able to combine the UPDATE and SELECT using the new OUTPUT clause .

However I'd suggest backing up and thinking about your database schema, and whether it really fits your problem -- especially with multi-threading!

I get the impression you want to count the calls from each thread. It would work better to have each call INSERT a row into a simple ThreadCallCount table that simply has one ThreadID column. Every call is a new row. Later you can Sum() this table by ThreadID to get the total calls per thread. That would be simple and easy to ensure it's thread-safe.

It sounds like there's some other data you're trying to retrieve, and it's not clear how/when it gets stored. But a similar analysis -- and more, simpler tables -- might help you there.

In general: Don't feel like you need to squeeze it all in one table. With multi-threading it will help to break things into smaller pieces. Feel free to use more tables, each of which has a single, clear purpose. SQL Server is designed to handle row transactions safely and efficiently, so try to leverage that as much as possible.

I would recommend writing thead safe code instead of doing that in stored procedure.

You did not mention your coding language, in C# one way is to wrap the code that calls this stored procedure inside lock block:

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();
            ...
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM