Saya telah mengembangkan T-SQL selama beberapa tahun dan saya selalu menggali lebih dalam, terus mempelajari semua yang saya bisa tentang semua aspek bahasa. Saya baru-baru ini mulai bekerja di perusahaan baru dan telah menerima apa yang saya pikir merupakan saran aneh mengenai transaksi. Jangan pernah menggunakannya. Alih-alih, gunakan solusi yang mensimulasikan transaksi. Ini berasal dari DBA kami yang bekerja dalam satu basis data dengan banyak transaksi dan selanjutnya, banyak pemblokiran. Basis data tempat saya bekerja tidak mengalami masalah ini dan saya melihat transaksi telah digunakan di masa lalu.
Saya memahami bahwa pemblokiran diharapkan dengan transaksi karena sudah menjadi sifatnya untuk melakukan hal itu dan jika Anda dapat pergi tanpa menggunakannya, tentu saja lakukanlah. Tetapi saya memiliki banyak kesempatan di mana setiap pernyataan HARUS dilaksanakan dengan sukses. Jika salah satu gagal mereka semua harus gagal untuk melakukan.
Saya selalu menjaga ruang lingkup transaksi saya sesempit mungkin, selalu digunakan bersama dengan SET XACT_ABORT ON dan selalu dalam TRY / CATCH.
Contoh:
CREATE SCHEMA someschema;
GO
CREATE TABLE someschema.tableA
(id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
ColA VARCHAR(10) NOT NULL
);
GO
CREATE TABLE someschema.tableB
(id INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
ColB VARCHAR(10) NOT NULL
);
GO
CREATE PROCEDURE someschema.ProcedureName @ColA VARCHAR(10),
@ColB VARCHAR(10)
AS
SET NOCOUNT, XACT_ABORT ON;
BEGIN
BEGIN TRY
BEGIN TRANSACTION;
INSERT INTO someschema.tableA(ColA)
VALUES(@ColA);
INSERT INTO someschema.tableB(ColB)
VALUES(@ColB);
--Implement error
SELECT 1/0
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@trancount > 0
BEGIN
ROLLBACK TRANSACTION;
END;
THROW;
RETURN;
END CATCH;
END;
GO
Inilah yang mereka sarankan agar saya lakukan.
GO
CREATE PROCEDURE someschema.ProcedureNameNoTransaction @ColA VARCHAR(10),
@ColB VARCHAR(10)
AS
SET NOCOUNT ON;
BEGIN
BEGIN TRY
DECLARE @tableAid INT;
DECLARE @tableBid INT;
INSERT INTO someschema.tableA(ColA)
VALUES(@ColA);
SET @tableAid = SCOPE_IDENTITY();
INSERT INTO someschema.tableB(ColB)
VALUES(@ColB);
SET @tableBid = SCOPE_IDENTITY();
--Implement error
SELECT 1/0
END TRY
BEGIN CATCH
DELETE FROM someschema.tableA
WHERE id = @tableAid;
DELETE FROM someschema.tableB
WHERE id = @tableBid;
THROW;
RETURN;
END CATCH;
END;
GO
Pertanyaan saya kepada komunitas adalah sebagai berikut. Apakah ini masuk akal sebagai solusi untuk transaksi?
Pendapat saya dari apa yang saya ketahui tentang transaksi dan apa yang diusulkan solusinya adalah tidak, ini bukan solusi yang layak dan memperkenalkan banyak poin kegagalan.
Dalam solusi yang disarankan, saya melihat empat transaksi implisit terjadi. Dua sisipan dalam percobaan dan kemudian dua transaksi lagi untuk penghapusan tangkapan. Itu "membatalkan" sisipan tetapi tanpa memutar apa pun sehingga tidak ada yang benar-benar dibatalkan.
Ini adalah contoh yang sangat mendasar untuk menunjukkan konsep yang mereka sarankan. Beberapa prosedur tersimpan aktual yang telah saya lakukan ini membuatnya sangat panjang dan sulit untuk dikelola karena "memutar kembali" beberapa hasil set vs dua nilai parameter dalam contoh ini menjadi sangat rumit seperti yang dapat Anda bayangkan. Karena "memutar kembali" sedang dilakukan secara manual sekarang, kesempatan untuk melewatkan sesuatu karena nyata.
Masalah lain yang menurut saya ada adalah untuk timeout atau koneksi terputus. Apakah ini masih bisa dibatalkan? Ini adalah pemahaman saya tentang mengapa SET XACT_ABORT ON harus digunakan sehingga dalam kasus ini, transaksi akan dibatalkan.
Terima kasih atas tanggapan Anda sebelumnya!