FILESTREAM 애플리케이션에서 데이터베이스 작업과의 충돌 방지
SqlOpenFilestream()을 사용하여 FILESTREAM BLOB 데이터를 읽거나 쓰기 위해 Win32 파일 핸들을 여는 애플리케이션은 일반적인 트랜잭션에서 관리되는 Transact-SQL 문과 충돌 오류가 발생할 수 있습니다. 여기에는 실행을 완료하는 데 시간이 오래 걸리는 Transact-SQL 또는 MARS 쿼리가 포함됩니다. 이러한 유형의 충돌을 방지하도록 애플리케이션을 신중하게 디자인해야 합니다.
SQL Server 데이터베이스 엔진 또는 애플리케이션이 FILESTREAM BLOB를 열려고 하면 데이터베이스 엔진 이 연결된 트랜잭션 컨텍스트를 확인합니다. 데이터베이스 엔진 은 열기 작업이 DDL 문, DML 문, 데이터 검색 또는 트랜잭션 관리 등을 사용하는지에 따라 요청을 허용하거나 거부합니다. 다음 표에서는 데이터베이스 엔진이 트랜잭션에 열려 있는 파일 형식에 따라 Transact-SQL 문을 허용할지 아니면 거부할지를 결정하는 방법을 보여 줍니다.
Transact-SQL 문 | 읽기 권한으로 열림 | 쓰기 권한으로 열림 |
---|---|---|
CREATE TABLE, CREATE INDEX, DROP TABLE 및 ALTER TABLE과 같은 데이터베이스 메타데이터를 사용하는 DDL 문 | 허용됨 | 차단되고 시간 초과 오류가 발생합니다. |
UPDATE, DELETE 및 INSERT와 같이 데이터베이스에 저장된 데이터를 사용하는 DML 문 | 허용됨 | 거부됨 |
SELECT | 허용됨 | 허용됨 |
COMMIT TRANSACTION | 거부됨* | 거부됨* |
SAVE TRANSACTION | 거부됨* | 거부됨* |
ROLLBACK | 허용됨* | 허용됨* |
* 트랜잭션이 취소되고 트랜잭션 컨텍스트의 열린 핸들이 무효화됩니다. 애플리케이션은 열려 있는 모든 핸들을 닫아야 합니다.
예
다음 예제에서는 Transact-SQL 문 및 FILESTREAM Win32 액세스로 인해 충돌이 발생할 수 있는 방법을 보여 줍니다.
A. 쓰기 권한으로 FILESTREAM BLOB 열기
다음 예에서는 쓰기 전용 권한으로 파일을 열었을 때 미치는 영향을 보여 줍니다.
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. 읽기 권한으로 FILESTREAM BLOB 열기
다음 예에서는 읽기 전용 권한으로 파일을 열었을 때 미치는 영향을 보여 줍니다.
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. 여러 FILESTREAM BLOB 파일 열기 및 닫기
여러 파일이 열린 경우 가장 제한적인 규칙이 사용됩니다. 다음 예에서는 두 파일을 엽니다. 첫 번째 파일은 읽기 권한으로 열리고 두 번째 파일은 쓰기 권한으로 열립니다. 두 번째 파일이 열리기 전까지 DML 문은 거부됩니다.
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. 커서 닫기 실패
다음 예에서는 닫히지 않은 문 커서가 OpenSqlFilestream()
에서 쓰기 권한으로 BLOB를 열지 못하게 하는 방법을 보여 줍니다.
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.
참고 항목
OpenSqlFilestream을 사용하여 FILESTREAM 데이터 액세스
MARS(Multiple Active Result Sets) 사용