Tomasz Zadora

Tomasz Zadora programuję

Temat: LOCK after LOCK

Witam,

Sprawa dotyczy tabel typu MyISAM, w dokumentacji czytam:

"If a session issues a LOCK TABLES statement to acquire a lock while already holding locks, its existing locks are released implicitly before the new locks are granted."

rozumiem, że w tym momencie między "LOCKAMI" powstaje "dziura", tak, że jeżeli:

1) Zakładam LOCK READ na tabele "product"
2) Czytam z tabeli "product" wartość kolumny "price"
3) Zakładam nowy LOCK WRITE na tabelę product
4) Wartość odczytana w kroku 2) może być już nieaktualna, ponieważ w momencie wykonania kroku 3) istnieje szansa, że inna sesja/połączenie zablokuje tabelę WRITE LOCKiem zaraz po ściągnięciu LOCK READ ustawionego w kroku 1) i nadpisze wartość "price" ?

Mam akurat taki przypadek, że muszę to zrobić na MyISAM a nie transakcjach w InnoDB.Tomasz Zadora edytował(a) ten post dnia 25.05.11 o godzinie 23:19
Michał Jarosz

Michał Jarosz Frontend Developer &
Team Leader

Temat: LOCK after LOCK

A dlaczego w ogóle robisz najpierw LOCK READ a potem LOCK WRITE na tej samej tabeli?
Tomasz Zadora

Tomasz Zadora programuję

Temat: LOCK after LOCK

Ponieważ nie zawsze będzie potrzeba wykonania operacji aktualizacji/skasowania danych, więc lepiej, sprawdzając dane nie blokować innych odczytów z tej tabeli prowadzonych przez inne połączenia działające w tym samym czasie.

W tym hipotetycznym przykładzie będzie to zależeć od wartości "price" - zakładając, że jest to sprawdzane bardzo często a aktualizowane rzadko, byłoby źle za każdym razem całkowicie blokować tabelę write lockiem.
Michał Jarosz

Michał Jarosz Frontend Developer &
Team Leader

Temat: LOCK after LOCK

No to chyba zostaje Ci po sprawdzeniu, że trzeba wykonać update, zrobić WRITE LOCK i sprawdzić na wszelki wypadek jeszcze raz. Jak dobrze pójdzie i w międzyczasie dane w tabeli się nie zmieniły, to dostaniesz odpowiedź wprost z query cache (jeżeli masz) więc koszt minimalny.
Tomasz Zadora

Tomasz Zadora programuję

Temat: LOCK after LOCK

Dzięki, wiem, że można tutaj zastosować technikę podwójnego sprawdzenia, ale to dotyczy także innych sytuacji gdzie muszę zrobić podobnie i tej techniki już nie zastosuje.

Dlatego zależy mi na odpowiedzi dokładnie na to pytanie, a nie na rozważania jak zrobić inaczej :)

Zadałem to pytanie już na forum MySQL, nawet ich profilu na facebooku i nic :( Chyba będę musiał uderzyć bezpośrednio do jakiegoś developera z Oracle :(
Michał Jarosz

Michał Jarosz Frontend Developer &
Team Leader

Temat: LOCK after LOCK

Ale to akurat możesz bardzo prosto sprawdzić odpalając dwie sesje w konsoli.

Sesja 1

mysql> select * from t1;
+------+------+------+
| t1ID | c1 | c2 |
+------+------+------+
| 0 | 1 | 1 |
| 1 | 1 | 2 |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
+------+------+------+
4 rows in set (0.00 sec)

mysql> lock tables t1 read;
Query OK, 0 rows affected (0.00 sec)


Sesja 2

mysql> update t1 set c1 = 2 where t1id = 1;

konsola nie zwraca propmptu, czyli zapytanie wisi i czeka na odblokowanie. Wracamy do sesji 1;

Sesja 1

mysql> lock tables t1 write;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1;
+------+------+------+
| t1ID | c1 | c2 |
+------+------+------+
| 0 | 1 | 1 |
| 1 | 2 | 2 |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
+------+------+------+
4 rows in set (0.00 sec)


A w sesji 2

Query OK, 1 row affected (7.06 sec)
Rows matched: 1 Changed: 1 Warnings: 0


I to by chyba odpowiadało na Twoje pytanie
Tomasz Zadora

Tomasz Zadora programuję

Temat: LOCK after LOCK

Dzięki. Czyli jednak jest "dziura", niedobrze....



Wyślij zaproszenie do