Dalam proyek kami, kami menggunakan TransactionScope untuk memastikan lapisan akses data kami melakukan tindakannya dalam transaksi. Kami bertujuan untuk tidak mengharuskan layanan MSDTC diaktifkan di mesin pengguna akhir kami.
Masalahnya adalah, pada setengah dari mesin pengembang kami, kami dapat berjalan dengan MSDTC dinonaktifkan. Setengah lainnya harus diaktifkan atau mereka mendapatkan pesan kesalahan "MSDTC pada [SERVER] tidak tersedia" .
Ini benar-benar membuat saya menggaruk-garuk kepala dan membuat saya serius mempertimbangkan untuk kembali ke solusi seperti TransactionScope home-spun berdasarkan objek transaksi ADO.NET. Ini tampaknya gila - kode yang sama bahwa karya (dan tidak meningkat) pada setengah dari pengembang kami yang melakukan Meningkat pada pengembang lain.
Saya berharap untuk jawaban yang lebih baik untuk Trace mengapa transaksi meningkat ke DTC tetapi sayangnya tidak.
Berikut adalah sedikit contoh kode yang akan menyebabkan masalah, pada mesin yang mencoba untuk meningkatkan, ia mencoba untuk meningkat pada koneksi kedua. Buka () (dan ya, tidak ada koneksi lain yang terbuka pada saat itu.)
using (TransactionScope transactionScope = new TransactionScope() {
using (SqlConnection connection = new SqlConnection(_ConStr)) {
using (SqlCommand command = connection.CreateCommand()) {
// prep the command
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()) {
// use the reader
connection.Close();
}
}
}
// Do other stuff here that may or may not involve enlisting
// in the ambient transaction
using (SqlConnection connection = new SqlConnection(_ConStr)) {
using (SqlCommand command = connection.CreateCommand()) {
// prep the command
connection.Open(); // Throws "MSDTC on [SERVER] is unavailable" on some...
// gets here on only half of the developer machines.
}
connection.Close();
}
transactionScope.Complete();
}
Kami benar-benar menggali dan mencoba mencari tahu ini. Berikut ini beberapa info tentang mesin yang bekerja:
- Pengembang 1: Windows 7 x64 SQL2008
- Pengembang 2: Windows 7 x86 SQL2008
- Pengembang 3: Windows 7 x64
SQL2005SQL2008
Pengembang yang tidak berfungsi:
- Dev 4: Windows 7 x64,
SQL2008SQL2005 - Dev 5: Windows Vista x86, SQL2005
- Dev 6: Windows XP X86, SQL2005
- PC Rumah Saya: Windows Vista Home Premium, x86, SQL2005
Saya harus menambahkan bahwa semua mesin, dalam upaya untuk mencari masalah, telah sepenuhnya ditambal dengan semua yang tersedia dari Pembaruan Microsoft.
Pembaruan 1:
- http://social.msdn.microsoft.com/forums/en-US/windowstransactionsprogramming/thread/a5462509-8d6d-4828-aefa-a197456081d3/ menjelaskan masalah yang sama ... kembali pada tahun 2006!
- http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope%28VS.80%29.aspx - membaca contoh kode itu, itu jelas menunjukkan koneksi bersarang-detik (ke server SQL kedua, sebenarnya) yang akan meningkat ke DTC. Kami tidak melakukan ini dalam kode kami - kami tidak menggunakan server SQL yang berbeda, atau string koneksi yang berbeda, kami juga tidak membuka sambungan koneksi sekunder - tidak boleh ada eskalasi ke DTC .
- http://davidhayden.com/blog/dave/archive/2005/12/09/2615.aspx (dari 2005) berbicara tentang bagaimana eskalasi ke DTC akan selalu terjadi ketika terhubung ke SQL2000. Kami menggunakan SQL2005 / 2008
- http://msdn.microsoft.com/en-us/library/ms229978.aspx MSDN tentang eskalasi transaksi.
Halaman eskalasi transaksi MSDN itu menyatakan bahwa kondisi berikut ini akan menyebabkan transaksi meningkat ke DTC:
- Setidaknya satu sumber daya tahan lama yang tidak mendukung pemberitahuan satu fase terdaftar dalam transaksi.
- Setidaknya dua sumber daya tahan lama yang mendukung notifikasi satu fase terdaftar dalam transaksi. Misalnya, mendaftar satu koneksi dengan tidak menyebabkan transaksi dipromosikan. Namun, setiap kali Anda membuka koneksi kedua ke database yang menyebabkan database terdaftar, infrastruktur System.Transactions mendeteksi bahwa itu adalah sumber daya tahan lama kedua dalam transaksi, dan meningkatkannya ke transaksi MSDTC.
- Permintaan untuk "marshal" transaksi ke domain aplikasi yang berbeda atau proses yang berbeda dipanggil. Misalnya, serialisasi objek transaksi melintasi batas domain aplikasi. Objek transaksi adalah marshaled-by-value, yang berarti bahwa setiap upaya untuk melewati batas domain aplikasi (bahkan dalam proses yang sama) menghasilkan serialisasi objek transaksi. Anda dapat melewati objek transaksi dengan melakukan panggilan pada metode jarak jauh yang mengambil Transaksi sebagai parameter atau Anda dapat mencoba mengakses komponen layanan transaksional jarak jauh. Ini membuat serial objek objek dan menghasilkan eskalasi, seperti ketika transaksi serial di seluruh domain aplikasi. Ini didistribusikan dan manajer transaksi lokal tidak lagi memadai.
Kami tidak mengalami # 3. # 2 tidak terjadi karena hanya ada satu koneksi pada satu waktu, dan itu juga untuk satu 'sumber daya tahan lama'. Apakah ada cara # 1 bisa terjadi? Beberapa konfigurasi SQL2005 / 8 yang menyebabkannya tidak mendukung pemberitahuan satu fase?
Pembaruan 2:
Diselidiki ulang, secara pribadi, semua versi SQL Server - "Dev 3" sebenarnya memiliki SQL2008, dan "Dev 4" sebenarnya adalah SQL2005. Itu akan mengajarkan saya untuk tidak pernah mempercayai rekan kerja saya lagi. ;) Karena perubahan data ini, saya cukup yakin kami telah menemukan masalah kami. Pengembang SQL2008 kami tidak mengalami masalah karena SQL2008 memiliki jumlah yang sangat banyak termasuk yang tidak dimiliki SQL2005.
Ini juga memberi tahu saya bahwa karena kita akan mendukung SQL2005 sehingga kita tidak dapat menggunakan TransactionScope seperti sebelumnya, dan jika kita ingin menggunakan TransactionScope kita harus melewati objek SqlConnection tunggal di sekitar ... yang tampaknya bermasalah dalam situasi di mana SqlConnection tidak dapat dengan mudah diteruskan ... hanya berbau instance global-SqlConnection. Bangku gereja!
Perbarui 3
Hanya untuk mengklarifikasi di sini dalam pertanyaan:
SQL2008:
- Mengizinkan beberapa koneksi dalam satu TransactionScope tunggal (seperti yang ditunjukkan dalam kode contoh di atas.)
- Peringatan # 1: Jika beberapa SqlConnections bersarang, yaitu, dua atau lebih SqlConnections dibuka pada saat yang sama, TransactionScope akan segera meningkat ke DTC.
- Peringatan # 2: Jika SqlConnection tambahan dibuka untuk 'sumber daya tahan lama' yang berbeda (yaitu: SQL Server yang berbeda,) itu akan segera meningkat ke DTC
SQL2005:
- Tidak mengizinkan banyak koneksi dalam satu TransactionScope, titik. Ini akan meningkat ketika / jika SqlConnection kedua dibuka.
Perbarui 4
Dalam kepentingan membuat pertanyaan ini bahkan lebih berantakan berguna, dan hanya demi kejelasan lebih lanjut, berikut adalah bagaimana Anda bisa mendapatkan SQL2005 meningkat ke DTC dengan tunggal SqlConnection
:
using (TransactionScope transactionScope = new TransactionScope()) {
using (SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
connection.Close();
connection.Open(); // escalates to DTC
}
}
Ini sepertinya rusak bagi saya, tapi saya rasa saya bisa mengerti jika setiap panggilan masuk SqlConnection.Open()
diambil dari pool koneksi.
"Tapi mengapa ini bisa terjadi?" Nah, jika Anda menggunakan SqlTableAdapter terhadap koneksi itu sebelum dibuka, SqlTableAdapter akan membuka dan menutup koneksi, secara efektif menyelesaikan transaksi untuk Anda karena Anda sekarang tidak dapat membukanya kembali.
Jadi, pada dasarnya, agar berhasil menggunakan TransactionScope dengan SQL2005 Anda harus memiliki semacam objek koneksi global yang tetap terbuka dari titik TransactionScope pertama instantiated sampai tidak lagi diperlukan. Selain bau kode dari objek koneksi global, membuka koneksi terlebih dahulu dan menutupnya terakhir bertentangan dengan logika membuka koneksi selambat mungkin dan menutupnya sesegera mungkin.
sumber
Jawaban:
SQL Server 2008 dapat menggunakan banyak
SQLConnection
s dalam satuTransactionScope
tanpa eskalasi, asalkan koneksi tidak terbuka pada saat yang sama, yang akan menghasilkan beberapa koneksi TCP "fisik" dan karenanya memerlukan eskalasi.Saya melihat beberapa pengembang Anda memiliki SQL Server 2005 dan yang lain memiliki SQL Server 2008. Apakah Anda yakin telah mengidentifikasi dengan benar mana yang meningkat dan mana yang tidak?
Penjelasan yang paling jelas adalah bahwa pengembang dengan SQL Server 2008 adalah orang-orang yang tidak meningkat.
sumber
TransactionScope
dapat dilakukan dengan satuCOMMIT
di sisi server, yang akan membuat eskalasi berlebihan.Hasil penelitian saya pada topik:
Lihat Menghindari Eskalasi yang tidak diinginkan ke Transaksi Terdistribusi
Saya masih menyelidiki perilaku eskalasi Oracle: Apakah transaksi yang mencakup banyak koneksi ke DB yang sama meningkat ke DTC?
sumber
Kode itu akan menyebabkan peningkatan saat menyambung ke 2005.
Periksa dokumentasi di MSDN - http://msdn.microsoft.com/en-us/library/ms172070.aspx
Saya tidak bisa menjelaskan mengapa Dev 3: Windows 7 x64, SQL2005 berhasil dan Dev 4: Windows 7 x64 gagal. Apakah Anda yakin itu tidak sebaliknya?
sumber
Saya tidak tahu mengapa jawaban ini dihapus tetapi ini sepertinya memiliki beberapa informasi yang relevan.
jawab 4 Agustus 10 pada 17:42 Eduardo
Tetapkan Daftar = palsu pada string koneksi untuk menghindari pendaftaran otomatis pada transaksi.
Secara manual mendaftar koneksi sebagai peserta dalam ruang lingkup transaksi. [ artikel asli kedaluwarsa] atau lakukan ini: Cara mencegah promosi MSDTC otomatis [archive.is]
sumber
Saya tidak terlalu yakin apakah koneksi bersarang adalah masalahnya. Saya memanggil contoh lokal dari server SQL dan tidak menghasilkan DTC ??
sumber
TransactionScope selalu meningkat ke transaksi DTC, jika Anda menggunakan akses lebih dari 1 koneksi di dalamnya. Satu-satunya cara kode di atas dapat bekerja dengan DTC dinonaktifkan adalah jika secara kebetulan Anda mendapatkan koneksi yang sama dari kumpulan koneksi dua kali.
"Masalahnya adalah, pada setengah dari mesin pengembang kami, kami dapat berjalan dengan MSDTC dinonaktifkan." Apakah Anda yakin itu dinonaktifkan;)
sumber
Pastikan connectionString Anda tidak mengatur pooling ke false. Ini akan menghasilkan koneksi baru untuk setiap SqlConnection baru di TransactionScope dan meningkatkannya ke DTC.
sumber