This is a discussion on Mysterious loss of data from mssql2k within the SQL Server forums, part of the Microsoft SQL Server category; --> Hi All, I'm trying to track down a mysterious problem we're experiencing in which updates and inserts to tables ...
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| Hi All, I'm trying to track down a mysterious problem we're experiencing in which updates and inserts to tables in our mssql2k server appear to be 'disappearing.' To explain our situation: We have a web page (written in ASP, if that's relevant) on which we accept enrollment information. When that page is submitted, the form data is passed to a stored procedure on our mssql2k server, which performs several operations, all of which are wrapped in a transaction. In particular, the stored procedure performs an update operation on a record in one table (i'll call it TableA) and an insert into another table (TableB). If the procedure encounters a problem (ie after each update / insert operation in the procedure we test for IF @@Error<>0) it performs a rollback, performs a select similar to the one immediately below, and then RETURNs. SELECT '1' as error, 'Unable to update TableA' as errormsg If the procedure doesn't fail any of the @@Error tests, the transaction is committed, and a membership number is SELECTed to be returned. SELECT '0' as error, @memnum as membershipnumber The @memnum variable is populated within the transaction. Back in the ASP page we test both for the proc returning an empty recordset, or for it passing an explicit value in the error field, and push the page to an error page if either of these conditions are met. If, on the other hand, none of these conditions are met, and the membershipnumber field in the recordset is populated with a valid membership number, we push to a confirmation page. This confirmation page receives the membership number in a session variable, performs a SELECT against TableB (the table that received the insert during the proc) using that membership number in the WHERE clause, and the resultant recordset is used to populate the confirmation details on that page. That recordset is also then used to populate the details of a confirmation email, which is automatically sent by the confirmation page. And now here's our problem: we've become aware of a handfull of people who have gone through the enrollment process, have received the confirmation email containing the information they supplied as expected, but the data appears to be entirely missing from our tables. By that I mean that the record in TableA does not appear to have been updated (under normal circumstances that record should have had several flags set, and several other fields updated with information supplied by the person enrolling), and the record in TableB does not appear to have been inserted. In essence, looking at our tables, it *feels* like the transaction in the stored procedure for that particular enrollment hit a problem and was rolled back. However, the evidence that we have in the form of the confirmation email argues strongly that the data must have existed in our tables (particularly in TableB), if only for an unknown period of time. We're kind of at our wit's end to work out what is going wrong with these enrollments. From my understanding of transactions (and I could well be wrong) any changes to data (ie updates, inserts etc) contained within are essentially 'invisible' to any other operation (ie the SELECT that happens in the confirmation page) until the transaction is committed, implying that the effect of the update and insert should have been 'permanently' successful if no error code is received and if a valid membership number was returned. I ask, because someone in our team has suggested that maybe the operations in the transaction 'lasted long enough' in the tables to have been visible for the SELECT on the confirmation page to have worked, but were then subsequently rolled back, explaining why the confirmation email is appropriately populated and why the data then appears to be missing. However, as I said, this doesn't match my understanding of how transactions behave. Sorry for the length of this post, but I felt it was best to explain this as best as I could. Does anyone have any advice they can give us on this situation? ie, are there any known problems with operations in transactions 'bleeding over' into tables, but then being rolled back at some later point? Does anyone have any thoughts or suggestions on how we can further diagnose this issue? Truly, any help will be immensely appreciated... Thanks in advance, M Wells |
| |||
| "M Wells" <planetthoughtful@gmail.com> wrote in message news:hmba41p1gvtsmudtbus027ad3rapgo1ghd@4ax.com... > Hi All, > > I'm trying to track down a mysterious problem we're experiencing in > which updates and inserts to tables in our mssql2k server appear to be > 'disappearing.' > > To explain our situation: > > We have a web page (written in ASP, if that's relevant) on which we > accept enrollment information. > <snip> First, to address your question about data inside a transaction being visible to other connections, this would only happen if the other connection explicitly sets its transaction level to READ UNCOMMITTED, which would allow it to see data which has been inserted/updated but not committed. See SET TRANSACTION ISOLATION LEVEL in Books Online for more details - I suppose your ASP connections could be setting this isolation level, but it isn't the default, so it would be somewhat unusual. As for tracking down what's going on with the data, you can use Profiler to run a trace, perhaps filtered on those specific tables and any relevant stored procedures. If this problem happens fairly often, then running it interactively may be possible, otherwise see the sp_trace_% procs in Books Online for details of setting up a server-side trace. You might also want to check for any triggers on the tables, as sometimes they can be fired at times you don't expect. And if you have a middle tier layer, you could also see if it's initiating a transaction before calling the procedure - it could be that the procedure itself commits correctly, and the email is sent, but there's an additional outer transaction started by the middle tier which is then sometimes rolled back after sending the email. Checking @@TRANCOUNT inside the procedure would give you a clue. Simon |
| ||||
| M Wells (planetthoughtful@gmail.com) writes: > If the procedure doesn't fail any of the @@Error tests, the > transaction is committed, and a membership number is SELECTed to be > returned. > > SELECT '0' as error, @memnum as membershipnumber > > The @memnum variable is populated within the transaction. > > Back in the ASP page we test both for the proc returning an empty > recordset, or for it passing an explicit value in the error field, and > push the page to an error page if either of these conditions are met. > > If, on the other hand, none of these conditions are met, and the > membershipnumber field in the recordset is populated with a valid > membership number, we push to a confirmation page. > > This confirmation page receives the membership number in a session > variable, performs a SELECT against TableB (the table that received > the insert during the proc) using that membership number in the WHERE > clause, and the resultant recordset is used to populate the > confirmation details on that page. That recordset is also then used to > populate the details of a confirmation email, which is automatically > sent by the confirmation page. > > And now here's our problem: we've become aware of a handfull of people > who have gone through the enrollment process, have received the > confirmation email containing the information they supplied as > expected, but the data appears to be entirely missing from our tables. As I understand, this is an intermittent problem, and you don't have a reproducible scenario. This make such a problem much more difficult to track down. And if you make changes to address, you cannot really be sure that you fixed the right thing. One thing that is not clear to me is whether it is the same SQL Server process that runs the stored procedure and the gets the data to the confirmation page, or whether they are two different. (I should butt in that I don't know ASP or IIS, so this talk about session variables etc, tells me little.) If it is the same SQL Server process, here is something that could happen: 1) The stored procedure first run unsuccessfully, and a transaction is started, but then neither committed nor rolled back. 2) The process then runs the procedure successfully, and then gets the data to the confirmation page. This time a nested transaction was started and committed. However, "commit" in the case of an inner transaction just means that transaction count is decremented. 3) The process goes on and registers and confirms more enrollments. 4) Eventually the process is logged out, still with an open transaction. All enrollments are now rolled back. So why in step 1, would this happen? It can be a coding error in the stored procedure, so that a rollback is not executed when it should. But it could also be a client-side thing. Say that the procedure is blocked for some reason, and the client gets a command timeout. In this case the transaction started by the stored procedure is *not* rolled back. This a really nasty gotcha. If the confirmation page is really a separate SQL Server connection - and you should really use the SQL Server Profiler to verify this - then the data has been committed, and thus it has later been removed. Well, if the confirmation reads with NOLOCK, are back to the previous scenario. One thing you should investigate in either case, is whether these missing enrollments happened at different points in time, or if they are clustered. That could give a clue of what may have happened. I hope this has given you some more ideas of what to look for. -- Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se Books Online for SQL Server SP3 at http://www.microsoft.com/sql/techinf...2000/books.asp |