MariaDB/MySQL: Procedure facili per leggere la Diagnostics Area

English version

UPDATE 2013-08-30: Ho risolto 2 bug e creato un repo su GitHub chiamato sql_diagnostix. Scusate se non l’ho fatto prima. Se io o chiunque altro troverà altri bug, aggiornerò il repo.

Il problema

Per visualizzare velocemente le informazioni sugli errori e i warning generati dall’ultima istruzione eseguita, è possibile utilizzare SHOW WARNINGS. Però i risultati di questa istruzione non possono essere lette via SQL, perciò non è possibile usarla per gestire gli errori in uno Stored Program.

A questo scopo si può usare GET DIAGNOSTICS, che ha però due problemi:

  • Richiede molto codice
  • Non esiste un modo facile per mostrare tutte le informazioni presenti nella Diagnostics Area.

Il primo problema può scoraggiare molti sviluppatori dall’usare GET DIAGNOSTICS.

Il secondo problema nella maggior parte dei casi non è così importante, perché le info mancanti sono SQLSTATE e le informazioni che possono essere impostate solo con SIGNAL e RESIGNAL, e che non possono essere lette da un programma esterno (SCHEMA_NAME, CURSOR_NAME, etc). Tuttavia leggere SQLSTATE può essere importante, e accedere a tutte le clausole di SIGNAL può aiutare nel debug e nella soluzione dei problemi… ecco perché esistono :-)

Oracle MySQL 5.7 ha due Diagnostics Area e supporta la parola chiave STACKED per accedere alla seconda DA da un error HANDLER. Questo però non aiuta molto: permette solo di eseguire un’altra istruzione che accede a una tabella, prima di leggere le informazioni sugli errori che si sono verificati. Perciò la DA STACKED non sembra in grado di risolvere problemi reali.

La soluzione

Ho creato tre Stored Procedure per risolvere questi problemi:

  • _.materialize_diagnostics_area()
  • _.show_diagnostics_area()
  • _.show_full_diagnostics_area()

Tutte le procedure creano una tabella temporanea MEMORY chiamata DIAGNOSTICS_AREA in un database chiamato _. Se la tabella esiste già, viene eliminata e ricreata. Incidentalmente viene anche cancellata la Diagnostics Area del server, ma le informazioni rimangono disponibili nella tabella finché non si chiama di nuovo una di queste procedure.

_.DIAGNOSTICS_AREA ha una colonna chiamata ID, che indica la posizione di ogni singola condizione nella Diagnostics Area. Le altre colonne sono uguali alle proprietà delle condizioni della Diagnostics Area (MYSQL_ERRNO, etc). L’unica eccezione è la colonna SQLSTATE, che usa il nome utilizzabile in SIGNAL e RESIGNAL, non quello usato nella Diagnostics Area (cioè RETURNED_SQLSTATE).

Siccome sia gli Stored Program, sia i programmi esterni possono accedere a _.DIAGNOSTICS_AREA, questa permette ai programmi esterni di leggere tutte le informazioni che si possono impostare con SIGNAL.

Si può chiamare direttamente materialize_diagnostics_area() per copiare interamente la DA nella tabella, per poi leggere le informazioni con delle query.

show_full_diagnostics_area() mostra tutte le informazioni, dopo aver popolato la tabella. E’ una sorta di SHOW WARNINGS con molte colonne in più.

show_diagnostics_area() mostra solo le colonne ID, SQLSTATE, MYSQL_ERRNO, MESSAGE_TEXT.

Esempio:

MariaDB [test]> INSERT INTO `t` VALUES (1/0), (1/0), (1/0), (-1);
Query OK, 4 rows affected, 4 warnings (0.07 sec)
Records: 4  Duplicates: 0  Warnings: 4
 
MariaDB [test]> CALL _.show_diagnostics_area();
+----+----------+-------------+--------------------------------------------+
| ID | SQLSTATE | MYSQL_ERRNO | MESSAGE_TEXT                               |
+----+----------+-------------+--------------------------------------------+
|  1 | 22012    |        1365 | Division by 0                              |
|  2 | 22012    |        1365 | Division by 0                              |
|  3 | 22012    |        1365 | Division by 0                              |
|  4 | 22003    |        1264 | Out of range value for column 'c' at row 4 |
+----+----------+-------------+--------------------------------------------+
4 rows in set (0.09 sec)

Limitazioni

Se uno Stored Program deve essere veloce, queste procedure possono essere utilizzate solo per il debug.

Come detto sopra, ogni chiamata elimina le informazioni già presenti nella tabella _.DIAGNOSTICS_AREA. E’ una scelta di progettazione.

C’è un’informazione presente nell’output di SHOW WARNING che però manca nella tabella _.DIAGNOSTICS_AREA: la colonna Level. Il motivo è che non sono riuscito a trovare nella documentazione di MySQL come distinguere un Warning da una Nota, se non con SHOW WARNINGS. Se non c’è modo, o se un modo esiste ma non è documentato, non posso aggiungere questa informazione.

La Diagnostics Area STACKED di 5.7 non viene condiderata.

Il codice

Va bene, ho scritto abbastanza. Ora, se siete interessati:

Scaricate il codice SQL

Non spiego qui il codice perché mi sembra molto semplice ed è commentato. Date un’occhiata a materialize_diagnostics_area() e capirete cosa ho fatto.

A presto!

About these ads

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...