FILESTREAM 응용 프로그램에서 데이터베이스 작업과의 충돌 방지Avoid Conflicts with Database Operations in FILESTREAM Applications

FILESTREAM BLOB 데이터를 읽거나 쓰기 위해 SqlOpenFilestream()을 사용하여 Win32 파일 핸들을 여는 응용 프로그램은 공통된 트랜잭션에서 관리되는 Transact-SQLTransact-SQL 문과의 충돌 오류가 발생할 수 있습니다.Applications that use SqlOpenFilestream() to open Win32 file handles for reading or writing FILESTREAM BLOB data can encounter conflict errors with Transact-SQLTransact-SQL statements that are managed in a common transaction. 여기에는 실행 시간이 오래 걸리는 MARS 쿼리 또는 Transact-SQLTransact-SQL 이 포함됩니다.This includes Transact-SQLTransact-SQL or MARS queries that take a long time to finish execution. 이러한 유형의 충돌을 방지하도록 응용 프로그램을 신중하게 디자인해야 합니다.Applications must be carefully designed to help avoid these types of conflicts.

SQL Server 데이터베이스 엔진SQL Server Database Engine 또는 응용 프로그램이 FILESTREAM BLOB를 열려고 하면 데이터베이스 엔진Database Engine 이 연결된 트랜잭션 컨텍스트를 확인합니다.When SQL Server 데이터베이스 엔진SQL Server Database Engine or applications try to open FILESTREAM BLOBs, the 데이터베이스 엔진Database Engine checks the associated transaction context. 데이터베이스 엔진Database Engine 은 열기 작업이 DDL 문, DML 문, 데이터 검색 또는 트랜잭션 관리 등을 사용하는지에 따라 요청을 허용하거나 거부합니다.The 데이터베이스 엔진Database Engine allows or denies the request based on whether the open operation is working with DDL statements, DML statements, retrieving data, or managing transactions. 다음 표에서는 트랜잭션에서 열려 있는 파일 유형에 따라 데이터베이스 엔진Database EngineTransact-SQLTransact-SQL 문을 허용 또는 거부할지를 결정하는 방법을 보여 줍니다.The following table shows how the 데이터베이스 엔진Database Engine determines whether a Transact-SQLTransact-SQL statement will be allowed or denied based on the type of files that are open in the transaction.

Transact-SQL 문Transact-SQL statements 읽기 권한으로 열림Opened for read 쓰기 권한으로 열림Opened for write
CREATE TABLE, CREATE INDEX, DROP TABLE 및 ALTER TABLE과 같은 데이터베이스 메타데이터를 사용하는 DDL 문DDL statements that work with database metadata, such as CREATE TABLE, CREATE INDEX, DROP TABLE, and ALTER TABLE. 허용함Allowed 차단되고 시간 초과 오류가 발생합니다.Are blocked and fail with a time-out.
UPDATE, DELETE 및 INSERT와 같이 데이터베이스에 저장된 데이터를 사용하는 DML 문DML statements that work with the data that is stored in the database, such as UPDATE, DELETE, and INSERT. 허용함Allowed 거부됨Denied
SELECTSELECT 허용함Allowed 허용함Allowed
COMMIT TRANSACTIONCOMMIT TRANSACTION 거부됨Denied 거부됨Denied.
SAVE TRANSACTIONSAVE TRANSACTION 거부됨Denied 거부됨Denied
ROLLBACKROLLBACK 허용됨Allowed 허용됨Allowed

* 트랜잭션이 취소되고 트랜잭션 컨텍스트의 열린 핸들이 무효화됩니다.* The transaction is canceled, and open handles for the transaction context are invalidated. 응용 프로그램은 열려 있는 모든 핸들을 닫아야 합니다.The application must close all open handles.

Examples

다음 예에서는 Transact-SQLTransact-SQL 문 및 FILESTREAM Win32 액세스 권한이 충돌을 발생시키는 방법을 보여 줍니다.The following examples show how Transact-SQLTransact-SQL statements and FILESTREAM Win32 access can cause conflicts.

1.A. 쓰기 권한으로 FILESTREAM BLOB 열기Opening a FILESTREAM BLOB for write access

다음 예에서는 쓰기 전용 권한으로 파일을 열었을 때 미치는 영향을 보여 줍니다.The following example shows the effect of opening a file for write access only.

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.  

2.B. 읽기 권한으로 FILESTREAM BLOB 열기Opening a FILESTREAM BLOB for read access

다음 예에서는 읽기 전용 권한으로 파일을 열었을 때 미치는 영향을 보여 줍니다.The following example shows the effect of opening a file for read access only.

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.  

3.C. 여러 FILESTREAM BLOB 파일 열기 및 닫기Opening and closing multiple FILESTREAM BLOB files

여러 파일이 열린 경우 가장 제한적인 규칙이 사용됩니다.If multiple files are open, the most restrictive rule is used. 다음 예에서는 두 파일을 엽니다.The following example opens two files. 첫 번째 파일은 읽기 권한으로 열리고 두 번째 파일은 쓰기 권한으로 열립니다.The first file is opened for read and the second for write. 두 번째 파일이 열리기 전까지 DML 문은 거부됩니다.DML statements will be denied until the second file is opened.

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.  

4.D. 커서 닫기 실패Failing to close a cursor

다음 예에서는 닫히지 않은 문 커서가 OpenSqlFilestream() 에서 쓰기 권한으로 BLOB를 열지 못하게 하는 방법을 보여 줍니다.The following example shows how a statement cursor that is not closed can prevent OpenSqlFilestream() from opening the BLOB for write access.

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.  

참고 항목See Also

OpenSqlFilestream을 사용하여 FILESTREAM 데이터 액세스 Access FILESTREAM Data with OpenSqlFilestream
MARS(Multiple Active Result Sets) 사용 Using Multiple Active Result Sets (MARS)