OV5 finished
This commit is contained in:
parent
e1257294e2
commit
46248eac04
3
newDb.sh
Executable file
3
newDb.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
mysql -u root -p --execute "CREATE DATABASE IF NOT EXISTS $1; GRANT ALL PRIVILEGES ON $1.* TO 'idatt2103'@'localhost'; FLUSH PRIVILEGES; "
|
10
ov5/konto.sql
Normal file
10
ov5/konto.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE konto(
|
||||||
|
kontonr INTEGER PRIMARY KEY,
|
||||||
|
saldo INTEGER NOT NULL);
|
||||||
|
|
||||||
|
INSERT INTO konto(kontonr, saldo) VALUES(1, 35);
|
||||||
|
INSERT INTO konto(kontonr, saldo) VALUES(2, 120);
|
||||||
|
INSERT INTO konto(kontonr, saldo) VALUES(3, 100);
|
||||||
|
INSERT INTO konto(kontonr, saldo) VALUES(4, 35);
|
||||||
|
INSERT INTO konto(kontonr, saldo) VALUES(5, 100);
|
||||||
|
INSERT INTO konto(kontonr, saldo) VALUES(6, 30);
|
154
ov5/losning.md
154
ov5/losning.md
@ -62,7 +62,7 @@ Altså er flere problemer ved både innsetting, redigering og slettet fikset, me
|
|||||||
For eksempel er det ikke sikkert at man kan endre adressen til en kunde uten flere endringer.
|
For eksempel er det ikke sikkert at man kan endre adressen til en kunde uten flere endringer.
|
||||||
Den bryter fortsatt 3NF, fordi kunde_navn, adresse og telefon avhenger av kunde_id.
|
Den bryter fortsatt 3NF, fordi kunde_navn, adresse og telefon avhenger av kunde_id.
|
||||||
|
|
||||||
#### Forslag på 3NF:
|
#### Forslag på 3NF ( /BCNF ):
|
||||||
|
|
||||||
![Figur 3NF](3NF.png)
|
![Figur 3NF](3NF.png)
|
||||||
|
|
||||||
@ -76,14 +76,158 @@ Her har jeg altså vist at man kan ta denne tabellen fra 1NF til 3NF via 2NF. De
|
|||||||
|
|
||||||
Skrevet på relasjonsform:
|
Skrevet på relasjonsform:
|
||||||
```
|
```
|
||||||
kunde(id, navn, adresse, telefon)
|
kunde(id*, navn, adresse, telefon)
|
||||||
|
|
||||||
eier(id, navn, adresse, telefon)
|
eier(id*, navn, adresse, telefon)
|
||||||
|
|
||||||
eiendom(id, adresse, eier_id)
|
eiendom(id*, adresse, eier_id)
|
||||||
|
|
||||||
leieforhold(eiendom_id, kunde_id, fra_uke, til_uke, pris)
|
leieforhold(eiendom_id*, fra_uke*, kunde_id, til_uke, pris)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# DEL 2: Transaksjoner
|
||||||
|
|
||||||
|
## Teori
|
||||||
|
|
||||||
|
### Hvilke typer låser har databasesystemene?
|
||||||
|
|
||||||
|
- __Delt lås__
|
||||||
|
- Flere klienter kan ha flere låser samtidig
|
||||||
|
- Tillater at andre kan lese dataen, men ikke skrive underveis
|
||||||
|
- __Eksklusiv lås__
|
||||||
|
- Kun en transaksjon kan holde låsen til samme tid
|
||||||
|
- Må vente til ingen andre har lås på objektet
|
||||||
|
- Andre kan heller ikke lese
|
||||||
|
|
||||||
|
|
||||||
|
### Hva er grunnen til at at man gjerne ønsker lavere isolasjonsnivå enn SERIALIZABLE?
|
||||||
|
|
||||||
|
Med SERIALIZABLE isolasjon nekter vi andre transaksjoner og uttrykk i å bruke data som har vært endret av den isolerte operasjonen.
|
||||||
|
|
||||||
|
Hvis vi bruker SERIALIZABLE, og kjører et UPDATE-uttrykk, vil vi sette en ekslusiv lås slik at andre ikke kan lese innholdet. Dette beholder strengt den atomiske egenskapen i en transaksjon, ved at du enten leser helt ny eller helt gammel data (før og etter transaksjonen), aldri delvis. I praksis fører dette til mye venting på blokkerte ressurser, selv om andre bare skal lese.
|
||||||
|
|
||||||
|
Med REPEATABLE READ er ny data satt inn med "INSERT" lesbart for andre, og med READ COMMITED er lesing av bekreftet endret data tillatt. I veldig mange tilfeller er dette OK, og vi trenger ikke bruke like mange ekslusive låser.
|
||||||
|
|
||||||
|
|
||||||
|
### Hva skjer om to pågående transaksjoner med isolasjonsnivå serializable prøver `select sum(saldo) from konto`?
|
||||||
|
|
||||||
|
SELECT-setninger alene vil bare lage delte låser, ikke ekslusive, selv i SERIALIZABLE. Altså vil begge transaksjonene kunne lese og bruke dataen samtidig. SUM gjør også aldri endringer i dataen, og påvirker ikke låsene.
|
||||||
|
|
||||||
|
### Hva er to-fase-låsing?
|
||||||
|
|
||||||
|
Når man starter en databasetransaksjon kan man tenke seg at det sikreste er å låse alle tabellene / objektene i databasen, men dette skaper unødvendig mange låser og mye venting.
|
||||||
|
|
||||||
|
Fase 1: Begynn å bruke / endre data, sett stadig flere låser __ettter hvert som de trengs__.
|
||||||
|
|
||||||
|
Fase 2: Commit / Rollback, __fjern alle låsene på en gang.__
|
||||||
|
|
||||||
|
Delingen holder låsingen til et minimum, uten å forstyrre normal operasjon av databasen.
|
||||||
|
|
||||||
|
### Hvilke typer samtidighetsproblemer (de har egne navn) kan man få ved ulike isolasjonsnivåer? Hva er optimistisk låsing/utførelse? Hva kan grunnen til å bruke dette være?
|
||||||
|
|
||||||
|
#### Vi kan få samtidighetsproblemer som
|
||||||
|
- Overskriving / kollisjon: Flere oppdateringer skjer samtidig, alle untatt den siste kan gå tapt.
|
||||||
|
- Ikke-bekreftede data: En annen transaksjon bruker data som ikke er COMMIT-et.
|
||||||
|
- Inkonsistent uthenting ( Non-repeatable read ): Deler av den hentede dataen er ferdig oppdatert, deler er ikke oppdatert enda.
|
||||||
|
|
||||||
|
#### Optimistisk låsing/utførelse:
|
||||||
|
|
||||||
|
I mange applikasjonstilfeller kan vi si det er usannsynlig at data skal settes inn eller fjernes samtidig med andre prosesser.
|
||||||
|
I slike tilfeller kan man med fordel vente med å sette låser til det er nødvendig.
|
||||||
|
|
||||||
|
Vi leser dataen vi kanskje planlegger å endre, men setter ikke lås enda.
|
||||||
|
|
||||||
|
Etter å ha gjort arbeidet vi trenger å gjøre, sjekker vi om dataen har endret seg(sjekk en spesifikk verdi, en hash eller et timestamp, avhengig av implementasjon).
|
||||||
|
Hvis den ikke har endret seg kan vi sette en eksklusiv lås og gjøre endringen vi trenger.
|
||||||
|
|
||||||
|
Dersom dataen (mot formodning, ikke sannsynlig) har endret seg i mellomtiden, vil operasjonen feile og vi må prøve på nytt.
|
||||||
|
|
||||||
|
I tilfeller med få kollisjoner vil dete være effektivt siden vi har låser bare når det er helt nødvendig, men det gjør at vi kan måtte gjøre arbeid flere ganger om noe skulle kollidere.
|
||||||
|
|
||||||
|
Dette gjør paralellt arbeid lettere med en enklere dataflyt.
|
||||||
|
|
||||||
|
### Hvorfor kan det være dumt med lange transaksjoner (som tar lang tid)? Vil det være lurt å ha en transaksjonhvor det kreves input fra bruker?
|
||||||
|
|
||||||
|
Om man bruker transaksjoner med streng isolasjon, for eksempel SERIALIZABLE, som bruker mange ekslusive låser, betyr det at alle andre operasjoner må vente i kø til transaksjonen blir bekreftet eller avbrutt.
|
||||||
|
Over tid kan køen bygge seg opp, og det er alltid noe man må vente på. Derfor kan data ofte gjøres klar i forveien, for eksempel det som skal brukes i INSERT og DELETE, slik at brukerinput og lignende er samlet inn og sjekket før man setter låsen.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Oppgaver om transaksjoner
|
||||||
|
|
||||||
|
### Oppg 1:
|
||||||
|
|
||||||
|
Serializable setter delt lås ved SELECT, så klient 1 blir stoppet med exception når den kjører UPDATE.
|
||||||
|
|
||||||
|
Dataen blir ikke endret. Dette skjer bare ved SERIALIZABLE, det strengeste isolasjonsnivået.
|
||||||
|
|
||||||
|
### Oppg 2:
|
||||||
|
|
||||||
|
a) Den siste dataen vil commites, og dermed lagres, til sist. Det tilsvarer endringene fra klient 2.
|
||||||
|
|
||||||
|
| **kontonr** | **saldo** |
|
||||||
|
|-------------|-----------|
|
||||||
|
| 1 | 2 |
|
||||||
|
| 2 | 2 |
|
||||||
|
|
||||||
|
b) I dette tilfellet vil vi se en deadlock, fordi klient 1 setter ekslusiv lås på kontonr 1, og klient 2 setter ekslusiv lås på kontonr 2. Deretter vil k1 vente på ledig kontonr 2, og k2 vil vente på ledig kontonr 1, uten at noen kan bli ferdige.
|
||||||
|
|
||||||
|
Alle isolasjonsnivåer setter ekslusiv lås på UPDATE, så det vil ikke ha noen effekt.
|
||||||
|
|
||||||
|
### Oppg 3:
|
||||||
|
|
||||||
|
#### Hva skjer?
|
||||||
|
|
||||||
|
Klient 1 vil se initialverdien ved første select, og den nye, større, verdien i de to siste.
|
||||||
|
|
||||||
|
### Hva vil skje om Klient 1 bruker read committed, repeatable read eller serializable?
|
||||||
|
|
||||||
|
Serializable:
|
||||||
|
|
||||||
|
Serializable isolasjonsnivå vil sette en delt lås ved SELECT, og derfor vil ikke klient 2kunne skrive endringer før transaksjonen er slutt.
|
||||||
|
|
||||||
|
Repeatable read / read committed:
|
||||||
|
|
||||||
|
Klient 1 vil se initialverdien ved de to første select, og den nye, større verdien i den siste.
|
||||||
|
|
||||||
|
### Oppgave 4
|
||||||
|
#### Lag en kjøring med to klienter som tester phantom reads. Her kan det være lurt å tenke igjennom isolasjonsnivå. Om resultatet ikke er som forventet så kan det være lurt å sjekke dokumentasjonen.
|
||||||
|
|
||||||
|
Begge klienter:
|
||||||
|
```sql
|
||||||
|
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
|
||||||
|
START TRANSACTION;
|
||||||
|
```
|
||||||
|
|
||||||
|
k1:
|
||||||
|
> SELECT * FROM konto WHERE kontonr > 3;
|
||||||
|
|
||||||
|
viser konto 4-7
|
||||||
|
|
||||||
|
k2:
|
||||||
|
> INSERT INTO konto SET kontonr=8, saldo=120;
|
||||||
|
|
||||||
|
k1:
|
||||||
|
> SELECT * FROM konto WHERE kontonr > 3;
|
||||||
|
|
||||||
|
viser konto 4-7
|
||||||
|
|
||||||
|
k2:
|
||||||
|
> COMMIT;
|
||||||
|
|
||||||
|
k1:
|
||||||
|
> SELECT * FROM konto WHERE kontonr > 3;
|
||||||
|
|
||||||
|
viser konto 4-7
|
||||||
|
|
||||||
|
k1:
|
||||||
|
> COMMIT;
|
||||||
|
|
||||||
|
> SELECT * FROM konto WHERE kontonr > 3;
|
||||||
|
|
||||||
|
viser konto 4-8
|
||||||
|
|
||||||
|
|
||||||
|
Altså viser ikke min databaseserver(MariaDB med InnoDB) noen tegn til phantom read, selv om isolasjonsnivået ( REPEATABLE READ) skulle tilsi det, basert på tabell i foiler fra foreleser.
|
||||||
|
Loading…
Reference in New Issue
Block a user