System.Transaksi Infrastruktur di Dunia .NET


Pernahkah Anda melihat konstruksi seperti using (var scope = new TransactionScope(TransactionScopeOption.Required)) di C #? Ini berarti bahwa kode yang berjalan di blok using dalam transaksi dan setelah keluar dari blok ini perubahan akan dilakukan atau dibatalkan. Kedengarannya bisa dimengerti sampai Anda mulai menggali lebih dalam. Dan semakin dalam Anda menggali, "aneh dan aneh" itu menjadi. Dalam kasus apa pun, ketika saya menjadi lebih akrab dengan kelas TransactionScope dan, secara umum, dengan transaksi NET., Banyak pertanyaan muncul.

Apa kelas TransactionScope ? Segera setelah kami menggunakan konstruk using (var scope = new TransactionScope()) , apakah semua yang ada di program kami langsung menjadi transaksional? Apa itu "Manajer Sumber Daya" dan "Manajer Transaksi"? Bisakah saya menulis manajer sumber daya saya sendiri dan bagaimana cara "terhubung" ke instance TransactionScope dibuat? Apa itu transaksi terdistribusi dan apakah benar transaksi terdistribusi dalam SQL Server atau Oracle Database sama dengan transaksi .NET terdistribusi?

Dalam publikasi ini, saya mencoba mengumpulkan materi yang membantu menemukan jawaban atas pertanyaan-pertanyaan ini dan membangun pemahaman transaksi di dunia .NET.


Pendahuluan


Apa transaksi dan masalah apa yang mereka pecahkan?


Transaksi yang dipermasalahkan di sini adalah operasi yang memindahkan sistem dari satu kondisi yang dapat diterima ke kondisi lain dan dijamin tidak meninggalkan sistem dalam keadaan yang tidak dapat diterima bahkan jika situasi yang tidak terduga muncul. Seperti apa kondisi yang dapat diterima ini, dalam kasus umum, tergantung pada konteksnya. Di sini kami akan mempertimbangkan situasi yang dapat diterima di mana data yang kami proses merupakan bagian integral. Dapat dipahami bahwa perubahan yang membentuk transaksi dilakukan bersama atau tidak dilakukan. Selain itu, perubahan pada satu transaksi dapat diisolasi dari perubahan yang dilakukan pada sistem oleh transaksi lainnya. Persyaratan dasar untuk transaksi dilambangkan dengan akronim ACID. Untuk kenalan pertama dengan mereka, artikel di Wikipedia cocok.


Contoh klasik dari suatu transaksi adalah transfer uang antara dua akun. Dalam situasi ini, menarik uang dari akun No. 1 tanpa mengkredit ke akun No. 2 tidak dapat diterima, dengan cara yang sama seperti menyetor ke akun No. 2 tanpa menarik dari akun No. 1. Dengan kata lain, kami ingin kedua operasi penarikan dan pemberian kredit - dilakukan segera. Jika salah satu dari mereka gagal, maka operasi kedua tidak boleh dilakukan. Anda dapat menyebut prinsip ini "semua atau tidak sama sekali." Selain itu, diharapkan bahwa operasi dilakukan secara serentak bahkan jika terjadi kegagalan sistemik seperti pemadaman listrik, yaitu, bahwa kita melihat sistem dalam keadaan yang dapat diterima segera setelah tersedia setelah pemulihan.

Dalam istilah matematika, kita dapat mengatakan bahwa berkenaan dengan sistem ada invarian yang pasti ingin kita pertahankan. Sebagai contoh, jumlah pada kedua akun: perlu bahwa setelah transaksi (pengiriman uang) jumlahnya tetap sama seperti sebelumnya. By the way, dalam contoh transfer uang klasik, akuntansi juga muncul - area subjek di mana konsep transaksi muncul secara alami.

Kami menggambarkan contoh mentransfer uang antara dua akun. Gambar pertama menunjukkan situasi ketika transfer 50 rubel dari akun No. 1 ke akun No. 2 selesai dengan sukses. Warna hijau menunjukkan bahwa sistem berada dalam kondisi yang dapat diterima (data lengkap).


Sekarang bayangkan bahwa transfer dilakukan di luar transaksi dan setelah menarik uang dari akun No. 1, terjadi kegagalan, di mana uang yang ditarik tidak dikreditkan ke akun No. 2. Sistem akan berada dalam keadaan yang tidak dapat diterima (warna merah).


Jika terjadi kesalahan antara operasi penarikan dan pemberian kredit, tetapi transfer dilakukan sebagai bagian dari satu transaksi, operasi penarikan akan dibatalkan. Akibatnya, sistem akan tetap dalam kondisi semula yang dapat diterima.


Saya akan memberikan contoh situasi dari pengalaman perusahaan kami di mana transaksi berguna: akuntansi untuk barang (akuntansi untuk jumlah barang dari berbagai jenis yang ada di toko-toko tertentu dan dalam perjalanan), akuntansi untuk sumber daya penyimpanan (akuntansi untuk volume kamar yang ditempati oleh barang dari jenis tertentu, volume kamar, gratis untuk penempatan barang, jumlah barang yang dapat dipindahkan oleh karyawan dan sistem penyimpanan otomatis per hari).

Masalah yang muncul saat integritas data dilanggar sudah jelas. Informasi yang disediakan oleh sistem tidak hanya menjadi salah - ia kehilangan kontak dengan kenyataan dan berubah menjadi omong kosong.

Transaksi apa yang dipertimbangkan di sini


Manfaat yang diberikan oleh transaksi diketahui. Jadi, untuk menjaga integritas data, apakah kita memerlukan basis data relasional, karena di situlah transaksi dilakukan? Tidak juga. Dikatakan di atas bahwa konsep transaksi tergantung pada konteksnya, dan sekarang kita akan secara singkat mempertimbangkan transaksi apa yang dapat kita bicarakan ketika membahas sistem informasi.

Untuk memulainya, kami memisahkan konsep transaksi domain perihal (transaksi bisnis) dan transaksi sistem. Yang kedua dapat diimplementasikan di tempat yang berbeda dan dengan cara yang berbeda.

Mari kita pergi dari level tertinggi - area subjek. Orang yang tertarik dapat menyatakan bahwa ada beberapa negara yang dapat diterima dan dia tidak ingin melihat sistem informasi di luar negara-negara ini. Kami tidak akan memberikan contoh tambahan: mentransfer uang antar rekening cocok di sini. Kami hanya mengklarifikasi bahwa transfer belum tentu merupakan transfer uang antara rekening penyelesaian dua pelanggan bank. Yang tidak kalah penting adalah tugas akuntansi, ketika akun harus mencerminkan sumber dan tujuan dana organisasi, dan transfer harus mencerminkan perubahan dalam distribusi dana berdasarkan sumber dan tujuan ini. Ini adalah contoh transaksi domain perihal .

Sekarang mari kita lihat contoh paling umum dan menarik dari implementasi transaksi sistem. Dalam transaksi sistem, berbagai cara teknis menyediakan persyaratan area subjek. Solusi klasik yang terbukti dari jenis ini adalah transaksi DBMS relasional (contoh pertama). Sistem manajemen basis data modern (baik yang bersifat relasional maupun yang tidak terlalu ) menyediakan mekanisme transaksi yang memungkinkan Anda untuk menyimpan (melakukan) semua perubahan yang dilakukan selama periode kerja tertentu, atau membuangnya (memutar kembali). Ketika menggunakan mekanisme seperti itu, operasi penarikan uang dari satu akun dan mengkredit ke akun lain yang membentuk transaksi area subjek, sarana DBMS akan digabungkan menjadi sistem transaksi dan akan dieksekusi bersama atau tidak dilakukan sama sekali.

Menggunakan DBMS, tentu saja, tidak perlu. Secara kasar, Anda biasanya dapat menerapkan mekanisme transaksi DBMS dalam bahasa pemrograman favorit Anda dan menikmati analog yang tidak stabil dan bermasalah dari alat yang ada. Tetapi "sepeda" Anda dapat dioptimalkan untuk situasi tertentu di area subjek.

Ada opsi yang lebih menarik. Bahasa pemrograman industri modern (C # dan Java di tempat pertama) menawarkan alat yang dirancang khusus untuk mengatur transaksi yang melibatkan subsistem yang sama sekali berbeda, dan bukan hanya DBMS. Dalam publikasi ini, kami akan memanggil perangkat lunak transaksi tersebut. Dalam kasus C #, ini adalah transaksi dari System.Transaksi namespace (contoh kedua), dan mereka dijelaskan di bawah ini.

Sebelum pindah ke System.Transactions transaksi, seseorang tidak dapat gagal untuk menyebutkan satu lagi fenomena menarik. Alat System.Transactions memungkinkan programmer untuk secara mandiri menerapkan memori transaksi terprogram . Dalam hal ini, operasi program yang mempengaruhi keadaan sistem (dalam kasus bahasa pemrograman imperatif klasik, ini adalah operasi penugasan) secara default termasuk dalam transaksi yang dapat dilakukan dan dikembalikan seperti halnya transaksi DBMS. Dengan pendekatan ini, kebutuhan untuk menggunakan mekanisme sinkronisasi (dalam C # - lock , dalam Java - synchronized ) berkurang secara signifikan. Pengembangan lebih lanjut dari ide ini adalah memori transaksional perangkat lunak, didukung pada level platform (contoh ketiga). Mukjizat semacam itu diharapkan dapat ditemukan dalam bahasa yang keanggunannya melampaui penerapan industri - Clojure. Dan untuk bahasa pekerja-tani, ada perpustakaan plug-in yang menyediakan fungsionalitas memori transaksional terprogram.

Sistem transaksi dapat mencakup beberapa sistem informasi, dalam hal ini mereka didistribusikan. Terdistribusi dapat berupa transaksi dan perangkat lunak DBMS; itu semua tergantung pada fungsionalitas apa yang didukung oleh alat transaksi tertentu. Transaksi didistribusikan lebih rinci dibahas di bagian yang sesuai. Saya akan memberikan gambar untuk membuatnya lebih mudah untuk memahami topik yang dibahas.


TL; bagian DR


Ada proses yang terdiri dari beberapa operasi (atom) yang tidak dapat dipisahkan yang diterapkan pada sistem, dalam kasus umum belum tentu bersifat informasi. Setiap operasi yang tidak dapat dibagi dapat membuat sistem dalam keadaan tidak dapat diterima ketika integritas data terganggu. Misalnya, jika transfer uang antara dua akun diwakili oleh dua operasi penarikan dari akun No. 1 yang tidak terpisahkan dan mengkredit ke akun No. 2, maka hanya satu dari operasi ini yang akan melanggar integritas data. Uang entah menghilang di antah berantah, atau muncul di antah berantah. Suatu transaksi menggabungkan operasi yang tidak dapat dibagi sehingga semuanya dilakukan bersama-sama (tentu saja, secara berurutan, jika perlu) atau tidak dilakukan sama sekali. Kita dapat berbicara tentang transaksi domain dan transaksi dalam sistem teknis yang biasanya menerapkan transaksi domain.

Transaksi berdasarkan System.Transaksi


Apa ini


Di dunia .NET, ada kerangka kerja perangkat lunak yang dirancang oleh pencipta platform manajemen transaksi. Dari perspektif programmer transaksional, kerangka kerja ini terdiri dari TransactionScope , TransactionScopeOption , TransactionScopeAsyncFlowOption dan TransactionOptions System.Transactions . Namespace TransactionOptions . Jika kita berbicara tentang .NET Standard, maka semua ini tersedia mulai dengan versi 2.0 .

Transaksi dari System.Transactions namespace didasarkan pada standar X / Open XA dari The Open Group . Standar ini memperkenalkan banyak istilah yang dibahas di bawah ini, dan yang paling penting, menjelaskan transaksi terdistribusi, yang juga tercakup dalam publikasi ini di bagian khusus. Implementasi transaksi perangkat lunak di platform lain, misalnya , Java, didasarkan pada standar yang sama.

Kasus penggunaan transaksi khas untuk programmer C # adalah sebagai berikut:

 using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required)) { // -  ,    . scope.Complete(); } 

Di dalam blok using adalah kode yang melakukan pekerjaan, yang hasilnya harus dilakukan atau dibatalkan bersama-sama. Contoh klasik dari pekerjaan tersebut adalah membaca dan menulis ke database atau mengirim dan menerima pesan dari antrian. Ketika kontrol meninggalkan blok using , transaksi akan dilakukan. Jika Anda menghapus panggilan Complete , transaksi akan dibatalkan. Cukup sederhana.

Ternyata selama pengembalian transaksi, semua operasi yang dilakukan di dalam blok using akan dibatalkan? Dan jika saya menetapkan variabel nilai yang berbeda, maka variabel ini akan mengembalikan nilai lama? Ketika saya pertama kali melihat desain yang sama, saya pikir begitu. Sebenarnya, tentu saja, tidak semua perubahan akan dibatalkan, tetapi hanya yang sangat istimewa . Jika semua perubahan dibatalkan, maka ini akan menjadi memori transaksional perangkat lunak yang dijelaskan di atas. Sekarang mari kita lihat apa perubahan khusus ini yang dapat berpartisipasi dalam transaksi program berdasarkan System.Transactions .

Manajer sumber daya


Untuk sesuatu untuk mendukung transaksi berdasarkan System.Transactions , perlu bahwa ia memiliki informasi bahwa transaksi saat ini sedang berlangsung, dan bahwa itu terdaftar di beberapa peserta pendaftaran transaksi. Anda dapat memperoleh informasi tentang apakah pekerjaan transaksional sedang berlangsung dengan memeriksa properti statis Current of System.Transactions.Transaction class. Memasuki blok using tipe yang ditunjukkan di atas hanya menyetel properti ini, jika belum disetel sebelumnya. Dan untuk mendaftar sebagai peserta dalam transaksi, Anda dapat menggunakan metode bertipe Transaction.Enlist Smth . Selain itu, Anda perlu mengimplementasikan antarmuka yang diperlukan oleh metode ini. Resource Manager - ini hanyalah "sesuatu" yang mendukung interaksi dengan transaksi dari System.Transactions (definisi yang lebih spesifik diberikan di bawah).

Apa itu manajer sumber daya? Jika kita bekerja dari C # dengan DBMS, misalnya, SQL Server atau Database Oracle, maka kita biasanya menggunakan driver yang sesuai, dan mereka adalah sumber daya pengelolaan. Dalam kode, mereka diwakili oleh jenis System.Data.SqlClient.SqlConnection dan Oracle.ManagedDataAccess.Client.OracleConnection . Mereka juga mengatakan bahwa MSMQ mendukung transaksi berdasarkan System.Transactions . Dipandu oleh pengetahuan dan contoh-contoh yang diambil dari Internet, Anda dapat membuat manajer sumber daya Anda sendiri. Contoh paling sederhana diberikan pada bagian selanjutnya.

Selain manajer sumber daya, kita juga harus memiliki Manajer Transaksi, yang akan memantau transaksi dan memberikan pesanan kepada manajer sumber daya secara tepat waktu. Bergantung pada manajer sumber daya mana yang terlibat dalam transaksi (karakteristik apa yang mereka miliki dan di mana mereka berada), manajer transaksi yang berbeda terhubung ke pekerjaan. Dalam hal ini, pemilihan versi yang sesuai adalah otomatis dan tidak memerlukan intervensi seorang programmer.

Lebih spesifik, manajer sumber daya adalah turunan dari kelas yang mengimplementasikan antarmuka System.Transactions.IEnlistmentNotification khusus. Instance kelas, seperti yang diarahkan oleh klien, terdaftar sebagai peserta dalam transaksi menggunakan System.Transactions.Transaction.Current properti statis.Transaksi.Transaksi.Current. Selanjutnya, manajer transaksi memanggil metode dari antarmuka yang ditentukan sebagaimana diperlukan.


Jelas bahwa pada saat run time, himpunan manajer sumber daya yang terlibat dalam transaksi dapat berubah. Misalnya, setelah memasukkan blok using , pertama-tama kita dapat melakukan sesuatu di SQL Server, dan kemudian di Oracle Database. Tergantung pada set manajer sumber daya ini, manajer transaksi yang digunakan ditentukan. Untuk lebih tepatnya, protokol transaksional yang digunakan ditentukan oleh himpunan manajer sumber daya, dan manajer transaksi yang mendukungnya ditentukan berdasarkan protokol. Kita akan melihat protokol transaksional nanti ketika kita berbicara tentang transaksi yang didistribusikan. Mekanisme untuk secara otomatis memilih manajer transaksi yang sesuai pada waktu berjalan ketika mengubah manajer sumber daya yang terlibat dalam transaksi disebut Promosi Transaksi.

Jenis Manajer Sumber Daya


Manajer sumber daya dapat dibagi menjadi dua kelompok besar: tahan lama dan variabel.

Durable Resource Manager - manajer sumber daya yang mendukung transaksi bahkan jika sistem informasi tidak tersedia (misalnya, ketika komputer dinyalakan kembali). Volatile Resource Manager - manajer sumber daya yang tidak mendukung transaksi jika sistem informasi tidak tersedia. Manajer sumber daya yang tidak konsisten hanya mendukung transaksi dalam memori.

Manajer sumber daya jangka panjang klasik adalah DBMS (atau driver DBMS untuk platform perangkat lunak). Tidak peduli apa yang terjadi - setidaknya kerusakan pada sistem operasi, setidaknya pemadaman listrik - DBMS akan menjamin integritas data setelah kembali ke kondisi kerja. Untuk ini, tentu saja, Anda harus membayar beberapa ketidaknyamanan, tetapi dalam artikel ini kami tidak akan mempertimbangkannya. Contoh dari manajer sumber daya non-persisten adalah memori transaksional perangkat lunak yang disebutkan di atas.

Menggunakan TransactionScope


Saat membuat objek bertipe TransactionScope Anda dapat menentukan beberapa parameter.

Pertama, ada pengaturan yang memberi tahu runtime apa yang dibutuhkan:

  1. Gunakan transaksi yang sudah ada saat ini;
  2. Pastikan untuk membuat yang baru;
  3. sebaliknya, jalankan kode di dalam blok using luar transaksi.

System.Transactions.TransactionScopeOption bertanggung jawab untuk semua ini.

Kedua, Anda dapat mengatur tingkat isolasi transaksi. Ini adalah parameter yang memungkinkan Anda menemukan kompromi antara independensi perubahan dan kecepatan. Level paling independen - serializable - memastikan bahwa tidak ada situasi di mana perubahan yang dilakukan dalam satu transaksi yang belum dilakukan dapat dilihat dalam transaksi lain. Setiap level berikutnya menambahkan satu situasi spesifik seperti itu, ketika secara bersamaan menjalankan transaksi dapat saling memengaruhi.Secara default, transaksi dibuka pada tingkat serializable, yang bisa jadi tidak menyenangkan (lihat, misalnya, komentar ini ).

Menetapkan tingkat isolasi transaksi selama pembuatan TransactionScopeadalah nasihat untuk manajer sumber daya. Mereka bahkan mungkin tidak mendukung semua level yang terdaftar System.Transactions.IsolationLevel. Selain itu, harus diingat bahwa ketika menggunakan pool koneksi untuk bekerja dengan database, koneksi yang tingkat isolasi transaksi telah diubah akan mempertahankan level ini setelah kembali ke pool . Sekarang, ketika programmer menerima koneksi ini dari pool dan bergantung pada nilai default, ia akan mengamati perilaku yang tidak terduga.

Skenario kerja tipikal cTransactionScopedan perangkap yang signifikan (yaitu, transaksi bersarang) tercakup dengan baik dalam artikel ini tentang "Habr" .

Penerapan Transaksi Perangkat Lunak


Harus dikatakan bahwa di hampir semua sistem informasi dalam operasi komersial, proses diluncurkan yang dapat menyebabkan sistem ke keadaan yang tidak dapat diterima. Oleh karena itu, mungkin perlu untuk mengontrol proses ini, mencari tahu apakah keadaan sistem saat ini dapat diterima, dan, jika tidak, kembalikan. Transaksi perangkat lunak - alat siap pakai untuk menjaga sistem dalam keadaan yang dapat diterima.

Dalam setiap kasus, konstruktif untuk mempertimbangkan biaya:

  1. mengintegrasikan proses ke dalam infrastruktur transaksi perangkat lunak (proses-proses ini juga perlu memperhatikan TransactionScopebanyak hal lain);
  2. memelihara infrastruktur ini (misalnya, biaya menyewa peralatan dengan Windows on board);
  3. pelatihan karyawan (karena topik transaksi .NET tidak umum).

Kita tidak boleh lupa bahwa proses transaksi mungkin diminta untuk melaporkan kemajuannya ke "dunia luar", misalnya, untuk membuat jurnal tindakan di luar transaksi.

Jelas, penolakan transaksi perangkat lunak akan membutuhkan penciptaan atau implementasi beberapa cara lain untuk menjaga integritas data, yang juga akan memiliki nilainya. Pada akhirnya, mungkin ada kasus-kasus di mana pelanggaran integritas data sangat jarang terjadi sehingga lebih mudah untuk memulihkan keadaan sistem yang dapat diterima dengan intervensi bedah daripada mempertahankan mekanisme pemulihan otomatis.

Contoh manajer sumber daya yang berubah-ubah


Sekarang mari kita lihat contoh manajer sumber daya sederhana yang tidak mendukung pemulihan dari kegagalan sistem. Kami akan memiliki blok memori transaksional perangkat lunak yang menyimpan beberapa nilai yang dapat dibaca dan ditulis. Dengan tidak adanya transaksi, blok ini berperilaku seperti variabel normal, dan di hadapan transaksi, ia menyimpan nilai awal, yang dapat dikembalikan setelah transaksi tersebut dibatalkan. Kode untuk manajer sumber daya disajikan di bawah ini:

 internal sealed class Stm<T> : System.Transactions.IEnlistmentNotification { private T _current; private T _original; private bool _enlisted; public T Value { get { return _current; } set { if (!Enlist()) { _original = value; } _current = value; } } public Stm(T value) { _current = value; _original = value; } private bool Enlist() { if (_enlisted) return true; var currentTx = System.Transactions.Transaction.Current; if (currentTx == null) return false; currentTx.EnlistVolatile(this, System.Transactions.EnlistmentOptions.None); _enlisted = true; return true; } #region IEnlistmentNotification public void Commit(System.Transactions.Enlistment enlistment) { _original = _current; _enlisted = false; } public void InDoubt(System.Transactions.Enlistment enlistment) { _enlisted = false; } public void Prepare(System.Transactions.PreparingEnlistment preparingEnlistment) { preparingEnlistment.Prepared(); } public void Rollback(System.Transactions.Enlistment enlistment) { _current = _original; _enlisted = false; } #endregion IEnlistmentNotification } 

Dapat dilihat bahwa satu-satunya persyaratan formal adalah implementasi antarmuka System.Transactions.IEnlistmentNotification. Yang menarik, metode Enlist(yang bukan merupakan bagian System.Transactions.IEnlistmentNotification) dan Prepare. Metode Enlisthanya memeriksa apakah kode yang diberikan bekerja dalam kerangka transaksi, dan, jika demikian, mendaftarkan instance kelasnya sebagai manajer sumber daya yang tidak konstan. Metode Prepareini dipanggil oleh manajer transaksi sebelum melakukan perubahan. Manajer sumber daya kami menandakan kesiapannya untuk berkomitmen dengan memanggil metode System.Transactions.PreparingEnlistment.Prepared.

Berikut ini adalah kode yang menunjukkan contoh menggunakan manajer sumber daya kami:

 var stm = new Stm<int>(1); using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required)) { stm.Value = 2; scope.Complete(); } 

Jika Anda usingmembaca properti segera setelah keluar dari blok stm.Value, maka nilai yang diharapkan akan diharapkan di sana 2. Dan jika Anda menghapus panggilan scope.Complete, transaksi akan dibatalkan dan properti stm.Valueakan memiliki nilai yang 1ditetapkan sebelum dimulainya transaksi.

Urutan panggilan yang disederhanakan ketika bekerja dengan transaksi System.Transactionsditunjukkan pada diagram di bawah ini.


Dapat dilihat bahwa dalam contoh ini, tidak semua kemungkinan yang disediakan oleh infrastruktur dipertimbangkan System.Transactions. Kami akan mempertimbangkannya lebih lengkap setelah kami mengenal protokol transaksional dan mendistribusikan transaksi di bagian selanjutnya.

TL; bagian DR


Seorang programmer dapat menggunakan kelas TransactionScopeuntuk mengeksekusi beberapa kode dalam transaksi yang ada atau baru. Suatu transaksi dilakukan jika dan hanya jika TransactionScopemetode dipanggil pada instance kelas yang ada Dispose, meskipun metode itu dipanggil sebelumnyaComplete. Seorang programmer dapat menunjukkan apakah dia ingin memulai transaksi baru, mengambil keuntungan dari yang sudah ada, atau, sebaliknya, mengeksekusi kode di luar transaksi yang sudah ada. Hanya manajer sumber daya yang terlibat dalam transaksi - komponen perangkat lunak yang menerapkan fungsi tertentu. Manajer sumber daya bisa bersifat jangka panjang (pulih dari kegagalan sistem) dan intermiten (tidak pulih). DBMS adalah contoh manajer sumber daya yang berumur panjang. Manajer sumber daya dikoordinasikan oleh manajer transaksi - komponen perangkat lunak yang secara otomatis dipilih oleh runtime tanpa partisipasi programmer.

Manajer sumber daya tidak konsisten adalah kelas yang mengimplementasikan antarmuka System.Transactions.IEnlistmentNotificationdalam metode iniPreparemengkonfirmasikan kesiapannya untuk melakukan perubahan atau, sebaliknya, menandakan kemunduran perubahan. Ketika penelepon melakukan sesuatu dengan manajer sumber daya, dia memeriksa untuk melihat apakah transaksi terbuka sekarang, dan jika terbuka, masuk menggunakan metode System.Transactions.Transaction.EnlistVolatile.

Transaksi Terdistribusi


Apa ini


Transaksi terdistribusi melibatkan beberapa subsistem informasi (pada kenyataannya, tidak semuanya begitu sederhana, lebih lanjut tentang ini di bawah). Dapat dipahami bahwa perubahan dalam semua sistem yang terlibat dalam transaksi terdistribusi harus dilakukan atau dibatalkan.

Berbagai cara untuk mengimplementasikan transaksi disajikan di atas: DBMS, infrastruktur System.Transactions, dan memori transaksional terprogram yang dibangun ke dalam platform. Transaksi terdistribusi juga dapat disediakan dengan alat-alat ini. Misalnya, dalam Oracle Database, mengubah (dan benar-benar membaca) data dalam beberapa database dalam satu transaksi secara otomatis mengubahnya menjadi yang terdistribusi. Selanjutnya, kita akan berbicara tentang transaksi yang didistribusikan perangkat lunak, yang mungkin termasuk manajer sumber daya yang heterogen.

Protokol transaksional


Protokol transaksional adalah seperangkat prinsip dimana aplikasi yang terlibat dalam transaksi berinteraksi. Di dunia .NET, protokol berikut ini paling sering ditemukan.

Ringan Tidak ada lebih dari satu manajer sumber daya tahan lama yang digunakan. Semua interaksi transaksional terjadi dalam domain aplikasi yang sama, atau manajer sumber daya mendukung promosi dan komitmen satu fase (implementasi IPromotableSinglePhaseNotification).

OleTx. Interoperabilitas antara beberapa domain aplikasi dan beberapa komputer diperbolehkan. Anda dapat menggunakan banyak manajer sumber daya yang tahan lama. Semua komputer yang berpartisipasi harus menjalankan Windows. Gunakan Panggilan Prosedur Jarak Jauh (RPC).

WS-AT.Interoperabilitas antara beberapa domain aplikasi dan beberapa komputer diperbolehkan. Anda dapat menggunakan banyak manajer sumber daya yang tahan lama. Komputer yang berpartisipasi mungkin menjalankan berbagai OS, bukan hanya Windows. Hypertext Transmission Protocol (HTTP) digunakan.

Telah dicatat di atas bahwa protokol transaksi saat ini mempengaruhi pilihan manajer transaksi, dan karakteristik sumber daya kontrol yang terlibat dalam transaksi mempengaruhi pilihan protokol. Sekarang kami daftar manajer transaksi yang terkenal.

Manajer Transaksi Ringan (LTM) . Diperkenalkan di .NET Framework 2.0 dan yang lebih baru. Mengelola transaksi menggunakan protokol Ringan.

Manajer Transaksi Kernel (KTM). Diperkenalkan pada Windows Vista dan Windows Server 2008. Mengelola transaksi menggunakan protokol Ringan. Itu dapat memanggil Sistem File Transaksional (TxF) dan Transaksional Registry (TxR) pada Windows Vista dan Windows 2008.

Koordinator Transaksi Terdistribusi (MSDTC) . Mengelola transaksi menggunakan protokol OleTx dan WS-AT.

Juga harus diingat bahwa beberapa manajer sumber daya tidak mendukung semua protokol yang terdaftar. Misalnya, MSMQ dan SQL Server 2000 tidak mendukung Ringan, sehingga transaksi yang melibatkan MSMQ atau SQL Server 2000 akan dikelola oleh MSDTC, bahkan jika mereka adalah satu-satunya peserta. Secara teknis, batasan ini muncul dari kenyataan bahwa manajer sumber daya yang ditentukan, menerapkan, tentu saja, antarmukaSystem.Transactions.IEnlistmentNotificationJangan mengimplementasikan antarmuka System.Transactions.IPromotableSinglePhaseNotification. Ini berisi, antara lain, metode Promoteyang dipanggil runtime, jika perlu, untuk beralih ke manajer transaksi yang lebih curam.

Ambiguitas konsep transaksi terdistribusi sekarang menjadi jelas. Misalnya, Anda dapat mendefinisikan transaksi terdistribusi sebagai transaksi di mana ia berpartisipasi:

  1. setidaknya dua dari manajer sumber daya;
  2. manajer sumber daya variabel sewenang-wenang dan setidaknya dua berumur panjang;
  3. setidaknya dua dari setiap manajer sumber daya selalu berada di komputer yang berbeda.

Karena itu, lebih baik untuk selalu mengklarifikasi transaksi tertentu yang terlibat.

Dan dalam konteks ini, MSDTC terutama dibahas. Ini adalah komponen perangkat lunak Windows yang mengelola transaksi terdistribusi. Ada antarmuka grafis untuk mengkonfigurasi dan memantau transaksi, yang dapat ditemukan dalam utilitas "Layanan Komponen", mengikuti jalur "Komputer - Komputer Saya - Koordinator Transaksi Terdistribusi - DTC Lokal".


Untuk konfigurasi, pilih item "Properti" di menu konteks simpul "DTC Lokal", dan untuk memantau transaksi yang didistribusikan, pilih item "Statistik transaksi" di panel pusat.

Fiksasi bifasik


Jika beberapa manajer sumber daya berpartisipasi dalam transaksi, hasil pekerjaan mereka mungkin berbeda: misalnya, salah satu dari mereka selesai dengan sukses, dan dia siap untuk melakukan perubahan, dan yang lainnya memiliki kesalahan, dan dia akan memutar balik perubahan. Namun, esensi dari transaksi terdistribusi terletak pada kenyataan bahwa perubahan dalam semua sumber daya kontrol yang terlibat dalam transaksi itu dilakukan bersama-sama atau dibatalkan. Oleh karena itu, dalam kasus seperti itu, protokol fiksasi dua fase biasanya digunakan.

Secara umum, inti dari protokol ini adalah sebagai berikut. Selama fase pertamaManajer sumber daya yang terlibat dalam transaksi menyiapkan informasi yang cukup untuk pulih dari kegagalan (jika merupakan manajer sumber daya jangka panjang) dan untuk penyelesaian yang berhasil sebagai hasil dari komitmen. Dari sudut pandang teknis, manajer sumber daya menandakan bahwa ia telah menyelesaikan fase pertama dengan memanggil metode System.Transactions.PreparingEnlistment.Prepareddalam metode tersebut Prepare. Atau manajer sumber daya dapat memberi tahu Anda bahwa perubahan telah dibatalkan dengan memanggil metode ForceRollback.

Ketika semua manajer sumber daya yang terlibat dalam transaksi "memilih", yaitu, mereka memberi tahu manajer transaksi apakah mereka ingin melakukan atau mengembalikan perubahan, tahap kedua dimulai. Pada saat ini, manajer sumber daya diinstruksikan untuk melakukan perubahan mereka (jika semua peserta memilih untuk memperbaiki) atau untuk menolak perubahan (jika setidaknya satu peserta memilih untuk mengembalikan). Secara teknis, ini dinyatakan dalam doa metode Commitdan Rollbackyang diterapkan oleh manajer sumber daya dan metode yang mereka gunakan System.Transactions.Enlistment.Done.

Manajer sumber daya juga dapat memanggil metode System.Transactions.Enlistment.Doneselama fase pertama. Dalam hal ini, dipahami bahwa ia tidak akan melakukan perubahan apa pun (misalnya, hanya berfungsi untuk membaca) dan tidak akan berpartisipasi dalam fase kedua. Baca lebih lanjut tentang komitmen dua fase di Microsoft .

Jika koneksi antara manajer transaksi dan setidaknya salah satu manajer sumber daya terputus, transaksi menjadi beku ("ragu", tidak diragukan). Manajer transaksi, dengan memanggil metode InDoubt, memberi tahu manajer sumber daya yang tersedia tentang peristiwa ini yang dapat merespons dengan tepat.

Masih ada fiksasi tiga fase dan modifikasi dengan kelebihan dan kekurangannya. Protokol komit tiga fase kurang umum, mungkin karena memerlukan lebih banyak biaya komunikasi antara subsistem yang berinteraksi.

Cheat sheet pada antarmuka System.Transactions


Sesuatu itu sulit. Untuk menyortir sedikit, saya akan menjelaskan secara singkat antarmuka namespace utama yang System.Transactionsdiperlukan untuk membuat manajer sumber daya. Berikut adalah diagram kelas.



IEnlistmentNotification. Manajer sumber daya mengimplementasikan antarmuka ini. Manajer transaksi memanggil metode yang diterapkan dalam urutan berikut. Selama fase pertama, ia memanggil metode Prepare(kecuali bintang-bintang berkumpul untuk memanggil metode ISinglePhaseNotification.SinglePhaseCommit, seperti yang dijelaskan dalam paragraf berikutnya). Di bawah metode ini, manajer sumber daya menyimpan informasi yang diperlukan untuk pulih dari kegagalan, mempersiapkan komitmen akhir dari perubahan di pihaknya, dan memberikan suara untuk melakukan atau mengembalikan perubahan. Jika ada datang tahap kedua, tergantung pada ketersediaan sumber daya dan kontrol dari hasil voting dari transaksi kontrol adalah salah satu dari tiga metode: Commit, InDoubt, Rollback.

ISinglePhaseNotification.Manajer sumber daya mengimplementasikan antarmuka ini jika ia ingin memberikan manajer transaksi kesempatan untuk mengoptimalkan eksekusi dengan mengurangi fase komit kedua. Jika manajer transaksi hanya melihat satu manajer sumber daya, maka pada tahap komit pertama ia mencoba memanggil metode manajer sumber daya SinglePhaseCommit(sebagai gantinya IEnlistmentNotification.Prepare) dan dengan demikian mengecualikan pemungutan suara dan transisi ke fase kedua. Pendekatan ini memiliki kelebihan dan kekurangan, yang paling jelas ditulis oleh Microsoft di sini .

ITransactionPromoter. Manajer sumber daya mengimplementasikan antarmuka ini (tidak hanya secara langsung, tetapi melalui antarmukaIPromotableSinglePhaseNotification), jika dia ingin memberikan manajer transaksi dengan kemampuan untuk mematuhi protokol Ringan bahkan ketika panggilan jarak jauh, sampai kondisi lain muncul yang memerlukan komplikasi protokol. Ketika Anda perlu menyulitkan protokol, metode akan dipanggil Promote.

IPromotableSinglePhaseNotification. Manajer sumber daya mengimplementasikan antarmuka ini dalam urutan, pertama, untuk mengimplementasikan antarmuka ITransactionPromoter, dan kedua, sehingga manajer transaksi dapat menggunakan komit fase tunggal, metode panggilan IPromotableSinglePhaseNotification.SinglePhaseCommitdan IPromotableSinglePhaseNotification.Rollback. Manajer transaksi memanggil metode IPromotableSinglePhaseNotification.Initializeuntuk menandai keberhasilan pendaftaran manajer sumber daya dengan cara yang disederhanakan. Lebih atau kurang, ini dapat dipahami dari dokumen Microsoft .

Mari kita lihat sedikit lagiSystem.Transactions.Enlistmentdan ahli warisnya. Jenis instance ini disediakan oleh manajer transaksi ketika ia memanggil metode antarmuka yang diterapkan oleh manajer sumber daya.



Pendaftaran. Manajer sumber daya dapat memanggil metode tunggal dari jenis ini - Done, - untuk menandai keberhasilan penyelesaian bagian pekerjaannya.

Mempersiapkan Pendaftaran. Menggunakan instance dari jenis ini selama fase komit pertama, manajer sumber daya dapat menandakan niatnya untuk melakukan atau memutar balik perubahan. Manajer sumber daya yang berumur panjang juga bisa mendapatkan informasi yang diperlukan untuk pulih dari kegagalan sistem.

SinglePhaseEnlistment. Menggunakan instance dari jenis ini, manajer sumber daya dapat mengirimkan informasi kepada manajer transaksi tentang hasil pekerjaannya menggunakan skema yang disederhanakan (komitmen fase tunggal).

Batasan dan Alternatif Transaksi Terdistribusi oleh Perangkat Lunak


Sebuah studi singkat tentang pendapat yang ditemukan di Internet menunjukkan bahwa di banyak daerah, transaksi yang didistribusikan tidak lagi populer. Lihatlah komentar jahat ini , misalnya . Objek utama kritik, yang disebutkan secara singkat di sini , adalah sifat sinkron (memblokir) transaksi yang didistribusikan. Jika pengguna mengirim permintaan selama pemrosesan transaksi terdistribusi diatur, maka ia akan menerima respons hanya setelah (berhasil atau dengan kesalahan) semua subsistem yang termasuk dalam transaksi selesai berfungsi. Pada saat yang sama, ada pendapat yang didukung oleh penelitian bahwa protokol komitmen dua fase menunjukkan kinerja yang buruk, terutama dengan peningkatan jumlah subsistem yang terlibat dalam transaksi, seperti disebutkan, misalnya, dalampublikasi ini di "Habré" .

Jika pencipta sistem lebih suka mengembalikan jawaban kepada pengguna sesegera mungkin, menunda koordinasi data untuk nanti, maka beberapa solusi lain akan lebih cocok untuknya. Dalam konteks teorema Brewer (teorema CAP ), kita dapat mengatakan bahwa transaksi terdistribusi cocok untuk kasus-kasus di mana konsistensi data lebih penting daripada ketersediaan.

Ada batasan praktis lain dalam penggunaan transaksi yang didistribusikan perangkat lunak. Misalnya, secara eksperimental ditetapkan bahwa transaksi terdistribusi menggunakan protokol OleTx tidak boleh melintasi domain jaringan. Bagaimanapun, upaya panjang untuk membuat mereka bekerja tidak berhasil. Selain itu, terungkap bahwa interaksi antara beberapa contoh Oracle Database (transaksi database terdistribusi) memberlakukan pembatasan serius pada penerapan transaksi perangkat lunak yang didistribusikan (sekali lagi, gagal untuk memulai).

Apa alternatif untuk transaksi terdistribusi? Pertama, saya harus mengatakan bahwa itu akan sangat sulit dilakukan tanpa transaksi teknis (normal, tidak didistribusikan). Mungkin ada beberapa proses dalam sistem yang dapat mengganggu integritas data untuk sementara waktu, dan bagaimanapun juga perlu untuk memberikan pengawasan terhadap proses tersebut. Dengan cara yang sama, dalam hal area subjek, sebuah konsep dapat muncul yang mencakup proses yang diimplementasikan oleh serangkaian proses dalam sistem teknis yang berbeda, yang harus dimulai dan berakhir di bidang data integral.

Beralih ke alternatif untuk transaksi terdistribusi, kami dapat mencatat solusi berdasarkan layanan pesan, seperti RabbitMQ dan Apache Kafka. Dalam publikasi ini tentang "Habré" empat solusi tersebut dipertimbangkan:

  1. , , ;
  2. , (Transaction Log Tailing);
  3. , ;
  4. (Event Sourcing).

Alternatif lain adalah template Saga. Ini melibatkan kaskade subsistem dengan transaksi lokalnya. Setelah menyelesaikan pekerjaan, setiap sistem memanggil yang berikut (baik secara mandiri atau dengan bantuan koordinator). Untuk setiap transaksi ada transaksi pembatalan terkait, dan alih-alih mentransfer kontrol, subsistem dapat memulai pembatalan perubahan yang dibuat sebelumnya oleh subsistem sebelumnya. Di "Habré" ada beberapa artikel bagus tentang templat "Saga". Misalnya, publikasi ini menyediakan informasi umum tentang mempertahankan prinsip-prinsip ACID dalam layanan-layanan microser, dan artikel ini merinci contoh penerapan templat Saga dengan koordinator.

Di perusahaan kami, beberapa produk berhasil menggunakan transaksi yang didistribusikan perangkat lunak melalui WCF, tetapi ada opsi lain. Suatu ketika, ketika kami mencoba berteman dengan sistem baru dengan transaksi terdistribusi, kami memiliki banyak masalah, termasuk tabrakan dengan batasan yang dijelaskan di atas dan masalah paralel dengan memperbarui infrastruktur perangkat lunak. Oleh karena itu, dalam kondisi kekurangan sumber daya untuk menjalankan keputusan modal lainnya, kami menerapkan taktik berikut. Pihak yang dipanggil menangkap perubahan dalam kasus apa pun, tetapi mencatat bahwa mereka dalam keadaan konsep, sehingga perubahan ini belum mempengaruhi operasi sistem yang disebut. Kemudian, penelepon, ketika menyelesaikan pekerjaannya melalui transaksi terdistribusi, DBMS mengaktifkan perubahan yang dibuat oleh sistem yang dipanggil. Dengan cara inialih-alih transaksi yang didistribusikan perangkat lunak, kami menggunakan transaksi DBMS terdistribusi, yang dalam hal ini ternyata jauh lebih andal.

Jadi, apakah itu dalam. NET Core?


Dalam .NET Core (dan bahkan dalam .NET Standard) ada semua jenis yang diperlukan untuk mengatur transaksi dan membuat manajer sumber daya Anda sendiri. Sayangnya, dalam .NET Core, transaksi berbasis System.Transactionsmemiliki batasan serius: mereka hanya bekerja dengan protokol yang Ringan. Misalnya, jika dua manajer sumber daya tahan lama digunakan dalam kode, maka saat runtime, lingkungan akan mengeluarkan pengecualian segera setelah manajer kedua dipanggil.

Faktanya adalah bahwa mereka mencoba untuk membuat .NET Core independen dari sistem operasi, sehingga tautan ke manajer transaksi seperti KTM dan MSDTC dikecualikan, yaitu mereka diperlukan untuk mendukung transaksi dengan properti yang ditentukan. Ada kemungkinan bahwa koneksi manajer transaksi akan diimplementasikan dalam bentuk plug-in, tetapi sejauh ini telah ditulis dengan garpu rumput, sehingga Anda tidak dapat bergantung pada penggunaan industri dari transaksi yang didistribusikan di .NET Core.

Dari pengalaman, Anda dapat memverifikasi perbedaan dalam transaksi terdistribusi dalam .NET Framework dan .NET Core dengan menulis kode yang sama, menyusun dan menjalankannya pada platform yang berbeda.

Contoh kode yang memanggil SQL Server dan Oracle Database secara berurutan.

 private static void Main(string[] args) { using (var scope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required)) { MsSqlServer(); Oracle(); scope.Complete(); } } private static void Oracle() { using (var conn = new Oracle.ManagedDataAccess.Client.OracleConnection("User Id=some_user;Password=some_password;Data Source=some_db")) { conn.Open(); using (var cmd = conn.CreateCommand()) { cmd.CommandText = "update t_hello set id_hello = 2 where id_hello = 1"; cmd.ExecuteNonQuery(); } conn.Close(); } } private static void MsSqlServer() { var builder = new System.Data.SqlClient.SqlConnectionStringBuilder { DataSource = "some_computer\\some_db", UserID = "some_user", Password = "some_password", InitialCatalog = "some_scheme", Enlist = true, }; using (var conn = new System.Data.SqlClient.SqlConnection(builder.ConnectionString)) { conn.Open(); using (var cmd = conn.CreateCommand()) { cmd.CommandText = "update t_hello set id_hello = 2 where id_hello = 1"; cmd.ExecuteNonQuery(); } conn.Close(); } } 

Proyek siap bangun ada di GitHub .

Menjalankan contoh untuk .NET Core gagal. Tempat dan jenis pengecualian yang dilemparkan bergantung pada urutan panggilan DBMS, tetapi dalam hal apa pun, pengecualian ini menunjukkan operasi transaksi yang tidak valid. Menjalankan contoh untuk .NET Framework berhasil jika MSDTC berjalan saat ini; namun, dalam antarmuka grafis MSDTC, Anda dapat mengamati registrasi transaksi terdistribusi.

Transaksi Terdistribusi dan WCF


Windows Communication Foundation (WCF) adalah .NET framework untuk mengatur dan menjalankan layanan jaringan. Dibandingkan dengan pendekatan REST dan ASP.NET Web API yang lebih modis, ia memiliki kelebihan dan kekurangannya sendiri. WCF adalah teman yang sangat baik dengan transaksi .NET, dan dalam dunia .NET Framework, nyaman untuk menggunakannya untuk mengatur transaksi yang didistribusikan antara klien dan layanan.

Di .NET Core, teknologi ini hanya berfungsi di sisi klien, yaitu, Anda tidak dapat membuat layanan, tetapi Anda hanya bisa merujuk ke yang sudah ada. Namun, ini tidak terlalu penting, karena, sebagaimana disebutkan di atas, dengan transaksi terdistribusi di .NET Core, semuanya tidak berjalan dengan baik.

Cara kerja WCF

Bagi pembaca yang tidak terbiasa dengan WCF, berikut adalah informasi latar belakang terpendek tentang apa teknologi ini dalam praktiknya. Konteks - dua sistem informasi yang disebut klien dan layanan. Klien saat runtime mengakses sistem informasi lain yang mendukung layanan yang menarik bagi klien, dan mengharuskan beberapa operasi dilakukan. Kemudian manajemen dikembalikan ke klien.

Untuk membuat layanan di WCF, Anda biasanya perlu menulis antarmuka yang menjelaskan kontrak untuk layanan yang dibuat dan kelas yang mengimplementasikan antarmuka ini. Kelas dan antarmuka ditandai dengan atribut WCF khusus yang membedakan mereka dari jenis lainnya dan menentukan beberapa detail perilaku selama penemuan dan doa layanan. Tipe-tipe ini dibungkus dengan sesuatu yang berfungsi sebagai server (misalnya, dalam DLL yang diatur IIS), dan dilengkapi dengan file konfigurasi (ada opsi), di mana rincian implementasi layanan ditunjukkan. Setelah memulai, layanan dapat diakses, misalnya, di alamat jaringan; di browser Internet Anda dapat melihat kontrak yang diterapkan oleh layanan yang diminta.

Seorang programmer yang ingin mengakses layanan WCF yang ada menggunakan utilitas konsol atau antarmuka grafis yang dibangun ke dalam lingkungan pengembangan untuk membentuk tipe dalam C # (atau dalam bahasa lain yang didukung) yang sesuai dengan kontrak layanan di alamat layanan. File dengan jenis yang diperoleh termasuk dalam proyek aplikasi klien, dan setelah itu programmer menggunakan istilah yang sama yang terkandung dalam antarmuka layanan, menikmati manfaat dari kemajuan (pengetikan statis). Selain itu, file konfigurasi klien menentukan karakteristik teknis dari layanan yang dipanggil (itu juga dapat dikonfigurasi dalam kode, tanpa file konfigurasi).

WCF mendukung berbagai jenis transportasi, enkripsi dan parameter teknis lainnya yang lebih halus. Kebanyakan dari mereka disatukan oleh konsep "mengikat" (Binding). Ada tiga parameter penting untuk layanan WCF:

  1. alamat di mana itu tersedia;
  2. mengikat
  3. kontrak (antarmuka).

Semua parameter ini diatur dalam file konfigurasi layanan dan klien.

Di perusahaan kami, WCF (dengan dan tanpa transaksi terdistribusi) banyak digunakan dalam produk yang diimplementasikan, namun, mengingat tren mode, penggunaannya dalam produk baru masih dipertanyakan.

Bagaimana cara memulai transaksi terdistribusi di WCF

Untuk memulai transaksi berbasis di WCF System.Transactions, programmer perlu menetapkan beberapa atribut dalam kode, pastikan bahwa binding menggunakan dukungan transaksi terdistribusi, transactionFlow="true"bahwa itu ditulis pada klien dan dalam layanan, dan bahwa manajer transaksi yang sesuai berjalan di semua komputer yang terlibat (kemungkinan besar , itu akan menjadi MSDTC).

Binding transaksi terdistribusi: NetTcpBinding, NetNamedPipeBinding, WSHttpBinding, WSDualHttpBinding, dan WSFederationHttpBinding.

Metode (operasi) dari antarmuka layanan harus ditandai dengan atribut System.ServiceModel.TransactionFlowAttribute. Kemudian, dengan parameter atribut tertentu dan ketika mengatur parameter TransactionScopeRequiredatribut , System.ServiceModel.OperationBehaviorAttributetransaksi akan didistribusikan antara klien dan layanan. Selain itu, secara default, layanan dianggap memilih untuk melakukan transaksi, kecuali ada pengecualian yang dilemparkan pada saat run time. Untuk mengubah perilaku ini, Anda harus menetapkan nilai parameter TransactionAutoCompleteatribut yang sesuai System.ServiceModel.OperationBehaviorAttribute.

Kode untuk layanan WCF sederhana yang mendukung transaksi terdistribusi.
 [System.ServiceModel.ServiceContract] public interface IMyService { [System.ServiceModel.OperationContract] [System.ServiceModel.TransactionFlow(System.ServiceModel.TransactionFlowOption.Mandatory)] int DoSomething(string input); } public class MyService : IMyService { [System.ServiceModel.OperationBehavior(TransactionScopeRequired = true)] [System.ServiceModel.TransactionFlow(System.ServiceModel.TransactionFlowOption.Mandatory)] public int DoSomething(string input) { if (input == null) throw new System.ArgumentNullException(nameof(input)); return input.Length; } } 

Jelas, ini berbeda dari kode layanan biasa hanya dalam penggunaan atribut System.ServiceModel.TransactionFlowdan pengaturan khusus atribut System.ServiceModel.OperationBehavior.

Konfigurasi sampel untuk layanan ini.
 <system.serviceModel> <services> <service name="WcfWithTransactionsExample.MyService" behaviorConfiguration="serviceBehavior"> <endpoint address="" binding="wsHttpBinding" bindingConfiguration="mainWsBinding" contract="WcfWithTransactionsExample.IMyService"/> <endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding"/> </service> </services> <bindings> <wsHttpBinding> <binding name="mainWsBinding" maxReceivedMessageSize="209715200" maxBufferPoolSize="209715200" transactionFlow="true" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"> <security mode="None"/> <readerQuotas maxArrayLength="209715200" maxStringContentLength="209715200"/> </binding> </wsHttpBinding> </bindings> </system.serviceModel> 

Perhatikan bahwa pengikatan adalah tipe WSHttpBinding dan atribut digunakan transactionFlow="true".

TL; bagian DR


Transaksi terdistribusi mencakup beberapa manajer sumber daya, dan semua perubahan harus dilakukan atau dibatalkan. Beberapa DBMS modern menerapkan transaksi terdistribusi yang menyediakan mekanisme yang nyaman untuk menghubungkan beberapa database. Transaksi yang didistribusikan perangkat lunak (tidak diterapkan dalam DBMS) dapat mencakup kombinasi yang berbeda dari manajer sumber daya pada komputer yang berbeda yang menjalankan sistem operasi yang berbeda, tetapi mereka memiliki batasan yang harus diperhitungkan sebelum mengandalkannya. Alternatif modern untuk transaksi terdistribusi adalah solusi pengiriman pesan. Di .NET Core, transaksi yang didistribusikan belum didukung.

WCF adalah salah satu alat standar dan terbukti untuk membuat dan mengakses layanan di dunia .NET, mendukung beberapa jenis transportasi dan enkripsi. WCF adalah teman yang sangat dekat dengan transaksi terdistribusi berdasarkan System.Transactions. Menyiapkan transaksi terdistribusi untuk WCF terdiri dari menandai kode dengan beberapa atribut dan menambahkan beberapa kata dalam layanan dan file konfigurasi klien. Tidak semua binding WCF mendukung transaksi yang didistribusikan. Selain itu, jelas bahwa transaksi di WCF memiliki batasan yang sama seperti tanpa menggunakan WCF. Platform .NET Core sejauh ini hanya memungkinkan Anda untuk mengakses layanan di WCF, daripada membuatnya.

Kesimpulan Boks


Posting ini adalah ikhtisar dasar-dasar transaksi perangkat lunak .NET. Beberapa kesimpulan mengenai tren dalam transaksi perangkat lunak dapat ditemukan di bagian tentang penerapan dan keterbatasan subjek yang dibahas, dan sebagai kesimpulan, tesis utama publikasi dikumpulkan. Saya kira mereka dapat digunakan sebagai lembar contekan ketika mempertimbangkan transaksi perangkat lunak sebagai salah satu opsi untuk menerapkan sistem teknis atau untuk menyegarkan informasi yang relevan dalam memori.

Transaksi (bidang studi, DBMS, perangkat lunak). Persyaratan bidang subjek kadang-kadang dirumuskan dalam bentuk transaksi - operasi yang, dimulai di bidang data integral, setelah selesai (termasuk tidak berhasil) juga harus datang ke bidang data integral (mungkin sudah berbeda). Persyaratan ini biasanya diterapkan sebagai sistem transaksi. Contoh klasik dari suatu transaksi adalah transfer uang antara dua akun, yang terdiri dari dua operasi yang tidak dapat dibagi - menarik uang dari satu akun dan mengkredit yang lain. Selain transaksi terkenal yang diterapkan oleh DBMS, ada juga transaksi perangkat lunak, misalnya, di dunia .NET. Manajer sumber daya adalah komponen perangkat lunak yang menyadari keberadaan transaksi tersebut dan memiliki kemampuan untuk dimasukkan di dalamnya, yaitu, melakukan atau mengembalikan perubahan yang dilakukan.Manajer sumber daya menerima instruksi tentang melakukan dan mengembalikan perubahan dari manajer transaksi, yang merupakan dasar dari infrastrukturSystem.Transactions.

Manajer sumber daya yang tahan lama dan terputus-putus. Manajer sumber daya jangka panjang mendukung pemulihan data setelah kegagalan sistem. Driver DBMS untuk .NET biasanya menawarkan fungsi seperti itu. Manajer sumber daya yang terputus-putus tidak mendukung pemulihan bencana. Memori transaksional terprogram - cara mengelola objek dalam RAM - dapat dilihat sebagai contoh manajer sumber daya yang berubah-ubah.

Transaksi dan .NET Resource Manager. Programmer .NET menggunakan transaksi perangkat lunak dan membuat manajer sumber dayanya sendiri menggunakan tipe dari namespaceSystem.Transactions. Infrastruktur ini memungkinkan penggunaan transaksi berbagai sarang dan isolasi (dengan keterbatasan yang diketahui). Menggunakan transaksi tidak rumit, dan itu terdiri dari membungkus kode di blok usingdengan karakteristik tertentu. Namun, manajer sumber daya yang dimasukkan dengan cara ini dalam transaksi harus mempertahankan fungsionalitas yang diperlukan untuk bagian mereka. Menggunakan manajer sumber daya yang heterogen dalam suatu transaksi atau menggunakan satu manajer dengan cara yang berbeda dapat secara otomatis mengubah transaksi menjadi transaksi yang terdistribusi.

Transaksi terdistribusi (DBMS, perangkat lunak).Transaksi terdistribusi mencakup beberapa subsistem, perubahan yang harus disinkronkan, yaitu, mereka dilakukan bersama-sama atau dibatalkan. Transaksi terdistribusi diimplementasikan dalam beberapa DBMS modern. Transaksi yang didistribusikan perangkat lunak (ini bukan yang diterapkan oleh DBMS) memberlakukan batasan tambahan pada proses dan platform yang berinteraksi. Transaksi yang didistribusikan secara bertahap keluar dari mode, memberi jalan ke solusi berdasarkan layanan pesan. Untuk mengubah transaksi biasa menjadi transaksi terdistribusi, programmer tidak perlu melakukan apa-apa: ketika seorang manajer sumber daya dengan karakteristik tertentu termasuk dalam transaksi pada saat run time, manajer transaksi akan secara otomatis melakukan apa pun yang diperlukan. Transaksi perangkat lunak reguler tersedia dalam .NET Core dan .NET Standard, dan transaksi yang didistribusikan tidak tersedia.

Transaksi terdistribusi melalui WCF. WCF adalah salah satu alat .NET standar untuk membuat dan menjalankan layanan, yang juga mendukung protokol standar. Dengan kata lain, layanan WCF yang dikonfigurasi dengan cara tertentu dapat diakses dari aplikasi apa pun, tidak hanya .NET atau Windows. Untuk membuat transaksi terdistribusi di atas WCF, Anda perlu menandai jenis yang membuat layanan dengan atribut tambahan dan membuat perubahan minimal pada layanan dan file konfigurasi klien. Anda tidak bisa membuat layanan WCF di .NET Core dan .NET Standard, tetapi Anda bisa membuat klien WCF.

Contoh untuk memeriksa Sistem. Transaksi di GitHub

Referensi

Konsep dasar


ACID ( «»)
( Microsoft)
( Microsoft)
( «»)
( «»)
( «»)


X/Open XA ( The Open Group)
Java Transaction API ( «»)
Cache ( InterSystems)

.NET


.NET ( Tech Blog Collection)
TransactionScope («»)
, ( Microsoft)
.NET Standard 2.0 ( .NET Standard GitHub)
( YarFullStack)


(«»)
(«»)
«» («»)
«» («»)
(«»)

Editorial

Source: https://habr.com/ru/post/id433136/


All Articles