MySQL – různé typy tabulek

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

Ne všichni ví, že v MySQL kromě výchozího typu tabulky MyISAM existují i další typy tabulek, které mají vlastnosti připisované obvykle pouze „vyspělejším“ databázím. Takže málokdo také ví, že díky tabulkám typu BDB a InnoDB jsou v MySQL již od verze 3.23 (tedy v produkční verzi od ledna 2001) k dispozici transakce a od verze 3.23.44 (říjen 2001) také cizí klíče. InnoDB je dokonce od MySQL 4.1.5 (září 2004) na Windows používána jako defaultní.

MySQL podporuje i další typy tabulek, např. pro příkaz CREATE TEMPORARY TABLE se báječně hodí typ MEMORY.

Pravda je taková, že i pro mě znamená MySQL v podstatě typ tabulky MyISAM. Je ale dobré vědět, že pokud někdo potřebuje např. transakce a nechce nebo nemůže se s MySQL rozloučit, má možnost volby.

Přijďte si o tomto tématu popovídat na školení Návrh a používání MySQL databáze.

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

Diskuse

T3RMiX:

Nějak mě uniká pointa tohoto příspěvku?! Uvítal bych popis BDB a InnoDB v CZ, místo odkazů na manual :)

RD:

nešlo by trošku popsat transkace a k čemu jsou dobré?

fliper:

transakcia je nieco ako davka v podstate .....

ak spravis
SELECT
DELETE
SELECT
DELETE - a tento spadne

tak bez transakcii to spravi to ze ti ten predtym delete vykona. ale ak chces aby ti spravilo delety 2 alebo ani jeden zaobalis to do BEGIN a END a uz je to transakcia .. a ak nieco spadne v transakcii DB sa vrati do stavu predtym ako transakcia bola spustena ....

snad staci tak strucne

KX:

To by se mi tedy taky líbilo, (trochu obsáhlejší popis pro laiky). Nešlo by to? ;-))

OttY:

Tiež sa pripájam. Stačilo by aspoň hmlisto načrtnúť. Ale podľa vyjadrenia, že aj pre neho je MySQL hlavne MyISAM neviem či ten úvod bude ;-) Je nás asi viac :-)

zby:

Jen velmi rychle.
Pointa je poukázat na jiné typy tabulek DB serveru MySQL a podnítit vás je vyzkoušet. Další typy vznikly na základě požadavků vývojářů, jinak by zde jiné typy vůbec nebyly.

Cizí klíče a transakce jsou tedy jak autor uvedl používány systémem InnoDB a BDB - Osobně používám InnoDB. Rozdílů může být víc, nicméně BDB používá stránkované transakce, kdežto InnoDB řádkový systém.

Pro provoz InnoDB je třeba mí naistalovýn PŘÍDAVNÝ balík, rpm MySQL-MAX a nastavený my.cnf. Příklad z provozní praxe:

# Uncomment the following if you are using InnoDB tables
innodb_data_home_dir = /var/lib/mysql/
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /var/lib/mysql/
innodb_log_arch_dir = /var/lib/mysql/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
innodb_buffer_pool_size = 16M
innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50


Tedy, InnoDB používá tablespace - datový systém databanky. Pro využití takového tablespace je třeba při vytvoření tabulky uvést ihned za definici create table()ještě engine=innodb.
Systém tabulek je stále ve .frm souboru, avšak data a indexy jsou v souboru "ibdata1" - tedy na tablespace.
Velikost tohoto úložiště je možno nastavit fixně, nebo dynamicky pomocí volby "autoextend". Pak se rozšiřuje po 8mi MB. Limit velikostí je omezen max. velikostí souborů v souborovém systému...


Od verze 4.1. je možno použít více tablespace souborů.

Proč transakce? Jistota a stabilita. Automatický rollback se provádí při nepotvrzené transakci - ztráta spojení s DB, nebo vedomě pomocí příkazu "rollback". Potvrzení transakce klientem je třeba provést pomocí příkazu "commit". Tedy jako u "velkých" DB - např. Oracle.

Cizí klíče jsou výhodou např. pro zajištění integrity dat mezi tabulkami.
Pro použití cizích klíčů je třeba mít všechny tabulky tzpu innodb. Míchačka nefunguje (kombinace MyISAM/InnoDB je nepřípustná). Proto byl zaveden systém InnoDB...

Provozuji InnoDB úspěšně již od verze 3.23.54a.

Stačí pro rozjezd?

zby@post.cz

Zde není prostor na další diskuse, ale doufám, že to zatím pro rozjezd stačí.

Mintaka:

Ukázka transakce přes PHP
<?php
$query
="START TRANSACTION;";
include (
'dotaz.php');
$query="DELETE FROM polozky WHERE id > 0;";
include (
'dotaz.php');
$query="SELECT * FROM polozky;";
include (
'dotaz.php');
include (
'vypis.php');
$query="ROLLBACK;";
include (
'dotaz.php');

$query="SELECT * FROM polozky;";
include (
'dotaz.php');
include (
'vypis.php');

?>
include ('dotaz.php'); předá dotaz MySql ke zpracování
include ('vypis.php'); vypíše do tabulky výsledek dotazu

U prvního selectu nic nevypíše nic, protože jsou smazány všechny položky.
U druhého selectu (po ROLLBACK) vypíše všechny, protože stav tabulky byl vrácen před smazání.

PeTa:

Když jsem nahoře zahlédl CREATE TEMPORARY TABLE, trošku mě trápí: Chtěl jsem ji použít v pětistránkovém registračním formuláři, protože řada uživatelů registraci nedokončila a vznikaly tak zbytečné "díry v AUTOINCREMENTU". Mínil jsem, že využiji toho, že tabulka je dočasná  a zaniká s ukončením relace, takže pokud by nedošel až k poslednímu kroku, který má  zkopírovat řádek z tmp do fyzické tabulky, data by prostě zanikla.
Vytvoření tabulky není problém (nemůže být MEMORY, protože obsahuje TEXT). INSERT INTO `tmp_table`proběhne korektně, ale jakmile se přeskočí na další část formuláře (je jedno, zda SWITCHEM, nebo fyzicky, tabulku už nelze adresovat a UPDATE už nemá kam zapsat. ERR: Table `database.tmp_table` not exists. Pochopitelně `database.tmp_table` nemůže existovat, protože by měla být v paměti. Kdybyste někdo věděli, co s tím...
(jo, ke všemu na WinXP to pracuje celé korekně (stejné PHP i MySQL))

ikona Jakub Vrána OpenID:

V první řadě je potřeba pochopit, jak funguje připojení k databázi z PHP. Každý proces webového serveru má vlastní připojení k databázi (u persistentních konexí) nebo se připojení dokonce po ukončení každého požadavku ihned zavírá. V tomto případě tedy dočasná tabulka zmizí v okamžiku dokončení požadavku na jednu konkrétní stránku, u persistentních konexí chybí jistota, že stejný proces dostane ke zpracování další část formuláře (k tomu pravděpodobně dochází pod Windows).

Dočasná tabulka se tedy pro tuto úlohu vůbec nehodí. Osobně ukládám dosud zadaná data do skrytých formulářových polí, někdo pro tuto úlohu používá sessions (což znemožňuje otevřít více registračních formulářů ve více oknech, to ale obvykle nevadí).

ikona dgx:

Odpověď jsi napsal sám - tabulka zaniká v okamžiku ukončení relace. A to je, používáš-li mysql_connect, v okamžiku ukončení skript. Mohlo by to vyřešit použití mysql_pconnect, ale rovnou tě od toho odradím - není to dobré řešení. Zkus dočasná data držet buď v session, nebo v klasické tabulce.

PeTa:

Tušil jsem, že to bude tímto. (Použito mysql_pconnect). Díky.

Ján Koštial:

Skúsil som na mojom hostingu zmeniť tabuľky MyISAM na InnoDB. Nadefinoval som aj cudzie kľúče. Ale celé stránky sa mi úžasne spomalili. Predpokladal som, že pomalšie to bude len pri INSERT, DELETE a UPDATE. Je to normálne? (Teda že oveľa pomalší je aj SELECT?)

Pashreee:

Muj dotaz je prosty: pomoci command promtu v ramci WinXP se pripojim do mysql. udelam nejaky select dat a tyto data bych chtel nasledne pouzit treba pro update zaznamu v jine tabulce. Jak to mam udelat? Dalji se nekde selectle data ulozit pro dalsi pouziti?

diky, doufam ze budu pochopen :)

pas.

ikona Jakub Vrána OpenID:

K prozkoumání bych doporučoval poddotazy: http://php.vrana.cz/mysql-5-0.php#poddotazy

Pro UPDATE na stejné tabulce potom http://php.vrana.cz/poddotaz-pri-update-na-stejne-tabulce.php

Pashreee:

Ahojky, v prvni rade jsem musel zvysit verzi mysql na 4.21. abych mohl provadet poddotazy. uz jsem si jeden vytvoril. narazil jsem na problem s prikazem update - a to takovy ze jsem chtel updatnout tabulku ale ve vnorenem selectu jsem bral data z te stejne a to neni povoleno :) takze jsem si vytvoril dalsi temporary tabulku nicmene ted mi to hlasi

Error: 1242 SQLSTATE: 21000 (ER_SUBQUERY_NO_1_ROW) Message: Subquery returns more than 1 row.

Dotaz vypada nasledovne: UPDATE sub_account SET sub_account.ecom_cnt=(SELECT distinct test_sub_account.cust_id, customer.ecom_cnt from test_sub_account, customer where customer.id=test_sub_account.cust_id)

Pokud pouziju jen ten select co je uvnitr uvozovek tak to funguje, ale jakmile to zakomponuji jako vnorenyu select tak dostavam tu error hlasku. pls help :)

ikona Jakub Vrána OpenID:

Z toho dotazu vůbec není jasné, co má dělat. Důležité je, že poddotaz musí v tomto případě vracet jeden sloupec a jeden řádek. Dá se v něm použít odkaz na upravovanou tabulku.

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.