Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Önermiyorum - 2
#1
Sanıyorum bu bir seri haline gelecek maalesef. Ama ben, uzun zaman Ferrari (Sql Server) kullandıktan sonra bu MySQL bana at arabası gibi gelmeye başladı. Muhtemelen biliyorsunuzdur ama ben yeni kullandığım için yeni öğrendim:

MySQL'de nested (iç içe) transactionj desteği YOK. ! Gerçekten de yok. İnanılır gibi değil açıkçası. Bir yanlışlık yapıyorumdur diye düşündüm, arkadaşımı çağırdım ve ona sordum; o da teyid etti. Sonra dökümantasyonda da gördüm. Uzun lafın kısası şu şekilde bir şey çalışmıyor.

CREATE PROCEDURE sp_Sil()
BEGIN
  START TRANSACTION;
  
  INSERT INTO tbl_dandik(Adi)
  SELECT 'Tuğrul';
  
  COMMIT;
END;

procedure SaveData;
var
  AProc : TMyStoredProc;
begin
  AProc := TMyStoredProc.Create(nil);
  AProc.Connection := VarOlanBirConnection;

  AProc.Connection.StartTransaction;

  try
    AProc.StoredProcName := 'sp_Sil';
    AProc.ExecProc;

    AProc.Connection.Rollback; // Bir nedenden ötürü Rollback yapmak istedik.
  finally
    if Assigned(AProc) then
      FreeAndNil(AProc);
  end;
end;

Göreceğiniz üzere, siz dıştaki transaction'u (Delphi tarafındaki); Rollback etseniz de veriler ilgili tabloya yazılmış olacak. Ayrıca dökümantasyonda bana saçma gelen bir başka nokta daha var, çok dikkatli olmayı gerektirecek.

Beginning a transaction causes any pending transaction to be committed. See Section 13.3.3, “Statements That Cause an Implicit Commit”, for more information.



Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. bulabilirsiniz. Bu kısımda özetle şunu diyor: Sizin açık bir transaction'unuz var ise yeni bir transaction başlatma eylemi açık olan transaction'un commit edilmesi ile neticelenir.

Ben inanamadım, böyle RDBMS mi olur. Aman siz siz olun ya uzak durun ya da çok dikkatli olun.

Son olarak nested (iç içe) transactionlar ile ilgili şu Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız. okumak isteyebilirsiniz.

Rezalet Angry
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#2
MySqL de şu stored proc lar çıktığı ilk zamanlarda kullanmaya kalkmıştım, fakat bir sürü acayip hatalar aldıktan sonra vazgeçmiştim, hataların neler olduğunu neden kaynaklandığını hiç araştırmamıştım şimdi farkediyorum neler olup bittiğini.
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
WWW
Cevapla
#3
(12-12-2018, Saat: 11:43)esistem Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.MySqL de şu stored proc lar çıktığı ilk zamanlarda kullanmaya kalkmıştım, fakat bir sürü acayip hatalar aldıktan sonra vazgeçmiştim, hataların neler olduğunu neden kaynaklandığını hiç araştırmamıştım şimdi farkediyorum neler olup bittiğini.

Sıkıntı stored procedure'lerin varlığı ya da onları kullanmak değil üstad. Ben kısa bir zamandır MySql kullanıyorum, ama gördüğüm çok ACEMİ bir veritabanı yönetim sistemi olduğu. Stored procedure zaten olmazsa olmaz. Nested (iç içe) transactionların tam olarak nerede nasıl işe yarayacağını daha önce tecrübe etmemiş ve dolayısı ile hayal edemeyen arkadaşlarım için şöyle kısa bir misal vereyim:

3 adet stored procedure'miz olsun.

SP-A (Stok tablosu ile ilgili işleri yapan procedure olsun)
--------------
  Transaction Başlat;
 
  Tablo A'yı güncelle;
  Tablo B'yi güncelle;
  Tablo C'yi güncelle;

  Hiç hata yoksa COMMIT et var ise ROLLBACK et;

SP-B (Cari tablosu ile ilgili işleri yapan procedure olsun)
--------------
  Transaction Başlat;
 
  Tablo D'yı güncelle;
  Tablo E'yi güncelle;
  Tablo F'yi güncelle;

  Hiç hata yoksa COMMIT et var ise ROLLBACK et;

SP-C (Muhasebe tablosu ile ilgili işleri yapan procedure olsun)
--------------
  Transaction Başlat;
 
  Tablo X'yı güncelle;
  Tablo Y'yi güncelle;
  Tablo Z'yi güncelle;

  Hiç hata yoksa COMMIT et var ise ROLLBACK et;

Bu tarz toplu işler için stored procedure'leri kullanırız. Aynı zamanda performans için kullanırız ama şimdi onun konusu değil. Herneyse, sizlerin de görebileceği gibi 3 ayrı stored procedure'miz 3'er farklı tabloyu güncellemeye çalışıyor ve hata olmaz ise COMMIT yapıyorlar. Buraya kadar herşey çok normal.

Şimdi şöyle bir ihtiyacınız olduğunu düşünelim. Uygulama tarafında bu 3 stored procedure'nin de sırası ile çalıştırılması gerekiyor ve ya hep ya hiç mantığında çalışması icap ediyor.

MySQL'in nested (iç içe) transactionları desteklememesinden ötürü şu şekilde bir kod hatalı çalışacaktır:

  Connection.StartTransaction;

  try
    try
      SP1.ExecProc;
      SP2.ExecProc;
      SP3.ExecProc;
    except
      if Connection.InTransaction then
        Connection.Rollback;
    end;
  finally
      if Connection.InTransaction then
        Connection.Commit;
  end;

Yukarıdaki kod 3 stored procedure'ü bir transaction ile sarmalamaya çalışıyor ve üçünden birisinde bile hata oluşması durumunda yapılan tüm işlemi geri alıyor(alamıyor). Ancak SP3'ün çalıştırılması sırasında bir hata oluştu ise maalesef SP1 ve SP2 de yapılmış olan DEĞİŞİKLİKLER siz ROLLBACK etseniz de COMMIT olmuş durumda. Tehlikeyi gördünüz mü Angry
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#4
ben her kayıt işlemi COMMIT yaptırıyorum o kayıta bağlı kayıtlar varsa o işlemleri de veritabanı kendisi içinde yapıyor. mesela fatura veresiye kesildi ise cari kayıt veritabanı tarafından açılıyor.
Cevapla
#5
(12-12-2018, Saat: 12:12)nguzeller Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.ben her kayıt işlemi COMMIT yaptırıyorum o kayıta bağlı kayıtlar varsa o işlemleri de veritabanı kendisi içinde yapıyor. mesela fatura veresiye kesildi ise cari kayıt veritabanı tarafından açılıyor.

Bence siz benim ne demek istediğimizi anlamadınız Wink
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#6
(12-12-2018, Saat: 12:12)nguzeller Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.ben her kayıt işlemi COMMIT yaptırıyorum o kayıta bağlı kayıtlar varsa o işlemleri de veritabanı kendisi içinde yapıyor. mesela fatura veresiye kesildi ise cari kayıt veritabanı tarafından açılıyor.

Hocam olay şu aslında, diyelim faturadakı stokları tek tek gonderıyorsunuz Stored Procedur ile, her biri gidince size sorun yok mesajı gonderıyor, ardından dıgerını yolluyorsunuz, ama arada bırınde hata alırsanız oncekıler de dahıl ıptal etmenız lazım! 

Nasıl yapıyorsunuz?

Bu arada aklıma geldi Tuğrul hocam şu kullanımın belki farklı bir şekli vardır?
CREATE PROCEDURE sp_Sil()
BEGIN
 START TRANSACTION;
  
 INSERT INTO tbl_dandik(Adi)
 SELECT 'Tuğrul';
  
 COMMIT;
END;
illaki start, commit yapmanız gerekmiyordur.
Linkleri Görebilmeniz İçin Üye Olmanız Gerekiyor. Üye Olabilmek İçin Lütfen Buraya Tıklayınız.
WWW
Cevapla
#7
olabilir Smile , kendimce anladığıma göre kendi çözüm yöntemimi önerdim. tam olarak karşılamayabilir tabi
Cevapla
#8
Firebird de aynı sorun var mi acaba merak ettim :S Sonucta yanlis bilmiyorsam stored procedure ,triger gibi ozellikleri mysql veritabanına ekleyen eleman firebird yazan kisi.

Firebird de denedim simdi,

3 tane procedure olusturdum. Ama asagidaki gibi kullandim.

CREATE PROCEDURE A 
as
begin
 update FIRMA set unvani='xxx';

 suspend;
end

CREATE PROCEDURE B
as
begin
 update FIRMA set unvani='yyy';

 suspend;
end

CREATE PROCEDURE C 
as
begin
 update FIRMA set unvani='zzz';

 suspend;
end


Delphi tarafında 

db.Connected:=true;

 tr.StartTransaction;
 s1.ExecProc;
 s2.ExecProc;
 s3.ExecProc;
 tr.Rollback;

Sonucu kontrol ettigimde ilgili tabloda bir update islemi gerceklesmedi. Siz procedure icerisine commit eklemissiniz. Firebird de  procedure icerisine commit yazinca kabul etmiyor.
Cevapla
#9
Herhangi bir stored procedure içinde birden fazla tabloyu ilgilendiren değişiklikler olacak ise; mantıken bu iş bir transaction içinde olmalıdır. Çünkü bu birden fazla işten herhangi birisinde hata meydana gelebilir ve veritabanı güvenliği için ya hep ya hiç mantığı devreye girmelidir. Bu sayede veriler de tutarlı olur. Bu bağlamda; benim örneğini verdiğim stored procedure'ler içinde kesinlikle bir transaction başlatılmalı ve commit ya da rollback çağrımları da duruma göre kodlanmalıdır.

Birden fazla stored procedure bu şekilde oluşturulduktan sonra, Delphi tarafında bu stored procedure'lere ihtiyacınız olduğunda durum ne olacak peki ? Birinci procedure düzgün şekilde çalışacak, stoklar güncellenecek, ikincisi procedure çalışacak ve cariler güncellenecek ancak son procedurenin çalışması sırasında yani muhasebe verileri güncellenirken bir hata olursa bu durumda ne olmuş olacak ? Stokları ve Carileri güncel olup muhasebe kayıtları güncel olmayan prematüre kayıtlarımız olacak.

Yani çok ciddi bir problemimiz olacak.

Procedure'ler içinde transaction başlatıp, rollback ile ya da commit ile sonlandırmaz isek ne olur peki ? İstediğimiz olmaz mı ? Hayır yine olmaz. Bu durumda, işlemlerin düzgün yürüyebilmesi için Delphi tarafında bir transaction başlatmayı unutmamalıyız. Peki unutur da sp'yi bir transaction başlatmadan çağırır isek ne olur. Örneğin Stok sp'sini Delphi tarafında transaction başlatmadan çağırdık. Bu durumda, ilgili procedure içinde güncellenen 3 adet tablodan 3ncüsünün güncellenmesi sırasında hata olursa bu durumda ondan önce güncellenen 2 adet tablodaki kayıtlar ne olacak ? Onlar otomatikman commit oldular. Yine tutarsız veriler ile dolu bir veritabanımız olacak.

Oysaki OOP mantığı icabı, her obje sadece kendisi ile alakalı işlerden sorumlu olmalı. Bu durumda, her procedure kendi içinde transaction başlatmalı ve bunu kontrol etmelidir. Birden fazla procedure ile işlem yapılacaksa da en dışta bir kapsayıcı transaction başlatılmalı ve hangi procedure'de olursa olsun bir hata durumunda ilgili transaction rollback edilmelidir.

Ayrıca, bir başka ciddi ve saçma husus; bir transaction açık durumda iken bir başka transaction açılmaya çalışılmasının açık olan transaction'u commit etmesi ! Bu da inanılmaz saçma unsurlardan bir diğeri. Hadi nested transaction desteklemiyorsun, bari ikinci bir transaction'u açmaya çalışır isek hata üret !

Bir veritabanı programcısı bir transaction başlatmış ise, bunu ilerleyen satırlarda commit ile ya da rollback ile sonlandırmak amacı ile başlatmıştır. Bu durumda, yeni bir transaction başlatılmaya çalışılması hatalı bir eylem olur (nested transaction desteklemediği için böyle söylüyorum). Bu durumda, ne demeye açık olan önceki transaction'u commit edersin be MySQL !
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#10
@Tuğrul HELVACI hocam anladığım kadarıyla masaüstü tarafında uygulama gelistiriyorsunuz. Sizin tecrubenizde biri Mysqle masaüstünde niye bulaştı anlamış değilim.
Yalnızım ama bir kente yürüyen ordu gibiyim, edebiyattan kaçınmalıyım..
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Önermiyorum - 4 Tuğrul HELVACI 9 1.215 25-01-2019, Saat: 15:03
Son Yorum: yhackup
  Önermiyorum - 9 (MySQL'de ALTER komutunun olmaması) Tuğrul HELVACI 13 1.312 16-01-2019, Saat: 09:01
Son Yorum: Tuğrul HELVACI
  Önermiyorum - 8 Tuğrul HELVACI 3 532 12-01-2019, Saat: 07:57
Son Yorum: Bay_Y
  Önermiyorum - 7 (Update ettiğin tabloyu Where kısmında kullanamazsın) Tuğrul HELVACI 14 1.219 04-01-2019, Saat: 14:12
Son Yorum: mad85
  Önermiyorum - 6 (Check_ConstrainsYok) uparlayan 9 1.024 04-01-2019, Saat: 09:13
Son Yorum: csunguray



Konuyu Okuyanlar: 1 Ziyaretçi