Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
sTumpF
Starting Member
6 Posts |
Posted - 2014-11-14 : 11:16:23
|
Hello I have an application which streams files in a database.The application is written in c# and uses System.Data.SqlClient.SqlCommand to write the filedata in parts of 1024 bytes. The query used for this is:UPDATE [File] SET FileData.WRITE(@Bytes,@Index,@Length), FileDBImportProgress=@Progress WHERE FileId = @IdHere is the code for the function:private static bool WriteFileDataToDb(Guid fileid, string filename, System.IO.Stream stream, long length) { bool success = true; using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(Config.ConnectionString)) { SqlCommand command = null; try { connection.Open(); command = connection.CreateCommand(); command.CommandTimeout = Config.SQLTimeout; command.CommandText = "UPDATE [File] SET FileData.WRITE(@Bytes,@Index,@Length) WHERE FileId = @Id"; SqlParameter param_bytes = command.CreateParameter(); SqlParameter param_index = command.CreateParameter(); SqlParameter param_length = command.CreateParameter(); SqlParameter param_id = command.CreateParameter(); param_bytes.DbType = DbType.Binary; param_bytes.ParameterName = "@Bytes"; param_index.ParameterName = "@Index"; param_length.ParameterName = "@Length"; param_id.ParameterName = "@Id"; command.Parameters.Add(param_bytes); command.Parameters.Add(param_index); command.Parameters.Add(param_length); command.Parameters.Add(param_id); int bufflength = 1024; int index = 0; byte[] buff = new byte[bufflength]; using (System.IO.BinaryReader br = new System.IO.BinaryReader(stream, Encoding.GetEncoding(Config.Encode))) { param_id.Value = fileid; int offset = 0; while ((buff = br.ReadBytes(buff.Length)).Length > 0) { offset = index * bufflength; param_bytes.Value = buff; param_index.Value = index * bufflength; param_length.Value = buff.Length; try { command.ExecuteNonQuery(); } catch (Exception ex) { var msg = ex.Message; var stack = ex.StackTrace; success = false; break; } index++; } } } catch (Exception ex) { success = false; } finally { if (command != null) command.Dispose(); if (connection.State == ConnectionState.Open) connection.Close(); if (connection != null) connection.Dispose(); } } return success; } Everything works fine just the last call of ExecuteNonQuery causes a timeout (when disable timeout the query tooks 2 minutes or longer).The only thing that changes is that at the end the data to write is shorter than 1024 bytes.When appending 0's, so the data has the length 1024, it works.Here is the profile of the last write for a simple image with size of 87KB:quote: <Event id="10" name="RPC:Completed"> <Column id="11" name="LoginName">ThatsMyName</Column> <Column id="15" name="EndTime">2014-11-14T16:56:02.417+01:00</Column> <Column id="12" name="SPID">55</Column> <Column id="16" name="Reads">30999954</Column> <Column id="1" name="TextData">exec sp_executesql N'UPDATE [File] SET FileData.WRITE(@Bytes,@Index,@Length), FileDBImportProgress=@Progress WHERE FileId = @Id',N'@Bytes varbinary(532),@Index int,@Length int,@Id uniqueidentifier,@Progress int',@Bytes=0x5001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145007FFD9,@Index=88064,@Length=532,@Id='CE0A63DD-4BC9-4B89-8FCE-9ED10C82F551',@Progress=99</Column> <Column id="9" name="ClientProcessID">4888</Column> <Column id="13" name="Duration">124121443</Column> <Column id="17" name="Writes">992494</Column> <Column id="2" name="BinaryData">00000000080000001A00730070005F006500780065006300750074006500730071006C00FC00000082001A00E7206E00760061007200630068006100720028003100300036002900D400000055005000440041005400450020005B00460069006C0065005D0020005300450054002000460069006C00650044006100740061002E005700520049005400450028004000420079007400650073002C00400049006E006400650078002C0040004C0065006E0067007400680029002C002000460069006C0065004400420049006D0070006F0072007400500072006F00670072006500730073003D004000500072006F00670072006500730073002000570048004500520045002000460069006C0065004900640020003D002000400049006400C400000082001800E7206E00760061007200630068006100720028003700390029009E0000004000420079007400650073002000760061007200620069006E00610072007900280035003300320029002C00400049006E00640065007800200069006E0074002C0040004C0065006E00670074006800200069006E0074002C00400049006400200075006E0069007100750065006900640065006E007400690066006900650072002C004000500072006F0067007200650073007300200069006E0074004C02000080001C00A530760061007200620069006E00610072007900280035003300320029000C00400042007900740065007300140200005001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145007FFD92200000003000600381069006E0074000C00400049006E00640065007800005801002400000003000600381069006E0074000E0040004C0065006E00670074006800140200004200000048002000241075006E0069007100750065006900640065006E007400690066006900650072000600400049006400DD630ACEC94B894B8FCE9ED10C82F5512800000003000600381069006E00740012004000500072006F0067007200650073007300630000001400000003000600380469006E00740000000000</Column> <Column id="6" name="NTUserName">ThatsMyName</Column> <Column id="10" name="ApplicationName">.Net SqlClient Data Provider</Column> <Column id="14" name="StartTime">2014-11-14T16:53:58.297+01:00</Column> <Column id="18" name="CPU">25631</Column> </Event>
Can this be a setting of the database?Because when using a fresh database the problem does not occur, just in my working database which has lots of files (~3GB).Both databases are created automatically, so there should be no difference.The PK is FileId (uniqueidentifier) and is the only index.The table has no trigger.I'm working on this problem for days and really have no clue what could be causing this.Does anyone have an idea?Kind regards |
|
sTumpF
Starting Member
6 Posts |
Posted - 2014-11-17 : 06:23:56
|
Now i can reproduce the error in the new created database.So the error occurs when at least some files are in the table.The earliest error I could reproduce when ~1GB was streamed into the table.Also I recognized that when the file is inserted I can stream it without problems again, the error occurs only the first time a file is streamed. The error then only occurs again for this file after a reboot.I could make a sample to demonstrate the problem if it would be helpfull to reproduce the beahvior.I still hope that there is someone who could help me with this, because I'm really clueless right now. |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2014-11-17 : 12:38:22
|
Sounds like a concurrency issue. Since you can now reproduce it, check sp_lock on the session that is running the update to see what locks it is using. Also check what it is blocking (select * from master..sysprocesses where blocked <> 0).Tara KizerSQL Server MVP since 2007http://weblogs.sqlteam.com/tarad/ |
|
|
sTumpF
Starting Member
6 Posts |
Posted - 2014-11-18 : 07:26:49
|
Hello Tara,thanks for the hint.This is the result of sp_lock:quote: 52 21 0 0 DB S GRANT52 21 0 0 DB [PLANGUIDE] S GRANT52 21 2121058592 0 TAB Sch-S GRANT52 21 2105058535 0 TAB Sch-S GRANT52 21 2105058535 0 TAB Sch-S GRANT52 21 2105058535 0 TAB [UPDSTATS] X GRANT52 21 0 0 MD 1(7d78a4e7:2:0) Sch-S GRANT52 21 0 0 MD 2(7d78a4e7:2:0) Sch-S GRANT52 21 0 0 MD 1(7d78a4e7:1:0) Sch-S GRANT52 21 0 0 MD 1(7d78a4e7:1:0) Sch-S GRANT53 21 0 0 DB S GRANT54 21 0 0 DB S GRANT
I selected only the results of the corresponding Table (21).Object 2121058592 is PK_File and 2105058535 is File.select * from master..sysprocesses where blocked <> 0 returns nothing. |
|
|
sTumpF
Starting Member
6 Posts |
Posted - 2014-11-18 : 09:07:52
|
Here is the script for the table:USE [Your database here]GO /****** Object: Table [dbo].[File] Script Date: 11/11/2014 21:07:42 ******/SET ANSI_NULLS ONGO SET QUOTED_IDENTIFIER ONGO SET ANSI_PADDING ONGO CREATE TABLE [dbo].[File]([FileId] [uniqueidentifier] ROWGUIDCOL NOT NULL,[FileName] [nvarchar](max) NULL,[FileData] [varbinary](max) NULL,[FileThumbnail] [varbinary](max) NULL,[FileCreated] [datetime] NULL,[FileLastEdit] [datetime] NULL,[FileReadyForUse] [bit] NULL,[FileType] [int] NULL,[FileTags] [nvarchar](255) NULL,[FileSize] [bigint] NULL,[FileDuration] [float] NULL,[FileSizeX] [int] NULL,[FileSizeY] [int] NULL,[FileError] [nvarchar](max) NULL,[FileDBImportProgress] [int] NULL,[FileConvertionProgress] [int] NULL,CONSTRAINT [PK_File] PRIMARY KEY CLUSTERED([FileId] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY] GO SET ANSI_PADDING OFFGO The error is definitely on sql side.I waited for the next timeout, copied query from SQL Server Profiler and ran the query from Sql Management Studio.This time I used the recommended buffersize of 8040. (http://msdn.microsoft.com/en-us/library/ms177523%28v=sql.105%29.aspx)It took 02:20 minutes for a simple Html file (1,83KB).In the Server Profiler I get 1.566.049 Writes and 48.401.388 Reads, thats a lot of operations. |
|
|
sTumpF
Starting Member
6 Posts |
Posted - 2014-11-18 : 09:58:04
|
Thanks to Tara I was able to find the reason for this behavior or at least a workaround to avoid it.The root of this behavior seems to be a bug in the auto_update_statistics option (https://connect.microsoft.com/SQLServer/feedback/details/174619/update-statistics-holding-exclusive-lock-and-blocking).After disabling the option for this table I could not reproduce the error.Thank you very much. |
|
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2014-11-18 : 10:42:55
|
That's a Sql Server 2005 issue, I think. Are you running 2005 or 2008 as per the forum? |
|
|
sTumpF
Starting Member
6 Posts |
Posted - 2014-11-18 : 11:07:52
|
It seems to be a problem on 2008 R2, too.At least disabling the auto update statistics solved the problem.I'm running on 2008 R2. |
|
|
|
|
|
|
|