abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    dnes 04:33 | IT novinky

    Společnost Espressif (ESP8266, ESP32, …) získala většinový podíl ve společnosti M5Stack, čímž posiluje ekosystém AIoT.

    Ladislav Hagara | Komentářů: 0
    včera 23:44 | Nová verze

    Byla vydána nová stabilní verze 3.5 svobodného multiplatformního softwaru pro editování a nahrávání zvukových souborů Audacity (Wikipedie). Přehled novinek také na YouTube. Nově lze využívat cloud (audio.com). Ke stažení je oficiální AppImage. Zatím starší verze Audacity lze instalovat také z Flathubu a Snapcraftu.

    Ladislav Hagara | Komentářů: 0
    včera 16:44 | Zajímavý článek

    50 let operačního systému CP/M, článek na webu Computer History Museum věnovaný operačnímu systému CP/M. Gary Kildall z Digital Research jej vytvořil v roce 1974.

    Ladislav Hagara | Komentářů: 0
    včera 16:22 | Pozvánky

    Byl zveřejněn program a spuštěna registrace na letošní konferenci Prague PostgreSQL Developer Day, která se koná 4. a 5. června. Na programu jsou 4 workshopy a 8 přednášek na různá témata o PostgreSQL, od konfigurace a zálohování po využití pro AI a vector search. Stejně jako v předchozích letech se konference koná v prostorách FIT ČVUT v Praze.

    TomasVondra | Komentářů: 0
    včera 03:00 | IT novinky

    Po 48 letech Zilog končí s výrobou 8bitového mikroprocesoru Zilog Z80 (Z84C00 Z80). Mikroprocesor byl uveden na trh v červenci 1976. Poslední objednávky jsou přijímány do 14. června [pdf].

    Ladislav Hagara | Komentářů: 6
    včera 02:00 | IT novinky

    Ještě letos vyjde Kingdom Come: Deliverance II (YouTube), pokračování počítačové hry Kingdom Come: Deliverance (Wikipedie, ProtonDB Gold).

    Ladislav Hagara | Komentářů: 4
    21.4. 19:11 | Komunita

    Thunderbird 128, příští major verze naplánovaná na červenec, přijde s nativní podporou Exchange napsanou v Rustu.

    Ladislav Hagara | Komentářů: 23
    21.4. 04:44 | Komunita

    Byly vyhlášeny výsledky letošní volby vedoucího projektu Debian (DPL, Wikipedie). Novým vedoucím je Andreas Tille.

    Ladislav Hagara | Komentářů: 7
    21.4. 00:11 | Nová verze

    Po osmi měsících vývoje byla vydána nová verze 0.12.0 programovacího jazyka Zig (GitHub, Wikipedie). Přispělo 268 vývojářů. Přehled novinek v poznámkách k vydání.

    Ladislav Hagara | Komentářů: 2
    20.4. 23:55 | Pozvánky

    Poslední měsíc byl plný zajímavých akcí, o kterých Vám bastlíři z projektu MacGyver mohou povědět, protože se na ně sami vydali. Kde všude byli, ptáte se? Objevili se na Installfestu, Arduino Day, Hackaday Europe a tajném srazu bastlířů z Twitteru. A z každé akce pro vás mají zajímavé poznatky.

    … více »
    bkralik | Komentářů: 1
    KDE Plasma 6
     (71%)
     (10%)
     (2%)
     (18%)
    Celkem 671 hlasů
     Komentářů: 4, poslední 6.4. 15:51
    Rozcestník

    Dotaz: Mysql - zamykání "cizích" řádků během transakce

    30.7.2011 00:33 brevnos
    Mysql - zamykání "cizích" řádků během transakce
    Přečteno: 724×
    Ahoj. V transakci bych potřeboval provádět následující:
    1. SELECT id FROM identifikatory WHERE nazev = 'nazev';
    // pokud predchozi select vrati id, pak
    2. INSERT INTO tabulka VALUES (id, .....)
    
    Tyto operace provádím v transakci s úrovní REPEATABLE READ, ale nemyslím si, že by samotná transakce ochránila bod 2 před tím, aby někdo mezitím smazal dané id. V tabulce tabulka je totiž id jako cizí klíč na tabulku identifikatory, takže ve druhém kroku potřebuju, aby id existovalo. Jakým způsobem mohu zajistit, aby id určitě existovalo ve 2. kroku?

    Odpovědi

    30.7.2011 01:09 Kit
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    Stačí jen jeden krok:
    INSERT INTO tabulka SELECT id, ..... FROM identifikatory WHERE nazev='nazev' LIMIT 1;
    Pokud nazev nebude existovat, nový záznam se nevloží.
    30.7.2011 01:15 brevnos
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    A nejde to rozdělit a provést to přitom jako atomickou operaci? Jde o to, že takových selectů se stejným id tam mám třeba několik tisíc a ptát se pokaždé jaké to id je bude asi časové náročné.
    30.7.2011 01:30 Kit
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    Nebude. Za prvé existuje databázová cache a za druhé máš určitě tabulku identifikatory indexovánu podle sloupce nazev.

    Tu časovou náročnost jsem nedávno měřil. Není to tak zlé, jak se povídá. Navíc všech 1000 záznamů můžeš vložit jedním insertem, takže to bude i rychlé.
    30.7.2011 22:07 l0gik | skóre: 22
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    To nic nemění na tom, že pokud těch tisíc záznamů poběží každej zvlášť, tak to už rychlé nebude - a vkládat 1000 záíznamů najednou zas nemusí jít kvůli packet size.

    V úrovni repeatable reads se zámky se dávají zámky automaticky, takže netřeba řešit. Od toho to je repeatable reads, co se jednou přečte, tak se nemění (a je tedy znovupřečtitelné).
    31.7.2011 04:34 brevnos
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    Je to potřeba řešit, repeatable reads "ochraňuje" upravované záznamy z transakce k světu tak, že svět před commitem nevidí změnu. Pomohl příspěvek níže s LOCK IN SHARE MODE.
    1.8.2011 12:31 l0gik | skóre: 22
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    Nene, to co píšeš je READ COMMITED, to je izolace o úroveň níže. Ale já to taky nepopsal přesně: Repeatable reads nedává zámky na čtené věci, ale zajišťuje, že do konce transakce v transakci to, co přečteš stejným dotazem.

    V této situaci funguje konkrétně tak, že ten, kdo se první pokusí zapsat, tak uspěje, a druhý (ať při snaze změnit FK, nebo při snaze zapsat novou hodnotu se "starým FK" bude čekat na výsledek první transakce, pokud se commitne, tak příkaz neuspěje. Což je pravda, že to není úplně to, co tazatel chtěl, pokud ale implementuje opakování transakce (což je nutné tak jako tak, protože při repeatable reads transakce díky race condition může selhat i z jiných v podstatě neodstranitelných důvodů), tak už tím získá i řešení tohoto problému.

    Ale otázka jestli je lepší pesimistic nebo optimistic locking, nemá jednoznačnou odpověď, takže pokud se ten číselník moc nemění, tak klidně zamykat.
    1.8.2011 22:19 brevnos
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    protože při repeatable reads transakce díky race condition může selhat i z jiných v podstatě neodstranitelných důvodů)
    Jakých třeba? Opakování transakcí nikde implementováno nemám. Vyzkoušel jsem, že transakce v REPEATABLE READS může selhat takto:
    sezení 2:
    START TRANSACTION
    SELECT id FROM hlavni_tabulka WHERE id = 2;
    
    
    sezení 1:
    DELETE FROM hlavni_tabulka WHERE id = 2;
    
    
    sezení 2:
    INSERT INTO vedlejsi_tabulka (id, ...) VALUES (2, ....); // selže kvůli cizímu klíči id tabulky hlavni_tabulka tzn. ačkoliv mi v tomto bodě
    dotaz "SELECT id FROM hlavni_tabulka WHERE id = 2" vrací hodnotu, fyzicky už to tam neexistuje a foreign key zajímá
    jen poslední verze. Tohle nevím jak vyřešit kromě izolace SERIALIZABLE, která by měla zamknout čtené řádky, ale to bohužel (jak jsem dnes zjistil) nemohu udělat, protože potřebuju,
    aby ostatní sezení měla k dispozici RW přístup k řádkům hlavní tabulky během transakce (která může trvat i několik desítek minut - miliony řádků).
    O jiných důvodech proč by mělo REPEATABLE READS selhat nevím. Souběh už by měla mít databáze vyřešený ne?
    1.8.2011 23:02 kuka
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    Obecne vzdy "vyssi" uroven zabezpeceni transakce neco stoji, extremem je serializable, kde je treba s opakovanim pocitat prakticky vzdy. To ze bude jedne transakci zaruceno repeatable read znamena omezeni ostatnich transakci a naopak. Jedna z transakci tak ma ve vysledku proste smulu a protoze to muze byt "normalni prubeh" a transakce po opetovnem spusteni probehne dobre (jeji kolidujici transakce uz skocila), mela by obvykle aplikace tuto moznost resit. Proto mam osobne radeji explicitni zamykani tam, kde je to nutne.

    Mozna ze v tvem konkretnim pripade nemuze kolize nastat, ale je treba to dobre promyslet a na to je treba znat vsechny mozne operace nad konkretnimi tabulkami. Stroj nemuze vedet, k cemu presne ten repeatable read pouzivas - napr. muzes zjistit radek v hlavni tabulce a pokud neexistuje tak ho zalozit. Pak na zaklade toho neco pocitat a pak neco s radkem udelat. Jestlize na zacatku existoval a mezitim ho nekdo smaze, tak ti to selze, ale po retartu transakce uz to projde dobre (pokud tam zase nekdo neskodi), protoze ten radek si tam sam zalozis. Tzn. de facto misto explicitniho zamykani mas implicitni a to co bys pro explicitni zamek resil pri neuspechu zamceni (napr. cekani az se zamceni podari nebo se zjisti ze radek uz neexistuje), resis restartem transakce jako celku. Kazdy pristup se muze hodit v jine situaci.

    Mozna trochu zjednodusene pokud je opravdu repeatable reads vecne potreba, tak vetsinou existuje i moznost restartu transakce. Pokud potreba neni, tak je lepsi ji nepouzit a potrebe restartu se vyhnout.

    2.8.2011 02:06 l0gik | skóre: 22
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    No, todle je zrovna jeden z případů. Obecně repeatable reads selže, pokud něco změníš transakci pod rukama a tím zrušíš integritu dat. Dál při různejch race condition, např. obě transakce se pokusej změnit stejnej řádek, apod.

    I když teď jsem to zkoušel a musím říci, že se to chová divně, IMHO tam má mysql bug, protože todle projde a nemělo by
    CREATE TABLE a (a integer) engine innodb;
    INSERT INTO a values (1);
    
    když spustím následující řádky synchronně ve dvou transakcích (vždy stejný řádek v jedné a pak v druhé), tak mi ta druhá nezařve, i když by měla (a např. v postgresql zařve) a normálně počká na commit první transakce a pak zahlásí nula modifikovaných řádek.
    set session transaction isolation level repeatable read ;
    BEGIN;     
    SELECT * FROM a;
    UPDATE a set a=2 /*v druhé =3*/ where a=1;     
    COMMIT
    
    Přitom další SELECT * FROM a; furt tvrdí, že tam v té tabulce je jednička. Tomu tedy rozhodně neříkám repeatable reads, tomu říkám paskvil.

    ---

    Nicméně obecně: pokud chceš mít dlouhé transakce, během kterých ostatní transakce mají RW přístup, nemůžeš zajistit konzistenci. To prostě z principu nelze. Buď máš konzistentní čtení/zápis, pak ale když se sejdou dvě transakce nad stejnými daty, ne vždy jdou uspořádat a tedy je potřeba někdy jednu zrušit a pak zavolat znova. To u dlouhé transakce je blbina, pak ji musíš rozsekat na krátké transakce. Anebo se vykašleš na konzistenci. Zajistit obojí prostě nejde - když té dlouhé transakci změní něco krátká transakce pod rukama, tak to prostě "automaticky" vyřešit nejde.

    2.8.2011 03:12 brevnos
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    Mám tam případy, kdy se může najednou modifikovat (respektive většinou DELETE + INSERT) stejný řádek v tabulce, takže k selhání může dojít. Díky za objasnění, nějak jsem nepočítal s tím, že by transakce mohla skončit i v takovém případě jako v tom příkladu. Podle mě by se to správně mělo chovat tak, že se náhodně zvolí, která z transakcí má přednost a ta druhá počká do jejího vykonání - je to celkem logické. K těm dlouhým transakcím - většinou se jedná o smazání celé tabulky (pomocí DELETE, aby se to dalo v mysql zpracovat transakčně), poté INSERT nových řádků, s tím, že bych chtěl, aby se tabulka navenek chovala jako kdyby se nic nedělo (RW dotazy) a po provedení transakce došlo k jejímu přepsání - v těchto případech se mi jedná o konzistenci dat nově vkládaných, jestli bude někdo během transakce měnit tabulku mi nevadí, ale mělo by to jít.
    3.8.2011 02:05 brevnos
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    Ještě k těm opakováním transakcí? Jak se to ošetřuje v programu? Viděl jsem nějaké příklady a tam to nechávali v nekonečném cyklu, což je podle mě kravina. Jak jsem dnes zkoumal, tak db může vyhodit během transakce skoro všechny možný chyby a ty se nedají odlišit od chyb stálých tzn. nepoznám jestli transakce skončila kvůli race condition, dead locku nebo třeba kvůli nějaké trvalé chybě, která nemá s předchozími nic společné. Jak to tedy řešit resp. jak se to řeší? Opakovat n-krát?
    3.8.2011 16:35 l0gik | skóre: 22
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    No tak u lepší databáze (postgresql např.) jsou selhání transakční izolace hlášený speciální výjimkou, takže to detekovatelný je. U MySQL tomu bohužel tak není - teda deadlock poznáš, ale některý jiný chyby tuším ne. Takže nic lepšího, než n-násobný opakování Ti asi nezbývá.
    30.7.2011 02:09 Kit
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    A ještě něco: Pokud by tabulka identifikatory byla stabilní a potřeboval bys větší výkon databáze, zvaž její odstranění. Místo cizího klíče pak použiješ datový typ ENUM. Databáze s ENUM pracuje o něco rychleji a hlavně je s ním mnohem pohodlnější práce. Vně se chová jako varchar, ale uvnitř je to jen jednobajtový (příp. dvoubajtový) identifikátor.
    30.7.2011 14:35 kuka
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    SELECT id FROM identifikatory WHERE nazev = 'nazev' LOCK IN SHARE MODE
    31.7.2011 04:34 brevnos
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    Díky, tohle je to co hledám.
    30.7.2011 22:19 Sten
    Rozbalit Rozbalit vše Re: Mysql - zamykání "cizích" řádků během transakce
    SELECT id FROM identifikatory WHERE nazev = 'nazev' FOR UPDATE;
    

    Založit nové vláknoNahoru

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.