Jak to jest z tą blokadą wiersza w InnoDB

Odpowiedz Nowy wątek
2011-10-19 10:01
0

Witam

jak już większości wiadomo, zapis danych do bazy MySQL o typie InnoDB, odbywa się sekwencyjnie, czyli występuje kolejkowanie, czyli dany wiersz jest blokowany na czas zapisu (przeciwnie niż MyISAM, gdzie blokowana była cała tabela).
Inni piszą, że można dodać dodatkową kolumnę np. 'blocked', której nadajemy wartość 1, gdy wykonujemy jakieś operacje na niej i sprawa załatwiona :)

Ja na przykład chcę wykonać taką operację :
otóż chciałbym po zapisie wiersza do bazy zablokować go od razu, gdyż nie wszystkie pola są uzupełnione, np. identyfikator, który powstaje na zapisanych wcześniej danych - MD5(IDuser + NameUser + DT). Po utworzeniu 'identyfikatora' i wykonaniu UPDATE, odblokowuje dany wiersz.

W tym samym czasie inni użytkownicy wykonują to samo, wtedy wiem, że dany wiersz jest bezpieczny i co najważniejsze ID (właściwość autoincrement) będzie to które odpytuje a nie inne, kolejne.

Ktoś napisał :

W pracy mam baze oracle i do obsługi jest wykorzstywana java.
Podczas zapisu do bazy za pomocą jakiejś funkcji(nie pamiętam nazwy) blokuje dany rekord,
a po zapisie odblokowuje go.
Pytanie moje po części dotyczyło tego czy php (a może mysql) posiada funkcję do blokowania rekordów

edytowany 1x, ostatnio: amator1, 2011-10-19 10:04

Pozostało 580 znaków

2011-10-19 10:11
0

... wpadł mi do głowy pomysł, aby zrobić to za pomocą transakcji (TRANSACTION), ale znalazłem coś takiego :

http://forum.webhelp.pl/php-i[...]ck-in-share-mode-t205428.html

i znowu w czarnej d...

edytowany 1x, ostatnio: amator1, 2011-10-19 10:24

Pozostało 580 znaków

2011-10-19 10:41
0

Napisz trigger który wygeneruje identyfikator w chwili dodawania rekordu i masz problem z głowy, ew. przed "dotknięciem" rekordu w innej części aplikacji sprawdzaj czy ma wygenerowany identyfikator.

Pozostało 580 znaków

2011-10-19 10:47
0

na pewno rozwiązuje to część problemu, ale nie rozwiązuje głównego, blokowania wierszy

Pozostało 580 znaków

2011-10-19 11:00
0

Zastanów się czy rzeczywiście masz jakiś problem czy może sam go sobie tworzysz?

Pozostało 580 znaków

2011-10-19 11:07
0

takie coś robi się inaczej - właśnie za pomocą transakcji

  1. rozpoczynasz transakcję
  2. robisz insert
  3. generujesz identyfikator
  4. robisz update
  5. robisz commit
    i teraz dopóki nie wykonasz punktu 5 to NIKT poza transakcją, która zrobiła inserta nie widzi tego wiersza więc nie ma konieczności jego blokowania

- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij

Pozostało 580 znaków

2011-10-19 11:23
0

Transakcje to jedno rozwiązanie, ale podobno można to też zrobić za pomocą "lock in share mode"

SESSION1:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into tst values(1);
Query OK, 1 row affected (0.00 sec)

SESSION2:
mysql> begin ;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from tst;
Empty set (0.01 sec)

#Session2 does not see any rows as transaction was not commited yet.

SESSION1:
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

SESSION2:
mysql> select * from tst;
Empty set (0.00 sec)

mysql> select * from tst lock in share mode;
+---+
| i |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

mysql> select * from tst for update;
+---+
| i |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

#Standard SELECT does not see rows while SELECT for UPDATE and LOCK IN SHARE MODE  sees it. 

Pozostało 580 znaków

2011-10-19 11:37
0

można no i co z tego? BTW w tym co podałeś masz DOKŁADNIE opisane OBIE metody


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij

Pozostało 580 znaków

2011-10-19 12:55
0

Aby nie rozpoczynać nowego postu, chciałbym zapytać o Triggery. Prosty przykład z :
http://hengrui-li.blogspot.co[...]for-cant-update-table-in.html

mam dokładnie to samo, tzn. przy próbie wstawienia wiersza - działam tylko na jednej testowej tabeli- otrzymuje komunikat :

Error Code : 1442
Can't update table 'test' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

Skoro nie mogę na tej samej tabeli wykonać wyzwalacza, to jak inaczej ?

Jeśli zas zrobię to, tak :

DELIMITER |

CREATE
    TRIGGER TcreateName_AI AFTER INSERT ON test 
    FOR EACH ROW BEGIN
    SET NEW.nazwa = "test" ;
    END;
|

DELIMITER ;

Wówczas błędu brak, ale nie widzę nowej wartości dla kolumny 'nazwa'

edytowany 1x, ostatnio: amator1, 2011-10-19 13:10

Pozostało 580 znaków

2011-10-19 13:12
0

jeśli potrzebujesz zrobić coś takiego to w 99% przypadków oznacza to błąd w projekcie. Jak sobie wyobrażasz działanie np. trigerra before/after insert, który wstawiał by inny wiersz w TEJ SAMEJ tabeli??

AFTER jest wywoływane PO wstawieniu wiersza


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij
edytowany 1x, ostatnio: Misiekd, 2011-10-19 13:13

Pozostało 580 znaków

2011-10-19 14:04
0

no i tak ma działać, tylko nie PO a PRZED, sorry za zamieszanie... ;)

edytowany 1x, ostatnio: amator1, 2011-10-19 14:13

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0