Szerző Téma: MySQL R39-2, avagy mi is az threaded query?  (Megtekintve 10083 alkalommal)

Nem elérhető KovaNovik

  • 1121
  • KovaNovik
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Dátum: 2014. június 28. - 13:19:59 »
+11 Show voters
BlueG MySQL R39-2 ~ Tudnivalók, haszna, kezelése
Üdv mindenkinek!
Mostanában nagyon sok embert látok kérdezõsködni mindenfelé afelõl, hogy igazából hogy is kell használni ezt a plugint. Milyen kóddal tölt be adatokat, milyen kóddal ment le, mit mivel kell csinálni, egyátalán hol tudjuk külsõleg módosítani. Ezek mind-mind olyan kérdések, melyeknek jó része nem ettõl a plugintól, sokkal inkább az SQL nyelvtõl függ, hogy abban mit hogy kell csinálni. Nyilván ezt csak azután tehetjük meg, miután megtettük a szükséges elõkészületeket.
Sokan azt mondják az R39 nehéz; pedig nem. Az R6-hoz képest nagyon szokatlan (és igen, rossz is) volt az R7, de az R33-tól sokat könnyítettek a mûködésen a készítõk, így bátran tudom ajánlani azoknak, akik már a fájlkezelésû mentéssel megszenvedtek, vagy már valamennyire tapasztaltak pawn scriptelés terén.
Elõkészületek
Egy MySQL plugint használó scripthez nem elég maga a plugin és az include fájl; kell még hozzá egy SQL szerver is, melynek elküldjük a queryket (lekéréseket), de errõl majd késõbb.
MySQL szervert a legkönnyebben az XAMPP nevû programmal tudsz beüzemelni.
Windowsra ezen a linken töltheted le ezt az igen hasznos kis programot. A csomag tartalmazza az Apache szervert, a MySQL szervert és még pár, számodra felesleges dolgot. Miután letöltötted, tulajdonképpen csak párszor megnyomjuk a tovább gombot, és már települ is. Viszonylag sok idõt (~5-10 percet) vesz igénybe a telepítés.
Amíg várakozol, elkezdheted letölteni a a mysql plugint. Errõl az oldalról a legfelsõ \"Latest release\" (azaz legújabb kiadás) címkével rendelkezõ csomagok közül a windows-os változatot kell, hogy letöltsd. Kattints a \"mysql-r39-2-win.zip\" feliratú gombra a letöltéshez. Szokás szerint a plugins mappa tartalmát a plugins, a pawno/include mappa tartalmát a pawno/include mappába kell, hogy tedd. A server.cfg fájlod plugins sorába a \"mysql\", a modod elejére (az a_samp include után természetesen) pedig a \"#include a_mysql\" szót kell, hogy illeszd.
Sokaknak problémát okoz az, hogy a szerverük az MSVCP_100.dll fájl hiányára hivatkozva leáll, amikor beteszik a mysql plugint és includeot. Igen. Ennek elkerülésére innen kell leszedned a \"Download\" gombra kattintva az x86-os, 64-bites operációs rendszer esetében az x64-es verziójú csomagot, melyet a tõle balra, vele egy sorban lévõ pipa bepipálásával, majd a next gombra kattintással tehetsz meg. Ha kéri, hogy szedd le valamelyik másik ámulatbaejtõ terméküket, tiszta szívvel küldd el a fenébe a \"No thanks, take me to the download\" gomb használatával. Ezt a csomagot rendszergazdaként kell futtatni, szokásos (next-next-next-next) technikával feltelepíteni, majd örülni.
Minden bizonnyal már feltelepült az XAMPP programcsomag. A telepítés végén hagyjuk bepipálva azt a mezõt, hogy indítsa el az XAMPP Control Panelt, majd a \"Finish\" gombra kattintva fejezzük be a telepítést. Ezután megnyílik az XAMPP control panel.
Itt az Apache és a MySQL melletti Start gombot kell megnyomni. Ha \"kizöldül\" a két felirat, jól csináltuk a dolgokat. A Skype fontos, hogy be legyen zárva, és semmi más ne is foglalja ezen portokat! Így kell, kinézzen:
[hs width=368 height=233]http://i.imgur.com/bsmN9ii.png[/hs]
Query-k készítése:
Aki már PHP-ban, vagy valahol csinált queryket, az ezt átugorhatja nyugodtan!
Általánosan 4 fõ fajtája van:
 
  • INSERT: a táblába egy új sort ilesztünk be, melyen bármely értéket tetszõlegesen megadhatjuk. Ha nem adjuk meg az alapérrtelmezett értéke lesz betéve, ami alapból 0, de a phpMyAdmin-ban ezt is módosíthatjuk.

  • SELECT: a táblából megadott kritériumok szerint kiválasztunk sorokat. Ezért szuper a mysql. Egy sorral kiválaszthatsz minden rendõrt, akinek infernusa van, a tankja több mint 3/4-edig van, legalább két kulcsa van és 6 millió forintja. Képzeld el ezt fájlkezelõvel kikeresni :D

  • UPDATE: a táblában egy már meglévõ sor tartalmát frissíti, persze a megadott kritériumok szerinti sorokban.

  • DELETE: megadott kritériumok szerinti sorokat töröl a táblából. Ha csak annyit írsz, hogy DELETE jatekosok, mindent töröl!


Kezdetek
A legelsõ lépés az, hogy létrehozzuk az adatbázist, benne a táblá(ka)t, azokban az oszlopokat, melyeknek az értékei megadhatóak soronként. SQL parancsokkal közvetlenül is tehetnénk ezt, de sokkal egyszerûbb és átláthatóbb grafikus felületen keresztül tenni mindezt.
Nem fontos, de ajánlott megadni az SQL szerverünknek egy jelszót. Ezt úgy tehetjük meg, hogy felmegyünk a 127.0.0.1 (localhost) oldalra, ez igazából csak nekünk látható, mert a gépünkön fut, de természetesen ha nyitva van a 80-as port, mások is elérhetik.Ki kell választani az angol (english) nyelvet, majd a baloldalt kiválasztandó security menüpontban a \"http://localhost/security/xamppsecurity.php\" linkre kattintva elõjövõ oldalon kettõször megadni a jelszavunkat, legyen ez most \"tesztjelszo\".
Ezután menjünk fel a 127.0.0.1/phpmyadmin webhelyre. Itt felül válaszd a magyar nyelvet, felhasználónévnek írjuk be, hogy root (ez az alap felhasználó), jelszónak pedig az általunk elõbb megadott jelszót: \"tesztjelszo\". Ezután egy ilyesmi kezelõfelület fog fogadni:
[hs width=639 height=411]http://i.imgur.com/q2MK7bh.png[/hs]
Kattintsunk az adatbázisok menüpontra, itt most létrehozzuk az adatbázist. Az \"adatbázis neve\" mezõbe írjunk be neki egy nevet (pl. teszt-adatb), majd kattintsunk a létrehozás gombra. Baloldalt megjelenik amint létrehozta, kattintsunk is rá. Rögtön fel is ajánlja nekünk, hogy készítsünk egy táblát. Ezt meg is tesszük. Tábla nevének írjunk be valami egyértelmû, de nem túl hosszú, ékezetmentes nevet, pl. jatekosok. Emellett meg kell adnunk, hány mezõre lesz szükségünk. Legyen egyelõre négy. Üssünk entert. Most meg kell adnunk a mezõket, tulajdonságaikat, speciális opcióikat.
Nézzük csak:
 
  • ID: ez a mysql-nél nagyon fontos. Erre egy egyszerû indoklás van; a megkülönböztetést. Egy hiba folytán elõfordulhat kettõ egyforma név, mindenféle hiba nélkül két egyforma pénzû, frakciójú, rangú, vagy bármilyen játékosok, DE egyforma ID-jû NEM LEHET, ugyanis kicsit jobbra tekerve bepipáljuk az A_I-t (Auto Increment, azaz automatikus növelés, vagy számláló rövidítése), amivel minden létrehozott játékosnál eggyel több lesz. Ha kitörlünk egyet, akkor is megy fel és fel. INT típusúnak nyugodtan meghagyhatjuk, hiszen ez egész szám.

  • Nev: amit pawnban stringnek, itt varcharnak hívjuk. Maximális hosszt itt is meg kell adni. Ez ugye a sampban 24, de én 25-öt szoktam megadni, hogy biztosan jó legyen.

  • Jelszo: Ezt titkosítva (SHA1-el) fogjuk tárolni, ezért bármekkora hosszú is lesz, az SHA1 titkosító 40 karaktereset generál. 40 karakter hosszú VARCHAR legyen.

  • Penz: Ez lesz az elsõ változó, ami ténylegesen csinál is valamit, nem csak azonosításra és védelemre szolgál. Ezen mutatom be majd, hogy kell betölteni. Ez természetesen maradhat INT, bár gondolom aki picit is foglalkozott samp scripteléssel, az ezt már tudja.

  • X, Y, és Z: ezek egyértelmûen float típusúak lesznek, itt fogjuk majd tárolni a kilépési koordinátáit a játékosainknak.

Késõbb ugyanitt, a teszt-adatb-n belül a jatekosok táblába navigálva módosíthatjuk a szerkesztés gombra kattintva a tábla szerkezetét. Vigyázz! A modban gyarkan el lesz rontva egy-egy query, így az exportálás menüben mindig csinálj róla visszaállítást, és ha baj van, az importálás menüben pár kattintással visszaállíthatod az eredeti állapotba!
Vágjunk is bele a pawnba!
A gamemode-unkba már a dolog elején includeoltuk (beszúrtuk) az a_mysql includeot, a server.cfg-be mysql plugint, és a megfelelõ mappákba a megfelelõ fájlokat.
Elsõ soron hozzuk létre a szükséges változókat. Nem sokra lesz szükségünk.
 
  • enum eJatekosInfo {Nev[25], Penz, Float:X, Float:Y, Float:Z}
    new JatekosInfo[MAX_PLAYERS][eJatekosInfo]; - A játékos adatait tároló tömb.

  • kapcs - ebben a mysql szerver-samp szerver kapcsolatát jelölõ ID-t fogjuk tárolni. Ez azért kell, mert egyszerre több kapcsolatunk is lehet, pl. ráköthetjük a fórumunkra, hogy az utolsó hozzászólást mutassa, stb. Mindegy, nekünk egyelõre csak egy lesz.

  • query[2000] - ez a query-t fogja tárolni stringként. A query egy szöveg, ami elmondja az sql szervernek, hogy mit csináljon.

  • enum {d_reg, d_belep} - Dialogok automatikus számozása.


Amikor a játékmód elindul, csatlakoznunk kell a mysql-szerverhez. A naplózást is bekapcsoljuk, hogy lássuk, sikeres volt-e a kapcsolódás, stb. Ezeket így tesszük meg:
 
public OnGameModeInit() {
mysql_log(LOG_ALL, LOG_TYPE_HTML); //Mindent naplózzon (igen, a sikeres dolgokat is), hogy lássunk mindent. A második paraméter azt jelzi, hogy HTML-be naplózzon; így szerintem jóval átláthatóbb.
kapcs = mysql_connect(\"127.0.0.1\", \"root\", \"teszt-adatb\", \"tesztjelszo\"); //A mysql_connect visszatérési értéke a kapcsolat id, ez pont kapóra jön nekünk, beletesszük a változóba.
if(mysql_errno(kapcs) != 0) printf(\"MySQL hiba! Hibakód: %d\", mysql_errno(kapcs)); //Amennyiben a hiba kód nem 0 (azaz van hiba), írassuk ki azt.
return 1;
}

 
Amikor a játékmód bezárul le kell csatlakoznunk a mysql-szerverrõl, ezt így tehetjük meg:
 
public OnGameModeExit() {
mysql_close(kapcs); //Lezárjuk a kapcsolatot, ez csak akkor történik meg, ha minden késleltetett (threaded) query végzett. Ha nem zárnánk le, a háttérben futna tovább a kapcsolat.
return 1;
}

 
Amikor egy játékos csatlakozik, meg kell néznünk regisztrált-e. Én még létrehozom az enumot, természetesen ezt behelyettesíthetitek a saját változóitokkal.
 
public OnPlayerConnect(playerid) {
TogglePlayerSpectating(playerid, true); //eltûntetjük a spawn gombot.
for(new a; eJatekosInfo:a < eJatekosInfo; a++) JatekosInfo[playerid][eJatekosInfo:a] = 0; //Nullázzuk az enumjait, nehogy baj legyen.
GetPlayerName(playerid, JatekosInfo[playerid][Nev], 25); //Lekérjük a nevét.
if(strfind(JatekosInfo[playerid][Nev], \"_\") == -1) //Nem tartalmaz alsóvonást; egyelõre nem csinálunk semmit ,de itt akár ki is rúghatjuk.
for(new a; a < strlen(JatekosInfo[playerid][Nev]); a++) if(JatekosInfo[playerid][Nev][a] == \'_\') JatekosInfo[playerid][Nev][a] = \' \';//Végigfutunk a nevén. Ha az egyik karaktere \'_\', kicseréli \' \'-re.
mysql_format(kapcs, query, 256, \"SELECT ID,Nev FROM jatekosok WHERE Nev=\'%e\' LIMIT 1\", JatekosInfo[playerid][Nev]);
//Azért kell formázni a queryt, hogy mindig az adott játékos nevét tegye bele. Azért kell mysql_format, mert itt van a %e specifier, ami a stringnek a mysql-kompatibilitis változatát teszi a stringbe.
//Ez itt jelen esetben tulajdonképpen felesleges, azonban ezt is meg kell mutatnom valahol; ilyen %e-t kell mindenhova, ahol a felhasználó által változtatható szöveget formázunk bele, pl. egy bugjelentés dialognál a beírt szöveg. Na ott kihasználhatná ezt, %e kéne, itt speciel felesleges. A limit 1 azért van ott, hogy ha 250 játékos közül a másodikban megtalálta õt, akkor ne nézze tovább, több után kutatva, mert mi nekünk csak egyre lesz szükségünk. De arra nagyon.
mysql_tquery(kapcs, query, \"RegEllenorzes\", \"d\", playerid); //A \"kapcs\" id-jû kapcsolatra elküldjük a fent megformázott queryt. megadjuk neki, hogy a query befejezése után a RegEllenorzes eljárásra ugorjon. A \"d\" az eljárás paramétereinek a formátuma (ugyanúgy adható meg mint a SetTimerEx-nél például), a playerid pedig, hogy kit ellenõriztünk.
return 1;
}

 
Ahol meghívjuk a query lefutása után az eljárásainkat, az alá szoktam tenni az eljárásokat, hogy rögtön mellette lássam. Íme a fent meghívott:
 
forward RegEllenorzes(playerid);
public RegEllenorzes(playerid) {
new sorok_szama = cache_get_row_count(); //A sorok_szama változóba lekérjük, hány sort talált. Mint fentebb is beszéltük, ha 0, nincs regelve, ha 1, igen.
if(sorok_szama == 0) ShowPlayerDialog(playerid, d_reg, DIALOG_STYLE_PASSWORD, \"Regisztráció\", \"{FFFFFF}Üdv a szerveren!\\nMég nem regisztráltál!\\nKérlek adj meg egy megjegyezhetõ és erõs jelszót!\", \"Regisztrál!\", \"Kilép!\");
else ShowPlayerDialog(playerid, d_belep, DIALOG_STYLE_PASSWORD, \"Bejelentkezés\", \"{FFFFFF}Üdv a szerveren!\\nMár regisztráltál!\\n\\nKérlek add meg a jelszavad, amivel regisztráltált!\", \"Regisztrál!\", \"Kilép!\");
return 1;
}

 
Amikor egy játékos kilép, el kell mentenünk az adatait, a következõképpen:
 
public OnPlayerDisconnect(playerid, reason) {
GetPlayerPos(playerid, JatekosInfo[playerid][X], JatekosInfo[playerid][Y], JatekosInfo[playerid][Z]);
mysql_format(kapcs, query, 384, \"UPDATE jatekosok SET Penz=\'%d\',X=\'%f\',Y=\'%f\',Z=\'%f\' WHERE Nev=\'%s\'\", JatekosInfo[playerid][Penz], JatekosInfo[playerid][X], JatekosInfo[playerid][Y], JatekosInfo[playerid][Z], JatekosInfo[playerid][Nev]);
mysql_tquery(kapcs, query);
return 1;
}

 
A threaded query (mysql_tquery) azért jó, mert elküldjük neki, várólistára helyezi, és futhat tovább a kód, nem akad be 6 másodpercre, mint a réginél például. Majd a háttérben lefut (lehet, hogy kicsivel késõbb), ezt nem tudhatjuk mikor, éppen emiatt meg kell adnunk egy eljárást, ami meghívódik, ha lefutott a query. Így biztosan kérhetünk le adatokat, annak veszélye nélkül, hogy 0-kat kapunk vissza, vagy valami más hiba fellép. És még gyorsabb is.
Pontosabban:
Egy jobb magyarázat a threaded queryre, hatalmas köszönet érte Anthony-nak:
 
Idézetet írta: Anthony date=1409221133\" data-ipsquote-contentapp=\"forums\" data-ipsquote-contenttype=\"forums\" data-ipsquote-contentid=\"49083\" data-ipsquote-contentclass=\"forums_Topic
Ezt a threaded query dolgot tegyük rendbe, mert azért ez kicsit érdekesen van leírva.
Elõször is a threadet magyarul \"szál\"nak szokás fordítani. Mi is egy szál? Gyakorlatilag tekinthetõ egy-egy önálló programnak. Azt azért a nagy többség tudja, hogy manapság a processzorok több szálon képesek programokat futtatni, ezt párhuzamos szálkezelésnek, vagy angolul multithreadingnek hívjuk. Egy processzor alapesetben annyi szálat tud kezelni, ahány processzormag található benne (ez így teljesen nem igaz már manapság, de most képzeljük azt hogy így van). Ha nekünk több szálon fut a programunk(/programjaink) mint ahány processzor magunk van, akkor a processzor idõ megoszlik a szálak között. Ezt általában az oprendszerek oldják meg, vagy fordításkor belekerül a programkódba. Na tehát mire is jó ez akkor konkrétan, ha külön szálakra helyezzük a programjaink bizonyos részét?
- programunk felgyorsítása, lassabb részek külön szálra helyezése, háttérben futtatása -> nem kell várnunk az eredményre, a \"fõ\" programunk tovább futhat (pl. bizonyos programrészletek háttérben való betöltése)
- bizonyos programrészek \"pihentetése\" (sleep, wait, vagy várakozás valamilyen eseményre)
A többszálú kezelés fõ elõnye tehát, hogy különbözõ háttérfolyamatokat indíthatunk, vagy a programunkat szétválaszthatjuk több egymástól független szálra, az elvégzendõ feladat tekintetében (pl. egy multi-client socket szerver esetén minden felhasználó számára saját threaded érdemes biztosítani, valamint egy threadet a bejövõ kapcsolatoknak, így mindenki \"programrészlete\" a többiekétõl függetlenül tud futni, nem kell egymásra várakozni). A különbözõ szálak, még ha az egyik végtelen ciklusba is futna, akkor sem fogják egymást akadályozni a végrehajtódásban (maximum a végrehajtás sebességét befolyásolja).
Esetünkben a threaded query értelme, hogy nem szükséges megvárnunk az eredményt. Pl. nagy szerverek esetén OnGameModeInit alatt meghívunk egy 2000 rakordot érintõ lekérdezést, és hagyjuk futni egy másik szálon, miközben a szerver a többi dolog betöltésével foglalatoskodik.
DE szó nincs semmiféle várólistáról. A szálak párhuzamosan hajtódnak végre, nem pedig egymás után, annak pont ugyanúgy semmi értelme nem lenne, mint az egyszálú programkezelésnek, hisz ugyanúgy egyetlen program lefoglalná a teljes CPU-t.
Valamint, ennek semmi köze ahhoz, hogy mivel tér vissza az SQL lekérésünk. Ettõl még kaphatunk vissza 0-t, vagy errort, a többszálúsításnak kizárólag a végrehajtódás sebességére, és a programrészek egymástól független futására van kihatása, de ezen kívül semmi másra. (Igazából nem is nagyon értem hogy itt mire értetted hogy nem kapunk 0-t eredményül)
 
Csakis akkor kell eljárást (3. paramétertõl) megadni, ha szeretnénk tudni a query ereményét. Pl. kiválasztottuk a játékost. Itt szeretnénk tudni, ugyanis kíváncsiak vagyunk, hogy van-e találat (ezesetben már regisztrálva van), vagy nincs (nincs ilyen sor, ahol a név az õ neve).
Pl. egy insert querynél nem igazán leszünk kíváncsiak az eredményre, viszont lehet, hogy pont a query lefutása   után szeretnénk lefuttatni egy másik kódot; ezesetben is kell majd az eljárás.
Egy UPDATE querynél is ugyanaz a helyzet mint az insertnél.
A DELETE-nél is. Ha meg szeretnénk tudni, hány sor törlõdött ((vagy akár a fenti kettõnél beszúródott, vagy frissült), ld. cache_affected_rows()), akkor adjunk meg eljárást; egyébként minek?
Kezdõdjenek az eljárások és a dialogresponse rész:
 
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) {
switch(dialogid) {
case d_reg: {
   if(!response) return Kick(playerid);
   if(strlen(inputtext) < 5 || strlen(inputtext) > 32) return ShowPlayerDialog(playerid, d_reg, DIALOG_STYLE_PASSWORD, \"Regisztráció\", \"{FFFFFF}Üdv a szerveren!\\nMég nem regisztráltál!\\nKérlek adj meg egy megjegyezhetõ és erõs jelszót!\\n\\n{FF0000}Jelszavadnak 5-32 karakter között kell lennie!\", \"Regisztrál!\", \"Kilép!\");
   mysql_format(kapcs, query, 256, \"INSERT INTO jatekosok (Nev,Jelszo,Penz,X,Y,Z) VALUES (\'%e\',SHA1(\'%e\'),\'185000\',-1980.6168,141.2433,27.6875)\", JatekosInfo[playerid][Nev], inputtext);
   mysql_tquery(kapcs, query, \"JatekosBeregelt\", \"d\", playerid);
}
case d_belep: {
   if(!response) return Kick(playerid);
   if(strlen(inputtext) < 5 || strlen(inputtext) > 32) return ShowPlayerDialog(playerid, d_belep, DIALOG_STYLE_PASSWORD, \"Bejelentkezés\", \"{FFFFFF}Üdv a szerveren!\\nMár regisztráltál!\\nKérlek add meg a jelszavad, amivel regisztráltáltál!\\n\\n{FF0000}Jelszavadnak 5-32 karakter között kell lennie!\", \"Regisztrál!\", \"Kilép!\");
   mysql_format(kapcs, query, 256, \"SELECT * FROM jatekosok WHERE Nev=\'%e\' AND Jelszo=SHA1(\'%e\')\", JatekosInfo[playerid][Nev], inputtext);
   mysql_tquery(kapcs, query, \"JatekosBelep\", \"d\", playerid);
   //Jatekosunk megpróbált belépni \'inputtext\' jelszóval. Kiválasztottuk a sorokat, ahol a név a játékos neve, a jelszó a beírt szöveg titkosított változata. Folytatás a callbackben.
}
}
return 0;
}
forward JatekosBeregelt(playerid);
public JatekosBeregelt(playerid) {
SendClientMessage(playerid, 0xFFFFFFFF, \"Sikeresen regisztráltál!\");
SetSpawnInfo(playerid, 0, 7, -1980.6168, 141.2433, 27.6875, 90.0, 0, 0, 0, 0, 0, 0); //Beállítjuk a spawn pozíciót, skint egyebeket.
TogglePlayerSpectating(playerid, false); //Elõhozzuk a spawn gombot, hogy így le tudja spawnolni a szerver.
SpawnPlayer(playerid); //Lespawnoljuk.
JatekosInfo[playerid][Penz] = 185000;
SendClientMessage(playerid, 0xFFFFFFFF, \"Jó játékot kívánok!\");
return 1;
}
forward JatekosBelep(playerid);
public JatekosBelep(playerid) {
new sorok_szama = cache_get_row_count(); //A sorok_szama változóba lekérjük, hány sort talált. Ha 0, nem jó a jelszó, ha 1 igen, mert van olyan (1) sor, amelynél ez a név és a jelszó is.
if(sorok_szama == 0) return ShowPlayerDialog(playerid, d_belep, DIALOG_STYLE_PASSWORD, \"Bejelentkezés\", \"{FFFFFF}Üdv a szerveren!\\nJatekosInfo regisztráltál!Kérlek add meg a jelszavad, amivel regisztráltált!\\n\\n{FF0000}Hibás jelszó!\", \"Regisztrál!\", \"Kilép!\");
//Az elõbb, ha hibás volt a jelszó visszatértünk volna, szóval innenztõl ami lefut kód, az már jó jelszóval fut le:
SendClientMessage(playerid, 0xFFFFFFFF, \"Sikeresen bejelentkeztél!\");
SetSpawnInfo(playerid, 0, 7, cache_get_field_content_float(0, \"X\"), cache_get_field_content_float(0, \"Y\"), cache_get_field_content_float(0, \"Z\"), 90.0, 0, 0, 0, 0, 0, 0); //Beállítjuk a spawn pozíciót, skint egyebeket.
TogglePlayerSpectating(playerid, false); //Elõhozzuk a spawn gombot, hogy így le tudja spawnolni a szerver.
SpawnPlayer(playerid); //Lespawnoljuk.
JatekosInfo[playerid][Penz] = cache_get_field_content_int(0, \"Penz\"); //A 0. sorból (a legelsõ, mivel csak 1 találat van, a játékos, akit kerestünk) a pénz oszlop tartalmát integerként (egész számként) lekérjük, és beletesszük a JatekosInfo[playerid][Penz] változóba.
new string[128]; format(string, sizeof(string), \"Pénzed: %dFt.\", JatekosInfo[playerid][Penz]);
SendClientMessage(playerid, 0xFFFFFFFF, \"Üdv újra itt!\");
return 1;
}

 
Változókat (természetesen csakis select query után) így kérhetsz le a kapott sorokból:
- Sor- és oszlopszám szerint:
Ezek akkor lehetnek hasznosak, ha egy ciklussal végig akarunk futni egy játékos minden oszlopán, és pl. kiíratni azokat.
 
cache_get_row(0, 1, string); //1. sor 2. oszlopának lekérése (0-tól indul a számozás ugye), a string nevû karakterláncba.
JatekosInfo[playerid][Penz] = cache_get_row_int(0, 3); //1. sor 4. oszlopának lekérése (pénz) lekérése. Ennek a visszatérési értéke maga a kapott érték, szóval elé kell írni, mely változóba akarjuk tenni.
JatekosInfo[playerid][Elet] = cache_get_row_float(0, 3); //1. sor 4. oszlopának lekérése floatként, a játékos élet változójába.


Például:
 
new string[128], oszlopnev[64], tartalom[64];
for(new i = 0; i < cache_get_field_count(); i++) {//Addig növeljük az i-t, amíg el nem éri az oszlopok számát, azaz végigfutunk minden oszlopon.
cache_get_field_name(i, oszlopnev);
cache_get_row(0, i, tartalom);
format(string, sizeof(string), \"%s: %s\", oszlopnev, tartalom);
SendClientMessage(playerid, 0xFFFFFFFF, string);
}

 
A fenti példa, akárhány oszlopod is van, kiíratja mindet.
- Sorszám és oszlopnév alapján:
 
cache_get_field_content
cache_get_field_content_int
cache_get_field_content_float

 
Ezek ugyanúgy mûködnek, mint a fentebb lévõ három, annyi különbséggel, hogy itt oszlopszám helyett a nevét kell megadni. Ez jobb, ha nem ciklusban használjuk, és nem szeretnénk, hogy elcsússzon az egész egy oszlop beillesztése miatt, hiszen a név nem változik olyankor, csak a sorszám.
Tehát az SQL tábla így néz ki:
 
CREATE TABLE IF NOT EXISTS `jatekosok` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Nev` varchar(25) NOT NULL,
  `Jelszo` varchar(40) NOT NULL,
  `Penz` int(11) NOT NULL,
  `X` float NOT NULL,
  `Y` float NOT NULL,
  `Z` float NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

 
A script egészben:
 
#include a_samp
#include a_mysql
main(){}
enum eJatekosInfo {Nev[25], Penz, Float:X, Float:Y, Float:Z}
new JatekosInfo[MAX_PLAYERS][eJatekosInfo];
new kapcs, query[2000];
enum {d_reg, d_belep} //Dialogok automatikus számozása.
public OnGameModeInit() {
mysql_log(LOG_ALL, LOG_TYPE_HTML); //Mindent naplózzon (igen, a sikeres dolgokat is), hogy lássunk mindent. A második paraméter azt jelzi, hogy HTML-be naplózzon; így szerintem jóval átláthatóbb.
kapcs = mysql_connect(\"127.0.0.1\", \"root\", \"teszt-adatb\", \"tesztjelszo\"); //A mysql_connect visszatérési értéke a kapcsolat id, ez pont kapóra jön nekünk, beletesszük a változóba.
if(mysql_errno(kapcs) != 0) printf(\"MySQL hiba! Hibakód: %d\", mysql_errno(kapcs)); //Amennyiben a hiba kód nem 0 (azaz van hiba), írassuk ki azt.
return 1;
}
public OnGameModeExit() {
mysql_close(kapcs); //Lezárjuk a kapcsolatot, ez csak akkor történik meg, ha minden késleltetett (threaded) query végzett.HTTP Ha nem zárnánk le, a háttérben futna tovább a kapcsolat.
return 1;
}
public OnPlayerConnect(playerid) {
TogglePlayerSpectating(playerid, true); //eltûntetjük a spawn gombot.
for(new a; eJatekosInfo:a < eJatekosInfo; a++) JatekosInfo[playerid][eJatekosInfo:a] = 0; //Nullázzuk az enumjait, nehogy baj legyen.
GetPlayerName(playerid, JatekosInfo[playerid][Nev], 25); //Lekérjük a nevét.
if(strfind(JatekosInfo[playerid][Nev], \"_\") == -1) //Nem tartalmaz alsóvonást; egyelõre nem csinálunk semmit ,de itt akár ki is rúghatjuk.
for(new a; a < strlen(JatekosInfo[playerid][Nev]); a++) if(JatekosInfo[playerid][Nev][a] == \'_\') JatekosInfo[playerid][Nev][a] = \' \';//Végigfutunk a nevén. Ha az egyik karaktere \'_\', kicseréli \' \'-re.
mysql_format(kapcs, query, 256, \"SELECT ID,Nev FROM jatekosok WHERE Nev=\'%e\' LIMIT 1\", JatekosInfo[playerid][Nev]);
//Azért kell formázni a queryt, hogy mindig az adott játékos nevét tegye bele. Azért kell mysql_format, mert itt van a %e specifier, ami a stringnek a mysql-kompatibilitis változatát teszi a stringbe.
//Ez itt jelen esetben tulajdonképpen felesleges, azonban ezt is meg kell mutatnom valahol; ilyen %e-t kell mindenhova, ahol a felhasználó által változtatható szöveget formázunk bele, pl. egy bugjelentés dialognál a beírt szöveg. Na ott kihasználhatná ezt, %e kéne, itt speciel felesleges. A limit 1 azért van ott, hogy ha 250 játékos közül a másodikban megtalálta õt, akkor ne nézze tovább, több után kutatva, mert mi nekünk csak egyre lesz szükségünk. De arra nagyon.
mysql_tquery(kapcs, query, \"RegEllenorzes\", \"d\", playerid); //A \"kapcs\" id-jû kapcsolatra elküldjük a fent megformázott queryt. megadjuk neki, hogy a query befejezése után a RegEllenorzes eljárásra ugorjon. A \"d\" az eljárás paramétereinek a formátuma (ugyanúgy adható meg mint a SetTimerEx-nél például), a playerid pedig, hogy kit ellenõriztünk.
return 1;
}
forward RegEllenorzes(playerid);
public RegEllenorzes(playerid) {
new sorok_szama = cache_get_row_count(); //A sorok_szama változóba lekérjük, hány sort talált. Mint fentebb is beszéltük, ha 0, nincs regelve, ha 1, igen.
if(sorok_szama == 0) ShowPlayerDialog(playerid, d_reg, DIALOG_STYLE_PASSWORD, \"Regisztráció\", \"{FFFFFF}Üdv a szerveren!\\nMég nem regisztráltál!\\nKérlek adj meg egy megjegyezhetõ és erõs jelszót!\", \"Regisztrál!\", \"Kilép!\");
else ShowPlayerDialog(playerid, d_belep, DIALOG_STYLE_PASSWORD, \"Bejelentkezés\", \"{FFFFFF}Üdv a szerveren!\\nMár regisztráltál!\\n\\nKérlek add meg a jelszavad, amivel regisztráltált!\", \"Regisztrál!\", \"Kilép!\");
return 1;
}
public OnPlayerDisconnect(playerid, reason) {
GetPlayerPos(playerid, JatekosInfo[playerid][X], JatekosInfo[playerid][Y], JatekosInfo[playerid][Z]);
mysql_format(kapcs, query, 384, \"UPDATE jatekosok SET Penz=\'%d\',X=\'%f\',Y=\'%f\',Z=\'%f\' WHERE Nev=\'%s\'\", JatekosInfo[playerid][Penz], JatekosInfo[playerid][X], JatekosInfo[playerid][Y], JatekosInfo[playerid][Z], JatekosInfo[playerid][Nev]);
mysql_tquery(kapcs, query);
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) {
switch(dialogid) {
case d_reg: {
   if(!response) return Kick(playerid);
   if(strlen(inputtext) < 5 || strlen(inputtext) > 32) return ShowPlayerDialog(playerid, d_reg, DIALOG_STYLE_PASSWORD, \"Regisztráció\", \"{FFFFFF}Üdv a szerveren!\\nMég nem regisztráltál!\\nKérlek adj meg egy megjegyezhetõ és erõs jelszót!\\n\\n{FF0000}Jelszavadnak 5-32 karakter között kell lennie!\", \"Regisztrál!\", \"Kilép!\");
   mysql_format(kapcs, query, 256, \"INSERT INTO jatekosok (Nev,Jelszo,Penz,X,Y,Z) VALUES (\'%e\',SHA1(\'%e\'),\'185000\',-1980.6168,141.2433,27.6875)\", JatekosInfo[playerid][Nev], inputtext);
   mysql_tquery(kapcs, query, \"JatekosBeregelt\", \"d\", playerid);
}
case d_belep: {
   if(!response) return Kick(playerid);
   if(strlen(inputtext) < 5 || strlen(inputtext) > 32) return ShowPlayerDialog(playerid, d_belep, DIALOG_STYLE_PASSWORD, \"Bejelentkezés\", \"{FFFFFF}Üdv a szerveren!\\nMár regisztráltál!\\nKérlek add meg a jelszavad, amivel regisztráltáltál!\\n\\n{FF0000}Jelszavadnak 5-32 karakter között kell lennie!\", \"Regisztrál!\", \"Kilép!\");
   mysql_format(kapcs, query, 256, \"SELECT * FROM jatekosok WHERE Nev=\'%e\' AND Jelszo=SHA1(\'%e\')\", JatekosInfo[playerid][Nev], inputtext);
   mysql_tquery(kapcs, query, \"JatekosBelep\", \"d\", playerid);
   //Jatekosunk megpróbált belépni \'inputtext\' jelszóval. Kiválasztottuk a sorokat, ahol a név a játékos neve, a jelszó a beírt szöveg titkosított változata. Folytatás a callbackben.
}
}
return 0;
}
forward JatekosBeregelt(playerid);
public JatekosBeregelt(playerid) {
SendClientMessage(playerid, 0xFFFFFFFF, \"Sikeresen regisztráltál!\");
SetSpawnInfo(playerid, 0, 7, -1980.6168, 141.2433, 27.6875, 90.0, 0, 0, 0, 0, 0, 0); //Beállítjuk a spawn pozíciót, skint egyebeket.
TogglePlayerSpectating(playerid, false); //Elõhozzuk a spawn gombot, hogy így le tudja spawnolni a szerver.
SpawnPlayer(playerid); //Lespawnoljuk.
JatekosInfo[playerid][Penz] = 185000;
SendClientMessage(playerid, 0xFFFFFFFF, \"Jó játékot kívánok!\");
return 1;
}
forward JatekosBelep(playerid);
public JatekosBelep(playerid) {
new sorok_szama = cache_get_row_count(); //A sorok_szama változóba lekérjük, hány sort talált. Ha 0, nem jó a jelszó, ha 1 igen, mert van olyan (1) sor, amelynél ez a név és a jelszó is.
if(sorok_szama == 0) return ShowPlayerDialog(playerid, d_belep, DIALOG_STYLE_PASSWORD, \"Bejelentkezés\", \"{FFFFFF}Üdv a szerveren!\\nJatekosInfo regisztráltál!Kérlek add meg a jelszavad, amivel regisztráltált!\\n\\n{FF0000}Hibás jelszó!\", \"Regisztrál!\", \"Kilép!\");
//Az elõbb, ha hibás volt a jelszó visszatértünk volna, szóval innenztõl ami lefut kód, az már jó jelszóval fut le:
SendClientMessage(playerid, 0xFFFFFFFF, \"Sikeresen bejelentkeztél!\");
SetSpawnInfo(playerid, 0, 7, cache_get_field_content_float(0, \"X\"), cache_get_field_content_float(0, \"Y\"), cache_get_field_content_float(0, \"Z\"), 90.0, 0, 0, 0, 0, 0, 0); //Beállítjuk a spawn pozíciót, skint egyebeket.
TogglePlayerSpectating(playerid, false); //Elõhozzuk a spawn gombot, hogy így le tudja spawnolni a szerver.
SpawnPlayer(playerid); //Lespawnoljuk.
JatekosInfo[playerid][Penz] = cache_get_field_content_int(0, \"Penz\"); //A 0. sorból (a legelsõ, mivel csak 1 találat van, a játékos, akit kerestünk) a pénz oszlop tartalmát integerként (egész számként) lekérjük, és beletesszük a JatekosInfo[playerid][Penz] változóba.
new string[128]; format(string, sizeof(string), \"Pénzed: %dFt.\", JatekosInfo[playerid][Penz]);
SendClientMessage(playerid, 0xFFFFFFFF, \"Üdv újra itt!\");
return 1;
}

 
A script ingame:
[videó]
Nos ennyi lenne, a fõbb részeket bemutattam a pawn-os részérõl, kicsit bele is mentünk az SQL nyelvezetébe, habár fõként nem ez akart lenni a célja a tutorialnak.
Ha van valami kérdésetek (vagy hiba a kódban, ez simán lehetséges), nyugodtan írjátok le, viszont miután megtanultátok, hogy kell használni a pawn scriptben a plugin segítségével az SQL nyelvet, onnantól csak arra lesz szükségetek.
Pl. nem tudom, hogy kell insert queryt csinálni.
Google: mysql insert query examples.
Elsõ találat elsõ bekezdésében:
 

INSERT INTO table_name (column1, column2, column3,...)
VALUES (value1, value2, value3,...)

 
[/quote]
Megjegyzés: a modban sokkal jobb, hogyha mondjuk egy Whirlpool pluginnal generálod a jelszó hash-t, és azt illeszted be a querybe. Hostolt szervereken különösen nem érdemes a querybe illeszteni a jelszót magát, mert így az SQL logból bárki kilophatja!
Köszönöm, hogy elolvastátok az útmutatómat, mindenkinek sok szerencsét, és további jó scriptelést! :thumbsup:
« Utoljára szerkesztve: 2015. január 04. - 17:17:28 írta kzyn »

Nem elérhető Flash

  • 5726
  • (っ◕‿◕)っ
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #1 Dátum: 2014. június 28. - 13:51:29 »
0 Show voters
Nem olvastam végig csak szúrta a szemem ez az egy hiba:
 

`Z` int(11) NOT NULL,

 
[/quote]
>>
 
`Z` float NOT NULL,

 


Szép leírás hozzád képest :)

Nem elérhető Pedró

  • 3341
  • 2014 © Az év Szkriptere
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #2 Dátum: 2014. június 28. - 13:54:20 »
0 Show voters
Idézetet írta: Flash date=1403956289\" data-ipsquote-contentapp=\"forums\" data-ipsquote-contenttype=\"forums\" data-ipsquote-contentid=\"49083\" data-ipsquote-contentclass=\"forums_Topic
Szép leírás hozzád képest :)
Miért pont hozzá képest? Ezt kár volt hozzátenni.
Szép leírás, és kész.

Nem elérhető KovaNovik

  • 1121
  • KovaNovik
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #3 Dátum: 2014. június 28. - 13:54:59 »
0 Show voters
Idézetet írta: Flash date=1403956289\" data-ipsquote-contentapp=\"forums\" data-ipsquote-contenttype=\"forums\" data-ipsquote-contentid=\"49083\" data-ipsquote-contentclass=\"forums_Topic
Nem olvastam végig csak szúrta a szemem ez az egy hiba:
 

`Z` int(11) NOT NULL,

 
>>
 
`Z` float NOT NULL,

 

[/quote]
Köszi, hogy szóltál, javítom. Igazából a táblában floatként van, meg annak is magyaráztam, nem tudom oda hogy került az.
 

 
Szép leírás hozzád képest :)
[/quote]
Miért pont hozzá képest? Ezt kár volt hozzátenni.
Szép leírás, és kész.
 
[/quote]
Köszi! :)
« Utoljára szerkesztve: 2014. június 28. - 13:59:28 írta KovaNovik »

Nem elérhető Flash

  • 5726
  • (っ◕‿◕)っ
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #4 Dátum: 2014. június 28. - 14:02:57 »
0 Show voters
Idézetet írta: Pedró date=1403956460\" data-ipsquote-contentapp=\"forums\" data-ipsquote-contenttype=\"forums\" data-ipsquote-contentid=\"49083\" data-ipsquote-contentclass=\"forums_Topic
Miért pont hozzá képest? Ezt kár volt hozzátenni.
 
Mert 13 éves. És te tudtál magadtól ennyit 13 évesen?
Ebben a korban még csak most kezdenek el hallani a mysql-ról, õ meg már egy összetett leírást készített róla!

Nem elérhető KovaNovik

  • 1121
  • KovaNovik
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #5 Dátum: 2014. június 28. - 14:05:18 »
0 Show voters
Idézetet írta: Flash date=1403956977\" data-ipsquote-contentapp=\"forums\" data-ipsquote-contenttype=\"forums\" data-ipsquote-contentid=\"49083\" data-ipsquote-contentclass=\"forums_Topic
magadtól
 
Wiki --> google fordító --> én (értelmetlen mondatok javítása) --> notepad --> sampforum.
Ja meg még pár magyar nyelvû sql tutorial, de azt csak olvasni kell.
Ennek csak az 1/5-öde történt \"magamtól\" :D
Szerintem pedig térjünk vissza a témára.
« Utoljára szerkesztve: 2014. június 28. - 18:44:48 írta KovaNovik »

Nem elérhető BackUP

  • 908
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #6 Dátum: 2014. június 28. - 16:43:20 »
0 Show voters
Nagyon jó leírás, el leszek vele egy darabig :D

Dupla hozzászólás automatikusan összefûzve. ( 2014. június 28. - 19:00:04 )

Regisztrálásnál van ez a mysql_formatban:
 
VALUES (\'%e\',SHA1(\'%e\')

 
nincs kihagyva egy lezárás? (\')\')
Elnéztem, nincs  :D

Dupla hozzászólás automatikusan összefûzve. ( 2014. június 28. - 19:29:28 )

Nekem akadt egy kisebb problémám:
 

mysql_format(kapcs,query, sizeof(query),\"SELECT ID,nev FROM \'jatekosok\' WHERE nev = \'%e\' LIMIT 1\",PlayerInfo[playerid][pNev]);
mysql_tquery(kapcs,query, \"RegAllapot\", \"d\", playerid);

 
Ennél amikor csatlakozok a log ezt írja:
[hs width=500 height=400]http://kepfeltoltes.hu/140628/sqlerror_www.kepfeltoltes.hu_.png[/hs]
Mostmár tényleg jobban odafigyelek, megoldva! :D
« Utoljára szerkesztve: 2014. június 28. - 19:36:59 írta BackUP »

Nem elérhető ZyZu.

  • Globális moderátor
  • 8939
  • my turbo diesel forum
  • Discord: ZyZu.
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #7 Dátum: 2014. június 29. - 06:44:52 »
0 Show voters
Tetszik nagyon a leírás! Kevés ember van a fórumon aki ezt megírja mivel sok függvény és szöveg van hozzá.. :D Idõvel kiemelem csak látom, hogy még szerkesztés alatt van így várok még vele. :) Le a kalappal, szép leírás!  ;)

Nem elérhető KovaNovik

  • 1121
  • KovaNovik
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #8 Dátum: 2014. június 29. - 09:45:27 »
0 Show voters
Köszi! Önmagában igazából már mûködõképes ez a mod, csak még nincs teljesen minden fajta query bemutatva benne. Majd csinálok még hozzá 1-2 példát, pl. Offline játékosokat is kifizetõ rendszer, barátkozási rendszer, stb.

Nem elérhető Blowy

  • 194
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #9 Dátum: 2014. július 11. - 21:56:44 »
0 Show voters
Köszönöm, sokat segített a leírás.
« Utoljára szerkesztve: 2014. július 11. - 22:32:52 írta Blowy »

Nem elérhető Loren

  • 1401
  • Ex Moderátor
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #10 Dátum: 2014. július 12. - 10:55:18 »
0 Show voters
[mod]Téma kiemelve! Szép leírás![/mod]

Nem elérhető tonyo

  • 1335
  • Moderális Generátor
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #11 Dátum: 2014. augusztus 28. - 12:18:53 »
+2 Show voters
Ezt a threaded query dolgot tegyük rendbe, mert azért ez kicsit érdekesen van leírva.
Elõször is a threadet magyarul \"szál\"nak szokás fordítani. Mi is egy szál? Gyakorlatilag tekinthetõ egy-egy önálló programnak. Azt azért a nagy többség tudja, hogy manapság a processzorok több szálon képesek programokat futtatni, ezt párhuzamos szálkezelésnek, vagy angolul multithreadingnek hívjuk. Egy processzor alapesetben annyi szálat tud kezelni, ahány processzormag található benne (ez így teljesen nem igaz már manapság, de most képzeljük azt hogy így van). Ha nekünk több szálon fut a programunk(/programjaink) mint ahány processzor magunk van, akkor a processzor idõ megoszlik a szálak között. Ezt általában az oprendszerek oldják meg, vagy fordításkor belekerül a programkódba. Na tehát mire is jó ez akkor konkrétan, ha külön szálakra helyezzük a programjaink bizonyos részét?
- programunk felgyorsítása, lassabb részek külön szálra helyezése, háttérben futtatása -> nem kell várnunk az eredményre, a \"fõ\" programunk tovább futhat (pl. bizonyos programrészletek háttérben való betöltése)
- bizonyos programrészek \"pihentetése\" (sleep, wait, vagy várakozás valamilyen eseményre)
A többszálú kezelés fõ elõnye tehát, hogy különbözõ háttérfolyamatokat indíthatunk, vagy a programunkat szétválaszthatjuk több egymástól független szálra, az elvégzendõ feladat tekintetében (pl. egy multi-client socket szerver esetén minden felhasználó számára saját threaded érdemes biztosítani, valamint egy threadet a bejövõ kapcsolatoknak, így mindenki \"programrészlete\" a többiekétõl függetlenül tud futni, nem kell egymásra várakozni). A különbözõ szálak, még ha az egyik végtelen ciklusba is futna, akkor sem fogják egymást akadályozni a végrehajtódásban (maximum a végrehajtás sebességét befolyásolja).
Esetünkben a threaded query értelme, hogy nem szükséges megvárnunk az eredményt. Pl. nagy szerverek esetén OnGameModeInit alatt meghívunk egy 2000 rakordot érintõ lekérdezést, és hagyjuk futni egy másik szálon, miközben a szerver a többi dolog betöltésével foglalatoskodik.
DE szó nincs semmiféle várólistáról. A szálak párhuzamosan hajtódnak végre, nem pedig egymás után, annak pont ugyanúgy semmi értelme nem lenne, mint az egyszálú programkezelésnek, hisz ugyanúgy egyetlen program lefoglalná a teljes CPU-t.
Valamint, ennek semmi köze ahhoz, hogy mivel tér vissza az SQL lekérésünk. Ettõl még kaphatunk vissza 0-t, vagy errort, a többszálúsításnak kizárólag a végrehajtódás sebességére, és a programrészek egymástól független futására van kihatása, de ezen kívül semmi másra. (Igazából nem is nagyon értem hogy itt mire értetted hogy nem kapunk 0-t eredményül)

Nem elérhető kurta999

  • 2759
  • Éllő fédisznó
    • Profil megtekintése
MySQL R39-2, avagy mi is az threaded query?
« Válasz #12 Dátum: 2014. szeptember 04. - 21:32:21 »
0 Show voters
Na ilyen szépen még senki nem fogalmazta meg a magyar fórumon, hogy mit jelent a threaded query pontosan. Grat.

MySQL R39-2, avagy mi is az threaded query?
« Válasz #13 Dátum: 2014. december 26. - 20:02:02 »
0 Show voters
Szép leírás, énis most tanulgatom, igaz, már a mode-om dini-vel írtam, de valahogy csak átállok.  :confused:

MySQL R39-2, avagy mi is az threaded query?
« Válasz #14 Dátum: 2015. január 10. - 12:04:00 »
0 Show voters
Egy aprócska ám de annál gonoszabb hiba. Szóval a játékos csatlakozásnál lenullázol mindent. A d_belep dialognál ez után ha a játékos a \'Kilép!\' gombra kattint a szerver kidobja, meghívódik az OnPlayerDisconnect callback, az adatbázisba pedig a lenullázott értékek kerülnek (pl. a pénz), kivétel a koordináták, mivel azok a kilépésnél le vannak kérdezve, így oda a 0-tól különböző értékek kerülnek.
Amúgy nagyon szép leírás, sokat tanultam belőle.

 

SimplePortal 2.3.7 © 2008-2024, SimplePortal