Avatar billede tchami Nybegynder
03. september 2003 - 21:45 Der er 14 kommentarer og
2 løsninger

Låse tabel?

Hej,

Jeg har to tabeller som styrer en menu på mit site.Den ene tabel (menu) holder styr på hvilken rækkefølge menupunkterne skal sorteres og den anden (content) indeholder selve indholdet af de forskellige menupunkter.
Det fungerer også fint nok, men jeg er lidt i tvivl om hvor sikker min metode er hvis der er flere brugere der på samme tid forsøger at ændre i menuen.
Her er et eksempel på hvad der sker når der skal indsættes et menupunkt over et eksisterende:

'## Vælg id som der skal indsættes et nyt menupunkt over
strSelectidSQL = "SELECT * FROM menu WHERE id = " & intActionid & ""
Set SelectidRS = Conn.Execute(strSelectidSQL)

'## Læg 1 til menu_sortorder for alle menupunkter med menu_sortorder større
'## eller lig det menupunkt vi indsætter over
strUpdateidInfoSQL = "UPDATE menu SET menu_sortorder = menu_sortorder+1
WHERE parent_id = " & SelectidRS("parent_id") & " AND menu_sortorder >= " &
SelectidRS("menu_sortorder") & ""
Conn.Execute(strUpdateidInfoSQL)

'## Indsæt nyt menupunkt
strInsertNewidSQL = "INSERT INTO menu(parent_id,menu_sortorder) VALUES("
& SelectidRS("parent_id") & "," & SelectidRS("menu_sortorder") & ")"
Conn.Execute(strInsertNewidSQL)

'## Vælg sidst indsatte id
strSelectLastInsertedRecord = "SELECT LAST_INSERT_ID() AS intLastId FROM
menu"
Set LastRecordRS = Conn.Execute(strSelectLastInsertedRecord)

'## Indsæt indhold i content tabellen
strInsertIntoContentSQL = "INSERT INTO content(id) VALUES (" & LastRecordRS("intLastId") & ")"
Conn.Execute(strInsertIntoContentSQL)

Der jeg er bange for det går galt er i UPDATE sætningen, så hvis jeg har ret hvad gør jeg så for at forhindre dette? Det skulle gerne være en løsning hvor flere brugere samtidigt kan tilføje menupunkter, men uden at det på nogen måder laver konflikter med andre brugere.

Håber det er til at forstå.
Avatar billede arne_v Ekspert
03. september 2003 - 21:52 #1
Det må kunne gå meget galt hvis 2 forsøger at sætte ind samme sted i
menu strukturen.

Og SelectidRS("menu_sortorder") er den samme for begge.

LOCK TABLES og UNLOCK TABLES er ihvertfald en måde at løse problemet på.
Avatar billede arne_v Ekspert
03. september 2003 - 21:54 #2
Det er en dårlig løsning, hvis der er rigtigt mange samtidige brugere.

Men jeg formoder at vi snakker om et 1 cifret antal samtidige brugere her.
Avatar billede -mundi- Nybegynder
03. september 2003 - 21:55 #3
Teoretisk kan det godt ske, hvis du vil være helt sikker så må det være noget med at tildele hver bruger der logger på et unikt nummer, noget med milisekunder der er gået indtil nu siden midnat sammensat med et tilfældigt tal mellem 1000000 og 9999999 (eller noget lignende), og så skrive det tal med ned i tabellen ved oprettelsen af en record. for så at få det id laver du bare en "select max(id) from tabel where uniqueid="+ditunikkebrugerid
Avatar billede arne_v Ekspert
03. september 2003 - 21:56 #4
Alternativt skal du lave om på din tabel-struktur så du kan nøjes
med rene INSERT og auto increment id's.

Og så ville du skulle sortere efter overmenuis,undermenuid - eller
noget i den stil.
Avatar billede tchami Nybegynder
03. september 2003 - 22:02 #5
>> arne_v
At SelectidRS("menu_sortorder") er den samme for begge er ikke noget problem, for i UPDATE sætningen (strUpdateidInfoSQL) ligger den 1 til menu_sortorder hvor menu_sortorder er større eller lig med SelectidRS("menu_sortorder"), og i strInsertNewidSQL indsætter den SelectidRS("menu_sortorder") hvilket også er hvad den skal.

At lave om på tabel-strukturen er desværre ikke en mulighed, så at bruge LOCK TABLES og UNLOCK TABLES er nok vejen frem, men hvordan gør jeg?

Og ja, det er formentlig ikke mere end et 1 cifret antal samtidige brugere.

>> -mundi--
Hmm, det kunne man selvfølgelig gøre, men det kræver en omstrukturering af mine tabeller, og det duer ikke desværre. Men tak for svaret.
Avatar billede -mundi- Nybegynder
03. september 2003 - 22:04 #6
Avatar billede -mundi- Nybegynder
03. september 2003 - 22:05 #7
som der står i linket :

mysql_query( "LOCK TABLES tabelnavn WRITE" );
mysql_query( "UNLOCK TABLES" );
Avatar billede arne_v Ekspert
03. september 2003 - 22:11 #8
LOCK TABLES menu WRITE; (evt. LOCK TABLES menu WRITE, content WRITE;)
lav UPDATE og INSERT
UNLOCK TABLES;
Avatar billede arne_v Ekspert
03. september 2003 - 22:13 #9
Og jeg forstår ikke hvorfor det ikke er et problem med 2 ens
SelectidRS("menu_sortorder") i menu tabellen !?

Hvis det var OK hvorfor så ligge 1 til alle de andre ??
Avatar billede tchami Nybegynder
03. september 2003 - 22:14 #10
Ok, det var jo let nok så, men er det ikke noget med at man også kan sige LOCK TABLES tabelnavn READ? Så hvad er forskellen på READ og WRITE, kan gætte mig til at det er noget med læse/skrive rettighedder, men for hvem?
Avatar billede tchami Nybegynder
03. september 2003 - 22:17 #11
>> arne_v
Der kommer ikke 2 ens i tabellen.

Eks. Jeg har tre records der ser således ud:
id | menu_sortorder
1 - 1
2 - 2
3 - 3

Efter strUpdateidInfoSQL ser de således ud:
id | menu_sortorder
1 - 2
2 - 3
3 - 4

Og efter strInsertNewidSQL ser de således ud:
id | menu_sortorder
4 - 1
1 - 2
2 - 3
3 - 4

Hvis der er en nemmere måde at gøre det på er jeg lutter øren :)
Avatar billede arne_v Ekspert
03. september 2003 - 22:18 #12
En WRITE LOCK er en exclusive lock d.v.s. at ingen andre kan noget.

En READ LOCK forhindrer alle inklusive en selv i at skrive men alle
kan læse.
Avatar billede arne_v Ekspert
03. september 2003 - 22:23 #13
Hvis vi nu har 2 processer der opdaterer.

Process 1 laver SELECT og får en SelectidRS("menu_sortorder") som er x.

Så bliver process 1 swappet ud.

Process 2 laver SELECT og får en SelectidRS("menu_sortorder") som er x.

Process 2 laver en INSERT med menu_sortorder x.

Process 2 bliver swappet ud.

Process 1 laver en INSERT med menu_sortorder x.

Og vi har 2 ens menu_sortorder.
Avatar billede arne_v Ekspert
03. september 2003 - 22:25 #14
Eller har jeg misforstået noget ?
Avatar billede tchami Nybegynder
03. september 2003 - 22:25 #15
Ahh, ja ok, men med LOCK TABLES undgår jeg vel det?
Avatar billede arne_v Ekspert
03. september 2003 - 22:30 #16
Ja.

Hvis du starter med LOCK og slutter med UNLOCK, så kommer process 2
ikke til (heller ikke med SELECT) førend process 1 er helt færdig.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester