use conference_host go create procedure sp_predaja ( @id_konf int, @naslov varchar(50), @link varchar(50), @autori varchar(100) ) as begin begin try set transaction isolation level repeatable read begin tran declare @status_pr varchar(20) select @status_pr=status_predaja from konferencije where id=@id_konf if @status_pr='otvoreno' begin insert into radovi(redni_broj, id_konferencije, naslov_rada, link_do_rada, autori) values (null, @id_konf, @naslov, @link, @autori) print 'Uspesno poslat rad' end else begin print 'Prihvatanje radova zatvoreno, rad nije poslat na vreme.' end commit tran end try begin catch rollback tran print 'Predaja nije uspesno izvrsena, pokusajte ponovo.' end catch end go -- sp_predaja vs. sp_zatvaranje_predaje -- read committed, potvrdjena anomalija pri stampanju -- repeatable read -- Ako je sp_predaja RC i procita da je predaja jos uvek otvorena, -- a onda sp_zatvaranje_predaje zatvori predaju i izlista sve radove predate pre roka -- a onda sp_predaja ipak ubaci novi rad, -- ispada da se ne poklapa ono sto stampa sp_zatvaranje_predaje i ono sto stoji u tabeli radovi. -- Zato mora RR za sp_predaja. Tada ce select from konferencije blokirati update konferencije. -- Za sp_zatvaranje_predaje, ako gledamo samo u odnosu na ovde date upite, moze RU. -- Ako krene prvo update konferencije da se izvrsava, nijedan drugi upit nece moci da poremeti sp_zatvaranje_predaje exec sp_predaja 4, 'Rad 3 konf ICML', 'link 13', 'autori 13' select * from radovi delete from radovi where id=14 select * from konferencije update konferencije set status_predaja='otvoreno' where id=4 go create procedure sp_prihvatanje ( @id_rada int, @prihvacen varchar(10) ) as begin begin try set transaction isolation level repeatable read begin tran if @prihvacen='da' begin declare @id_konf int, @max_redni_broj int, @novi_redni_broj int select @id_konf=id_konferencije from radovi where id=@id_rada select @max_redni_broj=max(redni_broj) from radovi where id_konferencije=@id_konf if @max_redni_broj is null set @novi_redni_broj = 1 else set @novi_redni_broj = @max_redni_broj+1 update radovi set status_prihvacen='da', redni_broj=@novi_redni_broj where id=@id_rada end else begin update radovi set status_prihvacen='ne' where id=@id_rada end commit tran end try begin catch rollback tran print 'Prihvatanje rada nije uspelo, pokusajte ponovo.' end catch end go -- sp_prihvatanje vs. sp_prihvatanje_2 -- read committed, potvrdjena anomalija -- repeatable read, potvrdjeno resava -- Ako se dve instance sp_prihvatanje izvrsavaju istovremeno, -- obe mogu da procitaju isti maksimalni redni broj -- i da svom radu dodele za jedan veci broj -- i tako dobijamo dva rada sa istim rednim brojem. -- Ovo se sprecava sa RR, select u jednoj instanci sprecice update u drugoj. -- Ovo dovodi do deadlocka. exec sp_prihvatanje 11, 'da' --exec sp_prihvatanje_2 12, 'da' select * from radovi update radovi set status_prihvacen=null, redni_broj=null where id=11 or id=12 go create procedure sp_uplata ( @id_rada int, @id_konf int ) as begin begin try set transaction isolation level repeatable read begin tran declare @status_reg varchar(20) select @status_reg=status_registracija from konferencije where id = @id_konf if @status_reg='otvoreno' begin insert into uplate(id_rada, vreme_uplate) values(@id_rada, getdate()) print 'Uspesno izvrsena uplata' end else begin print 'Registracija zatvorena, zakasnili ste sa uplatom.' end commit tran end try begin catch rollback tran print 'Uplata nije uspela, pokusajte ponovo.' end catch end go -- sp_uplata vs. sp_zatvaranje_registracije -- RC vs SER, potvrdjena anomalija -- RR vs RR, potvrdjena anomalija -- RR vs SER, nema anomalije -- Najkomplikovanija anomalija -- I problem - ako se select konferencije u sp_uplata izvrsi pre update-a konferencija u sp_zatvaranje_registracije, -- insert nove uplate se moze izvrsiti i nakon sto sp_zatvaranje_registracije evidentira sve uplate -- i onda bismo imali uplatu u tabeli uplate za rad za koji pise da nije uplacen i koji nece ici na konferenciju. -- Resavamo sa RR na sp_uplata. -- II problem - cak i kad stavimo RR na sp_uplata, i dalje moze da se desi problem ako sp_zatvaranje_registracije -- procita uplate pre nego sto sp_uplata ubaci novu. Zato sp_zatvaranje_registracije mora biti SER da bi blokirao insert. -- RC vs SER - Insert se samo odlaze, ali se izvrsi na kraju sto opet predstavlja problem -- RR vs SER - Dolazi do deadlocka, prolazi samo jedan, sve ostaje validno exec sp_uplata 6, 2 select * from radovi select * from uplate select * from konferencije delete from uplate where id_rada=6 update radovi set status_uplata=null where id=5 or id=6 update konferencije set status_registracija='otvoreno' where id=2 go create procedure sp_zatvaranje_predaje ( @id_konf int ) as begin begin try set transaction isolation level read committed begin tran update konferencije set status_predaja = 'zatvoreno' where id=@id_konf print 'Svi poslati radovi' select naslov_rada, autori from radovi where id_konferencije=@id_konf commit tran end try begin catch rollback tran print 'Zatvaranje predaje nije uspelo, pokusajte ponovo.' end catch end go -- sp_predaja vs. sp_zatvaranje_predaje -- moze i Read Uncommitted ako gledamo samo ovde date upite exec sp_zatvaranje_predaje 4 go create procedure sp_zatvaranje_registracije ( @id_konf int ) as begin begin try set transaction isolation level serializable begin tran update radovi set status_uplata='da' where status_prihvacen='da' and id in ( select id_rada from uplate ) update konferencije set status_registracija = 'zatvoreno' where id=@id_konf print 'Svi radovi koji ce biti prezentovani na konferenciji' select naslov_rada, autori from radovi where id_konferencije=@id_konf and status_uplata='da' commit tran end try begin catch rollback tran print 'Zatvaranje registracije nije uspelo, pokusajte ponovo.' end catch end go -- sp_uplata vs. sp_zatvaranje_registracije exec sp_zatvaranje_registracije 2