Üdv,
MySQL v5.3-astól felfelé változik a locking kezelés: már nem lehet táblát létrehozni, ha bármely másik tábla lock-olva van.
Ref.: http://docs.oracle.com/cd/E17952_01/refman-5.5-en/create-table.html
"Beginning with MySQL 5.5.3, you cannot execute CREATE TABLE or CREATE TABLE ... LIKE while a LOCK TABLES statement is in effect."
5.5 alatt kellene megoldanom, hogy míg más táblák lock-olva vannak, létrehozzak táblákat a műveletek közben, de úgy, hogy a többin a lock-ot nem oldom fel.
Lenne erre ötlete valinek? Köszi.
- 8428 megtekintés
Hozzászólások
Mindenképpen fizikai tábla kellene?
-----------
"640GB sokmindenre elég"
- A hozzászóláshoz be kell jelentkezni
Temporary táblára gondolsz? Az nekem nem jó, mert igazából 2 dolog miatt kellene nekem a fenti:
- egyrészt temporary táblának, csak éppen session után is kell még, és én döntöm el mikor törlöm - tehát a beépített "create temporary table" megoldás nem jó, mert az a session lezárásakor (vagyis a weboldal legenerálásának végeztekor) törli azt automatikusan ugye
- másrészt megnézem, hogy egy tábla már létezik-e, és ha nem, akkor létrehozom - itt meg olyan a helyzet, hogy kényelmetlen és kicsit áttekinthetetlen lenne, ha előre hoznám létre azokat
Ez miatt a kérdésedre a válasz: igen.
- A hozzászóláshoz be kell jelentkezni
Hmm...
mysql> create database A;
mysql> create database B;
mysql> use A;
mysql> create table table1 (id int(6) auto_increment);
mysql> lock table A.table1;
mysql> use B;
mysql> create table table1 (id int(6) auto_increment);
Így az utolsó create table statementet sem tudja végrehajtani a B adatbázisban, mert A-ban lockoltam egy táblát?
Mysql 5.1 FTW!
-----------
"640GB sokmindenre elég"
- A hozzászóláshoz be kell jelentkezni
Mondjuk nekem 1 db-n belül kell az egész. Egy weboldalhoz használom, de csak 1 db-t.
5.1 alatt ez lefut rendben:
mysql> use mydb;
mysql> unlock tables;
mysql> drop table if exists t1;
mysql> drop table if exists t2;
mysql> create table t1 (id int);
mysql> lock table t1 read;
mysql> create table t2 like t1;
vagy
mysql> create table t2 (id int);
5.5-ön az utolsó parancsnál hibát dob:
"ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES"
- A hozzászóláshoz be kell jelentkezni
Nem vagyok egy db szaki, de a menetközbeni folyamatos tábla törlés/létrehozás nem tűnik túl meggyőzőnek. Ha már mindenképp táblát akarsz űríteni, akkor neked a TRUNCATE lenne a hasznos és tranzakcióval kombinálva.
BEGIN;
TRUNCATE TABLE IF EXISTS T1;
TRUNCATE TABLE IF EXISTS T2;
COMMIT;
(Nem tudom a truncate mennyire tranzakció barát, de ki fog derülni asszem.)
- A hozzászóláshoz be kell jelentkezni
Ez csak példakód volt.
- A hozzászóláshoz be kell jelentkezni
(nem ide)
- A hozzászóláshoz be kell jelentkezni
A truncate-nek direkt az az egy értelme van a delete-tel szemben, hogy nem logol, nem lehet rollback-elni.
- A hozzászóláshoz be kell jelentkezni
Egy megjegyzés: a fenti úgy kellene nekem, hogy nem szeretnék a "create table" parancsaim előtt "unlock tables"-öt futtatni, mert akkor az egész locking megoldásom értelmét veszti.
Azt nem értem, hogy ez miért így van? Nem életszerű, hogy egy weboldal legenerálásakor locking-ot használok bizonyos táblákra (hogy ezek állapota ne változhasson más user-ek interakciója miatt a műveletem alatt), és ez közben van szükségem egy tábla létrehozására?
- A hozzászóláshoz be kell jelentkezni
Szerintem nem, en ugy altalaban nem csinalnek olyat hogy egy alkalmazas tablakat hoz letre futas kozben. Biztos van mellette indok, es most nem tudok felhozni ellene, de en mar csak ilyen konzervativ vagyok :)
- A hozzászóláshoz be kell jelentkezni
Adatbázis kezelő app-ot csinálok.
- A hozzászóláshoz be kell jelentkezni
akkor meg főleg nem értem:)
Egy adatbázis kezelő app kezelje az adatbázist, ne gyártsa:)
- A hozzászóláshoz be kell jelentkezni
Egyaltalan nem eletszeru az, hogy tablakat hozol letre a _normal mukodes reszekent_. Setup/upgrade az nyilvan mas. Ha neked a mukodes reszekent kell tablakat gyartanod, akkor el kell gondolkodnod azon, hogy lehet, hogy rossz az adatbazisod szervezese.
Illetve nem ertem, miert gond a tabla lete/nemlete. Ha ures, akkor annyira mindegy, hogy ott van-e nem?
Egyekbent meg: CREATE TABLE IF NOT EXISTS.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal
- A hozzászóláshoz be kell jelentkezni
5.5-től emlékeim szerint InnoDB a default táblatípus, amivel remekül lehet tranzakciókat kezelni. Minek használsz külön LOCK-ot? A címet pedig 5.5.3-ra lenne érdemes javítanod, mert 5.3-as MySQL tudtommal sosem volt kiadva, csak 5.4 (asszem mint tech preview).
- A hozzászóláshoz be kell jelentkezni
csatlakozom, en sem gondolom, hogy egy acid dbnel kellene az OPnak lockolgatni barmit is.
- A hozzászóláshoz be kell jelentkezni
A remek mysql autocommit állapotban van MyISAM esetén és sokan ehhoz vannak szokva. Az érdemi adatbázis kezelős feature-ők fel sem szoktak sajnos merülni. A MyISAM + autocommit + LOCK megoldást pedig sokan kvázi tranzakciózásnak fogják fel.
Nemrég szomorúan tudtam meg, (ugyanis annó LOCK TABLE jogot valamiért nem kapott minden dbuser a webszerveren, de ez nem volt szándékos), hogy a remek új Joomla nekiállt LOCK TABLES-özni... hát fogtam a fejem.
- A hozzászóláshoz be kell jelentkezni
Nem tudom tranzakcióba összeszedni a műveleteket. Egy adatbázis kezelő app-ot csinálok. Sokat gondolkodtam rajta, de kell olyan, hogy db művelet -> saját program műveletek -> db műveletek megint -> program, és ezek lefutásáig adott táblához fenntartani a lock-ot.
- A hozzászóláshoz be kell jelentkezni
PHP-ból remekül ment:
BEGIN;
UPDATE...
-- phpból ellenőrzöm hogy sikeres-e, ha igen akkor
DELETE...
-- megint jön a PHP..., ha sikeres
INSERT...
-- ha ez is jó, akkor
COMMIT;
A PHP kódként írt részekben remekül elférne más is, és szerintem volt is a kedvenc projektemben, és a false ágakon végig ott volt szépen a ROLLBACK, hogy ne érjen meglepetés.
- A hozzászóláshoz be kell jelentkezni
Az életben nem foglalkoztam DB-vel, ezért könnyen lehet hogy rosszul látom a dolgokat. Mégis úgy gondolom, hogy ez nekem nem jó, mert a legelső SQL művelet és az legutolsó között nem szabad hogy változzanak a szóban forgó tábláim.
Ha jól értem a tranzakció lényegét, az az, hogy egyben be tudod küldeni a műveleteket - tehát sebességben sokat számíthat, illetve ott a rollback. De nekem az a célom, hogy egy másik user-t várakoztasson a lock-om, amíg az előző user-nek le nem generáltam az oldalt. Különben csúnya adat korrupciók lehetnek.
Amúgy köszi mindenkinek a segítséget.
- A hozzászóláshoz be kell jelentkezni
A tranzakció lényegét nem érted. Mivel "az életben nem foglalkoztál DB-vel", ez nem is meglepő.
Olvass utána annak a fogalomnak, hogy transaction isolation.
- A hozzászóláshoz be kell jelentkezni
Könnyen meglehet hogy nem jól értem, de ez kevésbé zavar, mert még nem igazán foglalkoztam db-vel, így ez előfordulhat. Ha azt mondod nem jól értem, akkor utánanézek.
- A hozzászóláshoz be kell jelentkezni
Ez eddig is elég egyértelmá volt:
http://dev.mysql.com/doc/refman/5.0/en/commit.html
"With START TRANSACTION, autocommit remains disabled until you end the transaction with COMMIT or ROLLBACK."
Az isolation level-t is nézegetem, de még nem igazán értem hogy ez hogy segít rajtam. Így is úgyis meg kell mondanom előre, hogy a művelet kezdete előttől mely táblák nem változhatnak. A lock-on kívül még mindig nem értem hogy erre miért lenne jobb a tranzakció, vagy mi más lenne jobb?
- A hozzászóláshoz be kell jelentkezni
Így is úgyis meg kell mondanom előre, hogy a művelet kezdete előttől mely táblák nem változhatnak.
Nem jó irányból közelíted meg a problémát. Hogy egy klasszikust idézzek: ha kalapács van a kezedben, minden tárgy szögnek látszik.
Mi az a szituáció, ami tábla szintű lock nélkül problémát okozna?
- A hozzászóláshoz be kell jelentkezni
Pl az, ha a tranzakcióm lépései között egy másik user megváltoztatná a használt tábláim adatait. Lépések közt azt értem, hogy a parancsok közt kell script-et futtatnom, és felhasználnom táblák adatait. Tehát vakós időben előfordulthat, hogy a következő műveletnél rossz adatot kapok - mivel az adatok is kapcsolatban állnak egymással.
- A hozzászóláshoz be kell jelentkezni
De írd le egy példában, hogy hogyan gondoltad.
Megfelelő tranzakciókezelés esetén ez nem lehetséges ugyanis.
- A hozzászóláshoz be kell jelentkezni
Újra végig kell gondolnom az egész megoldásomat. Egyelőre nem látom át azonnal, hogy megtudnám-e oldani a problémakört úgy, hogy összeszedem az összes SQL műveletet 1 csokorba és tranzakcióként adom át. Már elég nagy a kódbázisom, de átgondolom és megírom majd mire jutottam.
- A hozzászóláshoz be kell jelentkezni
Nem kell mindenképp egy csokorba gyűjtened, de tényleg nem egészséges sokáig variálni tranzakció közben, ha több egyidejű felhasználó is lehetséges az adatbázison. A tranzakciók óriási előnye a ROLLBACK opciód a végén, mert ha valahol gebaszba ütközöl, amit előre nem tudhatsz, akkor egyszerűen aszondod ROLLBACK és ennyi. A LOCK TABLES-ös megoldásnál viszont esélyed sincs visszaállni, hacsak nem követed valahogy a változásokat.
- A hozzászóláshoz be kell jelentkezni
Még annyit hozzátennék ismét, hogy nem csak adatokkal dolgozok, hanem az adatbázis kezelését valósítom meg. Ezért gondolkodok tábla lock-ban. Tehát a user azt mondhatja, hogy 1 táblához hozzáad egy oszlopot, vagy éppen töröl. A műveleteim közt ez elég problémás lenne.
- A hozzászóláshoz be kell jelentkezni
Nem kapsz. Ettől tranzakció a tranzakció. A LOCK TABLE-ös játékot direkt tranzakció szimulálásra szokták használni, ahelyett hogy rendes adatbázis kezelőt vagy esetleg táblatípus használnának. A tranzakciók izolálása az adatbázis kezelő dolga, neked nem kell vele törődni.
- A hozzászóláshoz be kell jelentkezni
repeatable read és serializable izolációs szintnél ez nem történhet meg.
plz read carefully: http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html
All consistent reads within the same transaction read the snapshot established by the first read. This convention means that if you issue several plain (nonlocking) SELECT statements within the same transaction, these SELECT statements are consistent also with respect to each other.
Azért ez a neve, mert ha pl egy tranzakción belül többször is lekérdezed ugyanazt, ugyanazt az eredményt fogod kapni + te módosításaid. Ezért "ismételhető".
This level is like REPEATABLE READ, but InnoDB implicitly converts all plain SELECT statements to SELECT ... LOCK IN SHARE MODE if autocommit is disabled. If autocommit is enabled, the SELECT is its own transaction. It therefore is known to be read only and can be serialized if performed as a consistent (nonlocking) read and need not block for other transactions.
A sorosítható pedig úgy lockol implicite, hogy hatás szinten úgy nézzen ki, mintha a két, egymást hatásban átfedő (pl. uganazt a táblát használják), egymás után futottak volna le, nem párhuzamosan.
Tippem szerint téged a serializable izoláció tuti kisegít, viszont a DDL-ek tranzakciókra kifejtett hatásait nézd át alaposan.
- A hozzászóláshoz be kell jelentkezni
Megnézem, köszi.
- A hozzászóláshoz be kell jelentkezni
eredmény?
- A hozzászóláshoz be kell jelentkezni
Még nincs, de megírom majd.
- A hozzászóláshoz be kell jelentkezni
Most kezdtem el mélyebben nézegetni:
http://dev.mysql.com/doc/refman/5.5/en/innodb-transaction-model.html
Ha minden úgy megy ahogy gondolom, akkor kidobom az egész saját locking megoldásomat a francba, és csak transactions-szel oldom meg a lekéréseket. Még értelmezem a dolgot, hogy tudom átültetni a megoldásomba.
- A hozzászóláshoz be kell jelentkezni
külön figyelj arra, hogy mely DLD-ek csinálnak implicit commit-ot, nehogy meglepetések érjenek...
- A hozzászóláshoz be kell jelentkezni
Pont ezt nézegetem..
Kezd az lejönni, hogy a tranzakcióval valóban megoldódnak a locking kérdések, tehát eleve rossz irányba indultam. De azért nem is olyan egyszerű.
Annyi már látszik, hogy az 5.5-ban az InnoDB a default tábla, és akkor átállok erre. Itt ugye row locking-ot csinál automatikusan és ez is gyorsíthat akkor ha jól gondolom, mert ha olyan műveletet végzek, amely más sorokat nem érint, és ezekhez akar párhuzamosan másik user hozzáférni, akkor nem fogja várakoztatni őt.
Azt még nem látom át teljesen, hogy az bekavarhatna-e nekem, hogy a tranzakció idejére a tranzakció előtti állapotot látják a user-ek. Ez még nem világos, ezt végig kell gondolnom. Mert ugye habár íráshoz lock-olva lesznek és várakozásba kerülnek, az olvasáskor régi adatot kapnak - habár lehet már új van. Ezt még nem látom át hogy rossz-e nekem vagy sem.
- A hozzászóláshoz be kell jelentkezni
Ha egy sorból olvasol, azt nem fogja módosítani más tranzakció, ha olyannak adod meg.
Read lock lehet shared, tx-ek között, de egy write lock sorba fog állni, mert az exkluzív.
Amint valaki írna, az a tx vagy beáll és vár amíg minden readlock el nem tűnik, vagy a többi tranzakció a saját snapshotjával dolgozik tovább. Te döntésed.
- A hozzászóláshoz be kell jelentkezni
Úgy látom nem fog kelleni a "serializable" mód, hanem az 5.5-től default "repeatable read" mód is megfelelő lesz nekem, mert ha jól értem, itt is csinálja a locking-ot szépen automatikusan az InnoDB. És nem kell minden select-emhez "lock in share mode", csak az írásokhoz. Azt meg lock-olja amúgy is.
- A hozzászóláshoz be kell jelentkezni
A kettő mód között egyetlen egy apró különbség van:
A repeatable read csak annyit garantál, hogy egy SELECT által visszaadott sor nem változhat meg és nem tűnhet el alólad (a DELETE vagy UPDATE megvárja, hogy befejezd a tranzakciót), a serializable ezen felül azt is garantálja, hogy új sor nem "nőhet" be a SELECT alá (azaz minden olyen INSERT is várni fog, ami a select WHERE feltételeibe beleesne). A második verzió teljesítményben sokkal "drágább", mivel minden tranzakció minden SELECT-jét memóriában tárolni kell, és minden INSERT-nél az összes releváns SELECT WHERE feltételét kiértékelni. A repeatable read-hez elegendőek a SELECT által kiolvasott sorokra/mezőkre vonatkozóan lockokat tárolni.
- A hozzászóláshoz be kell jelentkezni
köszi szépen, ez már világosabbá teszi.
- A hozzászóláshoz be kell jelentkezni
igen.
a repeatable read a tx által megkezdett verziójú page-ről olvas végig.
a serializable lockolja is a sorokat, hogy a háttérben se változhasson meg. (ekkor a többi serializable vár, a repeatable read-ek meg a legutolsó kommitolt verziót fogják el maguknak, azaz azt, amit a sor elején említett tx is használ)
- A hozzászóláshoz be kell jelentkezni
Úgy látom mégis a "serializable" mód fog kelleni nekem. Ha jól értem, ez átkonvertál ugye minden select-et " SELECT ... LOCK IN SHARE MODE"-ra, így mindig várakozni fog a párhuzamos kérés, amíg a teljes tranzakciót be nem fejeztem.
- A hozzászóláshoz be kell jelentkezni
mondjuk, hogy hasonlóra.
- A hozzászóláshoz be kell jelentkezni
http://dev.mysql.com/doc/refman/5.5/en/metadata-locking.html
Ez egy remek dolog, hogy igy van, te pedig rosszul csinalod. Esetedben ennek ugy kene kineznie hogy db, kulso muvelet, db helyett kulso muvelet, ellenorzom a kodomban, hogy sikerult e a kulso muvelet, majd db. Tranzakciokat hosszu ideig nyitvatartani eleg koltseges dolog. Az, hogy alkalmazas csinal es eldob tablakat szinten rossz design, aminek MySQL 5.1-ben csunya mellekhatasai vannak. Egyreszt drop table-kor tortenik egy szinkron unlink(), masreszt ha InnoDB-t hasznalsz, akkor a MySQL vegig fogja scannelni a buffer poolt, hogy van a tablahoz tartozo page, es ha igen, akkor kidobja belole. Nagy buffer poolnal ez sokat szamit. Amit csinaltal sok usernel egyebkent sem mukodik, keves usernel meg tudod legalabb remelni, hogy ugysem lesz race condition:).
Percona server 5.5-ben levo innodb_lazy_drop_table nevu feature megoldja a fenti drop table problemat egyebkent.
- A hozzászóláshoz be kell jelentkezni
A lock-olt tábláknál relatíve kevés user fog versenyezni egymással - inkább sok tábla lesz - de mégis a lock-om lényege az a race condition-ből származó hibák elkerülése. Semmi más.
- A hozzászóláshoz be kell jelentkezni
Kérdés:
Miért kell lock-olnod egy táblát a táblalétrehozáshoz?
Más:
GET_LOCK és RELEASE_LOCK?
- A hozzászóláshoz be kell jelentkezni
Nem akarom lock-olni a létrehozandó táblát. Ha feljebb megnézed, az a probléma, hogy ha bármely más tábla lock alatt van, akkor nem lehet létrehozni táblát.
- A hozzászóláshoz be kell jelentkezni
get/release_lock nem táblazárolás, hanem globális lock engine (a string amit átadsz, az lesz a lock tokenje), ez benne a poén.
- A hozzászóláshoz be kell jelentkezni
Subscrible
- A hozzászóláshoz be kell jelentkezni
Megoldottam. Kidobtam az összes "lock tables ..." és "unlock tables" hivatkozásomat. A kódom legelejére betettem egy "begin"-t, a legutolsó kilépő exit részemhez meg egy "commit"-ot, azt annyi. Ha mindent jól gondolok, akkor a db majd gondoskodik a locking-ról. És így megoldottam, hogy MySQL 5.1-től 5.5>-ig is gond nélkül menni fog a cuccom.
Lépésenként végig gondolva a progimat elvileg akkor így mennie kell. Frissítem majd a bejegyzéseimet itt, most meg indul a tesztelés. Később talán majd dobok ide is infót arról, hogy mihez kellett.
Mindenkinek kösz a segítséget. Egy számomra új területen akartam gyorsan produkálni valamit, és ezek sokat segítettek.
- A hozzászóláshoz be kell jelentkezni
lépkedd azt is végig, hogy párhuzamosan meghívva a kódod, mi lesz.
- A hozzászóláshoz be kell jelentkezni
Persze, most megint az egészet újra kell tesztelnem minden szempontból, párhuzamos hozzáférésekkel is, sebesség stb.
- A hozzászóláshoz be kell jelentkezni