Aktuální ID uživatele z SHOW PROCESSLIST rubrika: Databáze: SQL

8 rmaslo
položil/-a 3.12.2018
 
upravil/-a 3.12.2018

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?

Komentáře

  • harrison314 : Nieje vhdnejsie si na to spravit tabulku pre auditny log? Plus nemyslim, ze zaznemanvat SQL dopyty je rozumne, skor je rozumne zaznemnavat operacie na aplikacnej urovni s parametrami. Pretoze SQL-ko sa ti moze zmenit (napriklad refaktoringom, optmalizaciou, zmenou spravania,...) a uz ti to nebude sediet. 3.12.2018
  • rmaslo : Log je trochu jiný pohled na věc a logovat všechny (selektovací) SQL dotazy na takto nízké úrovni mi přijde poněkud zbytečné. Processlist je prostě jenom nástroj pro takový rychlý pohled co se děje, akorát bohužel neposkytuje toho aplikačního uživatele. S logováním na vyšší aplikační vrstvě (nikoliv SQL) souhlas, to dělám, v principu vždy minimálně pro všechny operace jenž mají za následek INSERT, DELETE, UPDATE. 4.12.2018
odkaz Vyřešeno
8 rmaslo
odpověděl/-a 5.12.2018
 
upravil/-a 5.12.2018

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:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.