![]() | |
![]() |
| | Thread Tools | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
I have 1 SQL statement selecting data from various tables and updating other tables. The question then is how do I prevent other applications from modifying the tables that I'm working on (that is while my transaction is being executed)? I know that the isolation level should be either REPEATABLE READ or SERIALIZABLE. But I need confirmation on if one of these actually solve my issue - prevents other applications/threads from modifying/inserting data into the same tables that I'm working on. |
#3
| |||
| |||
|
|
dhek (dhek (AT) dhek (DOT) dk) writes: I have 1 SQL statement selecting data from various tables and updating other tables. The question then is how do I prevent other applications from modifying the tables that I'm working on (that is while my transaction is being executed)? I know that the isolation level should be either REPEATABLE READ or SERIALIZABLE. But I need confirmation on if one of these actually solve my issue - prevents other applications/threads from modifying/inserting data into the same tables that I'm working on. It's difficult to give a single answer, since I don't know your exact requirements, so I have to answer in genric terms. If you want a consistent snapshot of how the data looks in this precise moment, the isolation level you should use is snapshot isolation. Snapshot isolation is available only in SQL 2005 and later. Furthermore the database must be configured to permit snapshot isolation. When you have snapshot is created when the transaction starts, or at latest when you start to read data. If data is updated while your query runs, you will not see these updates. This gives you a consistent view - but it may also give you outdated data, depending on how you look at it. On SQL 2000, snapshot isolation is not available, and the only foolproof way to get consistent data, is to set the database in single-user mode. In the default isolation level, READ COMMITTED, if you read the same row twice, you may get different results in different accesses. For instance, if you run: SELECT O.OrderID, E.EmployeeID, E.LastName FROM Orders O JOIN Employees E ON O.EmployeeID = E.EmployeeID You may see different last names for the same employee ID if the query plan uses a loop join, and the last name is updated while the query is running. In the next level, REPEATABLE READ locks are held, and you are guaranteed that reading the same row twice will yield the same result. However, if the last name of employee 8 was Grønkjær when the query started, and updated to Gravesen before you have read any orders with employee 8, you would see Gravesen in the result set. SERIALIZABLE adds protection against "phantom insert", so if you read the same range twice, you will get the same result. That is, if you run SELECT MAX(OrderID) FROM Orders twice in the same serializable transaction, you will get the same result. But if a order is added after you started the transaction, but before your query runs, the order will show up. -- Erland Sommarskog, SQL Server MVP, esquel (AT) sommarskog (DOT) se Books Online for SQL Server 2005 at http://www.microsoft.com/technet/pro...ads/books.mspx Books Online for SQL Server 2000 at http://www.microsoft.com/sql/prodinf...ons/books.mspx |
#4
| |||
| |||
|
|
Well, my issue is that I'm reading data from tables A, B, C and D and updates table E. What I need to prevent is 2 things: 1) New rows must not be added to either table A and B while my transaction is executing 2) Existing rows must not be modified |
|
My query is executed on a SQL server 2005. I do not have the option to change the configuration of it. |
#5
| |||
| |||
|
|
Well, my issue is that I'm reading data from tables A, B, C and D and updates table E. What I need to prevent is 2 things: 1) New rows must not be added to either table A and B while my transaction is executing 2) Existing rows must not be modified |
|
My query is executed on a SQL server 2005. I do not have the option to change the configuration of it. Am I supposed to use table locks in my query SELECT A.c1, B.c1, C.c1, D.d1 FROM ... WHERE ... WITH (TABLOCK, UPDLOCK, HOLDLOCK) UPDATE E.1 SET ... WHERE ... "Erland Sommarskog" <esquel (AT) sommarskog (DOT) se> wrote in message news:Xns99DD791FBE224Yazorman (AT) 127 (DOT) 0.0.1... dhek (dhek (AT) dhek (DOT) dk) writes: I have 1 SQL statement selecting data from various tables and updating other tables. The question then is how do I prevent other applications from modifying the tables that I'm working on (that is while my transaction is being executed)? I know that the isolation level should be either REPEATABLE READ or SERIALIZABLE. But I need confirmation on if one of these actually solve my issue - prevents other applications/threads from modifying/inserting data into the same tables that I'm working on. It's difficult to give a single answer, since I don't know your exact requirements, so I have to answer in genric terms. If you want a consistent snapshot of how the data looks in this precise moment, the isolation level you should use is snapshot isolation. Snapshot isolation is available only in SQL 2005 and later. Furthermore the database must be configured to permit snapshot isolation. When you have snapshot is created when the transaction starts, or at latest when you start to read data. If data is updated while your query runs, you will not see these updates. This gives you a consistent view - but it may also give you outdated data, depending on how you look at it. On SQL 2000, snapshot isolation is not available, and the only foolproof way to get consistent data, is to set the database in single-user mode. In the default isolation level, READ COMMITTED, if you read the same row twice, you may get different results in different accesses. For instance, if you run: SELECT O.OrderID, E.EmployeeID, E.LastName FROM Orders O JOIN Employees E ON O.EmployeeID = E.EmployeeID You may see different last names for the same employee ID if the query plan uses a loop join, and the last name is updated while the query is running. In the next level, REPEATABLE READ locks are held, and you are guaranteed that reading the same row twice will yield the same result. However, if the last name of employee 8 was Grønkjær when the query started, and updated to Gravesen before you have read any orders with employee 8, you would see Gravesen in the result set. SERIALIZABLE adds protection against "phantom insert", so if you read the same range twice, you will get the same result. That is, if you run SELECT MAX(OrderID) FROM Orders twice in the same serializable transaction, you will get the same result. But if a order is added after you started the transaction, but before your query runs, the order will show up. -- Erland Sommarskog, SQL Server MVP, esquel (AT) sommarskog (DOT) se Books Online for SQL Server 2005 at http://www.microsoft.com/technet/pro...ads/books.mspx Books Online for SQL Server 2000 at http://www.microsoft.com/sql/prodinf...ons/books.mspx |
#6
| |||
| |||
|
|
Well, my issue is that I'm reading data from tables A, B, C and D and updates table E. What I need to prevent is 2 things: 1) New rows must not be added to either table A and B while my transaction is executing 2) Existing rows must not be modified My query is executed on a SQL server 2005. I do not have the option to change the configuration of it. Am I supposed to use table locks in my query SELECT A.c1, B.c1, C.c1, D.d1 FROM ... WHERE ... WITH (TABLOCK, UPDLOCK, HOLDLOCK) UPDATE E.1 SET ... WHERE ... "Erland Sommarskog" <esquel (AT) sommarskog (DOT) se> wrote in message news:Xns99DD791FBE224Yazorman (AT) 127 (DOT) 0.0.1... dhek (dhek (AT) dhek (DOT) dk) writes: I have 1 SQL statement selecting data from various tables and updating other tables. The question then is how do I prevent other applications from modifying the tables that I'm working on (that is while my transaction is being executed)? I know that the isolation level should be either REPEATABLE READ or SERIALIZABLE. But I need confirmation on if one of these actually solve my issue - prevents other applications/threads from modifying/inserting data into the same tables that I'm working on. It's difficult to give a single answer, since I don't know your exact requirements, so I have to answer in genric terms. If you want a consistent snapshot of how the data looks in this precise moment, the isolation level you should use is snapshot isolation. Snapshot isolation is available only in SQL 2005 and later. Furthermore the database must be configured to permit snapshot isolation. When you have snapshot is created when the transaction starts, or at latest when you start to read data. If data is updated while your query runs, you will not see these updates. This gives you a consistent view - but it may also give you outdated data, depending on how you look at it. On SQL 2000, snapshot isolation is not available, and the only foolproof way to get consistent data, is to set the database in single-user mode. In the default isolation level, READ COMMITTED, if you read the same row twice, you may get different results in different accesses. For instance, if you run: SELECT O.OrderID, E.EmployeeID, E.LastName FROM Orders O JOIN Employees E ON O.EmployeeID = E.EmployeeID You may see different last names for the same employee ID if the query plan uses a loop join, and the last name is updated while the query is running. In the next level, REPEATABLE READ locks are held, and you are guaranteed that reading the same row twice will yield the same result. However, if the last name of employee 8 was Grønkjær when the query started, and updated to Gravesen before you have read any orders with employee 8, you would see Gravesen in the result set. SERIALIZABLE adds protection against "phantom insert", so if you read the same range twice, you will get the same result. That is, if you run SELECT MAX(OrderID) FROM Orders twice in the same serializable transaction, you will get the same result. But if a order is added after you started the transaction, but before your query runs, the order will show up. -- Erland Sommarskog, SQL Server MVP, esquel (AT) sommarskog (DOT) se Books Online for SQL Server 2005 at http://www.microsoft.com/technet/pro...ads/books.mspx Books Online for SQL Server 2000 at http://www.microsoft.com/sql/prodinf...ons/books.mspx |
#7
| |||
| |||
|
|
dhek (dhek (AT) dhek (DOT) dk) writes: Well, my issue is that I'm reading data from tables A, B, C and D and updates table E. What I need to prevent is 2 things: 1) New rows must not be added to either table A and B while my transaction is executing 2) Existing rows must not be modified I'm not sure that I get this. Assuming you assemble data into a temp table or a table variable, and you batch goes: INSERT #tmp(...) SELECT .... FROM A, B ... INSERT #tmp(...) SELECT ... FROM C, D UPDATE E SET ... FROM E JOIN #tmp... |
|
Why would it be an issue if some adds or modifies rows into A or B once you have run that SELECT statement? I can possibly understand that you don't want permit rows to be added or modified in C or D while you are reading A and B. But once you have read A or B, it cannot matter if modifications happens while your transaction is running, or if they are held up until your transaction completes. |
|
My query is executed on a SQL server 2005. I do not have the option to change the configuration of it. Well, if you want to read that is consistent at a certain moment in time, snapshot isolation is your only foolproof option. It also has the advantage of not blocking updates. |
#8
| |||
| |||
|
|
Well, my issue is that I'm reading data from tables A, B, C and D and updates table E. What I need to prevent is 2 things: 1) New rows must not be added to either table A and B while my transaction is executing 2) Existing rows must not be modified Why? If that is truly the case, then yes, you need a table lock. But this seems like a fairly unusual requirement. Sure your design is really what you want? |
#9
| |||
| |||
|
|
With the setup u proposed in your example I agree - it would be foolish not to allow others to read/write data to table A,B when done with those table:-) If my sync-indicator had only been located in the records that are selected I would not have a problem at all - only need to set the transaction level to READ COMMITED or SYNCHRONIZED. I do not have the option of setting it to snapshot isolation (not supported by my application.) |
#10
| |||
| |||
|
|
I know that the isolation level should be either REPEATABLE READ or SERIALIZABLE. But I need confirmation on if one of these actually solve my issue - prevents other applications/threads from modifying/inserting data into the same tables that I'm working on. |
![]() |
| Thread Tools | |
| Display Modes | |
| |