Hindari konflik dengan operasi database dalam aplikasi FILESTREAM

Berlaku untuk:SQL Server

Aplikasi yang menggunakan SqlOpenFilestream() untuk membuka handel file Win32 untuk membaca atau menulis data BLOB FILESTREAM dapat mengalami kesalahan konflik dengan pernyataan Transact-SQL yang dikelola dalam transaksi umum. Ini termasuk kueri Transact-SQL atau MARS yang membutuhkan waktu lama untuk menyelesaikan eksekusi. Aplikasi harus dirancang dengan hati-hati untuk membantu menghindari jenis konflik ini.

Ketika SQL Server Database Engine atau aplikasi mencoba membuka BLOB FILESTREAM, Mesin Database memeriksa konteks transaksi terkait. Mesin Database memungkinkan atau menolak permintaan berdasarkan apakah operasi terbuka bekerja dengan pernyataan DDL, pernyataan DML, mengambil data, atau mengelola transaksi. Tabel berikut menunjukkan bagaimana Mesin Database menentukan apakah pernyataan Transact-SQL akan diizinkan atau ditolak berdasarkan jenis file yang terbuka dalam transaksi.

Pernyataan T-SQL Dibuka untuk dibaca Dibuka untuk penulisan
Pernyataan DDL yang berfungsi dengan metadata database, seperti CREATE TABLE, CREATE INDEX, DROP TABLE, dan ALTER TABLE. Diizinkan Diblokir dan gagal dengan waktu habis.
Pernyataan DML yang berfungsi dengan data yang disimpan dalam database, seperti UPDATE, DELETE, dan INSERT. Diizinkan Ditolak
SELECT Diizinkan Diizinkan
COMMIT TRANSACTION, ATAU Ditolak* Ditolak*.
SIMPAN TRANSAKSI Ditolak* Ditolak*
ROLLBACK Diperbolehkan* Diperbolehkan*

* Transaksi dibatalkan, dan handel terbuka untuk konteks transaksi tidak valid. Aplikasi harus menutup semua handel yang terbuka.

Contoh

Contoh berikut menunjukkan bagaimana pernyataan Transact-SQL dan akses FILESTREAM Win32 dapat menyebabkan konflik.

J. Membuka BLOB FILESTREAM untuk akses tulis

Contoh berikut menunjukkan efek membuka file hanya untuk akses tulis.

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. Membuka BLOB FILESTREAM untuk akses baca

Contoh berikut menunjukkan efek membuka file hanya untuk akses baca.

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. Membuka dan menutup beberapa file BLOB FILESTREAM

Jika beberapa file terbuka, aturan yang paling ketat digunakan. Contoh berikut membuka dua file. File pertama dibuka untuk dibaca dan yang kedua untuk menulis. Pernyataan DML akan ditolak hingga file kedua dibuka.

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. Gagal menutup kursor

Contoh berikut menunjukkan bagaimana kursor pernyataan yang tidak ditutup dapat mencegah OpenSqlFilestream() membuka BLOB untuk akses tulis.

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.  

Lihat Juga

Mengakses Data FILESTREAM dengan OpenSqlFilestream
Menggunakan Beberapa Set Hasil Aktif (MARS)