Sobes.tech
Middle

Co jsou zámky v kontextu práce s databázemi a proč jsou nutné?

sobes.tech AI

Odpověď od AI

Zámky v databázi jsou mechanismy používané k řízení přístupu více uživatelů nebo procesů ke stejným datům současně. Zabraňují konfliktům a udržují integritu dat v konkurenčním prostředí.

Jsou nezbytné pro řešení následujících problémů:

  • Race Conditions: Situace, kdy pořadí provádění operací ovlivňuje konečný výsledek. Zámky zajišťují, že operace budou prováděny sekvenčně nebo v bezpečném pořadí.
  • Inconsistent Reads: Jeden proces čte data, zatímco jiný je mění, což může vést k získání mezistavů nebo neúplných dat. Zámky tomu mohou zabránit.
  • Lost Updates: Dva procesy čtou stejná data, každý je mění a poté ukládá. Poslední uložení přepíše změny prvního, čímž je ztratí. Zámky pomáhají zabránit ztrátě změn.
  • Phantom Reads: V rámci jedné transakce opakovaný dotaz vrací jiný soubor řádků, protože jiný proces přidal nebo odstranil řádky odpovídající podmínkám dotazu.

Hlavní typy zámků:

  • Sdílený (Shared/Read Lock): Umožňuje více transakcím číst stejná data současně. Neumožňuje zápisové zámky na stejná data.
  • Exkluzivní (Exclusive/Write Lock): Poskytuje monopolní přístup k datům. Pouze jedna transakce může mít exkluzivní zámek na určitá data v daném okamžiku. Neumožňuje ani čtení, ani zápisové zámky na stejná data.

Zámky mohou být aplikovány na různých úrovních:

  • Úroveň databáze: Zamkne celou databázi. Zřídka používané.
  • Úroveň tabulky: Zamkne celou tabulku. Méně detailní, může snížit konkurenceschopnost.
  • Úroveň řádku: Zamkne samostatný řádek. Více detailní, podporuje vysokou konkurenceschopnost, ale může vyžadovat více zdrojů.
  • Úroveň stránky: Zamkne stránku dat (jednotka úložiště v DBMS obsahující několik řádků). Kompromis mezi zamknutím tabulky a řádku.

Implementace zámků závisí na konkrétním DBMS (například InnoDB a MyISAM v MySQL mají odlišné strategie zámků, PostgreSQL atd.). V PHP se často používají transakce k řízení zámků.

-- Příklad použití transakce a zámku v SQL
START TRANSACTION;

SELECT balance FROM accounts WHERE account_id = 123 FOR UPDATE;
-- FOR UPDATE klade exkluzivní zámek na vybraný řádek

UPDATE accounts SET balance = balance - 100 WHERE account_id = 123;

COMMIT;
-- Nebo ROLLBACK při chybě