Ukládání sesion dp databáze, je to dobrý nápad?
- zool
- Člen | 144
Ahoj chtěl jsem se zeptat, jestli nedělám neco špatně. Mám hosting u active a tam mám omezený počet souborů, ten počet je včetně souborů od session. Dělá mi to problém, protože souborů od session je nějak hodně, nechávám aktivní session po dobu 40 dnů, a tím nahromaděním souborů překročím limit. Proto jsem začal session ukládat do databáze. Nedá se to množství nějak omezit?? Složku používám standartní nikam to nepřeukládám.
Díky
- Filip Procházka
- Moderator | 4668
Ukládání session do databáze není problém, ale musíš spolehlivě vyřešit zamykání řádků, jinak budeš mít problémy.
- Filip Procházka
- Moderator | 4668
Nejprve si najdi nějaké čtení o tom, proč je to potřeba a jak se to dělá.
- zool
- Člen | 144
A nějaký odkaz by nebyl, já jsem hledal, ale nějak nemůžu najít. Co
jsem našel, tak tam o uzamykání tabulky nebylo třeba…Narazil jsem na ten
Redis, ale te je pro mě nepoužitelný, když je to na active
Díky
Jinak mám to podobně jako je to tady http://www.devshed.com/…-a-Database/ a tam právě taky nic jako zamykání tabulky neřeší.
Editoval zool (21. 11. 2012 16:28)
- Jan Tvrdík
- Nette guru | 2595
zool wrote: Jinak mám to podobně jako je to tady http://www.devshed.com/…-a-Database/ a tam právě taky nic jako zamykání tabulky neřeší.
Taky to tam mají špatně.
- zool
- Člen | 144
A kde to je tedy dobře? A to vzniká, ten problém, když se zadá
několika násobný ajax požadavek, který pracuje se session?? Nebo jsou
ještě jiné problémy?
Já už to mám právě napsané, a zatím to funguje, ale nemám to na ostrém
provozu, když to může dělat problémy. Chtěl bych to právě vyřešit a
pak to tady umístit, pro ostatní. Děkuji
Editoval zool (21. 11. 2012 17:20)
- Filip Procházka
- Moderator | 4668
Když jsem dělal zamykání pro svůj Redis storage, tak jsem dva dny studoval články a cizí zdrojáky a psal si testovací nástroje.
Google > „mysql locking“ – http://dev.mysql.com/…-tables.html
Google > „php mysql session storage locking“ – http://stackoverflow.com/…sion-handler
Jediné co se v tomto tématu týká Nette, tak je, jak tvojí storage implemetovat tento interface. Všechno ostatní je otázka na schopnost googlit, číst a chápat základy relačních databází a PHP.
Až budeš mít konkrétní problém, rád ti poradím, ale googlit to za tebe nebudu.
- juzna.cz
- Člen | 248
Pokud nezamknes session, tak ti to pri race condition treba pri ajaxu muze prepsat. Nastane to jen obcas, takze je to tezke odladit.
Predstav si ze se ti potkaji 2 requesty, napr uzivatel behem chvile klikne
na dva ajaxovy odkazy, a ty probihaji takto:
A: .....Start --------------- Konec .......
B: ...............Start–Konec.............
Oba pracuji se sesion. Request A to nacte, dela nejake zmeny. Pak zacne B, nacte (ale zmeny nevidi), udela svoje zmeny, zapise a zkonci. Pak dobehne A, ktere se trosku zpozdilo, a svoje zmeny zapise. V tuto chvili jsou data, ktere zapsal request B, kompletne ztracena.
A to je jen jeden priklad z mnoha, jak ti to muze race condition zabit, pokud to spravne neosetris.
(Btw ani Nette to nema uplne osetrene a stavalo se mi, ze mi mizely session. Musel jsem Nette Session kompletne vypnout. Zkusil jsem to sepsat …)
Editoval juzna.cz (21. 11. 2012 19:32)
- Filip Procházka
- Moderator | 4668
Nette neřeší zamykání session, protože to řeší PHP. Nedokážu si
představit, jak by to zapnutí Nette\Http\Session
bez vlastního
storage mohlo rozbít.
- zool
- Člen | 144
HosipLan napsal(a):
Nette neřeší zamykání session, protože to řeší PHP. Nedokážu si představit, jak by to zapnutí
Nette\Http\Session
bez vlastního storage mohlo rozbít.
Souhlasím,
No a když použiju transakce na celý životní cyklus té mé třídy, tak to nepujde? Nebo to bude pomalé
HosipLan:
díky za tip už to studuju
To je asi ta chyba http://race.phux.net/…/rc-test.php
Editoval zool (21. 11. 2012 19:28)
- Filip Procházka
- Moderator | 4668
Transkace řeší jiný problém – aby se ti vykonaly všechny SQLka, které tam nasypeš, nebo žádné. Zamknou ti databázi jenom na samotné vykonání, takže neřeší race conditions. Pokud se pletu, opravte mě někdo :)
- zool
- Člen | 144
No a při té transakci se tabulka neuzamkne? zkusel jsem pohledat a tady
něco o tom je (doufám že odkaz pujde) na staně 142
http://books.google.cz/books?…
- Filip Procházka
- Moderator | 4668
To je absolutně nežádoucí. Když nastane chyba během běhu aplikace, zahodí se úplně všechno? Budete dělat zanořené transakce? To není řešení. Navíc to takhle nefunguje.
Napište si na to pořádné testy a implementujte to. Garantuju vám, že to vůbec nebude dělat to, co potřebujete ;)
zamykání !== transakce
//edit: a mít dvě připojení je nechutné plýtvání ;)
- zool
- Člen | 144
Ahoj, stále se mi to nějak nedaří mám tuto třídu,
<?php
class MySessionStorage extends \Nette\Object implements \Nette\Http\ISessionStorage
{
/** @var \Nette\Database\Connection */
public $database;
public function __construct(\Nette\Database\Connection $database)
{
$this->database = $database;
}
public function open($savePath, $sessionName)
{
$id = session_id();
/** Je zamek? Jestli ano, tak cekej */
while(!$this->database->query("SELECT IS_FREE_LOCK('session_$id') AS lo")->fetch()->lo);
/** vztvor zamek pro dane id session */
$this->database->exec("SELECT GET_LOCK('session_$id', 160)");
return true;
}
public function close()
{
$id = session_id();
/** Uvolni zamek dane session */
$this->database->exec("SELECT RELEASE_LOCK('session_$id')");
return true;
}
/**\
* @param $id
* @return string
*/
public function read($id)
{
$data = $this->database->table('session')->find($id);
if($data->count('*'))
$data = $data->fetch()->data;
else
$data = "";
return $data;
}
/**
* @param $id
* @param $data
* @return bool
*/
public function write($id, $data)
{
$dat = $this->database->table('session')->find($id);
$this->database->exec("REPLACE INTO session (id, time, data) VALUES (?, ?, ?)",$id, time(),$data);
return true;
}
/**
* @param int $id
* @return bool
*/
public function remove($id)
{
$this->database->table('session')->find($id)->delete();
return true;
}
/**
* @param int $maxlifetime
* @return bool
*/
public function clean($maxlifetime)
{
$this->database->table('session')->where("time < ?", ( time() - $maxlifetime ))->delete();
return true;
}
}
No a problém je asi v tom, že při otevíraní session to nečekat na
uvolnení zámků(i když by mělo), nebo to může být způsobené, že by mi
prohlížeč nezobrazoval ajax požadavky postupně?? Jak zajišťuje te to
čekání?
Díky
Editoval zool (22. 11. 2012 21:00)
- zool
- Člen | 144
Určitě, podělím se
v configu
jen část ta důležitá
services:
database: @nette.database.default
sessionStorage: MySessionStorage(@database)
session:
setup:
- setStorage(@sessionStorage)
Tabulka
CREATE TABLE IF NOT EXISTS `session` (
`id` varchar(200) NOT NULL,
`time` varchar(200) NOT NULL,
`data` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Je lepší použít typ tabulky InnoDB
- tatyalien
- Člen | 239
Tak jsem se na to teprve teď dostal, data se mě už ukládají do DB v pořádku… jen mám problém s třídou ShoppingCart, která mě ukládá košík do session, v neonu i když jsem to přesunul za nastavenou session, tak uloženej košík se neukládá do dob a po redirectu se košík promázne. Jak mám do této třídy nastavit správnou sessionStorage?
edit: na localhostu mě to funguje, ale když to hodím na server, tak ten nebere v potaz košíkovou session ukládat do DB :(
services:
database: @Nette\Database\Connection
authenticator: Authenticator( @modelUser::getUsers(), '%security.salt%' )
modelShop: ShopModel( @database )
sessionStorage: MySessionStorage( @database )
session:
setup:
- setStorage(@sessionStorage)
- setExpiration(+ 30 day)
shoppingCart:
class: ShoppingCart
arguments: [@session, @modelShop, @user]
class ShoppingCart extends Nette\Object
{
// ShoppingCart object sessionu
private $cart;
/** @var \models\ShopModel */
private $model;
/** @var Nette\Security\User */
private $user;
/**
* @param Nette\Http\Session $session
* @param ShopModel $model
* @param Nette\Security\User $user
*/
public function __construct(Nette\Http\Session $session, ShopModel $model, Nette\Security\User $user)
{
$this->cart = $session->getSection(__CLASS__);
....
}
}
Editoval tatyalien (15. 12. 2012 9:03)
- tatyalien
- Člen | 239
Tak jsem zkoušel i dle: https://github.com/…e/issues/562 viz níže, ale závěr je stejný. Na localhostu vše ok, na serveru se už sice jednou za uherák něco propíše do db, ale pak už to hodnoty neaktualizuje.
Kulich:
Aha, poslal jsem předtím pouze půlku konfiguráku, takže takhle to funguje bez jakéhokoliv patche:
sessionStorage: SessionStorage(@database)
session:
class: Nette\Http\Session
setup:
- setStorage(@sessionStorage)
config.neon:
nette:
application:
errorPresenter: Error
database:
dsn: '%database.driver%:host=%database.host%;dbname=%database.dbname%'
user: %database.user%
password: %database.password%
#session:
#expiration: 14 days
services:
authenticator: Authenticator
routerFactory: RouterFactory
router: @routerFactory::createRouter
# Databáze:
database: @Nette\Database\Connection
sablonyModel: SablonyModel( @database )
sessionStorage: MySessionStorage(@database)
session:
class: Nette\Http\Session
setup:
- setStorage(@sessionStorage)
Presenter:
public function renderDefault()
{
$myCounter = $this->getSession('mySessionContainer');
$myCounter->a = "Pevná hodnota";
$myCounter->b = rand(1,100);
$this->flashMessage($myCounter->a, 'success');
$this->flashMessage($myCounter->b, 'success');
}
MySessionStorage ⇒ je od zool