locked
Locking the table RRS feed

  • Question

  • I have the below code

    SELECT
        CustomerDimId
    INTO #tempCustomer
    FROM tblCustomer
    WHERE RowOut IS NULL
    AND State= 'IL'

    BEGIN TRANSACTION
         
         UPDATE a
         SET Rowout = @Now
         FROM tblCustomer a
         WHERE CustomerDimId in ( Select CustomerDimId from tblCustomer)
         
         INSERT INTO tblCustomer (CustomerId,State,Status,RowIn,Rowout)
         SELECT CustomerId,State,Status,@Now,NULL FROM #tempCustomer
         
        IF @@error <> 0
            Rollback

    COMMIT TRANSACTION

    I have two questions:

    1. How do I lock the table tblCustomer( I didn't find resource..)
    2. whether really I need to lock the table to do the transaction?
     (Since ETL process will select * FROM tblCustomer where rowin >@lastrun and rowout is nuLL) and load data to warehouse. While I am doing this transaction I don't want anyone to select from the table..

    What is the best way to do it.

    Wednesday, March 3, 2010 8:08 PM

Answers

  • Use transactions(BEGIN TRAN COMMIT TRAN or ROLLBACK TRAN) if you are modifying the table and you want all the code to succeed or fail, as the examples I provided above.
    When you try to the UPDATE, an exclusive lock is acquired on the resource(table) and that can't be shared with any other lock, so your table is locked until the update is done. Once the update is done, the lock is released the SELECT can access the table.

    I hope this is helpful.


    Abdallah El-Chal, PMP, ITIL, MCTS
    • Proposed as answer by Naomi N Friday, March 5, 2010 4:40 AM
    • Marked as answer by Nai-dong Jin - MSFT Monday, March 8, 2010 3:19 AM
    Friday, March 5, 2010 4:07 AM

All replies

  • You can use the TABLOCK hint to create a shared lock on the table, however. In this case, the data is not being changed, so why would you want to prevent access to it. Also, I can't think of a way to block access to a table while doing a SELECT, whether inside a transaction or with using the LOCK.

    Abdallah El-Chal, PMP, ITIL, MCTS
    Wednesday, March 3, 2010 8:18 PM
  • Thanks.

    Where to use the TABLOCK and how?

    Other process will select the table WITHOUT USING [with (NOLOCK)]. My assumption is sql server will suspend other process  until the lock is released for the table, am I right?
    Wednesday, March 3, 2010 8:26 PM
  • The following will create a lock on the table and it will be released once the update is done.

    UPDATE TableName
    WITH(TABLOCK)
    SET ColumnName = 'Test1'
    WHERE ColumnName = 'Test2'
    Even if you specify the lock, SQL Server might choose not to honor it for many reasons.
    When you try to select from a table, a Shared lock is acquired, and when you have another select on the same table, it needs another Shared lock, and that's why you can still read because it's a Shared lock.

    I honestly don't like to control the behaviour of the locking and blocking and I let the engine does that because SQL Server does a good job with it.

    Here is a good article that could help you understand Lock modes a little better, and I know, this is not an easy subject to digest. :)
    http://msdn.microsoft.com/en-us/library/ms175519.aspx
    Abdallah El-Chal, PMP, ITIL, MCTS
    Wednesday, March 3, 2010 8:35 PM
  • Ok Let me put the question this way. Consider

    BEGIN TRANSACTION
               STEP 1 : UPDATE (from above)
               STEP 2 : INSERT (from Above)
    COMMIT TRANSACTION

    Consider step 1 is completed, another process select WITHOUT USING [with (NOLOCK)], So the sql server wiill suspend the another process until my transaction is committed?

    Wednesday, March 3, 2010 9:02 PM
  • If you run the entire above statement including COMMIT TRAN, the SELECT will(if executed in another SPID and without the NOLOCK), will not have access to the table until the COMMIT TRAN is committed or a ROLLBACK is committed if you have one.
    If you execute it with NOLOCK, you will have what is called DIRTY READS, meaning you will see data before it's committed or rolledback.



    Abdallah El-Chal, PMP, ITIL, MCTS
    Wednesday, March 3, 2010 9:10 PM
  • What if the vice verse happens i.e First Another SPID is selecting without NOlOCK, My statement will wait until the statement is completed?
    Thursday, March 4, 2010 4:33 PM
  • No, a SELECT statement will not block access to the table because there is data modifications.
    Abdallah El-Chal, PMP, ITIL, MCTS
    Thursday, March 4, 2010 4:58 PM
  • So here is my case ,consider the  select statement is in process(not completed) which is currently  selected 10 rows of verified(where clause) 50 rows out of 100 rows(total rows)
    if my update statement updates and commits in between the select statement process , the select won't verify the rows which is been updated now ?

    let me know the question is confusing?.
    Thursday, March 4, 2010 7:53 PM
  • Hello,

    First, you should never use explicit transactions. It will lock all used tables from outside sessions.
    Second, you don't need to lock the tables in your example.
    Third, it seems your INSERT should execute before your UPDATE.

    Adam

    Dibble and dabble but please don't babble.
    Thursday, March 4, 2010 8:10 PM
  • OP, the SELECT will not read data that is not committed yet by the UPDATE.

    Explicit transactions should be used where needed.

    In a bank transaction, if you are moving money from your checking to your saving, and you do the withdrawal first from your checking and something happens, and the withdrawal transaction is committed but not the deposit, you will loose your money.
    In this case, you will need to nest your script inside an explicit transaction where either both transactions commit or both fail.
    Abdallah El-Chal, PMP, ITIL, MCTS
    Thursday, March 4, 2010 8:19 PM
  • You should fix the issues that cause the transaction to fail and use standard error handling. Explicit transactions are an outdated concept and very poor programming practice. Unfortunately, in a maintenance, you don't always have the opportunity to redesign it, but bad design is something we always have to code around.

    SQL Server can handle transactions behind the scenes much more efficiently than a stored procedure or two. Trust me. I've had to prove this more times than I think I needed to...and it never hit home until after most of the database was locked up.

    Personally, I have yet to see an example of where explicit transaction were needed and not poor practice.

    Adam
    Dibble and dabble but please don't babble.
    Thursday, March 4, 2010 8:36 PM
  • Adam,

    can you provide any references that say "Explicit transactions are an outdated concept and very poor programming practice" ?
    Error handling and Locking are not the same.

    Thanks
    Abdallah El-Chal, PMP, ITIL, MCTS
    Thursday, March 4, 2010 8:57 PM
  • Abdallah,

    What type of references are you looking for? If you can show me an example where you think explicit transactions are the only option or even a considerable, I can help you understand how to code it more efficiently.

    For example, in some cases when you're inserting/updating in the same stored procedure, simply using an IF EXISTS after the INSERT using the same criteria as the INSERT in the IF EXISTS(SELECT ...), confirms that it's safe to apply the update. Depending on the severity, you can store the values in a #temp table for a virtual rollback (actual delete) if the update fails @@error.

    There are many ways to avoid explicit transactions and all should be considered. Unless you enjoy 3am phone calls or have a cursor to kill all spids, explicit transactions are never a good idea.

    In closing, you make a good point on the distinctions between error handling and transactions. This is the often abused an often reversed approach.

    Adam

    Dibble and dabble but please don't babble.
    Thursday, March 4, 2010 9:17 PM
  • I meant an article, a book, or a forum that says Explicit transactions should be avoided.
    Let me know what is the best solution forthe following two scenarios. Errors are not the only thing we face. Loss of power is one thing. Computer crash is another.

    DECLARE @t TABLE(EmployeeID INT,FName VARCHAR(20),LName VARCHAR(20))
    
    --I want them both to fail or both succeed
    BEGIN TRAN
    INSERT INTO @t(EmployeeID,FName,LName) VALUES(1,'John','Smith')
    INSERT INTO @t(EmployeeID,FName,LName) VALUES(2,'Mike','Jones')
    COMMIT TRAN
    
    SELECT * FROM @t
    
    --Example 2
    DECLARE @t2 TABLE(CustomerID INT,Checking DECIMAL(5,2),Saving DECIMAL(5,2))
    INSERT INTO @t2(CustomerID,Checking,Saving) VALUES(123,500.22,200)
    
    --I want them both to fail or both succeed
    BEGIN TRAN
    UPDATE @t2 
    SET Checking = Checking + 100
    
    UPDATE @t2
    SET Saving = Saving - 100
    COMMIT TRAN
    
    SELECT * FROM @t2

    Abdallah El-Chal, PMP, ITIL, MCTS
    • Proposed as answer by Naomi N Friday, March 5, 2010 4:40 AM
    Thursday, March 4, 2010 9:44 PM
  • Any source that you would deem more reputable than another?

    Ask Arnie Rowland Moderator/MVP/Phd

    To generally answer your question on those simple examples, you insert rows into a temp table, perform actions on the temp table and insert.

    Adam


    Dibble and dabble but please don't babble.
    Thursday, March 4, 2010 10:27 PM
  • Also,

    Let me elaborate a bit...

    In "most" cases, what is viewed as transactional behavior can be implemented inside a trigger through basic logic. The main problem with this is that many companies discourage the use of triggers, in some cases out of fear caused by ignorance, and in other cases to keep a neat stored procedure for maintenance reasons without having to look at a trigger. In either cases, it's lazy programming, and the trade-off is the potential to not only lock the table, but create a domino locking effect.

    Much of this is rooted to the set-based mindset that DBA's are taught and practice, when the irony is that a database is an object-oriented environment and should be viewed as such and coded as such. Trying to stuff all of your possessions into one pocket will have its drawbacks.

    If you're not satisfied with this, pick one of the 3 samples above and I'll take a few minutes to rewrite it without locking anything, but be aware, it does require a little extra work to acheive the same result but with a lot less risk.

    Adam


    Dibble and dabble but please don't babble.
    Thursday, March 4, 2010 10:50 PM
  • So I no need lock any thing. I can put my code in between

    BEGIN TRAN

    ....
    COMMIT


    that enough right?
    Thursday, March 4, 2010 11:40 PM
  • The way your logic is setup, you want to insert before update not the other way around. Correct?

    If you use BEGIN TRAN, you're locking. Get rid of the entire "BEGIN TRAN COMMIT" That is only used in management studio by an analyst not in a stored proc.

    Edit: Please use a practical example with real tables.

    Adam

    Dibble and dabble but please don't babble.
    Friday, March 5, 2010 1:08 AM
  • Use transactions(BEGIN TRAN COMMIT TRAN or ROLLBACK TRAN) if you are modifying the table and you want all the code to succeed or fail, as the examples I provided above.
    When you try to the UPDATE, an exclusive lock is acquired on the resource(table) and that can't be shared with any other lock, so your table is locked until the update is done. Once the update is done, the lock is released the SELECT can access the table.

    I hope this is helpful.


    Abdallah El-Chal, PMP, ITIL, MCTS
    • Proposed as answer by Naomi N Friday, March 5, 2010 4:40 AM
    • Marked as answer by Nai-dong Jin - MSFT Monday, March 8, 2010 3:19 AM
    Friday, March 5, 2010 4:07 AM
  • SQL Server will lock the table for the update. It has to. There's absolutely no reason to do it explicitly unless you like redundant bad design and permanent table locks that will freeze up your server.

    I don't think the OP wants to UPDATE the table first then INSERT. I believe it's backwards.

    Abdshall and OP, if you can provide a practical example, I can help you understand how to handle it properly.

    Adam
    Dibble and dabble but please don't babble.
    Friday, March 5, 2010 4:49 AM