Udostępnij za pośrednictwem


Unikanie konfliktów z operacjami bazy danych w aplikacjach FILESTREAM

Dotyczy:programu SQL Server

Aplikacje korzystające z SqlOpenFilestream() do otwierania dojść plików Win32 do odczytywania lub zapisywania danych FILESTREAM BLOB mogą napotkać błędy konfliktu z instrukcjami Transact-SQL zarządzanymi we wspólnej transakcji. Obejmuje to Transact-SQL lub zapytania MARS, które długo potrwają do zakończenia wykonywania. Aplikacje muszą być starannie zaprojektowane, aby uniknąć tego typu konfliktów.

Gdy aparat bazy danych programu SQL Server lub aplikacje próbują otworzyć pliki FILESTREAM BLOBs, aparat bazy danych sprawdza skojarzony kontekst transakcji. Aparat bazy danych zezwala na żądanie lub odrzuca je na podstawie tego, czy operacja otwarcia działa z instrukcjami DDL, instrukcjami DML, pobieraniem danych lub zarządzaniem transakcjami. W poniższej tabeli pokazano, jak aparat bazy danych określa, czy instrukcja Transact-SQL będzie dozwolona lub blokowana na podstawie typu plików otwartych w transakcji.

oświadczenia Transact-SQL Otwarte do odczytu Otwarte do zapisu
Instrukcje DDL, które działają z metadanymi bazy danych, takimi jak CREATE TABLE, CREATE INDEX, DROP TABLE i ALTER TABLE. Dozwolone Są blokowane i kończą się niepowodzeniem z powodu przekroczenia limitu czasu.
Instrukcje DML, które działają z danymi przechowywanymi w bazie danych, takimi jak UPDATE, DELETE i INSERT. Dozwolone Odmówiony
Wybierz Dozwolone Dozwolone
ZATWIERDZANIE TRANSAKCJI Odmówiony* Odmówiony*.
ZAPISZ TRANSAKCJĘ Odmówiony* Odmówiony*
PRZYWRACANIE Dozwolone* Dozwolone*

* Transakcja zostanie anulowana, a otwarte dojścia kontekstu transakcji zostaną unieważnione. Aplikacja musi zamknąć wszystkie otwarte uchwyty.

Przykłady

W poniższych przykładach pokazano, jak instrukcje Transact-SQL i dostęp FILESTREAM Win32 mogą powodować konflikty.

A. Otwieranie obiektu BLOB FILESTREAM na potrzeby dostępu do zapisu

W poniższym przykładzie pokazano efekt otwierania pliku tylko na potrzeby dostępu do zapisu.

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. Otwieranie obiektu BLOB FILESTREAM w celu uzyskania dostępu do odczytu

W poniższym przykładzie pokazano efekt otwierania pliku tylko do odczytu.

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. Otwieranie i zamykanie wielu plików BLOB FILESTREAM

Jeśli wiele plików jest otwartych, zostanie użyta najbardziej restrykcyjna reguła. Poniższy przykład otwiera dwa pliki. Pierwszy plik jest otwierany do odczytu i drugi dla zapisu. Instrukcje DML będą odrzucane, dopóki drugi plik nie zostanie otwarty.

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. Nie można zamknąć kursora

W poniższym przykładzie pokazano, jak kursor instrukcji, który nie jest zamknięty, może uniemożliwić OpenSqlFilestream() otwarcie obiektu BLOB na potrzeby dostępu do zapisu.

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.  

Zobacz też

Dostęp do danych FILESTREAM z użyciem OpenSqlFilestream
Korzystanie z wielu aktywnych zestawów wyników (MARS)