I write a asp.net website which upload flattext file to sql table. I use bcp command in stored-procedure to import the data in file to a table. and then in this table I should do some complex operation to the records. Each file has almount 60 thousands rows data, so the operation will low-efficiency. In this website, I should use multiple threads, That's means after user upload a file to web server, the web application will involk the sql stored-procedure to load the file data to table(tblImport) in a background thread, and the user can upload another file and create another thread. The threads involk stored-procedure to load the operate data to the sql server. Each file data will be loaded to the same table but seprate using a field FiledID. Data from diffrent file has different FiledID. So the operation to the file will operate the different data in the same table.Everything works well but the problem is when the user upload about ten files, that's there are ten threads involking the same stored-procedures. I have a stored-procedure as the following. When there is multiple threads involk it, that is there are several sessions of this stored-procedure operating the same table but different records. it will cause a deadlock in the table(tblImport).Then the deadlock comes up, the t-sql cause the deadlock is:-- update the data to the table according the temp table.-- When there are multiple threads running this t-sql, it will be cause a deadlock. UPDATE tblImport SET PackID=#tempTable.PackID, Line = #tempTable.Line FROM tblImport(NOLOCK) INNER JOIN #tempTable ON tblImport.ID = #tempTable.ID
I traced this sql in the Sql Server Profiler. When the deadlock came up, there are several links running this t-sql. But why this sql can cause the deadlock. I don't very understand. Who can help me. Thank you very much.ALTER PROCEDURE [dbo].[sp_Package]( @FieldID varchar(36), @packageSize int, @return int OUTPUT)ASDECLARE @PackID AS INTDECLARE @sql AS NVARCHAR(1024)DECLARE @Row AS INTSET @PackID = 0SET @Row = @packageSizeBEGIN TRY --BEGIN TRANSACTION --Because the record to operate will has 60 thousands, load the record to a temp table. SELECT * INTO #tempTable from tblImport(NOLOCK) WHERE FieldID=@pid--Apply a PackID for each @packageSize(for example 1000) records. Each @packageSize records as a package. WHILE(@Row = @packageSize) BEGIN SET @sql = 'UPDATE #tempTable SET PackID = ' + CAST(@PackID + 1 AS VARCHAR) + ' FROM #tempTable INNER JOIN (SELECT TOP ' + CAST(@packageSize AS VARCHAR) + ' * FROM #tempTable WHERE FieldID=''' + @FieldID + ''' AND PackID IS NULL) S ON #tempTable.ID = S.ID AND #tempTable.FieldID = S.FieldID AND #tempTable.CustomNumber = S.CustomNumber' EXEC sp_executeSql @sql SET @Row = @@ROWCOUNT IF(@Row <> 0) SET @PackID = @PackID + 1 END -- Apply a number to each record at each package. UPDATE #tempTable SET Line = tempTable.RowNumber FROM #tempTable INNER JOIN (SELECT ID, FieldID, PackID, CustomNumber, ROW_NUMBER() OVER (PARTITION BY FieldID, PackID ORDER BY FieldID, PackID) AS RowNumber FROM #tempTable) tempTable ON #tempTable.ID=tempTable.ID AND #tempTable.FieldID=tempTable.FieldID AND #tempTable.CustomNumber=tempTable.CustomNumber AND #tempTable.PackID = tempTable.PackID-- update the data to the table according the temp table.-- When there are multiple threads running this t-sql, it will be cause a deadlock. UPDATE tblImport SET PackID=#tempTable.PackID, Line = #tempTable.Line FROM tblImport(NOLOCK) INNER JOIN #tempTable ON tblImport.ID = #tempTable.ID --COMMIT TRANSACTION SET @return = 0END TRYBEGIN CATCH --ROLLBACK TRANSACTION DECLARE @ErrorMessage nvarchar(4000) DECLARE @ErrorSeverity int DECLARE @ErrorState int DECLARE @ErrorNumber int DECLARE @ErrorLine int SET @ErrorMessage = 'DB server:[sp_Package] an error occurs.' + ERROR_MESSAGE() SET @ErrorSeverity = ERROR_SEVERITY() SET @ErrorState = ERROR_STATE() SET @ErrorNumber = ERROR_NUMBER() SET @ErrorLine = ERROR_LINE() RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber, @ErrorLine) END CATCH