Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
deadlock hatası
#1
saygıdeğer programcı arkadaşlar... Uzun zamandır forma giremedim. Programcılığa da farklı programlar, nesnelerin interneti, robotik kodlama ile kendimi geliştirmek üzere farklı kurslara , çalışmalara yöneldim. Yıllar önce yazmış olduğum  cari programımım çok kullanıcı şekilde kullanılıyordu. Yıllardır belki de farkında olmadığımız bir hata tespit edildi. Hata sonrası biraz araştırma yaptım. Sorunu yaşamadığım için bilmiyordum. Bilenler bilir de hatayı kısaca yazayım. 

Çoklu kullanımda bir bilgisayarda bir cari kart açılmış ve işlem yapılmış olsun. (commit edilen bir işlem). Eğer bu işlem arkasından başka bir kişiye ait cari kart açılmadan, işlem (commit) yapılmadan başka bilgisayarda aynı kişiye ait bir işlem açılıp commit edilirse DEADLOCK hatası veriyor. Vermemesinin tek yolu işlem sonrası başka birine cari işlem yapmak. 

sorum şu: projeyi tekrar gözden geçirmeden bu sorunu çözebilir miyim? Firebird dosyaları üzerinden bu hatayı gidermenin yolu var mıdır? firebird üzerinden yoksa basit şekilde projede Transaction ayarlarından bir ayar ile bunu giderebilir miyim? Kısaca seçeneklerim var mıdır?  Firebird 2.0 versiyon kullanıldı. Delphi 7 ile yazıldı. Fibplus bileşen setiyle data bağlantısı yapıldı. Transaction ayarları aşağıdaki gibidir.

timeout:0
timeautaction:TARollback
TPMBMode: tpbReadCommitted

Yorumlarınızı ve tavsiyeleriniz bekler sağlıklı, mutlu günler dilerim.
Cevapla
#2
Deadlock hatası genelde aynı kaydı iki kullanıcı aynı anda editlemeye silmeye post etmeye kalkınca oluşur.
Aslında bu iyi bir durumdur Hata da değildir, Bir kaydı öteki kullanıcı editlememesi için diye yapılmış tasarımdır
Bununla ilgili hem Veritabanında yapılması gereken Hem de Delphide yapılması gereken şeyler vardı diye hatırlıyorum.
Çözümü, uyarı veren Query'e bağlı transaction Commit edilmemiş bir prosesi bulunuyor, commit edilene dek bekler, Başka biri kayıt güncelleme ile uğraşırsa kendisi de deadlock ile karşılaşır.

Kilitlenmeyi Önlemek için kullanabileceğiniz basit SQL 
SELECT * FROM TABLO_ISMI WITH(NOLOCK)


Query. Post un
Transaction Commit edildikten sonra ben genelde query nesnesini refresh ediyorum, ürettiğim çoklu kullanıcı insan kaynakları yazılımımda sizdeki gibi bir hata hiç görmedim fakat bende farklı bir hata oluşuyordu post ederken ara sıra (update failed 0 record şeklinde hata oluyordu) query refresh ile olayı çözdüm tabi queryde bulunan primary keyi object inspectorda required özelliğini false yaptıktan sonra işe yarıyordu nedendir bilmiyorum D7 kullanıyorum Firebird için bir bilgi daha vereyim 2.58 en iyisidir (Firebird 2. 59 da network parametrelerini işlevselliğini beğenmediğim bir özellik koymuşlar)
Kullandığım UniDac bileşenlerinde olan giderilmemiş bir hatamıdır bug mudur bilemiyorum.
Refresh ile çözdüm.
Kaydınız post ve COMMIT edildikten sonra Refreshi de deneyin.
Eğer yapabiliyorsanız işlem başlamadan goto bookmark ve get bookmark proseslerini yaparsanız refresh edilen tablo ilk kayda uçacağından bookmark ile ilgili kayda tekrar konumlanacaksınız.

UniQuERY1.Bookmark;
UniQuERY1.Edit;
///.... KODLAR 
UniQuERY1.Post;
UniQuERY1.Refresh;
UniQuERY1.GetBookmark;
Cevapla
#3
(20-12-2021, Saat: 23:36)COMMANDX Adlı Kullanıcıdan Alıntı: Query. Post un
Transaction Commit edildikten sonra ben genelde query nesnesini refresh ediyorum, ürettiğim çoklu kullanıcı insan kaynakları yazılımımda sizdeki gibi bir hata hiç görmedim fakat bende farklı bir hata oluşuyordu post ederken ara sıra (update failed 0 record şeklinde hata oluyordu) query refresh ile olayı çözdüm tabi queryde bulunan primary keyi object inspectorda required özelliğini false yaptıktan sonra işe yarıyordu nedendir bilmiyorum D7 kullanıyorum Firebird 2.58 en iyisidir (Firebird 2. 59 da network parametrelerini işlevselliğini beğenmediğim bir özellik koymuşlar)
Kullandığım UniDac bileşenlerinde olan giderilmemiş bir hatamıdır bug mudur bilemiyorum.
Refresh ile çözdüm.
Kaydınız post edildikten sonra Refreshi deneyin.
Eğer yapabiliyorsanız işlem başlamadan goto bookmark ve get bookmark proseslerini yaparsanız refresh edilen tablo ilk kayda uçacağından bookmark ile ilgili kayda tekrar konumlanacaksınız

Deadlock hatası ise genelde aynı kaydı iki kullanıcı aynı anda editlemeye silmeye post etmeye kalkınca oluşur.
Bununla ilgili hem Veritabanında yapılması gereken Hem de Delphide yapılması gereken şeyler vardı diye hatırlıyorum.

Teşekkür ederim değerli üstadım. Projeyi sil baştan gözden geçirmem neredeyse mümkün değil. Onlarca form ve bileneş satılar dolusu sorgular var. Bakalım bir çözüm bulabilecek miyiz...
Cevapla
#4
Çok emin değilim fakat
https://firebirdsql.org/refdocs/langrefu...hlock.html
buradaki (NOLOCK) işinizi görebilir.
Tek hamlede halledilebilecek bir sorun gibi durmuyor.
Kolay gelsin.
İmam Süleyman Yakub <--> Molla Mustafa Mansur
Evlatlarım!
Cismanımız TÜRK ruhumuz ise İSLAM.
Bu yolda daim olalım her an.
Cevapla
#5
(21-12-2021, Saat: 09:51)ahmet_sinav Adlı Kullanıcıdan Alıntı: Çok emin değilim fakat
https://firebirdsql.org/refdocs/langrefu...hlock.html
buradaki (NOLOCK) işinizi görebilir.
Tek hamlede halledilebilecek bir sorun gibi durmuyor.
Kolay gelsin.

ahmet bey öncelikle yanıtınız için teşekkür ederim. Burada anlatılanlardan anladığım firebirdde kilileme verileri korumak için gerekli olduğu... Sql cümlesi içine sorgunun arkasına WITH LOCK eklentisiyle sorgu içine de yazılabilir diyor. buradaki (NOLOCK) işinizi görebilir. ifadesindeki (NOLOCK) kısmını anlamadım.
Cevapla
#6
(20-12-2021, Saat: 23:36)COMMANDX Adlı Kullanıcıdan Alıntı: Deadlock hatası genelde aynı kaydı iki kullanıcı aynı anda editlemeye silmeye post etmeye kalkınca oluşur.
Aslında bu iyi bir durumdur Hata da değildir, Bir kaydı öteki kullanıcı editlememesi için diye yapılmış tasarımdır
Bununla ilgili hem Veritabanında yapılması gereken Hem de Delphide yapılması gereken şeyler vardı diye hatırlıyorum.
Çözümü, uyarı veren Query'e bağlı transaction Commit edilmemiş bir prosesi bulunuyor, commit edilene dek bekler, Başka biri kayıt güncelleme ile uğraşırsa kendisi de deadlock ile karşılaşır.

Kilitlenmeyi Önlemek için kullanabileceğiniz basit SQL 
SELECT * FROM TABLO_ISMI WITH(NOLOCK)


Query. Post un
Transaction Commit edildikten sonra ben genelde query nesnesini refresh ediyorum, ürettiğim çoklu kullanıcı insan kaynakları yazılımımda sizdeki gibi bir hata hiç görmedim fakat bende farklı bir hata oluşuyordu post ederken ara sıra (update failed 0 record şeklinde hata oluyordu) query refresh ile olayı çözdüm tabi queryde bulunan primary keyi object inspectorda required özelliğini false yaptıktan sonra işe yarıyordu nedendir bilmiyorum D7 kullanıyorum Firebird 2.58 en iyisidir (Firebird 2. 59 da network parametrelerini işlevselliğini beğenmediğim bir özellik koymuşlar)
Kullandığım UniDac bileşenlerinde olan giderilmemiş bir hatamıdır bug mudur bilemiyorum.
Refresh ile çözdüm.
Kaydınız post ve COMMIT edildikten sonra Refreshi de deneyin.
Eğer yapabiliyorsanız işlem başlamadan goto bookmark ve get bookmark proseslerini yaparsanız refresh edilen tablo ilk kayda uçacağından bookmark ile ilgili kayda tekrar konumlanacaksınız.

UniQuERY1.Bookmark;
UniQuERY1.Edit;
///.... KODLAR 
UniQuERY1.Post;
UniQuERY1.Refresh;
UniQuERY1.GetBookmark;

firebird UniDac niye tercih ettiniz, ne kadar süredir kullanıyorsunuz, bende mobilde interbasa firedac bırakıp Unidac geçmeye düşüyorum, bu konuda deyimleriz merak ediyorum.
Cevapla
#7
(22-12-2021, Saat: 11:59)nguzeller Adlı Kullanıcıdan Alıntı: firebird UniDac niye tercih ettiniz, ne kadar süredir kullanıyorsunuz, bende mobilde interbasa firedac bırakıp Unidac geçmeye düşüyorum, bu konuda deyimleriz merak ediyorum.
Delphi7 Kullanıyorum Bu nedenle D7 ye en uygun Datasetlerin Unidac Olduğu içindi, onlarca Dataset komponent yükledim sonunda en uygun ve basit, hızlı ve uyumlu datasetlerdir. 
"Update Failed Found 0 Record" hatası dışında Uygulamalarında Wan Network uygulamalı bir bağlantı kopması henüz yaşamadım şimdiye kadar. Tavsiye ederim.
Mobil aplikasyonlar hiç uğraşmadığım için UniDac komponentlerinin artısı eksisini bilemiyeceğim, ama Windows için Geliştirdiğim Uygulamalarda D7 de fazlasıyla bana yetiyor.
Cevapla
#8
When an UPDATE statement tries to access a record that is locked by another transaction, it either raises an update conflict exception or waits for the locking transaction to finish, depending
on TPB mode. Engine behaviour here is the same as if this record had already been modified by the locking transaction.
Yanlış anlamadıysam.
With lock ile update işlemine başlanıldığında aynı satırı update etmek isteyen olduğunda bu satır için exception dönecek demek oluyor.
bu exception'ı da handle edebilrsen
"Record is still on update. Wait for a while"
gibi bir exception throw edip rollback edersin.
İmam Süleyman Yakub <--> Molla Mustafa Mansur
Evlatlarım!
Cismanımız TÜRK ruhumuz ise İSLAM.
Bu yolda daim olalım her an.
Cevapla
#9
Merhaba,
Ben şahsen şöyle yapıyorum; bir kullanıcı bir cariye (veya kayıtlı faturaya vb.) giriş yaptığında veritabanında temptable oluşturup, girilen carinin cari kodunu yazdırıyorum. Başka bir kullanıcı herhangi bir cariye veri girişi denediğinde ilk önce bu temptable 'da bu cari kod var mı kontrol ettirip varsa giriş/edit yapamayacağına dair uyarı verdiriyorum, yani girişi engelliyorum. Cariye edit için ilk giren commit işlemini tamamladığında temptable 'dan bu cari kodu siliyorum. Bundan sonra ancak diğer kişiler girebiliyor. Kendimce çözümü bu şekilde uyguluyorum. Yıllardır çalışan programdan en ufak şikayet gelmedi. 
Not: Ben sql server kullanıyorum. Firebird 'de temptable herhalde vardır diye tahmin ediyorum.
Cevapla
#10
kanımca:

updatelerde;

kural, ilk gelen update eder;

ilk önce;
tek bir field alanda olabilir, kayıt içindeki guruplarada eklenebilir, son güncelleme alanları eklenir.
update ile birlikde songucelleme ms cinsinden zaman damgası timestamp yazılır, veya randomid de atayabilirsiniz çok önemi yok.

client record u query ile fetch ettiğinde bu zaman damgasının değerini aklında tutar,
update esnasında query içinden eğerki zamandamgası string i hala değişmediyse (burada zaman karşılaştırması yapılmıyor, string<> değişim kontrolü var)
update query yi gerçekleştir mantığına çevrilir, diğer türlü update query failed e düşer,
(where recid=xx and songuncellemetimestamp = 'xxxxxxx' limit 1)

failed e düştü ise; (ya record yok? ya timestamp farklı?)
tekrar kayıt query ile okunur, değişen alanlar operatöre gösterilir, tekrar dan bir teyid ile yeni alanlar tekrar update ettirilir, update başarılı ise,
son güncelleme zaman damgasıda değişmiş olacakdır,

bu record üzerinde işlem yapan tüm client ler aynı mantığı takip eder,

böylece 1 client record u çekmiş olsada, update anında, diğer clientin yazdığı yeni verileri, eski veriler üzerine yazılarak güncellenmemiş olur,
mantık update anında bu zaman damgasının değişikliğe dağir teyid edilmesidir.

her ne kadar siz 100 soketten 100 query geçsenizde, db bu query leri tek tek işler, 1 query donarsa diğer query lerde beklemeye geçer, ve zaman aşım süreleride vardır.

tabi siz görsel obje kullandığınız için bu esnekliği yaratamayabilirsiniz, orası ayrı konu..
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  FB matematiksel işlem de parametre hatası mcuyan 2 430 13-10-2023, Saat: 22:05
Son Yorum: mcuyan
Photo Firebird hatası HakanY 4 1.428 16-10-2021, Saat: 20:31
Son Yorum: HakanY
  Firebird - Unavailable Database Hatası sunbeki 12 4.115 23-06-2021, Saat: 16:16
Son Yorum: esistem
  Operating System Directive OpenFileMapping Failed Hatası sunbeki 2 1.406 29-04-2021, Saat: 23:48
Son Yorum: sunbeki
  SQLQueryl : Cannot open a non-select statement hatası sadikacar60 9 2.911 04-04-2021, Saat: 20:24
Son Yorum: sadikacar60



Konuyu Okuyanlar: 1 Ziyaretçi