Evitar conflictos con operaciones de base de datos en aplicaciones FILESTREAMAvoid conflicts with database operations in FILESTREAM applications

Se aplica a:Applies to: síSQL ServerSQL Server (todas las versiones admitidas) yesSQL ServerSQL Server (all supported versions) Se aplica a:Applies to: síSQL ServerSQL Server (todas las versiones admitidas) yesSQL ServerSQL Server (all supported versions)

Las aplicaciones que usan SqlOpenFilestream() para abrir los identificadores de archivos de Win32 con el fin de leer o escribir datos BLOB de FILESTREAM pueden encontrar errores de conflictos con las instrucciones de Transact-SQLTransact-SQL que se administran en una transacción común.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. Esto incluye las consultas de Transact-SQLTransact-SQL o MARS que tardan mucho en finalizar la ejecución.This includes Transact-SQLTransact-SQL or MARS queries that take a long time to finish execution. Las aplicaciones deben diseñarse cuidadosamente para ayudar a evitar estos tipos de conflictos.Applications must be carefully designed to help avoid these types of conflicts.

Cuando Motor de base de datos de SQL ServerSQL Server Database Engine o las aplicaciones intentan abrir BLOB de FILESTREAM, Motor de base de datosDatabase Engine comprueba el contexto de transacciones asociado.When Motor de base de datos de SQL ServerSQL Server Database Engine or applications try to open FILESTREAM BLOBs, the Motor de base de datosDatabase Engine checks the associated transaction context. Motor de base de datosDatabase Engine permite o deniega la solicitud en función de si la operación abierta opera con instrucciones DDL, instrucciones DML, la recuperación de los datos o la administración de las transacciones.The Motor de base de datosDatabase Engine allows or denies the request based on whether the open operation is working with DDL statements, DML statements, retrieving data, or managing transactions. La tabla siguiente muestra cómo Motor de base de datosDatabase Engine determina si una instrucción de Transact-SQLTransact-SQL se permitirá o denegará según el tipo de archivos que se abran en la transacción.The following table shows how the Motor de base de datosDatabase 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.

Instrucciones Transact-SQLTransact-SQL statements Abierto para lecturaOpened for read Abierto para escrituraOpened for write
Instrucciones DDL que trabajan con los metadatos de la base de datos, como CREATE TABLE, CREATE INDEX, DROP TABLE y ALTER TABLE.DDL statements that work with database metadata, such as CREATE TABLE, CREATE INDEX, DROP TABLE, and ALTER TABLE. PermitidaAllowed Se bloquean y agotan el tiempo de espera con un error.Are blocked and fail with a time-out.
Instrucciones DML que trabajan con los datos que están almacenados en la base de datos, como UPDATE, DELETE e INSERT.DML statements that work with the data that is stored in the database, such as UPDATE, DELETE, and INSERT. PermitidaAllowed DenegadoDenied
SELECTSELECT PermitidaAllowed PermitidaAllowed
COMMIT TRANSACTIONCOMMIT TRANSACTION Denegado*Denied* Denegado*Denied*.
SAVE TRANSACTIONSAVE TRANSACTION Denegado*Denied* Denegado*Denied*
ROLLBACKROLLBACK Permitido*Allowed* Permitido*Allowed*

* La transacción se cancela y se invalidan los identificadores abiertos para el contexto de transacciones.* The transaction is canceled, and open handles for the transaction context are invalidated. La aplicación debe cerrar todos los identificadores abiertos.The application must close all open handles.

EjemplosExamples

Los ejemplos siguientes muestran cómo las instrucciones Transact-SQLTransact-SQL y el acceso FILESTREAM de Win32 pueden producir conflictos.The following examples show how Transact-SQLTransact-SQL statements and FILESTREAM Win32 access can cause conflicts.

A.A. Abrir un BLOB de FILESTREAM para acceso de escrituraOpening a FILESTREAM BLOB for write access

En el ejemplo siguiente se muestra el efecto de abrir únicamente un archivo para acceso de escritura.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.  

B.B. Abrir un BLOB de FILESTREAM para acceso de lecturaOpening a FILESTREAM BLOB for read access

En el ejemplo siguiente se muestra el efecto de abrir únicamente un archivo para acceso de lectura.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.  

C.C. Abrir y cerrar varios archivos BLOB de FILESTREAMOpening and closing multiple FILESTREAM BLOB files

Si hay varios archivos abiertos, se usa la regla más restrictiva.If multiple files are open, the most restrictive rule is used. En el ejemplo siguiente se abren dos archivos.The following example opens two files. El primero se abre durante la lectura y el segundo para la escritura.The first file is opened for read and the second for write. Se denegarán las instrucciones DML hasta que se abra el segundo archivo.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.  

D.D. No se puede cerrar un cursorFailing to close a cursor

El ejemplo siguiente muestra cómo un cursor de instrucción que no se cierra puede evitar que OpenSqlFilestream() abra el BLOB para acceso de escritura.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.  

Consulte tambiénSee Also

Obtener acceso a los datos FILESTREAM con OpenSqlFilestream Access FILESTREAM Data with OpenSqlFilestream
Usar conjuntos de resultados activos múltiples (MARS)Using Multiple Active Result Sets (MARS)