Aktuální ID uživatele z SHOW PROCESSLIST rubrika: Databáze: SQL
V MySQL / MariaDB je příkaz SHOW [FULL] PROCESSLIST
případně SELECT FROM information_schema.processlist
.
Příkaz je bezva, určitě se hodí vědět, kdo a jaký dlouhý dotaz si případně pouští. Ovšem s tím kdo je tak trochu problém. Chápu, že SQL databáze byly v principu koncipovány tak, že autoři předpokládali, že každý uživatel bude mít své unikátní jméno. Nicméně realita webových aplikací je taková, že všichni uživatelé jedou přes jedno jméno zadané někde v nějakém configu na serveru a logování se neřeší na úrovni db, ale na úrovni aplikace.
Jak tedy zobrazit, kdo daný dotaz pustil?
U mne jedou všechny dotazy přes jednu funkci (RunSQL, která ošetřuje a loguje nějaké případné chybové stavy, atd...), takže není problém přidat třeba na začátek SQL stringu komentář s id aktuálního uživatele. Komentář je vidět i v Processlistu, takže to vypadá jako vyřešeno. Bohužel jsem dospěl k závěru, že se pak každý takový dotaz s různým komentářem pravděpodobě cachuje zvlášť (minimálně jeho parsování). Takže zas tak ideální to není.
Zná někdo nějaký rozumnější způsob jak si do Processlistu zapsat id uživatele?
Princip řešení: Využiji to, že každá řádka processlistu má connection_id (někdy se mu říká thread_id), které si také mohu zjistit, když jsem připojen. Takže si udělám nějakou pomocnou tabulku a do té si prostě po každém připojení k databázi zapíšu dvojici connection_id - user_id a pokud budu chtít zjistit, kdo co pouští tak to joinu.
Realizace:
Založím si tabulku:
RunSQL('CREATE TABLE `act_users` ( `conn_id` bigint(20) NOT NULL, `user_id` bigint(20) NOT NULL, KEY `conn_id` (`conn_id`), KEY `user_id` (`user_id`) )');
Za connect do db vložím dotaz:
RunSQL('INSERT INTO act_users (conn_id, user_id) VALUES (CONNECTION_ID(), '.CurrentUserId().')');
Kde CurrentUserId() je nějaká PHP funkce vracející id aktuálního uživatele (třeba ze sessions). CONNECTION_ID() je SQL funkce vracející aktuální connection (jenž se u každého dotazu vypisuje v precesslistu). Samozřejmě bych to ještě měl dát po úspěšném zalogování (když zjistím nové user_id)
A udělám stránku s nějakým gridem jehož podkladem bude dotaz:
RunSQL('SELECT INFORMATION_SCHEMA.PROCESSLIST.*, act_users.user_id FROM INFORMATION_SCHEMA.PROCESSLIST LEFT JOIN act_users ON INFORMATION_SCHEMA.PROCESSLIST.ID = act_users.conn_id');
Kam můžu případně přidat Kill nebo to joinout ještě přímo na tabulku users, abych viděl třeba příjmení a jméno atd...
Samozřejmě občas chci staré neaktivní záznamy smazat. K tomu mohu využít třeba zase processlist a zjistit z act_users ty záznamy co již v processlistu neexistují a ty smazat. K tomu mohu využít dotaz:
RunSQL('DELETE act_users FROM act_users LEFT JOIN INFORMATION_SCHEMA.PROCESSLIST ON act_users.conn_id = INFORMATION_SCHEMA.PROCESSLIST.ID WHERE INFORMATION_SCHEMA.PROCESSLIST.ID IS NULL');
Zavěsit to mohu klidně třeba za každé přihlášení do db nebo si pohrát s nějakým cronem...
Pro zobrazení všech 2 odpovědí se prosím přihlaste:
Nebo se přihlaste jménem a heslem:
Komentáře