Partilhar via


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

Aplica-se a:SQL Server

Aplicações que utilizam SqlOpenFilestream() para abrir identificadores de arquivo Win32 para leitura ou escrita de dados BLOB FILESTREAM podem enfrentar erros de conflito com as instruções Transact-SQL que são geridas numa transação comum. Isso inclui consultas Transact-SQL ou MARS que levam muito tempo para concluir a execução. Os aplicativos devem ser cuidadosamente projetados para ajudar a evitar esses tipos de conflitos.

Quando o Mecanismo de Banco de Dados do SQL Server ou aplicativos tentam abrir BLOBs FILESTREAM, o Mecanismo de Banco de Dados verifica o contexto de transação associado. O Mecanismo de Banco de Dados permite ou nega a solicitação com base no fato de a operação aberta estar trabalhando com instruções DDL, instruções DML, recuperação de dados ou gerenciamento de transações. 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.

Transact-SQL declarações Aberto para leitura Aberto para gravação
Instruções DDL que funcionam com metadados de banco de dados, como CREATE TABLE, CREATE INDEX, DROP TABLE e ALTER TABLE. Permitido São bloqueados e falham por esgotamento de tempo.
Instruções DML que funcionam com os dados armazenados no banco de dados, como UPDATE, DELETE e INSERT. Permitido Negado
SELECIONAR Permitido Permitido
CONFIRMAR TRANSAÇÃO Negado* Negado*.
SALVAR TRANSAÇÃO Negado* Negado*
REVERSÃO Permitido* Permitido*

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

Exemplos

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

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

O exemplo a seguir mostra o efeito de abrir um arquivo somente para acesso 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. Abrir um BLOB FILESTREAM para acesso de leitura

O exemplo a seguir mostra o efeito de abrir um arquivo somente para acesso 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 BLOB FILESTREAM

Se vários arquivos estiverem abertos, a regra mais restritiva será usada. O exemplo a seguir abre dois arquivos. O primeiro arquivo é aberto para leitura e o segundo para gravação. As declaraçõ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 que OpenSqlFilestream() abra 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.  

Ver também

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