Compartilhar via


Evitar conflitos com operações de banco de dados em aplicativos de FILESTREAM

Aplicativos que usam SqlOpenFilestream() para abrir identificadores de arquivo Win32 para ler ou gravar dados DE BLOB FILESTREAM podem encontrar erros de conflito com instruções Transact-SQL gerenciadas em uma transação comum. Isso inclui consultas Transact-SQL ou MARS que levam muito tempo para concluir a execução. Os aplicativos devem ser criados cautelosamente para evitar esses tipos de conflitos.

Quando o Mecanismo de Banco de Dados do SQL Server ou os aplicativos tentam abrir FILESTREAM BLOBs, o Mecanismo de Banco de Dados verifica o contexto de transação associado. O Mecanismo de Banco de Dados permite ou nega as solicitações, dependendo se a operação em aberto funciona com instruções DDL e DML, transações de recuperação de dados ou de gerenciamento. A tabela a seguir mostra como o Mecanismo de Banco de Dados determina se uma instrução Transact-SQL será permitida ou negada com base no tipo de arquivos abertos na transação.

instruções Transact-SQL Abertas para leitura Abertas para gravação
Instruções de DDL que funcionam com metadados de banco de dados, como CREATE TABLE, CREATE INDEX, DROP TABLE e ALTER TABLE. Permitido São bloqueadas e falham devido ao tempo limite esgotado.
Instruções DML que funcionam com os dados armazenados no banco de dados, como UPDATE, DELETE e INSERT. Permitido Negadas
SELECT Permitido Permitido
COMMIT TRANSACTION Negadas* Negadas*.
SAVE TRANSACTION Negadas* Negadas*
ROLLBACK Permitidas* Permitidas*

* A transação é cancelada e os identificadores abertos para o contexto da transação são invalidados. O aplicativo deve fechar todos os identificadores abertos.

Exemplos

Os exemplos a seguir mostram como instruções Transact-SQL e acesso FILESTREAM Win32 podem causar conflitos.

a. Abrindo um BLOB FILESTREAM para acesso de gravação

O exemplo a seguir mostra o efeito de abrir um arquivo para acesso apenas de gravação.

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. Abrindo um BLOB FILESTREAM para acesso de leitura

O exemplo a seguir mostra o efeito de abrir um arquivo para acesso apenas de leitura.

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. Abrindo e fechando vários arquivos de BLOB FILESTREAM

Se vários arquivos estiverem abertos, será usada a regra mais restritiva. O exemplo a seguir abre dois arquivos. O primeiro é aberto para leitura e o segundo, para gravação. As instruções DML serão negadas até que o segundo arquivo seja aberto.

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. Falha ao fechar um cursor

O exemplo a seguir mostra como um cursor de instrução que não está fechado pode impedir OpenSqlFilestream() de abrir o BLOB para acesso de gravação.

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.  

Consulte Também

Acessar dados do FILESTREAM com OpenSqlFilestream
Usando MARS (vários conjuntos de resultados ativos)