Showing posts with label OAT. Show all posts
Showing posts with label OAT. Show all posts

Friday, August 13, 2010

OAT: monitor dbspace usage / Monitorização de ocupação de dbspaces

This article is written in English and Portuguese
Este artigo está escrito em Inglês e Português

English version:

I keep working with OAT and the database scheduler and It keeps causing me a very good impression. The fact is that we can really get a structured way to deal with typical issues. The example I'll put here in this article is trivial, and every serious DBA has dealt with it. So, in a sense it doesn't bring anything new. Why the trouble? Because it serves as a very nice example on how things can fit together. During this article I'll show you how to take advantage of some components that you probably already use (alarmprogram and OAT) to build a robust, simple, configurable and also important, elegant space usage monitoring.

I'm sure you probably already have a script to monitor your space usage, so you may be thinking how will I convince you to dump it and use this. Let's see what are the usual issues with that kind of scripts:
  1. Typically they're launched by cron. Strangely or not, some customers are restricting the usage of cron. Hopefully this is not your case.
  2. Typically the scripts have the mechanism to send alarms inside them. If you need to change anything (email addresses, phone or page numbers), you may have to change several scripts
  3. Most of the times the scripts don't have "memory". Meaning for example, they'll keep sending alarms forever. In some cases this maybe useless and annoying.
  4. Since the scripts don't have "memory", they will not "clear" the alarm if the problem is solved
  5. The scripts typically will not send info to OAT. And OAT is elegant and easy to use
  6. Typically, different dbspaces in different instances will have acceptable usage thresholds different from each other. This means the scripts need to be more complex to allow customization
I think I could get a few more issues, but the above 6 will be enough. So, my value proposition is to create a mechanism that will solve all the issues above, and that also have some other advantages:
  • You can use is as a skeleton to build other monitoring tasks
  • It's all configurable within the database
As mentioned above we'll need several components:
  1. A fully functional ALARMPROGRAM script
    You should already have this, but some more customization will need to be implemented (a few lines)
  2. Open Admin Tool up and running
  3. Database scheduler active
  4. A procedure to call the ALARMPROGRAM script
    I took a look at a recent article from Andrew Ford about auto-extending dbspaces. He also has an example of a procedure to do this.
So, let's begin:

ALARMPROGRAM script changes


You should create a new class for the event generated by this monitoring task. I noticed Andrew recommends adding two classes (101 and 102 in his example), but I prefer to add just one and leave the decision to send email or paging/sms to the other ALARMPROGRAM parameter, the "severity". In fact I typically use a customized ALARMPROGRAM script where I can define that all events with a certain severity will send a short message and with lower will just send an email, or otherwise define a set of classes that send emails or sms independently of the severity

In any case configure and test your ALARMPROGRAM to receive another class and act accordingly to your needs. The advantage of using an ALARMPROGRAM script is that it becomes the only place where you'll need to change email addresses, pager or SMS numbers etc. Once configured it will work perfectly for you, and be re-usable for any kind of monitoring.

Open Admin Tool up and running

As you'll see, this task will generate alerts in the OAT screen. So you'll have something to show to your management. Typically they like to see some fancy graphics... You'll also be able to change the schedule and configuration of the task (including the thresholds). More on this later, as I have one complain about OAT :)

Database scheduler active

As already mentioned, this monitoring tool is implemented as a task in the database scheduler (introduced in version 11). So this is a requirement.

A procedure to call the ALARMPROGRAM script

As mentioned before, we'll need a procedure to call the ALARMPROGRAM script. This procedure will basically receive the parameters, construct a command and make a SYSTEM() call. The path of the ALARPROGRAM script will be queried from the sysmaster database. So if you ever want to change your script location you don't have to worry about this procedure. It will automatically adapt. The code for this procedure can be found in Listing 1 at the end of the article.
This procedure will be called in several places inside our monitoring task.


The task itself: Description and setup

The free space monitoring task is implemented as a stored procedure. You can find it in Listing 2 below. Let's check it nearly line by line.


  • Lines 1 and 2 are just the DROP/CREATE instructions. Notice that the procedure takes two arguments that are really great and helpful as we'll see later:
    task_id is the id in the ph_task table. It's unique for each task and allows us to cross reference several other tables in sysadmin
    v_id is the execution number of this task. It will change (increment) each time this task is executed
  • The next lines, up to 19, are just variable definitions. I won't explain them since they'll appear in several comments below
  • Lines 20 to 25 refer to debugging instructions. Just uncomment the lines 23 and 24 to get a trace of the task execution in a file created in your /tmp directory (obviously this can be changed)
  • Lines 29 to 31 are very important. The values defined are the last resort used by the task if all the other configuration parameters aren't in place. The defaults defined are:
    default yellow threshold (90): This will represent the percentage of use for each dbspace, above which an alarm of severity 3 will be raised
    default red threshold (95): This will represent the percentage of use for each dbspace, above which an alarm of severity 4 will be raised
    number of alarms (3): This will represent the number of alarms to send. A number of 0 will mean it will keep sending alarms until the situation is solved.

    As we shall see next, these values can be overridden by values configured in the task configuration, and the red/yellow threshold can be configured by dbspace. The above values will only be used if the other more specific configuration items are not setup. And of course, you can change these values in the code, so that they meet your environment.
  • Line 33 is very important since it defines the ALARMPROGRAM class number for lack of space in one dbspace. You should adjust these to the value you added to your ALARMPROGRAM. I use values above 900 for my "personal" extensions so that they won't match classes added to ALARMPROGRAM by IBM in the future (we'll never know how many will be added, but 900 seems a reasonable gap...)
  • Lines 35 to 93. Here we will try to get the defaults that were configured for the above values. These defaults are configuration items for the task. Unfortunately, current OAT versions don't allow us to use the GUI to setup these initial values. We have to create them using SQL. After that they can be changed using OAT's GUI.... I'd like to see the wizard for a new task creation to include the configuration of any task configuration items.... But it isn't there at this moment (version 2.28...). So we need to insert them via SQL. How to do it: These values are kept in the ph_threshold table, which has the following fields:
    name: This is the parameter name. In our case we have the following: DEFAULT NUM ALARMS, DBSPACE YELLOW DEFAULT, DBSPACE RED DEFAULT and then we can insert any in the forms DBSPACE YELLOW dbspace_name and DBSPACE RED dbspace_name. I think the names are self explanatory. The idea is that if you want to create red/yellow thresholds for specific dbspaces you'll have to insert the DBSPACE RED/YELLOW dbspace_name parameters in the ph_thresholds table. If there isn't a specific value for a certain dbspace it will use the value specified in the DBSPACE RED/YELLOW DEFAULT parameter. If these are also not defined, it will use the values defined in lines 29 to 31.
    task_name: the name of the task from the ph_task table. This value needs to match whatever name we give to the task and that's the one we will use to create the entry in the scheduler. For the purpose of this article I'll use IXMon Check Space. You can use whatever you want, as long as you're consistent.
    value: the value of the threshold. This will be the value to be used by the task. In our case, the DBSPACE RED/YELLOW * parameters will use percentage values (1-100)
    value_type: the data type of the threshold (STRING or NUMERIC). In our case we'll use NUMERIC. From some investigation I noticed that we can use NUMERIC(x,y) for non integer values. I didn't test it, but it should work in case it makes sense for you.
    description: a description of what the threshold does. This will be visible in the OAT's GUI if later you want to change the values using the GUI.

    So, to give you some examples, I'll just show the instructions used to create the values that are also specified in the code (number of alarms, red and yellow default thresholds). I'll use the same values:



    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DEFAULT NUM ALARMS', 'IXMon Check Space', '3', 'NUMERIC', 'Number of alarms to send');
    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DBSPACE YELLOW DEFAULT', 'IXMon Check Space', '90', 'NUMERIC', 'Generic yellow threshiold. It will be applied to any dbspace lacking a specific threshold');
    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DBSPACE RED DEFAULT', 'IXMon Check Space', '95', 'NUMERIC', 'Generic red threshiold. It will be applied to any dbspace lacking a specific threshold');


    And for example, if you have a dbspace called llogs_dbs, dedicated to logical logs which is nearly full and which doesn't make too much sense to monitor you could add:


    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DEFAULT YELLOW llogs_dbs', 'IXMon Check Space', '100', 'NUMERIC', 'Make llogs_dbs pass all tests....');
    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DEFAULT RED llogs_dbs', 'IXMon Check Space', '100', 'NUMERIC', 'Make llogs_dbs pass all tests....');


  • Line 97 creates a FOREACH loop. It's based on the query in the next lines which will check the used space in every dbspace in the system
  • Lines 98 to 111. This is the dbspace usage query. Some parts of it might not be necessary, but I took the query from another script... Don't worry, it should work. It gives the number of the pages and the number of free pages in all the dbspace chunks grouped together.
    Notice that the task is based on usage percentage. It could be improved to handle other types of parameters, like allocated GB, or free GB etc. For now I kept it simple....
  • Lines 114 to 153 are used just to try to find specific thresholds for the dbspace we're processing. If they're not found in the ph_threshold table the generic defaults will be used.
  • Lines 154 to 172. Here we calculate the used space percentage and check it against the red and yellow thresholds. If we're beyond any of these values we'll define an alert color and the alert message. If we're below the yellow threshold we leave the color as NULL.
  • Lines 175 to 200. If our current dbspace usage is below the yellow threshold we look for an alert in the ph_alert table for this specific dbspace with state equal to "NEW". If we find one we update it, changing it's state to "ADDRESSED". This can happen if after an alarm was generated someone drops a table for example. In this case I'm not calling the ALARMPROGRAM, but it could make sense to call it with a message like "Previous alarm for dbspace_name is canceled because it's now below the defined thresholds"
  • From 204 till the end, we have exceeded one of the thresholds.... So... First we query ph_alert to see if we have an alarm for this dbspace in the state "NEW". If we don't (223 - 239) we insert it and call the ALARMPROGRAM using the procedure above. If we already have an alarm we check if it's the same color. If it's not (244 - 252), we update two fields:
    alert_task_seq: we do this to reset the alarm counter
    alert_color: we update the color code of the alarm (for usage in OAT's GUI. Note that at this time we may have a RED alert with an YELLOW message text. I choose to do this, to show that there was a change between the current and previous situation. If the alarm has the same color than we check the field alert_task_seq and compare it with our task execution number (given as a parameter to the procedure) and decide, based on the configured number of alarms if we should call ALARMPROGRAM or not

So, finally, how do we schedule the task? Well you can do it by using OAT's GUI or if you want you can insert it directly into the ph_task table:


INSERT INTO ph_task
(
tk_id, tk_name, tk_description, tk_type, tk_dbs,
tk_execute, tk_start_time, tk_frequency,
k_monday, tk_tuesday, tk_wednesday, tk_thursday,
tk_friday, tk_saturday, tk_sunday,
tk_group, tk_enable, tk_priority
)
VALUES
(
0, 'IXMon Check Space', 'Check dbspace free space', 'TASK', 'sysadmin',
'ixmon_check_space', '00:00:00', '0 00:30:00',
't', 't', 't', 't', 't', 't', 't',
'USER','t',0
)



UPDATE [ 20 Aug 2010]:
I missed and IF block wrapping the UPDATE to move the existing alarm to the state ADDRESSED (lines 195-200). Like it was, it would try the update even if we didn't find an alert... This was not very serious, but it you want to call ALARMPROGRAM when the alert conditions clear up, then you need this IF or it will send alarms for every dbspace that is below the thresholds.... Sorry about this mess... So I added the IF on line 194 and the END IF on line 201.

Versão Portuguesa:

Conitnuo a trabalhar com o Open Admin Tool (OAT) e o scheduler de tarefas da base de dados e continuo a ficar bem impressionado com ambos. A verdade é que nos permitem uma abordagem estruturada na gestão de questões típicas. O exemplo que vou deixar neste artigo refere-se a um assunto trivial e qualquer DBA já se deparou com o mesmo. Neste sentido não trás nada de novo. Assim, porquê o trabalho? Porque serve como excelente exemplo de como as coisas se podem encaixar. Ao longo deste artico tentarei mostrar como tirar proveito de alguns componentes que provavelmente já utiliza nas suas instâncias (ALARMPROGRAM e OAT) para construir um mecanismo de monitorização de espaço utilizado que se pretende robusto, simples, configurável e igualmente importante, elegante.

Tenho a certeza que provavelmente já terá um script para monitorizar este aspecto, pelo que poderá estar a pensar como é que o vou convencer a desistir do mesmo e utilizar este (ou algo construído com base neste). Vejamos quais são os problemas habituais destes sripts:

  1. Normalmente são lançados pelo cron. Estranhamente ou não, alguns clientes estão a restringir a utilização do cron. Com sorte este não será o seu caso.
  2. Muitas vezes os scripts têm mecanismos para enviar alarmes dentro deles. Se necessitar de mudar alguma coisa (endereços de email, números de telefone ou pagers) poderá ter de mudar vários scripts.
  3. Na maioria dos casos os scripts não têm "memória". Isto quererá dizer, por exemplo, que continuarão a enviar alarmes sempre (enquanto o problema se mantiver). Em algumas situações isto pode ser inútil e irritante.
  4. Como os scripts não têm "memória" eles não irão "limpar" um alarme caso se verifique que o problema se resolveu.
  5. Em principio os scripts não enviam informação ao OAT. E o OAT é elegante e fácil de utilizar.
  6. Tradicionalmente, diferentes dbspaces em diferentes instâncias terão valores de ocupação aceitável diferentes uns dos outros. Isto obriga a maior complexidade dos scripts para permitir a customização.
Provavelmente conseguiria referir mais alguns problemas, mas os 6 acima deverão ser suficientes. Assim, a minha proposta de valor é criar um mecanismo que resolva todos os problemas acima, mas que traga também algumas outras vantagens:
  • Possa ser utilizado como esqueleto para outras operações de monitorização
  • Seja configurável exclusivamente dentro da própria base de dados
Como referi anteriormente iremos necessitar de vários componentes:
  1. Um script de ALARPROGRAM completamente funcional
    Já deverá ter isto, mas serão necessárias algumas alterações (poucas linhas)
  2. Open Admin Tool a funcionar
  3. O scheduler da base de dados activo
  4. Um procedimento ou função para chamar o script ALARMPROGRAM
    Li recentement um artigo do Andre Ford sobre como auto-estender os dbspaces. Nesse mesmo artigo também há um exemplo de um procedimento para efectuar isto
Comecemos então:

Alterações no script ALARMPROGRAM


Deverá criar uma nova classe para o evento gerado por esta tarefa de monitorização. Notei que o Andrew Ford indica a criação de duas classes (101 e 102 no exemplo dele), uma para enviar emails e outra para gerar SMS/paging, mas eu prefiro criar só uma e deixar a decisão de enviar email ou um pager/SMS baseada no outro parâmetro do ALARMPROGRAM, a severidade.
Na verdade, eu habitualmente utilizo uma versão alterada do ALARMPROGRAM onde eu posso definir que todos os eventos com uma dada severidade enviam um SMS e abaixo disso apenas enviam um email, ou alternativamente definir um conjunto de classes que enviam sempre ou emails ou SMS conforme a gravidade.

Em qualquer caso, configure e teste o seu script de ALARMPROGRAM para receber uma nova classe e agir em conformidade com as suas necessidades. A vantagem de utilizar o script de ALARMPROGRAM é que isto faz com que este seja o único sitío que terá de mexer caso necessite de alterar algum email ou endereço de paging ou número de SMS. Uma vez configurado irá trabalhar perfeitamente para si e será re-utilizável para qualquer tarefa de monitorização.

Open Admin Tool a funcionar

Como se verá mais adiante esta tarefa irá gerar alertas na consola do OAT. Assim terá alguma coisa para mostrar à sua chefia. Habitualmente gostam de ver gráficos agradáveis à vista.... Para além disso, e do ponto de vista prático, o OAT facilitará o agendamento e configuração da tarefa (incluindo os seus parâmetros). Falarei disto mais adiante, até porque tenho uma queixa relativamente ao OAT :)


O scheduler da base de dados activo

Como já foi referido, esta ferramenta de monitorização será implementada como uma tarefa no scheduler da base de dados (introduzido na versão 11). Portanto isto é um requisito directo.

Um procedimento ou função para chamar o script ALARMPROGRAM

Um dos requisitos, se queremos integrar a tarefa com o script de ALARMPROGRAM é ter um procedimento que possa chamar o referido script. Este procedimento irá basicamente receber parâmetros (semelhantes aos do ALARMPROGRAM), e construir um comando de sistema operativo que será depois executado com uma chamada à instrução SYSTEM(). O caminho do ALARMPROGRAM será obtido dinamicamente na base de dados sysmaster. Desta forma não terá de alterar o procedimento, caso necessite de alterar a localização do script no sistema de ficheiros. O código para este procedimento pode ser encontrado na Listagem 1) no final deste artigo. Este procedimento irá ser chamado em vários pontos da nossa tarefa


A tarefa propriamente dita: Descrição e instalação

A tarefa de monitorização é implementada como um procedimento em linguagem SPL. O código da mesma pode ser obtido na listagem 2 no final deste artigo. Vamos analisá-lo quase linha a linha.


  • Linhas 1 e 2 são apenas as instruções de DROP/CREATE. Repare-se que o procedimento recebe dois argumentos que são realmente uma grande ajuda, como veremos mais tarde:
    task_id é o id na tabela ph_task. É único para cada tareda e permite-nos referenciar outras tabelas na base de dados sysadmin que sustenta o scheduler e muitas funcionaliades do OAT
    v_id é o número da execução desta tarefa. Irá mudar (incrementalmente) cada vez que a tarefa é executada
  • As linhas seguintes, até à 19 são definições de variáveis. Não as irei explicar isoladamente pois serão referidas nos comentários abaixo
  • Linhas 20 a 25 referem-se a instruçoes de debug. Remova os comentários das linhas 23 e 24 para obter um trace da execução do procedimento, criado em /tmp (a localização pode obviamente ser mudada)
  • As linhas 29 a 31 são muito importantes. Os valores nelas definidos são o último recurso utilizado pelo procedimento se todos os outros parâmetros de configuração não forem definidos. Os valores aqui definidos por omissão são:
    default yellow threshold (90): Isto representa a percentagem de utilização de um qualquer dbspace, acima do qual será emitido um alerta amarelo (severidade 3 no ALARMPROGRAM)
    default red threshold (95): Isto representa a percentagem de utilização de um qualquer dbspace, acima do qual será emitido um alerta vermelho (severidade 4 no ALARMPROGRAM)
    number of alarms (3): Isto representa o número de alarmes a enviar. Um valor de zero sinaliza que devem ser enviados alarmes até que a situação seja resolvida

    Como veremos a seguir, estes valores podem ser sobrepostos por valores atribuídos a parâmetros de configuração da tarefa, e os limites vermelho e amarelo podem ser definidos por dbspace.
    Os valores acima só serão utilizados se os outros, mais específicos não forem definidos. E claro que estes valores podem ser alterados no código do procedimento antes de fazer a instalação no seu ambiente, de forma a adaptá-los às suas necessidades e preferências.
  • Linha 33 é muito importante dado que define a class passada ao ALARMPROGRAM referente a falta de espaço livre num dbspace. Isto deve ser ajustado ao valor da classe adicionada ao ALARMPROGRAM. Eu utilizo valores na casa dos 900 para as minhas extensões "pessoais", de forma a que não venham a sobrepor-se com classes presentes no ALARMPROGRAM, adicionadas pela IBM no futuro (não sabemos quantas poderão ser adicionadas, mas começar nos 900 dá uma margem razoável)
  • Linhas 35 a 93. Aqui tentamos ler os valores configurados para os parâmetros de funcionamento acima. Estes valores são items de configuração das tarefas. Infelizmente a versão actual do OAT não permite configurá-los via interface gráfica, ou melhor, não permite criá-los. Teremos de os inserir usando SQL e depois então podemos manipulá-los via OAT. Gostaria que o processo de criação das tarefas no OAT permitisse introduzir estes parâmetros. Mas de momento (versão 2.28) isto não está disponível e portanto teremos de os inserir via SQL. Como o fazer? Estes valores são guardados na tabela ph_threshold que contém os seguintes campos:
    name: Este é o nome do parâmetro. No nosso caso, temos os seguintes: DEFAULT NUM ALARMS, DBSPACE YELLOW DEFAULT, DBSPACE RED DEFAULT e depois podemos inserir qualquer um na forma DBSPACE YELLOW dbspace_name e DBSPACE RED dbspace_name. Penso que os nomes já explicam o significado. A ideia é que se quisermos ter limites "amarelos" e "vermelhos" para dbspaces específicos temos de inserir um parâmetro com o nome DBSPACE RED/YELLOW dbspace_name na tabela ph_thresholds. Se não existir um valor específico para um determinado dbspace o procedimento irá usar o valor indicado pelo parâmetro DBSPACE RED/YELLOW DEFAULT. Se estes também não estiverem definidos, irá usar os valores definidos nas linhas 29 a 31
    task_name: O nome da tarefa na tabela ph_task. Este valor tem de se igual ao nome que dermos a esta tarefa, e esse será o que dermos na criação do agendamento para a mesma. Neste artigo usarei "IXMon Check Space". Pode usar o que desejar, desde que mantenha a coerencia
    value: O valor do limite. Este valor será usado pela tarefa. No nosso caso, os parâmetros DBSPACE RED/YELLOW * serão representados em percentagem (1-100).
    value_type: O tipo de dados do limite (STRING ou NUMERIC). No nosso caso usaremos NUMERIC. Investigando um pouco foi possível perceber que podemos usar NUMERIC(x,y) para valores fraccionados. Não testei, mas deverá funcionar, caso isso faça sentido para as suas necessidades.
    description: Uma descrição do que o limite controla. Isto será utilizado pela interface gráfice do OAT, caso posteriormente queira editar os valores pelo OAT.

    Para dar alguns exemplos apresento de seguida as instruções para criar os parâmetros cuja definição também existe no código (número de alarmes, limites genéricos amarelo e vermelho). Usarei os mesmo valores:
    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DEFAULT NUM ALARMS', 'IXMon Check Space', '3', 'NUMERIC', 'Numero de alarmes a enviar');
    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DBSPACE YELLOW DEFAULT', 'IXMon Check Space', '90', 'NUMERIC', 'Limite amarelo generico. Sera aplicado a qualquer dbspace que nao tenha um parametro especifico');
    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DBSPACE RED DEFAULT', 'IXMon Check Space', '95', 'NUMERIC', 'Limite vermelho generico. Sera aplicado a qualquer dbspace que nao tenha um parametro especifico');


    E por exemplo, se tiver um dbspace com o nome
    llogs_dbs, dedicato aos logical logs, que esteja practicamente cheio e que portanto não fará sentido monitorizar poderia adicionar:


    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DEFAULT YELLOW llogs_dbs', 'IXMon Check Space', '100', 'NUMERIC', 'Faz com que o llogs_dbs passe todos os teses...');
    INSERT INTO ph_threshold ( name, task_name, value, value_type, description)
    VALUES ( 'DEFAULT RED llogs_dbs', 'IXMon Check Space', '100', 'NUMERIC', 'Faz com que o llogs_dbs passe todos os teses...');


  • Linha 97 cria um ciclo FOREACH. É baseado na query das linhas seguintes a qual verifica o espaço utilizado em cada dbspace do sistema.
  • Linhas 98 a 111. Esta é a query referida acima. Algumas partes dela podem não ser necessárias para este efeito, mas foi retirada de outro script... Não se preocupe, deve funcionar. Dá o número de páginas e o número de páginas livres em todos os chunks do dbspace.
    Note que esta tarefa é baseada em percentagem de utilização. Poderia ser melhorada para lidar com outros tipos de parâmetros como os GB alocados, os GB livres etc. Por agora mantive-a simples.
  • Linhas 114 a 153 são usadas para tentar obter limites específicos para o dbspace que está a ser processado. Se não forem encontrados na tabela ph_threshold os limites genéricos serão utilizados
  • Linhas 154 a 172. Aqui calculamos a percentagem de espaço utilizado e verificamos se excede o limite amarelo ou vermelho. Se tal acontecer inicializamos a variável com a cor do alerta e a mensagem de alerta. Se estivermos abaixo do limite amarelo então deixamos a variável da cor a NULL
  • Linhas 175 a 200. Se a utilização actual estiver abaixo do limite inferior (amarelo), procuramos um alerta já inserido na tabela ph_alert para este dbspace com o state igual a "NEW". Se encontrarmos alteramo-lo, mudando o estado para "ADDRESSED". Isto pode acontecer se depois de um alerta alguém apagar uma tabela por exemplo. Nesta situação não estou a chamar o ALARMPROGRAM, mas poderia fazer sentido chamá-lo com uma mensagem do tipo: "O alarme anterior para o dbspace dbspace_name foi cancelado porque estamos agora abaixo do limite definido"
  • Da 204 até ao final, código que trata as situações em que excedemos um dos limites.... Assim... Primeiro pesquisamos na ph_alert para ver se temos um alarme para este dbspace no estado "NEW". Se não tivermos (223 - 239) inserimo-lo e chamamos o ALARMPROGRAM usando o procedimento referido acima. Se já tivermos um alarme verificamos se é da mesma cor. Se não for (244 - 252), fazemos um UPDATE a dois campos:
    alert_task_seq: Fazemos isto para reposicionar o contador do alarme.
    alert_color: Alteramos o código de cor do alarm (para utilização na interface do OAT). Note que nesta altura podemos ter um alarme vermelho, com um texto de mensagem referente a um amarelo. Preferi manter assim, para mostrar que houve uma alteração entre a situação original e a actual. No entanto o alarme que é enviado ao ALARMPROGRAM tem a mensagem correspondente ao alarme vermelho. Só no OAT se verá a diferença. Se o alarme tiver a mesma cor, verificamos o campo alert_task_seq e comparamo-lo com o nósso número de execução da tarefa (dado como parâmetro na chamada do procedimento) e decidimos, baseado no número de alarmes se devemos ou não chamar o ALARMPROGRAM.
Finalmente, como é que agendamos a tarefa? Podemos fazê-lo via interface do OAT. ou se preferir podemos inserir directamente o registo na tabela ph_task:



INSERT INTO ph_task
(
tk_id, tk_name, tk_description, tk_type, tk_dbs,
tk_execute, tk_start_time, tk_frequency,
k_monday, tk_tuesday, tk_wednesday, tk_thursday,
tk_friday, tk_saturday, tk_sunday,
tk_group, tk_enable, tk_priority
)
VALUES
(
0, 'IXMon Check Space', 'Check dbspace free space', 'TASK', 'sysadmin',
'ixmon_check_space', '00:00:00', '0 00:30:00',
't', 't', 't', 't', 't', 't', 't',
'USER','t',0
)



Atualização [ 20 Ago 2010]:

Tinha-me esquecido de um bloco condicional (IF) em volta do UPDATE que altera o estado de um alerta já existente para 'ADDRESSED' (linhas 195-200)
Como estava, o UPDATE era sempre feito mesmo quando não tinhamos encontrado um alerta. Isto não seria um erro grave, mas caso também queira chamar
o ALARMPROGRAM quando as condições do alarme são reveridas então necessitamos deste ID, ou a tarefa irá enviar alarme para cada dbspace que esteja dentro dos limites
Peço desculpa pela confusão.... Portanto adicionei o IF da linha 194 e o END IF da linha 201.




Listing 1:



DROP PROCEDURE call_alarmprogram;
CREATE PROCEDURE call_alarmprogram(
v_severity smallint,
v_class smallint,
v_class_msg varchar(255) ,
v_specific varchar(255) ,
v_see_also varchar(255)
)


-- severity: Category of event
-- class-id: Class identifier
-- class-msg: string containing text of message
-- specific-msg: string containing specific information
-- see-also: path to a see-also file

DEFINE v_command CHAR(2000);
DEFINE v_alarmprogram VARCHAR(255);

--SET DEBUG FILE TO '/tmp/call_alarmprogram.dbg' WITH APPEND;
--TRACE ON;

SELECT
cf_effective
INTO
v_alarmprogram
FROM
sysmaster:sysconfig
WHERE
cf_name = "ALARMPROGRAM";

LET v_command = TRIM(v_alarmprogram) || " " || v_severity || " " || v_class || " '" || v_class_msg || "' '" || NVL(v_specific,v_class_msg) || "' '" || NVL(v_see_also,' ') || "'";
SYSTEM v_command;
END PROCEDURE;


Listing 2:



1 DROP FUNCTION ixmon_check_space;
2 CREATE FUNCTION "informix".ixmon_check_space(task_id INTEGER, v_id INTEGER) RETURNING INTEGER
3
4 DEFINE v_default_num_alarms, v_num_alarms SMALLINT;
5 DEFINE v_default_yellow_threshold, v_default_red_threshold SMALLINT;
6 DEFINE v_generic_yellow_threshold, v_generic_red_threshold SMALLINT;
7 DEFINE v_dbs_yellow_threshold, v_dbs_red_threshold SMALLINT;
8 DEFINE v_name LIKE ph_threshold.name;
9 DEFINE v_dbsnum INTEGER;
10 DEFINE v_dbs_name CHAR(128);
11 DEFINE v_pagesize, v_is_blobspace, v_is_sbspace, v_is_temp SMALLINT;
12 DEFINE v_size, v_free BIGINT;
13 DEFINE v_used DECIMAL(4,2);
14 DEFINE v_alert_id LIKE ph_alert.id;
15 DEFINE v_alert_task_seq LIKE ph_alert.alert_task_seq;
16 DEFINE v_alert_color,v_current_alert_color CHAR(6);
17 DEFINE v_message VARCHAR(254,0);
18
19 DEFINE v_severity, v_class SMALLINT;
20 ---------------------------------------------------------------------------
21 -- Uncomment to activate debug
22 ---------------------------------------------------------------------------
23 --SET DEBUG FILE TO '/tmp/ixmon_check_space.dbg' WITH APPEND;
24 --TRACE ON;
25
26 ---------------------------------------------------------------------------
27 -- Default values if nothing is configured in ph_threshold table
28 ---------------------------------------------------------------------------
29 LET v_default_yellow_threshold=90;
30 LET v_default_red_threshold=95;
31 LET v_default_num_alarms=3;
32
33 LET v_class = 908;
34
35 ---------------------------------------------------------------------------
36 -- Get the number of times to call the alarm...
37 ---------------------------------------------------------------------------
38
39 LET v_num_alarms=NULL;
40
41 SELECT
42 value
43 INTO
44 v_num_alarms
45 FROM
46 ph_threshold
47 WHERE
48 task_name = 'IXMon Check Space' AND
49 name = 'DEFAULT NUM ALARMS';
50
51 IF v_num_alarms IS NULL
52 THEN
53 LET v_num_alarms=v_default_num_alarms;
54 END IF;
55
56 ---------------------------------------------------------------------------
57 -- Get the defaults configured in the ph_threshold table
58 ---------------------------------------------------------------------------
59 LET v_generic_yellow_threshold=NULL;
60 LET v_generic_red_threshold=NULL;
61
62 SELECT
63 value
64 INTO
65 v_generic_yellow_threshold
66 FROM
67 ph_threshold
68 WHERE
69 task_name = 'IXMon Check Space' AND
70 name = 'DBSPACE YELLOW DEFAULT';
71
72 IF v_generic_yellow_threshold IS NULL
73 THEN
74 LET v_generic_yellow_threshold=v_default_yellow_threshold;
75 END IF;
76
77
78
79 SELECT
80 value
81 INTO
82 v_generic_red_threshold
83 FROM
84 ph_threshold
85 WHERE
86 task_name = 'IXMon Check Space' AND
87 name = 'DBSPACE RED DEFAULT';
88
89 IF v_generic_red_threshold IS NULL
90 THEN
91 LET v_generic_red_threshold=v_default_red_threshold;
92 END IF;
93
94 ---------------------------------------------------------------------------
95 -- Foreach dbspace....
96 ---------------------------------------------------------------------------
97 FOREACH
98 SELECT
99 d.dbsnum, d.name, d.pagesize, d.is_blobspace, d.is_sbspace, d.is_temp,
100 SUM(c.chksize), SUM(c.nfree)
101 INTO
102 v_dbsnum, v_dbs_name, v_pagesize, v_is_blobspace, v_is_sbspace, v_is_temp,
103 v_size, v_free
104 FROM
105 sysmaster:sysdbspaces d, sysmaster:syschunks c
106 WHERE
107 d.dbsnum = c.dbsnum
108
109
110 GROUP BY 1, 2, 3, 4, 5, 6
111 ORDER BY 1
112
113
114 ---------------------------------------------------------------------------
115 -- Get specific dbspace red threshold if available....
116 ---------------------------------------------------------------------------
117 LET v_name = 'DBSPACE RED ' || TRIM(v_dbs_name);
118
119 SELECT
120 value
121 INTO
122 v_dbs_red_threshold
123 FROM
124 ph_threshold
125 WHERE
126 task_name = 'IXMon Check Space' AND
127 name = v_name;
128
129 IF v_dbs_red_threshold IS NULL
130 THEN
131 LET v_dbs_red_threshold = v_generic_red_threshold;
132 END IF;
133
134 ---------------------------------------------------------------------------
135 -- Get specific dbspace yellow threshold if available....
136 ---------------------------------------------------------------------------
137 LET v_name = 'DBSPACE YELLOW ' || TRIM(v_dbs_name);
138
139 SELECT
140 value
141 INTO
142 v_dbs_yellow_threshold
143 FROM
144 ph_threshold
145 WHERE
146 task_name = 'IXMon Check Space' AND
147 name = v_name;
148
149 IF v_dbs_yellow_threshold IS NULL
150 THEN
151 LET v_dbs_yellow_threshold = v_generic_yellow_threshold;
152 END IF;
153
154 ---------------------------------------------------------------------------
155 -- Calculate used percentage and act accordingly...
156 ---------------------------------------------------------------------------
157 LET v_used = ROUND( ((v_size - v_free) / v_size) * 100,2);
158 IF v_used > v_dbs_red_threshold
159 THEN
160 LET v_alert_color = 'RED';
161 LET v_message ='DBSPACE ' || TRIM(v_dbs_name) || ' exceed the RED threshold (' ||v_dbs_red_threshold||'). Currently using ' || v_used ;
162 LET v_severity = 4;
163 ELSE
164 IF v_used > v_dbs_yellow_threshold
165 THEN
166 LET v_alert_color = 'YELLOW';
167 LET v_message ='DBSPACE ' || TRIM(v_dbs_name) || ' exceed the YELLOW threshold (' ||v_dbs_yellow_threshold||'). Currently using ' || v_used ;
168 LET v_severity = 3;
169 ELSE
170 LET v_alert_color = NULL;
171 END IF
172 END IF
173
174
175 IF v_alert_color IS NULL
176 THEN
177 ---------------------------------------------------------------------------
178 -- The used space is lower than any of the thresholds...
179 -- check to see if there is an already inserted alarm
180 -- If so... clear it...
181 ---------------------------------------------------------------------------
182 LET v_alert_id = NULL;
183
184 SELECT
185 p.id, p.alert_task_seq, p.alert_color
186 INTO
187 v_alert_id, v_alert_task_seq, v_current_alert_color
188 FROM
189 ph_alert p
190 WHERE
191 p.alert_task_id = task_id
192 AND p.alert_object_name = v_dbs_name
193 AND p.alert_state = "NEW";
194 IF v_alert_id IS NOT NULL
195 UPDATE
196 ph_alert
197 SET
198 alert_state = 'ADDRESSED'
199 WHERE
200 ph_alert.id = v_alert_id;
201 END IF;
202 ELSE
203
204 ---------------------------------------------------------------------------
205 -- The used space is bigger than one of the thresholds...
206 -- Check to see if we already have an alert in the ph_alert table in the
207 -- state NEW ...
208 ---------------------------------------------------------------------------
209
210 LET v_alert_id = NULL;
211
212 SELECT
213 p.id, p.alert_task_seq, p.alert_color
214 INTO
215 v_alert_id, v_alert_task_seq, v_current_alert_color
216 FROM
217 ph_alert p
218 WHERE
219 p.alert_task_id = task_id
220 AND p.alert_object_name = v_dbs_name
221 AND p.alert_state = "NEW";
222
223 IF v_alert_id IS NULL
224 THEN
225 ---------------------------------------------------------------------------
226 -- There is no alarm... or the alarm changed from NEW
227 ---------------------------------------------------------------------------
228
229 INSERT INTO
230 ph_alert (id, alert_task_id, alert_task_seq, alert_type, alert_color, alert_time,
231 alert_state, alert_state_changed, alert_object_type, alert_object_name, alert_message,
232 alert_action_dbs)
233 VALUES(
234 0, task_id, v_id, 'WARNING', v_alert_color, CURRENT YEAR TO SECOND,
235 'NEW', CURRENT YEAR TO SECOND,'DBSPACE', v_dbs_name, v_message, 'sysadmin');
236
237 EXECUTE PROCEDURE call_alarmprogram(v_severity, v_class, 'DBSPACE used space too high',v_message,NULL);
238
239 ELSE
240 ---------------------------------------------------------------------------
241 -- There is an alarm...
242 -- Need to check if it's still the same color...
243 ---------------------------------------------------------------------------
244 IF v_current_alert_color != v_alert_color
245 THEN
246 ---------------------------------------------------------------------------
247 -- Change the color... And reset the seq to reactivate the couter...
248 ---------------------------------------------------------------------------
249 UPDATE ph_alert
250 SET (alert_task_seq, alert_color) = (v_id,v_alert_color)
251 WHERE ph_alert.id = v_alert_id;
252 EXECUTE PROCEDURE call_alarmprogram(v_severity, v_class, 'DBSPACE used space too high',v_message,NULL);
253 ELSE
254 IF (v_id < v_alert_task_seq + v_num_alarms) OR v_num_alarms = 0
255 THEN
256 EXECUTE PROCEDURE call_alarmprogram(v_severity, v_class, 'DBSPACE used space too high',v_message,NULL);
257 END IF;
258 END IF;
259 END IF;
260 END IF;
261 END FOREACH
262
263 END FUNCTION;

Friday, July 30, 2010

OAT plugins: Do it yourself! / Plugins para o OAT: Faça você mesmo!

This article is written in English and Portuguese
Este artigo está escrito em Inglês e Português


English version:

Some time ago, during a customer engagement, I felt the need to be able to show them if there were lock waiting sessions in their most busy system. Of course any old time Informix DBA will tell that onstat -k/K is able to provide this. But in their environment they needed this to be available to a broader audience than just the DBA team (who are the ones with database server command line access). So we decided to create a simple PHP script with Informix connection that showed it in a web page available in their Intranet. They're currently moving into using Open Admin Tool (OAT) and I though it would be nice to move that into OAT. Note that OAT already includes some reports that provide similar (although with less detail) information (session waiting report).
So I thought it would be nice to do it properly and create a plug-in. I searched around, specifically in OAT's home ( http://www.openadmintool.org ) and found a link to an article about creating plugins in OAT: http://www.ibm.com/developerworks/db2/library/techarticle/dm-0808vonbargen/
The author of this article is Erika Von Bargen, an IBM colleague, which is very active in the OAT specific IIUG mailing list. People who went to this year's IIUG conference possibly also know her since she was there presenting sessions about OAT.
Now... To tell you the complete truth, sometimes I'm very lazy (aren't we all at times?) when it comes to properly read documentation. So I just jumped into a terminal and started looking at an example plug-in provided with OAT. In a few minutes I had changed the query and I was seeing the information we were used to see in the customized web page. Obviously every message and column header was missing, the menus were wrong etc. But It was enough to become enthusiastic about this subject. I posted a few messages in OAT's mailing list, and had a quick feedback from Erika, which was a great help.
After the initial startup I decided to do it properly, and I read the article above, and it's a nice, clear and concise article. It's perfect to get you started.

So, after the initial "code, test, fix error, test....", instead of the "read, plan, code, test, fix..." I was ready to do it properly and I took some time at home to play with this. And I kept adding some features, some usability details and finally got to a point where I think I have a working plug-in. It has four options:
  1. List all the instance locks
    This shows information similar to onstat -K, but most of the information is immediately readable (meaning you don't have to query sysmaster to get the table names, and you don't have to run onstat -u | grep .... to get the session number.
  2. List locks with waiters
    This shows information on every lock that has a lock list. The information includes:
    - The owner username, session number, process id and client machine
    - The waiter username, session number, process id and client machine
    - The table/index in question, the time the lock was established and how long the wait is waiting
  3. List locks per table
    This shows information about locking for every active table in your system. The information includes the number of currently held locks, the number of lock requests made on the table, the number of lock waits, the number of deadlocks and the number of lock timeouts
  4. List locks per session
    This shows the number of currently held locks, the number of lock requests made by the session, the number of lock waits, the number of deadlocks and the number of lock timeouts
One of the great things about OAT is how easy we can localize our plug-ins. In this case, due to my linguistic limitations, I've only included the standard English messages and naturally the Portuguese ones. I'd be glad to add more, if people who can write in other languages (already used by OAT) could send me the translated messages. The number of words/phrases to translate is really short and to be honest I'm tempted to give some online translation a try... But I would prefer some user contributions, in case you find the plug-in useful....
Also, I'd love to receive feedback about bugs or improvements. I have a few ones on my mind, but it's always better to listen to others...

So, where is it? I've just upload it to IIUG software repository. It's the first time I do it, so I'm not sure how long will it take to become available
[UPDATE 31 Aug 2010]: It's already available on the IIUG repository .

If you want to check the aspect of it, before giving it a try, please see below some snapshots.

How stable is it? It wasn't tested on big systems. But all it does is query the sysmaster. So, the worst thing that could happen would be giving you some wrong information. It should not do any harm to your system. In any case treat this as a beta release for now. One thing that can happen is that the pages show all the information fetched by the queries. In large systems, with thousands of locks, sessions, or tables, this can translate into very big HTML pages... Be aware of this.
To the best of my knowledge the queries return proper results. The locks with waiters page is based on a query being used for a fairly long time. The other queries were created and tested in a very controlled environment, so admittedly it's possible that they don't cover some situations.

Every feedback is welcome. Although OAT already includes some functionality in this area, I think this will give you a more direct and condensed tool to monitor your database locking activity. As such I believe the plug-in can be useful and it certainly can be improved.


Versão portuguesa:


Há algum tempo atrás, durante um trabalho num cliente, senti a necessidade de lhes mostrar se tinham sessões à espera de locks no sistema mais utilizado. Claro que qualquer DBA Informix com alguma experiência dirá que o onstat -k/K é capaz de responder a esta necessidade. Mas no caso que refiro, era necessário que esta informação estivesse disponível para uma audiência mais alargada que apenas a equipa de DBAs (os únicos com acesso à linha de comando no servidor de base de dados).
Por isso, decidimos criar um script PHP, simples, com conexão ao Informix, que mostrasse a informação numa página Web disponível na Intranet da empresa. Actualmente estão a começar a usar o Open Admin Tool (OAT) e pareceu-me adequado colocar esta funcionalidade dentro da mesma ferramenta. Note-se que o OAT já fornece informaçao semelhante (embora com menos detalhe) no relatório de sessões em espera.
Assim pensei que seria bom fazer isto como deve ser e criar um plug-in. Procurei informação, especificamente no website do OAT ( http://www.openadmintool.org ) e encontrei uma ligação a um artigo sobre criação de plug-ins para o OAT: http://www.ibm.com/developerworks/db2/library/techarticle/dm-0808vonbargen/

A autora deste artigo é a Erika Von Bargen, uma colega da IBM, bastante activa na mailing list do OAT do IIUG. Quem teve oportunidade de estar na conferência do IIUG este ano também teve oportunidade de assistir a sessões apresentadas por ela, precisamente relacionadas com o OAT
Bom... Para ser franco, ocasionalmente sou bastante preguiçoso (não seremos todos de vez em quando?) quando toca a ler documentação. Por isso, abri uma sessão e comecei a estudar um exemplo de plug-in fornecido com o OAT. Em apenas alguns minutos, tinha mudado a query que lhe serve de base e estava a ver a informação a que estávamos habituados na página personalizada. Naturalmente, todas as mensagens e cabeçalhos de tabelas estavam errados ou em falta, os menus estavam errados etc. Mas foi o suficiente para me tornar um entusiasta do assunto. Coloquei algumas mensagens na mailing list do OAT e obtive respostas rápidas da Erika que foram uma grande ajuda.
Após o arranque inicial, decidi que devia fazer as coisas devidamente, e li o artigo mencionado acima, que é bom, claro e conciso. Ideal para quem quer começar com a tarefa de criar um plug-in.

Assim, após a abordagem inicial de "codificar, testar, corrigir erros, testar....", passei para a de "ler, planear, codificar, testar, corrigir....". Estava preparado para fazer isto como deve ser e disponibilizei algum tempo em casa para "brincar" com isto. E fui adicionando funcionalidades, detalhes para melhorar a usabilidade, e finalmente cheguei a um ponto onde julgo ter um plug-in que funciona.
Tem quatro opções:


  1. Listar os bloqueios na instância
    Isto mostra informação semelhante ao onstat -K, mas a maioria da informação é de leitura imediata (ou seja, não é necessário pesquisar na sysmaster para obter os nomes das tabelas, e não temos de correr um onstat -u | grep ... para obter o número da sessão
  2. Listar os bloqueios com fila de espera
    Isto mostra informação de cada bloqueio que tenha uma lista de espera. Esta informação incluí:
    - O dono do bloqueio, incluindo nome de utilizador, número de sessão, número de processo e a máquina cliente
    - Quem está à espera, incluíndo o nome de utilizador, número de sessão, número de processo e a máquina cliente
    - A tabela/indíce que tem o bloqueio, o instante em que o bloqueio foi estabelecido e há quanto tempo existe a espera
  3. Listar os bloqueios por tabela
    Isto mostra informação sobre os bloqueios para todas as tabelas activas do seu sistema.
    A informação incluí o número de bloqueios activos no momento, o número de pedidos de bloqueios feitos sobre a tabela, o número de esperas por bloqueios sobre a tabela, o número de deadlocks que envolveram a tabela, e o número de vezes que os tempos de espera por bloqueios expiraram
  4. Listar os bloqueios por sessão
    Isto mostra o número de bloqueios que cada sessão mantém activos, o número de pedidos de bloqueio feitos pelas sessões, o número de esperas por bloqueios, o número de deadlocks da sessão, e o número de tempos de espera por bloqueios expirados

Uma das coisas boas do OAT é a facilidade com que se pode localizar ou traduzir os nossos plug-ins. Devido às minhas limitações linguísticas, neste caso, o plug-in só incluí as mensagens em Ingês (standard) e naturalmente em Português. Gostaria de adicionar mais, caso quem escreva noutras línguas (das já usadas pelo OAT) me queira enviar as mensagens traduzidas. O número de palavras/frases a traduzir é realmente pequeno, e para ser honesto sinto-me tentado a experimentar os tradutores automáticos online. Mas seria preferível se alguém contribuísse caso considere o plug-in útil.

Adicionalmente, terei todo o gosto em receber comentários sobre bugs ou melhorias. Tenho algumas em mente, mas é sempre melhor escutar opiniões de outros...

Então, onde está o plug-in? Acabei de fazer o envio para o repositório de software do IIUG. É a primeira vez que o faço, e sinceramente não sei quanto tempo levará a ficar disponível.
[ACTUALIZAÇÂO 31 Aug 2010]: Já está disponível no repositório de software do IIUG.

Se desejar ver o aspecto do plug-in, antes de o testar, por favor veja as imagens abaixo.

Quão estável é o plug-in? Não foi testado em sistemas grandes. Mas tudo o que faz é pesquisar a sysmaster. Por isso, além de alguma possível informação errada não deverá causar qualquer problema nos seus sistemas. Em todo o caso trate isto como uma release beta por enquanto. Algo que pode acontecer é que as páginas mostram toda a informação obtida nas queries. Em sistemas grandes, com milhares de bloqueios, sessões ou tabelas, isto pode traduzir-se em páginas HTML muito grandes.... Tenha algum cuidado com isso.
Tanto quanto me apercebi, as pesquisas retornam resultados correctos. A lista de bloqueios com lista de espera baseia-se numa query que utilizo há bastante tempo. As outras pesquisas foram criadas e testadas num ambiente muito controlado, logo é possível que possam não prever algumas situações.

Todo o feedback será muito bem vindo. Apesar de o OAT já incluir alguma funcionalidade nesta área, julgo que este plug-in será uma ferramenta mais directa e condensada para monitorizar toda a actividade relacionada com bloqueios nas suas instâncias Informix. Como tal, acredito que o plug-in possa ser útil e certamente poderá ser melhorado.


Snapshots/Écrans:

















Lock List
Lista de bloqueios


















Lock waiters
Lista de bloqueios com fila de espera

















Locks per table
Bloqueios por tabela























Locks per session
Bloqueios por sessão

Tuesday, May 4, 2010

OAT: One Admirable Tool

One first warning: I'm still lacking time to write the kind of articles I like, which are focused, technical and relatively deep.
Having said that I feel better proceeding with yet another "chat like" article. And in this I would like to write about Open Admin Tool, or simply OAT.

I had two great sessions in IIUG 2010 conference, which although not specifically about OAT, were somehow related to it. I'm talking about John Miller session about Auto Update Stats, and Hyun-Ju Vega session covering SQLTRACE. Unfortunately I had to miss the session about OAT itself from Erika Von Bargen (i was presenting at the same time). Now, why did I like this sessions so much? The speakers were great but they were not the reason. The reason is fairly simple: They changed the way I thought about some things and they made me look into OAT again. I don't recall having written many things about OAT, but to be honest I though it was nice, but maybe more directed to the new people starting with Informix. Long time Informix DBAs obviously have a pack of scripts for the trivial stuff: running update statistics (I wrote my own scripts based on previous work from Informix staff and obviously we all know dostats from Art Kagel), check some performance issues (sessions with more CPU usage, tables with full scans, tables with more read/writes etc.), historical data from the instance (profile counters, table access stats etc.).

So, a nice tool, much better than previous attempts like Informix Server Administrator (ISA), nice looking but maybe for "newbies". Honestly this was more or less in my mind, even though I did not have full conscience about it.

Then I assisted this two sessions. And during the sessions we were guided through lots of "accessories". John showed several tasks, the task scheduler, the intelligence behind the auto update stats, and eventually even without noticing it, he effectively showed the audience how easy it is to work with OAT. Then Hyun-Ju, guided us through a real case scenario where SQLTRACE was key to solve a customer issue. Again, OAT was not the main focus, but the ease of usage and how we can take advantage of SQLTRACE in OAT SQL Explorer again surprised me.

Then a real life scenario came... Today, while working on a customer, I was asked to help the DBA team to understand a big memory consumption from some sessions in a development instance. The developer team really didn't noticed anything strange, since the engine was doing what was expected. But the DBAs noticed some sessions occasionally grabbed around 8-10 times the maximum memory usually consumed by most of their sessions. The more or less strange thing was that the session allocated the memory but when we got to see that, the memory was mostly free (although still allocated to the session). So, no strange pool usage was evident. Since my job their is also to try to pass some knowledge, I showed them how to setup SQLTRACE for one specific user and we asked that user to run the job(s). After lunch we had everything explained in the SQLTRACE buffers. The onstat -g his could be used to get evidences, but I decided to give OAT a try. And there it was, in a graphical manner all the session steps. We noticed that they had a terrible amount of recursive procedures (actually proc_a calls proc_b and proc_b calls proc_a) inside a foreach loop. So a lot of stack was necessary to hold the context during execution and so the memory was allocated and then became free.

Could I have made this with other tools? Probably. Lots of onstats, scripts etc. Would it be so easy? Not even in my best dreams!

The true magic about OAT is not OAT itself. It's how OAT glues several new features and makes them usable. Think about some things we can do in OAT:
  1. Manage and use SQL history
  2. Manage all the engine programmable tasks
  3. Generate performance and usage reports
  4. Change the engine configuration
  5. Optimize storage
  6. Manage your cluster and replication
All these have something behind that you frequently see in the "new features" section of the release notes (using the same order as the previous list):

  1. SQLTRACE
  2. Database scheduler
  3. Automatic tasks and internal engine profiling
  4. SQL API
  5. Compression
  6. MACH 11
I could have made the list bigger. The point is that probably for the first time in Informix history we have a tool that matches the "features". This has always been one of the most criticized (what was probably fair) aspects of Informix. But since v11.10 and the beginning of OAT we see that OAT has been upgraded fixpack after fixpack to match the engine new functionalities. This shows it's not another tool that tries to keep critics away, but is in fact a fundamental piece of the engine. And it follows the engine "DNA": Simple to install, simple to use, reliable and light.

Is it perfect? Probably nothing is... I think one area or aspect could be improved. And here I'm just echoing a customer thoughts. OAT should be able to provide a view and working mode for enterprise wide environments. Meaning some of it's features should be aware of all the instances configured in a customer environment. Some simple examples:

  • A single alarm viewer page for all the instances (maybe "all belonging to one group")
  • The monitors could collect/centralize into a common repository
  • The monitors should have self conscience of the instances in a MACH-11 cluster
Some of these points and others I don't mention here could be provided by:
  • Replicate each instance captured data to a common repository (either by ER or simple tasks)
  • Create a plugin for showing data in that centralized repository
  • Change some of the monitors to INSERT also the server name and direct the data to the primary server (for read only secondaries) using for example the connection manager
So, this limitations can be solved by customers. But it would be nice to see some improvements in the future.
I'd like to end the article sending my compliments and appreciation to the OAT development team and leave here a few links to help you understand what's behind OAT: