|
Hello all, Id like to ask if I need to lock tables when I am disabling triggers in my script. I've got a script that deletes records from multiple tables. At the top of the script I am disabling all the triggers on the effected tables. e.g. Id like to know if I should be locking table SampleTable for the duration of the script. Otherwise someone could delete a record from that table half way through running my script and the copyOnDelete trigger would not be fired. This will lead to data corruption in my database. Thanks people of the internet :)
(comments are locked)
|
|
You can go without any locking hints and without any selects when you execute the DDL statement inside a transaction as the DDL will put a schema lock on the table and any delete command will wait for the original transaction to complete. Also you have to begin the transaction prior disabling the trigger, because otherwise you are not guaranteed that some delete command will not be issued out of your transaction with disabled trigger. You can test it by simple example:
(comments are locked)
|
|
I ended up using the approach here [http://stackoverflow.com/questions/4599082/is-tsql-disable-trigger-scoped-to-the-calling-context][1] as I'm running a script, not a stored procedure and so can't use return. This is a problem because I want to rollback transactions as well as commit them. Now I can use context_info to help me achieve this. Here is my final solution to Move a table safely. Thanks allot everyone for all your help :) [1]: http://stackoverflow.com/questions/4599082/is-tsql-disable-trigger-scoped-to-the-calling-context If that's what works for you, then happy we helped you come to a conclusion. I like the smiley's in the error messages.
May 17 '11 at 01:43 PM
Matt Whitfield ♦♦
(comments are locked)
|
|
You can get the behaviour you want by specifying a combination of locking hints within the scope of the transaction Basically what you are saying with the SELECT at the top is:
The lock will be a shared lock until you do the DELETE, at which time it will promote to an exclusive lock. If you want it to be an exclusive lock straight away, then you can swap the @Matt you do not need to do any select TABLOCK hint. As the DISABLE TRIGGER will place a schema lock on the table inside transaction and all other transactions will wait until the schema lock is released. As can be seen in example I put in the answer.
May 17 '11 at 06:15 AM
Pavel Pawlowski
@Pavel Pawlowski - Yep, I always err on the side of caution :)
May 17 '11 at 08:10 AM
Matt Whitfield ♦♦
(comments are locked)
|
|
One approach has been suggested here http://stackoverflow.com/questions/4599082/is-tsql-disable-trigger-scoped-to-the-calling-context - this uses the context_info property of the connection to determine control-flow through the trigger. I don't particularly like the cleanliness of this solution, as the trigger has extra code in it, but it could work. Interesting and good find ;) Unfortunately the system I'm using has updates weekly that modify DB tables and so id prefer not to modify the original software triggers as they then need to be maintained by me every week. :/
May 17 '11 at 05:13 AM
DeDogs
(comments are locked)
|
|
If your script needs to be run without affecting any other query, and without any other query affecting it, then put the whole lot into a transaction This could cause some serious locking issues, and hurt concurrency, but depending on the length of the script and the amount of data modified, may be what you need? Alternatively break the script down into individual transactions that need to be isolated. Firstly thank you for your time :) A far as i know you can't use transactions when your using GO statements? I need to use GO statements to make the DISABLE TRIGGER statements work? Otherwise I'd love to use transactions :) Cheers.
May 17 '11 at 04:18 AM
DeDogs
@DeDogs - you would disable the trigger, then run the delete inside a transaction (stopping anyone from doing something naughty). If that works out, you then commit and immediately re-enable the trigger.
May 17 '11 at 04:31 AM
WilliamD
As @WilliamD says (beat me to it) you can put the disable and delete within a tran, then either rollback or commit and re-enable
May 17 '11 at 04:35 AM
Kev Riley ♦♦
@DeDogs : right now I've had chance to test this, I'm going back to my original answer! Yes you can use 'GO' batch separators within the transaction. @Pavel 's answer shows a good example.
May 17 '11 at 06:24 AM
Kev Riley ♦♦
@Kev as you wrote, all needs to be executed inside a single transaction. Otherwise it is not guaranteed that other delete command will not be executed without enabled trigger. Even starting transaction after disable trigger as @WilliamD originally suggested will not work as other the delete command can be started between SQL processes the BEGIN Transaction and delete command. If the BEGIN TRANSACTION is executed prior the DISABLE TRIGGER, then a schema lock will be put on the table inside the tran and no other transaction can delete any row prior the transaction is commit or rolled back.
May 17 '11 at 06:37 AM
Pavel Pawlowski
(comments are locked)
|

