Dela via


Undvik konflikter med databasåtgärder i FILESTREAM-program

gäller för:SQL Server

Program som använder SqlOpenFilestream() för att öppna Win32-filhandtag för läsning eller skrivning av FILESTREAM BLOB-data kan stöta på konfliktfel med Transact-SQL-instruktioner som hanteras i en gemensam transaktion. Detta omfattar Transact-SQL- eller MARS-frågor som tar lång tid att slutföra utförandet. Program måste utformas noggrant för att undvika dessa typer av konflikter.

När SQL Server Database Engine eller program försöker öppna FILESTREAM BLOBs kontrollerar databasmotorn den associerade transaktionskontexten. Databasmotorn tillåter eller nekar begäran baserat på om den öppna åtgärden fungerar med DDL-instruktioner, DML-instruktioner, hämtning av data eller hantering av transaktioner. I följande tabell visas hur databasmotorn avgör om en Transact-SQL-instruktion ska tillåtas eller nekas baserat på vilken typ av filer som är öppna i transaktionen.

Transact-SQL-uttryck Öppnad för läsning Öppnad för skrivning
DDL-instruktioner som fungerar med databasmetadata, till exempel CREATE TABLE, CREATE INDEX, DROP TABLE och ALTER TABLE. Tillåten Blockeras och misslyckas på grund av en tidsgränsöverskridning.
DML-instruktioner som fungerar med de data som lagras i databasen, till exempel UPDATE, DELETE och INSERT. Tillåten Nekad
VÄLJ Tillåten Tillåten
GODKÄNN TRANSAKTION Nekad* Nekad*.
SPARA TRANSAKTION Nekad* Nekad*
TILLBAKARULLNING Tillåten* Tillåten*

* Transaktionen avbryts och öppna referenser för transaktionskontexten ogiltigförklaras. Programmet måste stänga alla öppna handtag.

Exempel

I följande exempel visas hur Transact-SQL-instruktioner och FILESTREAM Win32-åtkomst kan orsaka konflikter.

A. Öppna en FILESTREAM-BLOB för skrivåtkomst

I följande exempel visas effekten av att öppna en fil endast för skrivåtkomst.

dstHandle =  OpenSqlFilestream(dstFilePath, Write, 0,  
    transactionToken, cbTransactionToken, 0);  
  
//Write some date to the FILESTREAM BLOB.  
WriteFile(dstHandle, updateData, ...);  
  
//DDL statements will be denied.  
//DML statements will be denied.  
//SELECT statements will be allowed. The FILESTREAM BLOB is  
//returned without the modifications that are made by  
//WriteFile(dstHandle, updateData, ...).  
CloseHandle(dstHandle);  
  
//DDL statements will be allowed.  
//DML statements will be allowed.  
//SELECT statements will be allowed. The FILESTREAM BLOB  
//is returned with the updateData applied.  

B. Öppna en FILESTREAM-BLOB för läsåtkomst

I följande exempel visas effekten av att öppna en fil för skrivskyddad åtkomst.

dstHandle =  OpenSqlFilestream(dstFilePath, Read, 0,  
    transactionToken, cbTransactionToken, 0);  
//DDL statements will be denied.  
//DML statements will be allowed. Any changes that are  
//made to the FILESTREAM BLOB will not be returned until  
//the dstHandle is closed.  
//SELECT statements will be allowed.  
CloseHandle(dstHandle);  
  
//DDL statements will be allowed.  
//DML statements will be allowed.  
//SELECT statements will be allowed.  

C. Öppna och stänga flera FILESTREAM BLOB-filer

Om flera filer är öppna används den mest restriktiva regeln. I följande exempel öppnas två filer. Den första filen öppnas för läsning och den andra för skrivning. DML-instruktioner kommer att nekas tills den andra filen öppnas.

dstHandle =  OpenSqlFilestream(dstFilePath, Read, 0,  
    transactionToken, cbTransactionToken, 0);  
//DDL statements will be denied.  
//DML statements will be allowed.  
//SELECT statements will be allowed.  
  
dstHandle1 =  OpenSqlFilestream(dstFilePath1, Write, 0,  
    transactionToken, cbTransactionToken, 0);  
  
//DDL statements will be denied.  
//DML statements will be denied.  
//SELECT statements will be allowed.  
  
//Close the read handle. The write handle is still open.  
CloseHandle(dstHandle);  
//DML statements are still denied because the write handle is open.  
  
//DDL statements will be denied.  
//DML statements will be denied.  
//SELECT statements will be allowed.  
  
CloseHandle(dstHandle1);  
//DDL statements will be allowed.  
//DML statements will be allowed.  
//SELECT statements will be allowed.  

D. Misslyckas med att stänga en markör

I följande exempel visas hur en instruktionsmarkör som inte är stängd kan hindra OpenSqlFilestream() från att öppna BLOB för skrivåtkomst.

TCHAR *sqlDBQuery =  
TEXT("SELECT GET_FILESTREAM_TRANSACTION_CONTEXT(),")  
TEXT("Chart.PathName() FROM Archive.dbo.Records");  
  
//Execute a long-running Transact-SQL statement. Do not allow  
//the statement to complete before trying to  
//open the file.  
  
SQLExecDirect(hstmt, sqlDBQuery, SQL_NTS);  
  
//Before you call OpenSqlFilestream() any open files  
//that the Cursor the Transact-SQL statement is using  
// must be closed. In this example,  
//SQLCloseCursor(hstmt) is not called so that  
//the transaction will indicate that there is a file  
//open for reading. This will cause the call to  
//OpenSqlFilestream() to fail because the file is  
//still open.  
  
HANDLE srcHandle =  OpenSqlFilestream(srcFilePath,  
     Write, 0,  transactionToken,  cbTransactionToken,  0);  
  
//srcHandle will == INVALID_HANDLE_VALUE because the  
//cursor is still open.  

Se även

komma åt FILESTREAM-data med OpenSqlFilestream
Med Flera Aktiva Resultatuppsättningar (MARS)