MySQL 5.0

Školení, která pořádám

V pondělí 24.10.2005 vyšla dlouho připravovaná verze MySQL 5.0, která přináší z mého pohledu tyto hlavní novinky:

Správce tohoto serveru MySQL 5.0 promptně nainstaloval, ale protože předchozí verze byla MySQL 4.0, narazil zpočátku na problém s převodem kódování, který se naštěstí podařilo vyřešit.

Podotýkám, že již v MySQL 4.1 došlo k významným změnám:

Transakce a cizí klíče jsou už dlouhou dobu doménou tabulek typu InnoDB a před příchodem verze 5.1 se na tom nic nezmění.

Osobně se chystám na tomto webu využít triggery (na aktualizaci data modifikace článku při změně v diskusních příspěvcích), pohledy (pro jednotnou práci s články, které už byly vydány), kódování (v podstatě nelze ignorovat) a podporu časových pásem (časové pásmo serveru je GMT a převod času na CET nyní probíhá v PHP, ale lepší bude, když ho správně bude vracet přímo databáze). Uložené procedury do aplikace vnášejí další vrstvu, která se hodí především v případě, kdy z různých prostředí chceme s databází pracovat jednotně nebo kdy chceme změny v databázi např. kvůli zabezpečení provádět pouze přes uložené procedury a nikoliv přímo. Další vrstvu do aplikace konec konců přinášejí i triggery a dělají z databáze něco víc než jednoduché úložiště dat. Spoustu akcí mohou výrazně zjednodušit, ale pokud na jejich přítomnost zapomeneme, může se hledání chyby stát noční můrou. Výjimečně využiji i poddotazy, protože ve většině případů je lepší použít spojování tabulek.

Triggery

<?php
// starý kód
mysql_query("INSERT INTO diskuse (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")");
mysql_query("UPDATE clanky SET zmeneno = $set[vytvoreno] WHERE id = $set[clanek]");

// nový kód po CREATE TRIGGER diskuse_insert_after AFTER INSERT ON diskuse FOR EACH ROW UPDATE clanky SET zmeneno = NOW() WHERE id = NEW.clanek
mysql_query("INSERT INTO diskuse (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")");
?>

Pohledy

<?php
// starý kód - na mnoha místech
mysql_query("SELECT * FROM clanky WHERE publikovano <= NOW()");

// nový kód po CREATE VIEW clanky_vydane AS SELECT * FROM clanky WHERE publikovano <= NOW()
mysql_query("SELECT * FROM clanky_vydane");
?>

Je dobré mít na paměti, že CREATE VIEW … AS SELECT * pracuje s aktuálními sloupci tabulky a po přidání sloupce do tabulky se do pohledu nedoplní.

Časová pásma

<?php
// starý kód
putenv("TZ=CET");
$row = mysql_fetch_row(mysql_query("SELECT UNIX_TIMESTAMP(publikovano) FROM clanky"));
echo date("j.n.Y", $row[0]);

// nový kód
mysql_query("SET time_zone = CET");
$row = mysql_fetch_row(mysql_query("SELECT DATE_FORMAT(publikovano, '%e.%c.%Y') FROM clanky"));
echo $row[0]; // v budoucnu by měla také fungovat MySQL proměnná date_format
?>

Poddotazy

<?php
// starý kód
$id = mysql_result(mysql_query("SELECT id FROM clanky WHERE url = '" . mysql_real_escape_string($_GET["url"]) . "'"), 0);
mysql_query("INSERT INTO diskuse (clanek, zprava) VALUES ($id, '" . mysql_real_escape_string($_POST["zprava"]) . "')");

// nový kód
mysql_query("INSERT INTO diskuse (clanek, zprava) VALUES ((SELECT id FROM clanky WHERE url = '" . mysql_real_escape_string($_GET["url"]) . "'), '" . mysql_real_escape_string($_POST["zprava"]) . "')");
?>

Poddotaz musí být uzavřený do kulatých závorek. Tento poddotaz asi nakonec nepoužiji, protože spolu s triggerem vede k chybě 1442.

Přijďte si o tomto tématu popovídat na školení Konfigurace a výkonnost MySQL.

Jakub Vrána, Seznámení s oblastí, 28.10.2005, diskuse: 21 (nové: 0)

Diskuse

Michal:

Správce tohoto serveru při upgradu na adresu MySQL pronesl tolik sprostých nadávek, že se diví že se k němu databázoví bohové nadobro neotočili zády a nakonec ho nechali MySQL 5.0 zprovoznit :-)

Jarks:

> ...pronesl tolik sprostých nadávek...

Chci požádat našeho správce, aby upgradnul z MySQL 4.0.24 na MySQL 5.0.15 - windows. Opravdu rád bych začal využívat nových vlastností. Když ale čtu o těch problémech, nevím jestli nemám sepsat závěť, protože budu bez varování zastřelen.

Nebyl by prosím k dispozici alespoň rámcový popis takové migrace - hlavně v čem jsou potíže? Jestli tomu správně rozumím (informace v diskusi pod článkem o kódování  http://php.vrana.cz/mysql-4-1-kodovani.php se mi místy zdají mírně zmatené), jedná se hlavně o potíže s českým kódováním.

Jde tedy snad o to, nastavit všem databázím a tabulkám parametr "collation" a při připojování k databázi ještě určit v jakém kódování se bude komunikovat. Jestliže dosud data i webstránky byly v ISO-8859-2, udělám toto:

- Nastavím kódování všem stávajícím databázím:
  ALTER DATABASE jméno_databáze COLLATE latin2_czech_ci

- Musím nastavit kódování také všem tabulkám uvnitř takové databáze(?)
  ALTER TABLE jméno_tabulky COLLATE latin2_czech_ci

- Upravím script, který obstarává připojování k databázi takto:

<?php
mysql_connect
(SQL_HOST, SQL_USERNAME, SQL_PASSWORD);
mysql_select_db(SQL_DBNAME);
mysql_query("SET CHARACTER SET latin2");
?>

U nově zakládaných databází je pak třeba myslet na to, že se v příkazu CREATE musí určit kódování. Tedy něco jako "CREATE DATABASE jméno_databáze COLLATE latin2_czech_ci".

Nebo si to představuju příliš jednoduše?

ikona Jakub Vrána OpenID:

Pokud jsou všechny databáze ve stejném kódování, mělo by to být ještě jednodušší. Mělo by stačit nastavit výchozí znakovou sadu a porovnávání (defaultně je latin1_swedish_ci) a skripty se ani nemusí upravovat. Problém pokud vím vznikne v případě, kdy se výchozí znaková stránka nastaví na UTF-8 nebo jiné vícebajtové kódování.

houba:

> Osobně se chystám na tomto webu využít triggery (na aktualizaci data modifikace článku při změně v diskusních příspěvcích)

Aha, takže odteď to bude jako lepší, že datum vydání článku bude datum, kdy si někdo ublinknul do diskuse? Tak to je skvělý, lepší blbost dnes sotva potkám...

Milo Kmeť:

Ja tam čítam "datum modifikace článku" a nie dátum vydania, to je dosť veľký rozdiel.

ikona Jakub Vrána OpenID:

Přesně tak. Datum poslední modifikace článku používám pro posílání hlavičky Last-Modified, zobrazované datum je samozřejmě datum vydání článku - to se nemění.

KarolF:

Nefunguje odkaz http://php.vrana.cz/mysql-4.1-kodovani.php

ikona Jakub Vrána OpenID:

Díky za upozornění, opravil jsem to.

VS:

Už to zase nefunguje... :-)

Tiger:

Zdravím,

chtěl jsem se zeptat, zda je problém mít nainstalované a používat 2 verze MySQL (MySQL 4.1.x a MySQL 5.0.x)?

Díky za odpovědi

Jakub Podhorský:

není ale každou verzi musíš "namapovat" na jiný port

ikona spaze:

nebo na jinou IP adresu.

Petr Maizner:

zdravim,
mohu se optat jestli mi nekdo poradi jak v ramci VIEW pouzivat dynamicke razeni dat na strance ? jde mi o to ze za normalnich okolnosti jsem mel na mysql 4.1 bezny dotaz bez VIEW a pres promenne jsem si dynamicky v tom sql dotazu urcoval sloupec razeni a typ.
jak tohle ale udelat dynamicky za pouziti VIEW ? je to vubec mozne nejak obejit nebo mohu tim padem VIEW pouzit pouze v datech ktera chci radi jen jednim statickym zpusobem a ne jinym ?

a nebo je mozne udelat:
CREATE VIEW clanky_vydane AS SELECT * FROM clanky WHERE publikovano <= NOW()
mysql_query("SELECT * FROM clanky_vydane ORDER by xxx XXX");
pobere to ten pohled ?

nebo na razeni dat pouzivate uplne jine feature ?

moc dekuji za radu
PM

ikona Jakub Vrána OpenID:

Takováto konstrukce normálně funguje. S pohledem je možné pracovat skoro stejně jako s normální tabulkou. A ano, toto je správný způsob řazení.

Petr Maizner:

Super, moc dekuji za takovou rychlou odpoved :o)
Ja prave premyslel jeslti pohled vraci data ktera jsou v nem natvrdo nadefinovana a nebo jeslti je sam o sobe take variabilni na takove parametry (ono je to i logicke, jinak by to asi bylo k nicemu), coz evidetne je ale nemel jsme to ted vubec kde vyzkouset.
Takze jeste jednou diky
pm

Tomáš Matonoha:

Ovšem když mám v databázi tabulku, kde v jednom sloupci bude anglický text a v druhém český text, jaké nastavit kódování u celé tabulky?
utf8_general_ci nebo utf8_czech_ci?

ikona Jakub Vrána OpenID:

Je to jedno. Kódování tabulky říká jenom to, jaké kódování budou mít nově přidané sloupce. Takže správné řešení je českému sloupci dát czech a anglickému general.

melda:

Zdravte,

tak jsem si rozbehl MySQL 5.0.22-community-nt, k tomu mam Apache 2.2.3 a PHP 5.2.1. A mam nasledujici problem:

v databazi mam nekolik ulozenych procedur. Pomoci nastroje SQLyog je mam odladene a funguji ok.

Pokud je zavolam v php, tak dalsi sql dotaz po zavolani ulozene procedure mi skonci hlasenim:

2013 Lost connection to MySQL server during query ...

Co jsem googlil, tak je asi problem v php. Nasel jsem radu abych volal po kazdem zavolani procedury, mysql_free_result na vysledek dotazu, ale to taky nepomaha.

Setkal se s tim nekdo?
Dik za odpovedi

venca:

hochu tak to je asi tím, že bys měl volat spíš funkci než proceduru.

ikona Jakub Vrána OpenID:

Zkusil bych použít extenzi MySQLi a její funkci mysqli_multi_query().

petr:

v kombinaci s php a treba vicenasobnym insertem nebo ctenim dat z blobu muze byt tato chyba zpusobena take nizkou hodnotou sql promenne "max_allowed_packed" ve vasi session, viz http://dev.mysql.com/doc/refman/5.0/en/packet-too-large.html

Diskuse je zrušena z důvodu spamu.

avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.