Showing posts with label informix. Show all posts
Showing posts with label informix. Show all posts

Saturday, June 4, 2011

HP-UX: What now? / E agora?

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

English version:

You know I usually stick to Informix related topics, but a few weeks ago something was announced that has to make us think... As we all know by now, Oracle announced that future versions of their software products will not support HP-UX running on Intel Itanium chips.
Why do we have to think about it? Well, from my personal perspective because it raises a lot of serious doubts/questions. Let's see:

  1. First you read in the announcement that Intel is not truly committed to Itanium. The exact words are "Intel management made it clear that their strategic focus is on their x86 microprocessor and that Itanium was nearing the end of its life". Intel denied this in the following days. Who do we believe? The company that owns the chip in question or another (now also) hardware supplier? Is it normal that a company discontinues it's products on a platform that has not announced it's end of life plans?

  2. The announcement was made just before an important HP shareholders meeting... We could of course believe this was just a coincidence

  3. In the last months a lot of news came up referring to personal wars between Oracle's and HP's executives (ex HP CEO is now a very important Oracle executive). Meanwhile ex SAP CEO has been appointed as HP CEO, and Oracle and SAP had an ongoing court trial started at the time he was SAP's CEO. All these an point 2) may lead us to the feeling that while personalities clash, customers suffer. There's nothing wrong with having strong personalities as leaders of large companies, on the contrary. But we would expect their egos not to cause harm to their customers (of course "harm" translates into costs, uncertainty, fear and doubts - typically FUD that competitors like to spread, but in this case competitors don't have to bother...)

  4. Oracle mentions that others (Microsoft and Red Hat) have previously discontinued support for Itanium. This is true, but there is a big difference: The market share that these two companies had in the Itanium market was considered irrelevant. Now, for Oracle, the situation is completely different. They have a large share of Itanium customers (accordingly to this blog, there are around 140.000 Oracle/Itanium customers)

  5. Some people argue that supporting a platform has it's costs. Of course this is true, but the costs are certainly well covered if the above number holds true. That's part of the business. In order to provide a product, you incur in certain costs. And also note that Oracle always said, wrote an publicized that their code base was the same independently of the platform. So using this as an argument is hardly acceptable...

  6. Many people think this is just a commercial move from Oracle. They're trying to weak a competitor position while at the same time they hope to raise their own hardware sales. We can accept that this is normal, but we should keep in mind a few things. First, just a while ago Oracle choose HP as an hardware partner (remember Exadata?). Secondly Oracle CEO has said that it would like to see Oracle becoming the IBM of the sixties (integrated stack where the margins would be bigger), but that it would keep its software running on competitor platforms. Well something has changed :)

  7. Will this be the only case, or will Oracle do the same in the future with other OS? The fact is that the number of OS and Hardware vendors for enterprise computing is shrinking. You currently have Microsof Windows on Intel x86, IBM AIX on System p, HP-UX on Itanium, Solaris Sparc, Linux on Intel x86, and Solaris on Intel (I'm explicitley forgeting other platforms like IBM System Z and HP NonStop). Oracle is doing it's best to eliminate HP-UX/Itanium. Will it stop there? Or will it proceed it's path to become "the IBM of the 1960s" (meaning the closed system that locked customers in)? Note that IBM still suffers with the image it created at the time.

The above are just a list of some important points. I may be missing a few. The announcement must had a significant impact on HP Itanium customers running Oracle software. Imagine that you wake up one morning and find out that the software vendor you choose gave up supporting your platform. Of course you'll have support for your existing products, but you'd really appreciate a roadmap... By the way, wasn't that the same company that 10 years ago accused IBM of not having a roadmap for Informix? It's funny when we put things into perspective...
So, assuming you're one of those customers what will you do? You have a few options:
  1. You jump on the Oracle train and buy a one way ticket... I mean you choose Sparc for your upcoming hardware renovation... You don't know where the train will take you... You don't even know how much it will cost you... Specially because you just bought a one way ticket... Once you're "there" you'll figure what what price the next ride will cost... One thing you know: You'll be traveling with the same company since no other operates in the same region...

  2. You choose another hardware platform, and you really hope the same trick will not be played again

  3. You change your software supplier
I'd say none of the options above looks particularly attractive. But in case you need another database (and you're able to get your application running against it), you should really consider Informix. Here's why:
  1. It's robust, easy to use, reliable, works well in virtualized environments etc., but you should already know that

  2. It has a roadmap and has just completed a decade of improvements after the IBM acquisition

  3. It belongs to a company that will try to sell you it's hardware, because it believes it's good, and not because it tends to be the only option to run it's software

  4. It's already very well integrated with many of the other IBM software portfolio, and this is assumed to be a continuous effort

  5. It has a long history of working well with HP-UX (traditionally on PA-RISC and now with Itanium). A search for "informix" in the HP site will show you several HP documents about integration between Informix and HP-UX
To wrap up this article, I'd like to put here a few links that relate to this topic. I hope they'll allow you to see what's being written about this Oracle announcement, and to form your own opinion about it.




VersĂŁo Portuguesa:

Normalmente restrinjo-me a assuntos exclusivamente relacionados com Informix, mas há algumas semanas atrás foi anunciado algo que nos tem de fazer pensar.... Como já todos deveremos saber nesta altura, a Oracle anunciou que futuras versões do seu software não irão suportar HP-UX a correr em chips Itanium.
Porque é que devemos reflectir sobre isto? Bom, na minha opinião pessoal porque isto levanta uma série de dúvidas e questões importantes. Vejamos:

  1. Começamos por ler no anúncio que a Intel não está verdadeiramente empenhada no Itanium. As palavras exactas (tradução pessoal) foram: "... a gestão da Intel deixou claro que o foco da sua estratégia é a linha de processadores x86 e que o Itanium se está a aproximar do fim de vida..." . A Intel negou isto nos dias seguintes. Em quem acreditamos? Na empresa que detém o processador em questão ou noutra empresa (agora também) fornecedora de hardware? Será normal que uma empresa anuncie o fim de desenvolvimento dos seus produtos numa plataforma cujo fim de vida não foi sequer anunciado?

  2. O anĂşncio foi feito imediatamente antes de um encontro de accionistas da HP.... Podemos claro acreditar que isto foi apenas uma coincidĂŞncia

  3. Nos últimos meses vieram a público uma série de notícias referentes a guerras pessoais entre executivos da HP e Oracle (o ex CEO da HP é agora um quadro importante na Oracle - o número dois na verdade, logo abaixo do Larry Ellison). Entretanto o ex CEO da SAP foi nomeado CEO da HP, e a Oracle e HP tinham um processo em tribunal que remonta ao tempo em que o mesmo era CEO da SAP. Tudo isto e o ponto 2) podem levar-nos a pensar que enquanto as personalidades se chocam os clientes sofrem. Não há nada de errado em que grandes empresas tenham personalidades fortes na sua liderança, bem pelo contrário. Mas seria de esperar que os egos não prejudiquem os respectivos clientes. O "prejuízo" traduz-se em custos, incerteza, medos e dúvidas - o que em Inglês se chama "FUD - fear, uncertainty and doubt -", que normalmente é espalhado pela concorrência, mas que neste caso nem requer esforço da concorrência pois é feiro pelos próprios.

  4. A Oracle referiu que outros (Microsoft e Red Hat) já tinham previamente descontinuado o suporte para Itanium. Isto é verdade, mas há uma enorme diferença: A quota de mercado que estas duas empresas tinham em Itanium não é comparável à da Oracle. Esta tem uma grande percentagem dos clientes Itanium a usarem os seus produtos (de acordo com este blog, existem cerca de 140.000 clientes Oracle/Itanium)

  5. Algumas pessoas defendem que suportar uma plataforma tem os seus custos. Isto é uma verdade óbvia., mas esses custos são largamente cobertos se os números acima forem correctos. Isso faz parte do negócio. Para fornecer um produto as empresas (de qualquer tipo) incorrem em custos. Note-se ainda que a Oracle sempre disse, escreveu e publicitou que o seu código era o mesmo independente da plataforma. Por tudo isto, o argumento do custo de suportar uma plataforma não me parece aceiável...

  6. Muitas pessoas acreditam que isto Ă© apenas uma manobra comercial da Oracle. EstĂŁo a tentar enfraquecer um concorrente ao mesmo tempo que tentam aumentar as suas p´roprias vendas de hardware. Podemos encarar isto como algo relativamente normal, mas devemos manter em mente uma sĂ©rie de factos. Primeiro, apenas há algum tempo atrás, a Oracle escolheu a HP como o seu parceiro de hardware (lembram-se do Exadata?). Segundo, o CEO da oracle disse que gostava de ver (tradução pessoal) A Oracle tornar-se a IBM dos anos sessenta (soluções integradas onde as margens sĂŁo maiores), mas que manteria o seu software a correr nas plataformas da concorrĂŞncia. Parece que algo mudou entretanto... :)

  7. Será este um caso único, ou irá a Oracle fazer os mesmo com outras plataformas? A verdade é que as plataformas (SO e hardware) para computação empresarial estão a diminuir. Actualmente temos Microsof Windows em Intel x86, IBM AIX em System p, HP-UX em Itanium, Solaris Sparc, Linux em Intel x86, e Solaris em Intel (estou a omitir outras plataformas como IBM System Z e HP NonStop) . A Oracle está a fazer o seu melhor para eliminar HP-UX em Itanium. Irá parar por aí? Ou irá prosseguir os seu caminho para se tornar a "IBM dos anos sessenta" (neste caso um sistema fechado que prende os clientes)? Note-se que a IBM ainda sofre com a imagem criada nessa altura.

Acima está uma lista de alguns pontos importantes. Posso ter esquecido alguns. O anúncio deve ter tido um impacto significativo nos clientes HP Itanium que utilizam software Oracle. Imagine que acorda uma manhã e descobre que o fornecedor de software que seleccionou, deixou de suportar a sua plataforma. Claro que terá suporte para os produtos que já existem, mas certamente apreciaria a existência de um roadmap... Aliás, não foi esta a mesma empresa que há 10 anos atrás acusou a IBM de não ter um roadmap para Informix? É engraçado quando se colocam as coisas em perspectiva...
Assim, assumindo que é um desses clientes, o que irá fazer? A meu ver tem algumas opções:
  1. Apanha o compboio da Oracle e compra um bilhete de ida... Ou seja, escolhe SPARC para a sua próxima renovação de hardware... Não sabe para onde o comboio o leva... Nem sequer sabe quanto lhe vai custar... Especialmente porque comprará apenas um bilhete de ida... Depois de "lá" chegar logo verá qual o preço da próxima "viagem"... Uma coisa será certa: Irá viajar com a mesma empresa, pois mais ninguém opera na mesma "região"...

  2. Escolhe outra plataforma de hardware e espera ardentemente que o mesmo truque nĂŁo seja empregue novamente

  3. Muda de fornecedore de softtware
Diria que nenhuma das opções acima parece particularmente atractiva. Mas caso necessite de uma nova base de dados (e possa colocar a sua aplicação a correr nela), deveria considerar o Informix. Eis porquê:
  1. É robusto, confiável, corre bem em ambientes virtualizadoes etc.., mas isto já deverá saber

  2. Tem um roadmap e acabou de completar 10 anos de inovação após a aquisição pela IBMI

  3. Pertence a uma empresa que tentará vender-lhe o seu hardware porque acredita que é bom, e não apenas porque tende a ser a única plataforma onde pode correr o seu hardware

  4. Já está bastante bem integrado com muito do software IBM, e isto é assumidamente um esforço contínuo

  5. Tem uma longa história de bom desempenho em HP-UX (tradicionalmente em PA-RISC e actualmente em Itanium). Uma pesquisa por "informix" no site da HP irá mostrar-lhe vários documentos da HP sobre a integração entre Informix e HP-UX
Para fechar este artigo, gostaria de deixar alguns links relacionados com este assunto. Espero que lhe permitam ver o que tem sido escrito sobre este anĂşncio da Oracle, e que possa formar a sua p´ropria opiniĂŁo sobre o tema.

Tuesday, May 17, 2011

Informix Roadshow 2011 Lisboa (report)

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












English version:

The Lisbon Informix Roadshow 2011 was a success. We got a full room of customers and partners to learn about the latest news in the Informix world.
We had international speakers (Juan Brogeras - SWG Information Management Sales Director SPGI, Steve Shoaf - WW sales Executive - Informix and solidDB, Jose Manuel Ruiz Gallud - Informix Technical Sales - Southwest IOT and Manuel Jorge Sousa - Vice President 4JS for Iberia)

Juan started the sessions with an overview of the Informix business, followed by Steve which explained what Informix Warehouse is and what you can do with it. This was one of the hottest topics.
Manuel proceeded with an excellent overview of 4JS and what the new partnership can bring to customers.
After the break Jose gave us the news on 11.7. By obvious reasons this was another session that raised the assistance interest.
We ended up with a client presentation from PTSI. Eduardo Santana explained us how they migrate all their Informix environments to 11.50. We found out how they did it, what they achieved and what they plan to do next to take advantage of the new features.
I wrapped the session with an overview of the information available on the IBM site about Informix, more specifically the ROI tools, the analyst studies, the documentation, the several editions and the redbooks.
After that we had lunch "outside" which given the weather was a very nice idea. Of course during the break and lunch we had plenty of opportunities to interact with customers and partners and it really made my day receiving the positive feedback about the sessions.

Above you can see Jose Ruiz in action, updating us with all the new benefits of Informix 11.7


VersĂŁo Portuguesa:

O Informix Roadshow 2011 de Lisboa foi um sucesso. Tivemos uma sala cheia de clientes e parceiros que desejavam obter as Ăşltimas novidades sobre o mundo Informix.

Estre os oradores tivemos alguns com responsabilidades internacionais (Juan Brogeras - SWG Information Management Sales Director SPGI, Steve Shoaf - WW sales Executive - Informix and solidDB, Jose Manuel Ruiz Gallud - Informix Technical Sales - Southwest IOT and Manuel Jorge Sousa - Vice Presidente 4JS para a Iberia)

Juan iniciou as sessões com um apanhado do negócio Informix, seguido pelo Steve que explicou o que é o Informix Warehous Accelerator e o que podemos fazer com ele. Esta foi uma das sessões que mais atenção suscitou.
O Manuel prosseguiu com uma excelente visĂŁo da 4JS e o que esta parceria pode trazer aos clientes.
Depois do intervalo o Jose mostrou-nos as novidades da 11.7. Por razões óbvias esta foi outra sessão que despertou mais interesse na assistência.
Terminámos com uma apresentação de um cliente, a PTSI. O Eduardo Santana explicou-nos como é que migraram todos os seus ambientes para a versão 11.50. Descobrimos como o fizeram, o que alcançaram e o que pensam fazer para tirar proveito das novas funcionalidades.
Eu encerrei a sessão com uma descrição da informação disponível no site da IBM sobre Informix, mais especificamente as ferramentas de cálculo de ROI (return on investment), os estudos de analistas, a documentação, as várias edições disponíveis e os redbooks.
Após isso tivemos oportunidade de almoçar "fora", o que dado o bom tempo que se fazia sentir tornou a refeição mais agradável. Naturalmente que durante o intervalo e o almoço tivemos oportunidade de interagir com clientes e parceiros e foi com prazer que recebemos feedback positivo sobre as várias sessões.

Em cima podem ver o Jose Ruiz em acção, actualizando-nos com todos os benefícios do Informix 11.7

Sunday, April 17, 2011

Informix Roadshow 2011 Lisboa (Agenda)

This article is only written in Portuguese due to it's local nature
Este artigo só está escrito em Português dada a sua natureza local


A agenda do evento Informix Roadshow 2011 a realizar no próximo dia 3 de Maio nas instalações da IBM é:


AGENDA:
  • 9:45 Registo e Boas Vindas
  • 10.00 – 10.15 Discover the Next Decade of Informix at IBM
    Juan Brogeras - SWG Information Management Sales Director SPGI
  • 10.15 – 10.45 Informix UltimateWarehouse.Transformational and Continuous Improvements for Your DataWarehouse.
    Steve Shoaf -WWSales Executive - Informix & solidDB
  • 10.45 – 11.15 Informix Genero: Broadening the Informix 4GL Portfolio.
    Manuel Jorge Sousa - Vice President 4Js for Iberia
  • 11.15 – 11.45 CafĂ©
  • 11.45 – 12.15 Informix 11.7 solutions, features, roadmap and evolution
    José Manuel Ruiz Gallud - Database Sales, Southwest IOT
  • 12.15 – 12.45 Upgrading Informix Dynamic Server / Case study.
  • 12.45 – 13.15 Testemunho de um Informix Business Partner
  • 13.15 – 13.30 Wrap up / Almoço

Faça a sua inscrição através do email ibmdm@pt.ibm.com
Estacionamento gratuito no parque do Hotel Vip Art’s (mesmo em frente ao Edf IBM no Parque das Nações em Lisboa)

Wednesday, April 13, 2011

Informix Roadshow 2011 Lisboa

This article is written only in Portuguese due to it's local nature
Este artigo só está escrito em Português dada a natureza local

VersĂŁo Portuguesa:

A IBM vai realizar o Informix Roadshow 2011 no dia 3 de Maio, no IBM Fórum Lisboa (instalações da IBM no Parque das Nações).
Será meio dia dedicado às últimas novidades da família Informix. Em particular:

  • Funcionalidades da versĂŁo 11.7 (Panther)
  • Informix Warehouse Accelerator
  • Informix Genero
Comemoram-se este ano os primeiros 10 anos após a aquisição da Informix, pelo que será apresentado um balanço desta década e lançamento das bases para a próxima
As sessões contarão com oradores nacionais e internacionais. Haverá tempo para questões e interação entre clientes, parceiros e equipa IBM.
NĂŁo deixe se comparecer e se nĂŁo receber convite nos prĂłximos dias nĂŁo deixe de contactar a IBM ou a mim pessoalmente.
No final das sessões será proporcionado um almoço onde terá toda a equipa IBM e oradores à sua disposição para qualquer esclarecimento adicional.
O convite é extensível a todos os que não sendo clientes ou parceiros desejem conhecer melhor uma base de dados fiável, robusta, rápida, moderna, extensível e especialmente adaptada para ambientes "embebidos".

Finalmente, mantenha-se atento a este espaço para obter informação mais detalhada sobre a agenda.

Monday, March 28, 2011

Informix 11.70.xC2: It's out!

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

English Version:

It's been too long since my last post. The reason is the usual lack of time. Sorry for that...
This is just a small post to let you know that Informix version 11.70.xC2 is being made available. It's already possible to get if from the Fix Central site (link on the right). The Information Center documentation site is still not updated. But a quick look into the release notes shows some interesting stuff:
  • Installation without root privileges
    This makes it possible to install and use Informix without root privileges. But due to the Unix/Linux nature, some features may not be available. This was a request from some embedded solutions providers. So it's another feature that helps make Informix the right choice for those environments. I believe we'll see more developments in the usage without root privileges in the future.
  • More SQL Admin API commands
    This time will see things like CREATE/DROP DATABASE and ONTAPE/ONBAR/ONSMSYNC commands. This is great since you can trigger your backups as tasks. Something that we're missing.
  • More improvements in the BTS text search datablade. IBM continues to improve this datablade which it free of charges
  • Table and column ALIASES in DML instructions (SELECT, DELETE and UPDATE)
    The ALIAS can now be used in GROUP BY clauses. I like this one. We could use numbers, but if you change your projection list you also need to change the GROUP BY clause.
  • Case insensitive searches
    This was also a frequently asked for feature. It applies only to NCHAR and NVARCHAR fields and you need to specify it in the CREATE DATABASE statement
  • OAT improvements
    As usual, when we see engine improvements we also see them in OAT. This time, a new area lets you manage your backups. Other features include the ability to uninstall a plug-in (something I also missed), ability to create reports based on historical data, improvements in the schema manager plugin-in and a few more
  • Ability to configure the number of file descriptor servers
    This is an intriguing feature related to a nasty problem that affects Informix instances with very intensive usage (I'm talking about thousands of concurrent connections, and a very high rate of new connections per second - typical values lay in the vicinity of more than 2000 concurrent sessions and/or more than 15 new connections per second, but it really depends on the environment). This issue is worth a dedicated article, and tech support usually knows it by "nsf.lock issue". If you never heard about it, it's because you don't suffer from it. In any case, this feature is in fact present in several older versions (later v10 fixpacks and 11.50). Unfortunately it was not properly documented. Also note that v11.7 has some structural changes that should eliminate this problem. The feature is translated into a new parameter called NUMFDSERVERS. Classical versions (pre v10.??) used just one. Somewhere in the v10 family it was decided that more was better, but sometimes it isn't due to other points of contention (eliminated in v11.7). So now you can decide how many to use.
  • Informix Warehouse Accelerator
    This is a new product that uses new technology. It is composed of a new in-memory based query engine, and a tool you use to map your OLTP data into that new system. Then, when you send DSS like queries to the OLTP engine, it will decide if the "partner" system can handle them. If it does the query is routed transparently and the results sent back. If it doesn't than the OLTP will resolve the queries. The advantage is that you get much (really!) faster query times on the queries routed to the new system. There was a preview of these technology on IIUG conference last year and the results were impressive. Please be alert, because there will be some buzz around this (the same technology is already available on DB2 for z/OS)
In short that's it. And there as with any other fixpack there are some bug fixes.


VersĂŁo Portuguesa:


Passou muito tempo desde o Ăşltimo artigo. A razĂŁo Ă© a habitual falta de tempo. As minhas desculpas...
Este artigo serve apenas para dar conta de que a versão 11.7.xC2 do Informix está a ser disponibilizada. Já é possível obtê-la do site Fix Central (ligação à direita). A documentação no Information Center ainda estará a ser actualizada. Mas uma pequena espreitadela nas release notes mostra algumas coisas interessantes:
  • Instalação sem privilĂ©gios de root.
    Isto torna possível instalar e utilizar o Informix sem privilégios de root. Mas dada a natureza dos sistemas operativos Unix/Linux, algumas funcionalidades poderão não estar disponíveis. Isto foi um pedido de alguns fornecedores de soluções embebidas. Por isso é mais uma funcionalidade que ajuda o Informix a ser a escolha acertada para este tipo de ambientes. Acredito que iremos ver mais desenvolvimentos relativos à utilização sem root no futuro
  • Mais comandos da API de administração SQL
    Desta vez vemos comandos como CREATE/DROP DATABASE e ONTAPE/ONBAR/ONSMSYNC. Isto é óptimo pois passamos a poder despoletar backups como tarefas. Algo que já se sentia falta
  • Mais melhorias no datablade de pesquisa de texto livre (BTS)
    A IBM continua a melhorar este datablade que Ă© distribuĂ­do sem custos com o produto
  • ALIAS em tabelas e colunas nas instruções de DML ((SELECT, DELETE and UPDATE)
    Os ALIAS podem agora ser usados nas cláusulas de GROUP BY. Pessoalmente agrada-me bastante. Já podíamos usar números, mas se mudássemos a projection list teríamos também de arranjar a cláusula GROUP BY
  • Pesquisas por caracteres nĂŁo sensĂ­veis a maiĂşsculas ou minĂşsculas
    Esta funcionalidade fazia parte da lista com mais pedidos. Só se aplica a colunas NCHAR e NVARCHAR e tem de ser especificada na criação da base de dados (instrução CREATE DATABASE)
  • Melhorias no OAT
    Como vem sendo hábito, sempre que temos melhorias no motor também as vemos no OAT. Desta vez, uma nova área permite gerir os backups. Outras novidades inclúem a possibilidade de desinstalar plug-ins (algo que sentia falta), criação de relatórios baseados em dados de histórico, melhorias no plug-in de gestão de schema e mais alguns
  • Possibilidade de configurar o nĂşmero de servidores de file descriptors.
    Isto é uma funcionalidade algo intrigante, relacionada com um problema complexo que afecta instâncias Informix com uma utilização muito intensiva (estou a falar de milhares de sessões concorrentes e uma taxa muito alta de novas sessões por segundo - valores tipicos situam-se perto de mais de 2000 sessões concorrentes e/ou mais de 15 novas sessões por segundo, mas dependerá sempre de cada ambiente)
    Este assunto mereceria por si só um artigo, mas o suporte técnico reconhece-o por "problema do nsf.lock". Se nunca ouviu falar nele é porque nunca sofreu com ele. Em qualquer caso, esta funcionalidade está de facto presente em várias versões já antigas (últimos fixpacks da versão 10 e fixpacks da versão 11.50). Infelizmente não estava devidamente documentadas. Note-se também que a versão 11.7 tem algumas modificações estruturuais que deverão eliminar este problema. A funcionalidade traduz-se num novo parâmetro chamado NUMFDSERVERS. Versões antigas (pre v10.??) usavam apenas um servidor de file descriptors. Num determinado fixpack da versão 10 considerou-se que mais era melhora, mas em alguns casos não é, devido a outros pontos de contenção (eliminados na versão 11.7). Assim, agora podemos decidir e ajustar quantos queremos
  • Informix Warehouse Accelerator
    Isto é um novo produto que utiliza tecnologia nova. É composto por um motor de queries, baseado em memória, e uma ferramenta que pode usar-se para mapear alguns dados do sistema OLTP neste novo sistema. Depois, quando enviados uma query do tipo DSS ao motor OLTP, ele decide se o novo sistema associado pode resolver a query. Se sim, a query é enviada transparentemente ao novo sistema, e os resultados são enviados de volta. Se a query não puder ser processada pelo sistema "emparceirado", então o sistema OLTP irá resolvê-la. A vantagem é que obteremos muito (mesmo muito!) melhores tempos de execução nas querys enviadas ao novo sistema. Houve uma antevisão do sistema na última conferência do IIUG e os resultados eram realmente impressionantes. Mantenha-se alerta, pois isto irá certamente dar que falar nos próximos tempos (a mesma tecnologia já existe para DB2 em z/OS)
Em resumo é isto. E como em qualquer outro fixpack contém igualmente um número de correcções.

Tuesday, January 25, 2011

Informix making the world smarter...

This article is written only in English
Este artigo apenas está disponível em Inglês

Although I'm preparing some technical articles I'm happy to make a break to echo some good news...

Informix is helping an IBM Partner, Centric Solutions, in making the world smarter. Bank of China is using it for a SWIFT application, that also helps to save trees.

These are my words, but I think everyone agrees it must be robust, fast and trustworthy... and Informix is a perfect match for that!

Read all about it here:

http://www.prnewswire.com/news-releases/bank-of-china-in-the-uk-works-with-ibm-to-become-a-smarter-greener-bank-114573679.html

Saturday, January 8, 2011

Stored procedure PDQ / PDQ dos procedimentos

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

English version:

A few years ago I needed to check if I had some stored procedures created with PDQ. Maybe some readers don't know, but if you have SET PDQPRIORITY n in your session before creating a procedure it will run with that PDQ. And that can cause abnormal resource consumption. In most cases you'll want your procedures created without PDQ.
The PDQ associated with a procedure will also change if you run UPDATE STATISTICS FOR PROCEDURE [...], in a session with PDQ active. This is also a frequent issue when people forgot to turn it off or when the statistics are gathered for tables (where PDQ can be helpful) and procedures on the same command or script.

So, how to check the PDQ of your procedures? The catalog tables don't provide this information, so at the time I asked for help internally within IBM. Cosmo, from UK came to my rescue with a strange query that I used successfully a couple of times. The query checks the first 3 characters of the column "data" from sysprocplan where planid = -2.... Don't ask... supposedly this is an encode of the PDQ value.
Recently I had another situation on a customer, where we suspected they had their procedures with PDQ. We were expecting to see the value of 80 (which we caught in some sessions) but all we saw was NULL. Once again I asked Cosmo for help, and during our conversations we noticed that we only had run the query on little endian platforms (Linux on Intel and Tru64). So, Cosmo sent me a script that created 100 procedures with different PDQ levels and then returns the encoded values. It was no surprise that the values were different. Following Cosmo's suggestion I joined both set of values into a big CASE statement that you can check at the end of this article.

The query has a few important points:
  1. I used data[1,3] in the CASE statement. We could use data::CHAR(3), but with that it would not run on version 7. It's not supported anymore, but there are still people using it, so I decided to use a syntax that's compatible with those old versions.
  2. If I remember correctly Cosmo's first query was really a function that received the procedure name. I'm including that as another option in the end of the article. In that version the query raises and error if it enters the ELSE condition of the CASE statement. In the version I was using at the later customer, the case returned NULL and that fulled me... In this new version it will raise an error since it means there is something wrong with the query.
    For the non-procedural version, I did a small and dirty trick: If it enters the ELSE condition it will try to return a value divided by zero. This will cause an error.
    Note that this conditions can't happen because the PDQ must be a value between 0 and 100. So if in the future the encoding changes the query will start raising errors, and this should alert the user...
  3. The encoded values for PDQ 1 to 100 are distinct in the two types of platforms. The encoded value for 0 however is equal. That's why we have two WHEN conditions for each value between 1 and 100 and just one for 0.

VersĂŁo Portuguesa:

Há alguns anos atrás precisei de verificar se tinha criado algum procedimento com PDQ. Talvez alguns leitores não saibam, mas se tivermos executado SET PDQPRIORITY n na sessão antes de criar um procedimento, este irá ser executado com esse valor de PDQ. E isso pode causar um consumo anormal de recursos. Na maioria das situações não queremos ter procedimentos criados com PDQ.
O PDQ associado a um procedimento também muda se corrermos um UPDATE STATISTICS FOR PROCEDURE [...], numa sessão com PDQ activo. Isto é um problema habitual quando nos esquecemos de desligar o PDQ, ou quando as estatísticas são criadas para tabelas (processo onde o PDQ é benéfico) e procedimentos no mesmo comando ou script.

Como podemos verificar o PDQ dos procedimentos? As tabelas do catálogo não disponibilizam esta informação, por isso na altura pedi ajuda internamente na IBM. O Cosmo, de UK, auxiliou-me com o envio de uma query um pouco estranha que usei algumas vezes com sucesso. A query verifica os três primeiros caracteres de uma coluna "data" da tabela sysprocplan, onde "planid = -2"... Não pergunte... É suposto isto ser o valor de PDQ codificado de alguma forma.
Recentemente tive outra situação num cliente onde suspeitávamos que tinham os procedimentos com PDQ. Esperávamos ver o valor 80 (que tinhamos visto activo em algumas sessões), mas tudo o que a query nos dava era NULL. Note-se que se tivesse olhado bem para a query deveria ter percebido que o NULL implicava um erro. Mas como estávamos à espera de ver um valor (80) cometi um "erro de simpatia". Recorri novamente ao Cosmo para ajuda. E durante as nossas trocas de impressões notámos que só tinhamos corrido a query em plataforms que usam little endian (Linux em Intel e Tru64). Assim o Cosmo enviou-me um script que cria 100 procedimentos com diferentes valores de PDQ e que retorna os respectivos valores codificados. Não foi surpresa ver valores diferentes. Seguindo uma sugestão do Cosmo, juntei ambos os conjuntos de valores numa instrução CASE que pode ser consultada no final deste artigo.

A query tem alguns pontos importantes:
  1. Utilizei data[1,3] na instrução CASE. Podíamos utilizar data::CHAR(3), mas com isso a query não correria na versão 7. Esta versão já está sem suporte, mas ainda é usada, por isso preferi uma sintaxe compatível com versões mais antigas
  2. Se bem me recordo a primeira query que o Cosmo me enviou, era na realidade uma função que recebia o nome do procedimento que queríamos verificar. Esta forma está também incluída no final do artigo. Nesta forma o código causa um erro caso entre na condição ELSE do CASE. Na versão que estava a usar neste último cliente, o CASE retornava NULL e isso enganou-me... Nesta versão actualizada e corrigida, irá gerar um erro, dado que isso implica que algo não está correcto na query. Não versão não procedimental incluí um pequeno truque: Se entrar no ELSE do CASE vai tentar retornar um valor a dividir por zero. Isto irá causar um erro.
    Note-se que esta condição não pode acontecer pois o PDQ será sempre um valor entre 0 e 100. Se no futuro os valores codificados forem alterados a query deverá começar a dar erro, e isso deverá alertar o utilizador...
  3. Os valores codificados de PDQ de 1 a 100 são distintos nos dois tipos de plataforma (little endian e big endian). No entanto o valor codificado para 0 é igual. É por isso que temos duas condições WHEN para cada valor entre 1 e 100 e só um para o valor 0.

Non-procedural query:
Query nĂŁo procedimental:


SELECT
f.procname,
CASE data[1,3]
WHEN "AAA" THEN 0
WHEN "AQA" THEN 1
WHEN "AAE" THEN 1
WHEN "AgA" THEN 2
WHEN "AAI" THEN 2
WHEN "AwA" THEN 3
WHEN "AAM" THEN 3
WHEN "BAA" THEN 4
WHEN "AAQ" THEN 4
WHEN "BQA" THEN 5
WHEN "AAU" THEN 5
WHEN "BgA" THEN 6
WHEN "AAY" THEN 6
WHEN "BwA" THEN 7
WHEN "AAc" THEN 7
WHEN "CAA" THEN 8
WHEN "AAg" THEN 8
WHEN "CQA" THEN 9
WHEN "AAk" THEN 9
WHEN "CgA" THEN 10
WHEN "AAo" THEN 10
WHEN "CwA" THEN 11
WHEN "AAs" THEN 11
WHEN "DAA" THEN 12
WHEN "AAw" THEN 12
WHEN "DQA" THEN 13
WHEN "AA0" THEN 13
WHEN "DgA" THEN 14
WHEN "AA4" THEN 14
WHEN "DwA" THEN 15
WHEN "AA8" THEN 15
WHEN "EAA" THEN 16
WHEN "ABA" THEN 16
WHEN "EQA" THEN 17
WHEN "ABE" THEN 17
WHEN "EgA" THEN 18
WHEN "ABI" THEN 18
WHEN "EwA" THEN 19
WHEN "ABM" THEN 19
WHEN "FAA" THEN 20
WHEN "ABQ" THEN 20
WHEN "FQA" THEN 21
WHEN "ABU" THEN 21
WHEN "FgA" THEN 22
WHEN "ABY" THEN 22
WHEN "FwA" THEN 23
WHEN "ABc" THEN 23
WHEN "GAA" THEN 24
WHEN "ABg" THEN 24
WHEN "GQA" THEN 25
WHEN "ABk" THEN 25
WHEN "GgA" THEN 26
WHEN "ABo" THEN 26
WHEN "GwA" THEN 27
WHEN "ABs" THEN 27
WHEN "HAA" THEN 28
WHEN "ABw" THEN 28
WHEN "HQA" THEN 29
WHEN "AB0" THEN 29
WHEN "HgA" THEN 30
WHEN "AB4" THEN 30
WHEN "HwA" THEN 31
WHEN "AB8" THEN 31
WHEN "IAA" THEN 32
WHEN "ACA" THEN 32
WHEN "IQA" THEN 33
WHEN "ACE" THEN 33
WHEN "IgA" THEN 34
WHEN "ACI" THEN 34
WHEN "IwA" THEN 35
WHEN "ACM" THEN 35
WHEN "JAA" THEN 36
WHEN "ACQ" THEN 36
WHEN "JQA" THEN 37
WHEN "ACU" THEN 37
WHEN "JgA" THEN 38
WHEN "ACY" THEN 38
WHEN "JwA" THEN 39
WHEN "ACc" THEN 39
WHEN "KAA" THEN 40
WHEN "ACg" THEN 40
WHEN "KQA" THEN 41
WHEN "ACk" THEN 41
WHEN "KgA" THEN 42
WHEN "ACo" THEN 42
WHEN "KwA" THEN 43
WHEN "ACs" THEN 43
WHEN "LAA" THEN 44
WHEN "ACw" THEN 44
WHEN "LQA" THEN 45
WHEN "AC0" THEN 45
WHEN "LgA" THEN 46
WHEN "AC4" THEN 46
WHEN "LwA" THEN 47
WHEN "AC8" THEN 47
WHEN "MAA" THEN 48
WHEN "ADA" THEN 48
WHEN "MQA" THEN 49
WHEN "ADE" THEN 49
WHEN "MgA" THEN 50
WHEN "ADI" THEN 50
WHEN "MwA" THEN 51
WHEN "ADM" THEN 51
WHEN "NAA" THEN 52
WHEN "ADQ" THEN 52
WHEN "NQA" THEN 53
WHEN "ADU" THEN 53
WHEN "NgA" THEN 54
WHEN "ADY" THEN 54
WHEN "NwA" THEN 55
WHEN "ADc" THEN 55
WHEN "OAA" THEN 56
WHEN "ADg" THEN 56
WHEN "OQA" THEN 57
WHEN "ADk" THEN 57
WHEN "OgA" THEN 58
WHEN "ADo" THEN 58
WHEN "OwA" THEN 59
WHEN "ADs" THEN 59
WHEN "PAA" THEN 60
WHEN "ADw" THEN 60
WHEN "PQA" THEN 61
WHEN "AD0" THEN 61
WHEN "PgA" THEN 62
WHEN "AD4" THEN 62
WHEN "PwA" THEN 63
WHEN "AD8" THEN 63
WHEN "QAA" THEN 64
WHEN "AEA" THEN 64
WHEN "QQA" THEN 65
WHEN "AEE" THEN 65
WHEN "QgA" THEN 66
WHEN "AEI" THEN 66
WHEN "QwA" THEN 67
WHEN "AEM" THEN 67
WHEN "RAA" THEN 68
WHEN "AEQ" THEN 68
WHEN "RQA" THEN 69
WHEN "AEU" THEN 69
WHEN "RgA" THEN 70
WHEN "AEY" THEN 70
WHEN "RwA" THEN 71
WHEN "AEc" THEN 71
WHEN "SAA" THEN 72
WHEN "AEg" THEN 72
WHEN "SQA" THEN 73
WHEN "AEk" THEN 73
WHEN "SgA" THEN 74
WHEN "AEo" THEN 74
WHEN "SwA" THEN 75
WHEN "AEs" THEN 75
WHEN "TAA" THEN 76
WHEN "AEw" THEN 76
WHEN "TQA" THEN 77
WHEN "AE0" THEN 77
WHEN "TgA" THEN 78
WHEN "AE4" THEN 78
WHEN "TwA" THEN 79
WHEN "AE8" THEN 79
WHEN "UAA" THEN 80
WHEN "AFA" THEN 80
WHEN "UQA" THEN 81
WHEN "AFE" THEN 81
WHEN "UgA" THEN 82
WHEN "AFI" THEN 82
WHEN "UwA" THEN 83
WHEN "AFM" THEN 83
WHEN "VAA" THEN 84
WHEN "AFQ" THEN 84
WHEN "VQA" THEN 85
WHEN "AFU" THEN 85
WHEN "VgA" THEN 86
WHEN "AFY" THEN 86
WHEN "VwA" THEN 87
WHEN "AFc" THEN 87
WHEN "WAA" THEN 88
WHEN "AFg" THEN 88
WHEN "WQA" THEN 89
WHEN "AFk" THEN 89
WHEN "WgA" THEN 90
WHEN "AFo" THEN 90
WHEN "WwA" THEN 91
WHEN "AFs" THEN 91
WHEN "XAA" THEN 92
WHEN "AFw" THEN 92
WHEN "XQA" THEN 93
WHEN "AF0" THEN 93
WHEN "XgA" THEN 94
WHEN "AF4" THEN 94
WHEN "XwA" THEN 95
WHEN "AF8" THEN 95
WHEN "YAA" THEN 96
WHEN "AGA" THEN 96
WHEN "YQA" THEN 97
WHEN "AGE" THEN 97
WHEN "YgA" THEN 98
WHEN "AGI" THEN 98
WHEN "YwA" THEN 99
WHEN "AGM" THEN 99
WHEN "ZAA" THEN 100
WHEN "AGQ" THEN 100
ELSE
TRUNC(p.rowid / 0)
END pdq_value
FROM
sysprocplan p, sysprocedures f
WHERE
p.planid = -2 AND
f.procid = p.procid
ORDER BY 2 DESC


Procedural version:
VersĂŁo procedimental:


CREATE FUNCTION get_proc_pdq_value(v_proc_name VARCHAR(128))
RETURNING SMALLINT;

DEFINE v_ret_pdq_value SMALLINT;


SELECT
f.procname,
CASE data[1,3]
WHEN "AAA" THEN 0
WHEN "AQA" THEN 1
WHEN "AAE" THEN 1
WHEN "AgA" THEN 2
WHEN "AAI" THEN 2
WHEN "AwA" THEN 3
WHEN "AAM" THEN 3
WHEN "BAA" THEN 4
WHEN "AAQ" THEN 4
WHEN "BQA" THEN 5
WHEN "AAU" THEN 5
WHEN "BgA" THEN 6
WHEN "AAY" THEN 6
WHEN "BwA" THEN 7
WHEN "AAc" THEN 7
WHEN "CAA" THEN 8
WHEN "AAg" THEN 8
WHEN "CQA" THEN 9
WHEN "AAk" THEN 9
WHEN "CgA" THEN 10
WHEN "AAo" THEN 10
WHEN "CwA" THEN 11
WHEN "AAs" THEN 11
WHEN "DAA" THEN 12
WHEN "AAw" THEN 12
WHEN "DQA" THEN 13
WHEN "AA0" THEN 13
WHEN "DgA" THEN 14
WHEN "AA4" THEN 14
WHEN "DwA" THEN 15
WHEN "AA8" THEN 15
WHEN "EAA" THEN 16
WHEN "ABA" THEN 16
WHEN "EQA" THEN 17
WHEN "ABE" THEN 17
WHEN "EgA" THEN 18
WHEN "ABI" THEN 18
WHEN "EwA" THEN 19
WHEN "ABM" THEN 19
WHEN "FAA" THEN 20
WHEN "ABQ" THEN 20
WHEN "FQA" THEN 21
WHEN "ABU" THEN 21
WHEN "FgA" THEN 22
WHEN "ABY" THEN 22
WHEN "FwA" THEN 23
WHEN "ABc" THEN 23
WHEN "GAA" THEN 24
WHEN "ABg" THEN 24
WHEN "GQA" THEN 25
WHEN "ABk" THEN 25
WHEN "GgA" THEN 26
WHEN "ABo" THEN 26
WHEN "GwA" THEN 27
WHEN "ABs" THEN 27
WHEN "HAA" THEN 28
WHEN "ABw" THEN 28
WHEN "HQA" THEN 29
WHEN "AB0" THEN 29
WHEN "HgA" THEN 30
WHEN "AB4" THEN 30
WHEN "HwA" THEN 31
WHEN "AB8" THEN 31
WHEN "IAA" THEN 32
WHEN "ACA" THEN 32
WHEN "IQA" THEN 33
WHEN "ACE" THEN 33
WHEN "IgA" THEN 34
WHEN "ACI" THEN 34
WHEN "IwA" THEN 35
WHEN "ACM" THEN 35
WHEN "JAA" THEN 36
WHEN "ACQ" THEN 36
WHEN "JQA" THEN 37
WHEN "ACU" THEN 37
WHEN "JgA" THEN 38
WHEN "ACY" THEN 38
WHEN "JwA" THEN 39
WHEN "ACc" THEN 39
WHEN "KAA" THEN 40
WHEN "ACg" THEN 40
WHEN "KQA" THEN 41
WHEN "ACk" THEN 41
WHEN "KgA" THEN 42
WHEN "ACo" THEN 42
WHEN "KwA" THEN 43
WHEN "ACs" THEN 43
WHEN "LAA" THEN 44
WHEN "ACw" THEN 44
WHEN "LQA" THEN 45
WHEN "AC0" THEN 45
WHEN "LgA" THEN 46
WHEN "AC4" THEN 46
WHEN "LwA" THEN 47
WHEN "AC8" THEN 47
WHEN "MAA" THEN 48
WHEN "ADA" THEN 48
WHEN "MQA" THEN 49
WHEN "ADE" THEN 49
WHEN "MgA" THEN 50
WHEN "ADI" THEN 50
WHEN "MwA" THEN 51
WHEN "ADM" THEN 51
WHEN "NAA" THEN 52
WHEN "ADQ" THEN 52
WHEN "NQA" THEN 53
WHEN "ADU" THEN 53
WHEN "NgA" THEN 54
WHEN "ADY" THEN 54
WHEN "NwA" THEN 55
WHEN "ADc" THEN 55
WHEN "OAA" THEN 56
WHEN "ADg" THEN 56
WHEN "OQA" THEN 57
WHEN "ADk" THEN 57
WHEN "OgA" THEN 58
WHEN "ADo" THEN 58
WHEN "OwA" THEN 59
WHEN "ADs" THEN 59
WHEN "PAA" THEN 60
WHEN "ADw" THEN 60
WHEN "PQA" THEN 61
WHEN "AD0" THEN 61
WHEN "PgA" THEN 62
WHEN "AD4" THEN 62
WHEN "PwA" THEN 63
WHEN "AD8" THEN 63
WHEN "QAA" THEN 64
WHEN "AEA" THEN 64
WHEN "QQA" THEN 65
WHEN "AEE" THEN 65
WHEN "QgA" THEN 66
WHEN "AEI" THEN 66
WHEN "QwA" THEN 67
WHEN "AEM" THEN 67
WHEN "RAA" THEN 68
WHEN "AEQ" THEN 68
WHEN "RQA" THEN 69
WHEN "AEU" THEN 69
WHEN "RgA" THEN 70
WHEN "AEY" THEN 70
WHEN "RwA" THEN 71
WHEN "AEc" THEN 71
WHEN "SAA" THEN 72
WHEN "AEg" THEN 72
WHEN "SQA" THEN 73
WHEN "AEk" THEN 73
WHEN "SgA" THEN 74
WHEN "AEo" THEN 74
WHEN "SwA" THEN 75
WHEN "AEs" THEN 75
WHEN "TAA" THEN 76
WHEN "AEw" THEN 76
WHEN "TQA" THEN 77
WHEN "AE0" THEN 77
WHEN "TgA" THEN 78
WHEN "AE4" THEN 78
WHEN "TwA" THEN 79
WHEN "AE8" THEN 79
WHEN "UAA" THEN 80
WHEN "AFA" THEN 80
WHEN "UQA" THEN 81
WHEN "AFE" THEN 81
WHEN "UgA" THEN 82
WHEN "AFI" THEN 82
WHEN "UwA" THEN 83
WHEN "AFM" THEN 83
WHEN "VAA" THEN 84
WHEN "AFQ" THEN 84
WHEN "VQA" THEN 85
WHEN "AFU" THEN 85
WHEN "VgA" THEN 86
WHEN "AFY" THEN 86
WHEN "VwA" THEN 87
WHEN "AFc" THEN 87
WHEN "WAA" THEN 88
WHEN "AFg" THEN 88
WHEN "WQA" THEN 89
WHEN "AFk" THEN 89
WHEN "WgA" THEN 90
WHEN "AFo" THEN 90
WHEN "WwA" THEN 91
WHEN "AFs" THEN 91
WHEN "XAA" THEN 92
WHEN "AFw" THEN 92
WHEN "XQA" THEN 93
WHEN "AF0" THEN 93
WHEN "XgA" THEN 94
WHEN "AF4" THEN 94
WHEN "XwA" THEN 95
WHEN "AF8" THEN 95
WHEN "YAA" THEN 96
WHEN "AGA" THEN 96
WHEN "YQA" THEN 97
WHEN "AGE" THEN 97
WHEN "YgA" THEN 98
WHEN "AGI" THEN 98
WHEN "YwA" THEN 99
WHEN "AGM" THEN 99
WHEN "ZAA" THEN 100
WHEN "AGQ" THEN 100
ELSE
-1
END pdq_value
INTO
v_ret_pdq_value
FROM
sysprocplan p, sysprocedures f
WHERE
p.planid = -2 AND
f.procid = p.procid AND
f.procname = v_proc_name;

IF v_ret_pdq_value = -1
THEN
RAISE EXCEPTION -746,0,'Could not decode PDQ value. Please check query';
ELSE
RETURN v_ret_pdq_value;
END IF
END FUNCTION;



Updated on Jan 12, 2011: Cosmo noted that the procedure should be declared as a function and asked me to reference him as Cosmo instead of Simon David

Alterado em 12 de Jan de 2011: O Cosmo referiu que o procedimento deveria ser declarado como função e pediu para ser referido como Cosmo em vez de Simon David

Thursday, December 16, 2010

New French Blog / Novo blog em FrancĂŞs

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

English Version:

It's a great pleasure to present you another Informix blog. This one is written in French. The author is Eric Vercelletto, which was a colleague at Informix Portugal. Eric has a long history with Informix. We was working at Informix France and decided to join Informix Portugal mainly to participate in a big and complex project several years ago (before I joined Informix). After that we met and worked together on another customer. At the time I was working mainly with tools and he managed all the engine side stuff. When he decided to embrace other challenges outside Informix, I assumed his position at that customer. It was a big challenge for me (I had relatively low experience with the engine) and Eric was a great help. I still use some of his scripts today, and I learned many things with him.
But the world never stops spinning and currently Eric is back on Informix, and he's enthusiastic about it. I wish him all the best and I really hope he is able to share some of his knowledge about Informix with the community.
He decided to write the blog in French since French people like to take care of their language. This is great news for the French community. As for us, non French speaking people we can try our best to understand it. It would be interesting to see it in English also... (just a challenge Eric ;) ). But for now, the important it to keep a steady rate of articles. And I can assure you it's hard. Welcome Eric!

The blog address is:

http://levillageinformix.blogspot.com/

(something like "the Informix village")



VersĂŁo Portuguesa:

É um grande prazer poder apresentar-vos um novo blog Informix. Desta feita escrito em Francês. O autor é Eric Vercelletto, que foi um colega da Informix Portugal. O Eric tem um longo passado com Informix. Estava a trabalhar na Informix França e decidiu juntar-se à Informix Portugal, pricipalmente para participar num projecto grande e complexo há vários anos atrás (antes de eu ingressar na Informix Portugal). Após isso conhecemo-nos e trabalhámos juntos num outro cliente. Na altura eu trabalhava essencialmente com ferramentas e ele geria o lado do motor.
Quando ele decidiu abraçar outros desafios fora da Informix, assumi a sua posição no cliente. Foi um grande desafio para mim (tinha muito pouca experiência com o motor) e o Eric foi uma grande ajuda. Ainda utilizo alguns dos seus scripts hoje, e aprendi muitas coisas com ele.
Mas o mundo dá voltas e mais voltas e actualmente o Eric está de volta ao Informix, e continua entusiasta. Desejo-lhe tudo de bom e espero sinceramente que ele consiga partilhar algum do seu conhecimento Informix com a comunidade.
Ele decidiu escrever o blog em Francês porque os Franceses gostam de cuidar da sua língua. Isto são excelentes notícias para a comunidade Francófona. Quanto a nós, que não dominamos a língua, tentaremos o nosso melhor para o perceber. Era interessante ver o conteúdo também em Inglês (só um desafio Eric... :) ). Mas por agora, o importante é manter um ritmo constante de novos artigos. E posso assegurar que não é fácl. Bem vindo Eric!


O endereço do blog é:

http://levillageinformix.blogspot.com/

(algo como "a aldeia do Informix", o que vindo da Gália, trás boas recordações de criança)

Wednesday, December 15, 2010

Informix ROI webcast

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

English version:

Following the recent announcement of a Forrester study about Informix ROI, a webcast was held on December 13. The replay can be seen here:

https://www.techwebonlineevents.com/ars/eventregistration.do?mode=eventreg&F=1002717&K=4ON

You can listen to it in webcast format and also download the slides and sound file.
The presentation was done by Jon Erickson from Forrester and Richard Wozniak who browses through some of the Panther key features.
Be sure to pass this to your company management!



VersĂŁo Portuguesa:

No seguimento do recente anúncio sobre um estudo da Forrester sobre o ROI (return on investment) do Informix, foi apresentado um webcast no dia 13 de Dezembro. Pode rever esta apresentação aqui:

https://www.techwebonlineevents.com/ars/eventregistration.do?mode=eventreg&F=1002717&K=4ON

Pode ouvir/ver em formato webcast e também fazer o download dos ficheiros com os slides e o som.
A apresentação foi feita por Jon Erickson da Forrester e Richard Wozniak que abordou algumas das principais funcionalidades da versão Panther (11.7)
Não deixe de divulgar esta informação aos gestores da sua organização!

Sunday, December 12, 2010

Panther: Name service cache

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

English version:

A recent thread in the IIUG mailing list (relative to a reverse DNS issue) reminded me of a new Panther (version 11.7) functionality that was on my list for articles. I've been avoiding many of the bigger and more important features because they will take a lot of time to write about... I hope this one will be shorter.

Informix needs to read several files or interact with DNS servers each time you try to open a connection. Considering Unix and Linux (Windows is a bit different technically, but not that much conceptually), these are some of the actions the engine must do:
  1. Depending on your host resolution criteria it will probably open the /etc/hosts file to search for your client's IP address. If it's not there it will contact your DNS server in order to request the name associated with the IP address.
    Note that all this is done by a system call.
  2. It will access /etc/passwd (or equivalent) to get your user details (HOME dir, password - this is probably stored in another file like /etc/shadow - , user id, group id etc.)
The engine must also access /etc/services and /etc/group in other situations.
Depending on your environment these activities can take a bit of time, and require some significant CPU usage. There are systems with high number of connections per second which can naturally transform this into a significant issue.
To give you an example I do regular work on a system that used to receive a very large number of requests from CGI programs. So, each request received by HTTP required a new process on the application server, and a new connection on the database server. They had peaks of tens of requests per second. Currently they're using Fast CGI with noticeable improvements.
Anyway, IBM decided to give us the chance to optimize this by caching previous results (file searches and DNS requests). This is done with the new parameter called NS_CACHE (from Name Service Cache). The format of this $ONCONFIG parameter is:

host=num_secs,services=num_secs,user=num_secs,group=num_secs

Each comma separated pair (functionality=num_secs) configures the number of seconds that the engine will cache a query result for that functionality. I'm calling it functionality, because it can be implemented through files or system APIs. The documentation could be clearer, but let's check each one:
  • host
    This is the host and IP address resolution service. Depending on your system configuration (on most Unixes and Linux this is specified in /etc/nsswitch.conf) it can be resolved by reading the /etc/hosts file and/or making a request to your DNS servers
  • service
    This should be the map between service names and system ports, usually done by reading /etc/services. The only situation that comes to my mind where this is used is when you're trying to start a listener (either during engine startup or after that with onmode -P) or when you're trying to make a distributed query to another engine, and you use names in your INFORMIXSQLHOSTS instead of port numbers. In any case, I may be missing something...
  • user
    This is very important. It refers to all the user related info that Informix gathers from the OS and that is relevant to Informix. The information can be stored in /etc/passwd, /etc/shadow, or indirectly be managed by external services like LDAP. It can include:
    - Home dir
    - User ID
    - Group ID
    - Password
    - User status (enable or disable
  • group
    This relates to the OS group information. Usually done by reading /etc/group
If the specified number of seconds to cache the information is zero, it means that we don't want to cache it. So the behavior will be the old engine behavior (for each relevant request, the information must be obtained).
The parameter can be changed online with onmode -wm

It's important that you fully understand the implications of caching these kind of information. By asking Informix to cache this info, we're also assuming the risk of working with stale information. Let's imagine a simple scenario. Assume this sequence of events:
  1. At time T0 you connect using user and password to the engine which is setup to cache user information for 600s (10 minutes).
  2. At time T1 you change that user password
  3. At time T2, the same user tries to connect to the Informix database with the new password. It will fail!
  4. At time T3 (T0 + the number of seconds to cache user information) the user repeats the connection attempt with the new password. It will succeed!
How can you avoid situation 3? If you change the cache timeout to 0, it will work as a flush.
If for example you do some changes to your user's information you can run:


onmode -wm NS_CACHE="host=900,service=900,user=0,group=900"
onmode -wm NS_CACHE="host=900,service=900,user=900,group=900"


These commands will flush the user information cache, and then reactivate it.

So, the point I'd like to make is that this feature can help you improve performance (specially for systems with an high connection rate), but it can have some side effects. You can workaround these ones, but for that you must know they exist.


VersĂŁo Portuguesa:

Uma discussĂŁo recente na lista de correio do IIUG (relativa a um problema com reverse DNS) lembrou-me de uma funcionalidade nova do Panther (versĂŁo 11.7) que estava na minha lista de temas a abordar. Tenho andando a evitar muitas das maiores e mais importantes novidades porque vou demorar bastante tempo a escrever sobre elas.... Espero que esta seja mais reduzida.

O Informix tem de ler diversos ficheiros ou interagir com servidores de nomes (DNS) cada vez que abre uma conexão. Considerando o Unix e Linux (em Windows será um pouco diferente tecnicamente, mas não muito conceptualmente), estas são as acções que o motor tem de fazer durante o estabelecimento de uma conexão:

  1. Dependendo do critério usado para resolver endereços e nomes, provavelmente irá abrir o ficheiro /etc/hosts para procurar o IP da conexão. Se não o encontrar irá provavelmente contactar o servidor de nomes (DNS) e pedir o nome associado ao IP de onde chega a conexão.
    Note-se que isto é feito com uma chamada de sistema e não cabe ao Informix definir os critérios.
  2. Irá aceder ao /etc/passwd (ou equivalente) para obter os dados do utilizador (HOME dir, password - isto deve estar guardado noutro ficheiros como o /etc/shadow- , id de utilizador, id de grupo etc.)
O motor também tem de aceder ao /etc/services e /etc/group noutras situações.
Dependendo do seu ambiente estas operações podem demorar um pouco e requerer um consumo de CPU relevante. Existem sistemas com muitas conexões novas por segundo o que naturalmente pode transformar isto num problema sério.
Para dar um exemplo, trabalho regularmente com um sistema que em dada altura recebia um enorme número de pedidos por CGI. Sendo CGI, cada pedido recebido via HTTP requeria um novo processo na máquina do servidor aplicacional, e uma nova conexão na base de dados. Tinham picos de dezenas de ligações por segundo. Actualmente estão a usar Fast CGIs com benefício notórios.
De qualquer forma a IBM decidiu dar aos utilizadores a oportunidade de optimizarem estes aspectos, através de uma cache que guarda respostas anteriores (pesquisas em ficheiros e resultados de DNS). Isto é feito com um novo parâmetro designado NS_CACHE (de Name Service Cache). O formato do parâmtro do $ONCONFIG é:

host=num_segs,services=num_segs,user=num_segs,group=num_segs

Cada par (funcionalidade=num_segs) separado por vírgula, configura o número de segundos durante os quais o motor irá manter em cache o resultado de uma pesquisa para essa funcionalidade. Estou a chamar-lhe "funcionalidade", porque pode ser implementada usando ficheiros ou APIs de sistema. A documentação deveria ser mais clara, mas vamos ver cada uma:
  • host
    O serviço de resolução de nomes e endereços IP. Conforme a configuração do seu sistema (na maioria dos Unixes e Linux isto é definido em /etc/nsswitch.conf) pode ser resolvido pelo ficheiro /etc/hosts ou fazendo um pedido aos servidores de DNS
  • service
    Este é o mapeamento entre o nome de serviços e as portas de sistema, habitualmente feito através da leitura do ficheiro /etc/services. As únicas situações que me ocorrem em que isto é usado é quando arrancamos com um listener (seja no arranque do motor ou depois quando se usa o onmode -P), ou quando tentamos executar uma query distríbuida a outro motor, e usamos nomes no nosso INFORMIXSQLHOSTS em vez de números de portos. Mas pode estar a escapar-me alguma coisa, e haver outras...
  • user
    Este é muito importante. Refere-se a toda a informação relativa aos utilizadores que o Informix obtém do sistema operativo e que é relevante para o Informix. A informação é guardada no /etc/passwd e /etc/shadow, ou gerida indirectamente em serviços externos como LDAP. Pode incluir:
    - Home dir
    - ID de utilizador
    - ID de grupo
    - Palavra passe
    - Estado do utilizador (activo, inactivo)
  • group
    Isto diz respeito à informação de grupos do sistema operativo. Normalmente feito por consulta ao ficheiro /etc/group

Se o número de segundos especificado para a cache for zero, significa que não queremos fazer caching. Portanto o comportamento será o antigo do motor (para cada pedido a informação tem de ser obtida).

O parâmetro pode ser modificado online com o comando onmode -wm

É importante que entenda completamente todas as implicações de fazer caching deste tipo de informação. Ao pedir ao Informix que guarde e reutilize a informação já obtida, estamos também a assumir o risco de trabalhar com informação entretanto desactualizada. Vamos imaginar um cenário simples. Consideremos a seguinte sequência de eventos:

  1. No momento T0 conectamo-nos usando um utilizador e palavra chave a um motor configurado para efectuar caching por 600 segundos (10 minutos).
  2. No momento T1 mudamos a palavra chave desse mesmo utilizador.
  3. No momento T2 o mesmo utilizador tenta conectar-se ao Informix usando a nova palavra chave. Vai falhar!
  4. No momento T3 (T0+ o nĂşmero de segundos configurado para a cache de utilizador) o utilizador repete a tentativa de acesso com a nova palavra chave. Vai ter sucesso!
Como pode evitar a situação do ponto 3? Se mudar o tempo de cache para 0, funciona como uma limpeza da cache.
Se por exemplo efectuar mudanças na informação dos utilizadores, pode executar:


onmode -wm NS_CACHE="host=900,service=900,user=0,group=900"
onmode -wm NS_CACHE="host=900,service=900,user=900,group=900"


Estes comandos fazem a limpeza da informação e depois re-activam a cache.

Portanto, o ponto que gostaria de frisar é que esta funcionalidade pode melhorar o desempenho (especialmente em sistemas com elevada frequência de novas conexões), mas também pode ter efeitos secundários. Estes podem ser contornados, mas para isso temos de saber que existem.

Saturday, November 27, 2010

Panther: Extending extents / Estendendo os extents

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

English version:

Back to Panther... Although I'm not in the video on the right, I do love Informix. That doesn't mean I ignore some issues it has (or had in this particular case). One thing that always worries an Informix DBA is the number of extents in his tables. Why? Because it used to have a maximum amount, and because that maximum was pretty low (if compared with other databases). But what is an extent? In short an extent is a sequence of contiguous pages (or blocks) that belong to a specific table or table partition. A partition (a table has one or more partitions) has one or more extents.
Before I go on, and to give you some comparison I'd like to tell you about some feedback I had over the years from a DBA (mostly Oracle, but who also managed an Informix instance):
  • A few years ago he spent lots of time running processes to reduce the number of extents in a competitor database that had reach an incredible number of extents (around hundreds of thousands). This was caused by real large tables and real badly defined storage allocation
  • Recently I informed the same customer that Informix was eliminating the extent limits and the same guy told me that he was afraid that it could lead to situations as above. He added, and I quote, "I've always admired the way Informix deals with extents"
So, if a customer DBA is telling that he admires the way we used to handle extents, and he's afraid of this latest change, why am I complaining about the past? As in many other situations, things aren't exactly black and white... Let's see what Informix have done well since ever:

  1. After 16 allocations of new extents Informix automatically doubles the size of the next extent for the table. This decreases the number of times it will try to allocate a new extent. So, using only this rule (which is not correct as we shall see) if you create a table with a next size of 16K, you would reach 4GB with around 225 extents.
  2. If Informix can allocate a new extent contiguous to an already existing one (from the same table of course) than it will not create a new one, but instead it will extend the one that already exists (so it does not increase the number of extents). This is one reason why rule number one may not be seen in practice. In other words, it's more than probable that you can reach 4GB with less than 225 extents.
  3. In version 11.50 if I'm correct, a fix was implemented to prevent excessive extent doubling (rule 1). If the next extent size is X and the dbspace only has a maximum of Y (Y < X) informix will allocate Y and will not raise any error.
    If this happens many times, we could end up having a number of allocated pages relatively small, but a next extent size too big. There's a real problem in this: If in these circumstances we create another chunk in the same dbspace, and after that our table requires another extent, the engine could reserve a large part of the new (and possibly still empty) chunk to our table. This can be much more than the size already allocated to the table. To avoid this, extent doubling will only happen when there is a reasonable relation between the new calculated next extent size and the space effectively allocated to the table.
  4. Extent description in Informix have never been stored in the database catalog. This leads to simpler and efficient space management. Compared to other databases that used to do the management in the catalog, they tend to hit issues in the SQL layer and at the same time these were slower. One of our competitors changed that in their later versions, and DBAs have seen improvement with that (but they had to convert). Informix always worked the better way...
So, these are the good points. Again, why was I complaining? Simply because although Informix has done a pretty good job in preventing the number of extents to grow too much, we had a very low limit for the number of extents. In platforms with a system page size of 2K this was around 220-240 extents (max), and for 4K platforms is was around the double of that (440-480). With version 10 we started to be able to have greater page sizes, and that increases the maximum number of extents per partition.
Why didn't we have a fix limit and why was it different in several platforms? In order to explain that we must dive a bit deeper in the structure of a dbspace and tables. Each partition in Informix has a partition header. Each partition header is stored in exactly one Informix page. There is a special partition in every dbspace (tablespace tablespace) that holds every partition headers from that dbspace. This special partition starts in a specific page but then, it can contain more than one extent.
Also important to understand this is the notion of slot. Most Informix pages contain several slots. For a data page, a slot contains a row (in the simplest cases). A partition header is a page that contains 5 slots:
  1. Slot 1
    This contains the partition structure (things like creation date, partition flags, maximum row size, number of special columns - VARCHAR and BLOB -, number of keys - if it's an index or has index pages -, number of extents and a lot of other stuff. If you want to see all the details check the sysptnhdr table in $INFORMIXDIR/etc/sysmaster.sql. It's basically an SQL interface for the partition headers in the instance.
    In version 11.50 this slot should occupy 100 bytes. Previous versions can have less (no serial 8, and bigserial)
  2. Slot 2
    Contains the database name, the partition owner, the table name and the NLS collation sequence
  3. Slot 3
    Contains details about the special columns. If there are no special columns this slot will be empty
  4. Slot 4
    Contains the description for each key (if it's an index or a mix). Starting with version 9.40, by default the indexes are stored in their own partitions. This was not the case in previous versions. A single partition could contain index pages interleaved with data pages.
    Currently, by default, a partition used for data should not have any key, so this slot will be empty
  5. Slot 5
    Finally, this is the slot that contains the list of extents.
Now we know the list of extents must be stored in the partition header. And the partition header has 5 slots, and the size of first four may vary. This means that the free space for slot 5 (extent list) is variable. These are the reasons why we had a limit and why that limit was not fixed. It would vary with the table structure for example. And naturally it would vary with the page size.
A table that reached it's maximum number of extents was a very real and serious problem in Informix. If you reach the table limit for number of extents and all your table's data pages are full, the engine would need to allocate one more extent in order to complete new INSERTs. But for that it would require some free space in the partition header. If there was no space left, any INSERT would fail with error -136:

-136 ISAM error: no more extents.

After hitting this nasty situation there were several ways to solve it, but all of them would need temporary table unavailability, which in our days is rare... We tend to use 24x7 systems. Even systems that have a maintenance window would suffer with this, because most of the time the problem was noticed during "regular" hours...

So, I've been talking in the past... This used to be a problem. Why isn't it a problem anymore? Because Panther (v11.7) introduced two great features:
  1. The first one is that it is able to automatically extend the partition header when slot 5 (the extent list) becomes full. When this happens it will allocate a new page for the partition header that will be used for the extent list. So you should not see error -136 caused by reaching the extent limit. At first you may think like my customer DBA: "wow! Isn't that dangerous? Will I get tables/partitions with tens of thousands of extents?". The answer is simple. You won't get that high number of extents because all the nice features that were always there (automatic extent concatenation, extent doubling...) are still there. This will just avoid the critical situation where the use of the table would become impossible (new INSERTs). And naturally it doesn't mean that you should not care about the number of extents. For performance reasons it's better to keep them low
  2. The second great feature is an online table defragmenter. They can grow forever, but that's not good. Once you notice you have a table with too many extents you can ask the engine to defragment it. I will not dig into this simply because someone else already did it. I recommend you check the recent DeveloperWorks article entitled "Understand the Informix Server V11.7 defragmenter"

VersĂŁo Portuguesa:

De volta à Panther... Apesar de não estar no vídeo à direita, eu adoro o Informix. Isso não significa que ignore alguns problemas que ele tem (ou tinha neste caso particular). Uma coisa que preocupa qualquer DBA Informix é o número de extents das suas tabelas. Porquê? Porque esse número tinha um máximo, e porque esse máximo era bastante baixo (se comparado com outras bases de dados). Mas o que é um extent? De forma simples, um extent é uma sequência contígua de páginas (ou blocos) que pertencem a uma tabela ou partição de tabela. Uma partição (uma tabela tem uma ou mais partições) tem um ou mais extents.
Antes de continuar, e para estabelecer uma comparação, gostaria de transmitir algum feedback que ao longo de anos tive de um DBA (essencialmente Oracle, mas também geria uma instância Informix):

  • Há alguns anos atrás passou bastante tempo a executar processos para reduzir o nĂşmero de extents de uma base de dados concorrente do Informix. Essa base de dados tinha tabelas que atingiram um nĂşmero incrĂ­vel de extents (na casa das centenas de milhar). Isto foi causado por tabelas verdadeiramente grandes e cláusulas de alocação de espaço realmente mal definidas
  • Recentemente informei esse mesmo cliente que o Informix ia eliminar o limite de extents, e a mesma pessoa disse-me que tinha receio que isso pudesse levar a situações como a de cima. Ele acrescentou, e cito: "Se há coisa que sempre admirei foi a maneira como o Informix gere os extents".
Assim sendo, se um DBA de um cliente diz que admira a maneira como geríamos os extents e ele próprio receia a eliminação de limites, porque é que eu me queixo do passado? Como em muitas outras situações, as coisas não são bem a preto e branco... Vejamos o que o Informix sempre fez bem:

  1. Após cada 16 novos extents adicionados, o Informix automaticamente duplica o tamanho do próximo extent da tabela. Isto diminui o número de vezes que tenta reservar um novo extent. Usando apenas esta regra (o que não é correcto como veremos a seguir), se criar uma tabela com o extent mínimo (16KB), a tabela pode crescer até aos 4GB com cerca de 225 extents.
  2. Se o Informix conseguir reservar um novo extent que seja contíguo a um que já esteja alocado à mesma tabela, então em vez de criar um novo, vai alargar o já existente (portanto não aumenta o número de extents). Esta é a razão porque a regra anterior pode não ser verificada na práctica. Por outras palavaras é mais que provável que consiga atingir os 4GB com menos de 225 extents.
  3. Salvo algum erro, na versão 11.50 foi introduzida uma melhoria para prevenir a duplicação excessiva do tamanho do próximo extent (regra 1). Se o tamanho do próximo extent for X, mas o dbspace só tiver um máximo de Y espaço livre contíguo (Y < X) o Informix vai criá-lo com o tamanho Y e nem se queixará de nada. Se isto acontecer muitas vezes, podemos acabar por ter um número de páginas efectivas de uma tabela ou partição relativamente pequeno e um tamanho para o próximo extent muito grande. Existe um problema real nisto: Se nessas cirunstâncias for criado um novo chunk nesse dbspace, e a tabela precisar de novo extent, pode acontecer que o motor reserve grande parte, ou mesmo a totalidade do novo chunk para a tabela (possivelmente muito mais que o tamanho já reservado até então). Para evitar isto, a duplicação do tamanho do próximo extent só acontece quando o novo tamanho tem uma relação razoável com o espaço reservado até então. Caso contrário o tamanho do próximo extent a alocar não é duplicado.
  4. A informação dos extents em Informix nunca foi guardada nas tabelas de catálogo. Isto faz com que a sua gestão seja mais simples e eficiente. Comparada com outras bases de dados que faziam a gestão no catálogo, estas tendiam a encontrar problemas e constrangimentos próprios da camada de SQL, e ao mesmo tempo eram mais lentas. Um dos concorrentes mudou isto há umas versões atrás e os seus utilizadores viram benefícios bem notórios (mas tiveram de converter). O Informix sempre trabalhou da melhor forma...
Estes são os pontos positivos. Mais uma vez, porque é que me estava a queixar? Simplesmente porque apesar de o Informix sempre ter feito um trabalho extraordinário na prevenção contra um elevado número de extents, nós tinhamos um limite, e era muito baixo. Em plataformas com um tamanho de página de sistema de 2KB este limite rondava os 220-240 extents, e em plataformas de 4KB o limite era cerca do dobro (440-480). Com a versão 10 pudemos passar a ter páginas maiores, e isso aumenta o limite.
Porque é que o limite não é fixo, e porque é diferente consoante a plataforma? Para explicar isto temos de nos debruçar de forma mais detalhada na estrutura física de um dbspace e tabela. Cada partição em Informix tem um cabeçalho. Cada cabeçalho de partição é guardado numa página Informix. Existe uma partição especial em cada dbspace (designada habitualmente por tablespace tablespace) que guarda todos os cabeçalhos das partições criadas nesse dbspace. Esta partição especial começa numa página específica do primeiro chunk do dbspace, mas pode ter mais que um extent.
Igualmente importante para compreender isto é a noção de slot. A maioria das páginas Informix estão divididas em slots. Para uma página de dados um slot contém uma linha de dados da tabela (caso mais simples). Um cabeçalho de partição é uma página que contém cinco slots:

  1. Slot 1
    Este contém a estrutura da partição (coisas como a data de criação, flags, tamanho máximo de uma linha, numéro de colunas ditas especiais - VARCHAR e BLOBs -, número de chaves - se for um indíce ou tiver páginas de indíce -, número de extents e uma série de outros detalhes. Se tiver curiosidade em saber o que lá está guardado consulte a tabela sysptnhdr na base de dados sysmaster (ou o ficheiro $INFORMIXDIR/etc/sysmaster.sql). Basicamente esta tabela é um interface SQL sobre todos os cabeçalhos de partição da instância Informix.
    Na versão 11.50 este slot ocupa 100 bytes. Versões anteriores podem ocupar menos (ausência do serial8 e bigserial)
  2. Slot 2
    Contém o nome da base de dados, dono da partição, nome da tabela e a NLS collation sequence
  3. Slot 3
    Contém detalhes sobre todas as colunas especiais. Se não existirem colunas especiais (VARCHAR e BLOB) este slot estará vazio. Se existirem, o tamanho ocupado dependerá da estrutura da tabela.
  4. Slot 4
    Contém a descrição de cada chave (se for um índice ou um mix). Desde a versão 9.40, por omissão os indíces são guardados em partição à parte. Isto não era assim em versões anteriores. Uma partição podia conter páginas de indíces e de dados.
    Actualmente, por omissão, uma partição usada para dados não deve ter nenhuma chave, e assim este slot deve estar vazio
  5. Slot 5
    Finalmente, este é o slot que contém a lista dos extents.

Agora sabemos que a lista de estents tem de ser guardada no cabeçalho da partição. E este contém cinco slots sendo que o tamanho dos primeiros quatro varia. Isto implica que o espaço livre para o slot cinco (a lista de extents) é variável. Estas são as razões porque tinhamos um limite e porque esse limite era variável. Variava por exemplo com a estrutura da tabela. E naturalmente variava com o tamanho da página.
Uma tabela que atingisse o número máximo de extents tornava-se num problema sério em Informix. Quando tal acontece, se todas as páginas de dados estiverem cheias, o motor terá de reservar um novo extent para completar novos INSERTs. Mas para isso necessitaria de espaço livre no cabeçalho da partição. Portanto, não havendo aí espaço livre todos os INSERTs falhariam com o erro -136:

-136 ISAM error: no more extents.

Depois de batermos nesta situação havia várias formas de a resolver, mas todas elas necessitavam de indisponibilidade temporária da tabela, o que nos dias que correm é um bem raro... A tendência é usarmos sistemas 24x7. Mesmo sistemas que tenham janela de manutenção sofreriam com isto, porque na maioria das vezes o problema manifestava-se durante o horário normal ou produtivo...

Bom, mas tenho estado a falar no passado.... Isto costumava ser um problema. Porque é que já não o é? Porque a versão 11.7 (Panther) introduziu duas excelentes funcionalidades:

  1. A primeira é que a partir de agora é possível estender automaticamente o cabeçalho da partição quando o slot cinco enche. Nesta situação, uma nova página é reservada para o cabeçalho da partição e a lista de extents pode crescer. Portanto não deverá voltar a ver o erro -136 causado por atingir o limite de extents. À primeira vista pode ter a mesma reacção que o DBA do meu cliente. "Epa! Mas isso não é perigoso? Vou passar a ter tabelas/partições com dezenas de milhares de extents?". A resposta é simples. Não vai atingir esses números de extents porque todas as boas características que sempre existiram (junção automática de extents, duplicação de tamanho do próximo extent...) ainda estão presentes e funcionais. Isto apenas evitará a situação crítica em que o uso da tabela se tornava impossível (para novos INSERTs). E naturalmente isto não significa que passemos a ignorar o número de extents das nossas tabelas. Por questões de desempenho é melhor mantê-los baixos.
  2. A segunda grande funcionalidade é um desfragmentador online de tabelas ou partições. O número de extents pode crescer indefinidamente, mas isso não é bom. Assim que notar que tem uma partição com um número elevado de extents pode pedir ao motor que a desfragmente. Não vou aprofundar este tema, simplemente porque já foi feito. Recomendo que consulte um artigo recente do DeveloperWorks intitulado "Understand the Informix Server V11.7 defragmenter". Infelizmente o artigo só tem versão em Inglês

Wednesday, November 24, 2010

UDRs: In transaction? / Em transacção?

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

English version:

Introduction

I just checked... This will be post 100!!!... I've never been so active in the blog... We have Panther (full of features that I still haven't covered), I did some work with OAT and tasks that I want to share, and besides that I've been trying some new things... Yes... Although I've been working with Informix for nearly 20 years (it's scaring to say this but it's true...) there are aspects that I usually don't work with. I'd say the one I'm going to look into today is not used by the vast majority of the users. And that's a shame because:
  1. It can solve problems that we aren't able to solve in any other way
  2. If it was more used, it would be improved faster
Also, many people think that this is what marked the decline of the Informix company. You probably already figured out that I'm talking about extensibility. To recall a little bit of history, in 1995, Informix had the DSA architecture in version 7. And it acquired the Illustra company, founded by Michael Stonebraker and others. Mr. Stonebraker already had a long history of innovation (which he kept improving up to today) and he stayed with Informix for some years. All the technology around Datablades and extensibility in Informix comes from there... Informix critics say that the company got so absorbed in the extensibility features (that it believed would be the "next wave") that it loosed the market focus. Truth is that the extensibility never became a mainstream feature neither in Informix or in other databases, and all of them followed Informix launch of Universal Server (1996): Oracle, IBM DB2 etc.

But, this article will not focus on the whole extensibility concept. It would be impossible and tedious to try to cover it in one blog article. Instead I'll introduce one of it's aspects: User Defined Routines (UDRs), and in particular routines written using the C language.

There is a manual about UDRs, and I truly recommend that you read it. But here I'll follow another approach: We'll start with a very simple problem that without C UDRs would be impossible to solve, define a solution for it, and go all the way to implement it and use it with an example.


The problem

Have you ever faced a situation where you're writing a stored procedure in SPL, and you want to put some part of it inside a transaction, but you're afraid that the calling code is already in a transaction?
You could workaround this by initiating the transaction and catching the error (already in transaction) with an ON EXCEPTION block.
But this may have other implications (ON EXCEPTION blocks are tricky when the procedure is called from a trigger). So it would be nice to check if the session is already in a transaction. A natural way to do that would be a call to DBINFO(...), but unfortunately current versions (up to 11.7.xC1) don't allow that. Meaning there is no DBINFO() parameter that makes it return that information.


Solution search

One important part of Informix extensibility is the so called Datablade API. It's a set of programmable interfaces that we can use inside Datablades code and also inside C UDRs. The fine infocenter has a reference manual for the Datablade API functions. A quick search there for "transaction" makes a specific function come up: mi_transaction_state()
The documentation states that when calling it (no parameters needed) it will return an mi_integer (let's assume integer for now) type with one of these values:
  • MI_NO_XACT
    meaning we don't have a transaction open
  • MI_IMPLICIT_XACT
    meaning we have an implicit transaction open (for example if we're connected to an ANSI mode database)
  • MI_EXPLICIT_XACT
    meaning we have an explicit transaction open
This is all we need conceptually.... Now we need to transform ideas into runnable code!

Starting the code

In order to implement a C UDR function we should proceed through several steps:
  1. Create the C code skeleton
  2. Create the C code function using the Datablade API
  3. Create a makefile that has all the needed instructions to generate the executable code in a format the engine can use
  4. Compile the code
  5. Use SQL to define the new function, telling the engine where it can find the function and the interface to call it, as well as the language and other function attributes
  6. Test it!



Create the C code skeleton

Informix provides a tool called DataBlade Developers Kit (DBDK) which includes several components: Blade Manager, Blade Pack and Bladesmith. Blade Manager allows us to register the datablades against the databases, the Blade Pack does the "packaging" of all the Datablades files (executable libraries, documentation files, SQL files etc.) that make up a datablade. Finally Bladesmith helps us to create the various components and source code files. It's a development tool that only runs on Windows but can also be used to prepare files for Unix/Linux. For complex projects it may be a good idea to use Bladesmith, but for this very simple example I'll do it by hand. Also note I'm just creating a C UDR. These tools are intended to deal with much more complex projects. A Datablade can include new datatypes, several functions etc.
So, for our example I took a peek at the recent Informix Developer's Handbook to copy the examples.

Having looked at the examples above, it was easy to create the C code:


/*
This simple function returns an integer to the calling SQL code with the following meaning:
0 - We're not within a transaction
1 - We're inside an implicit transaction
2 - We're inside an explicit (BEGIN WORK...) transaction
-1 - Something unexpected happened!
*/

#include <milib.h>

mi_integer get_transaction_state_c( MI_FPARAM *fp)
{
mi_integer i,ret;
i=mi_transaction_state();
switch(i)
{
case MI_NO_XACT:
ret=0;
break;
case MI_IMPLICIT_XACT:
ret=1;
break;
case MI_EXPLICIT_XACT:
ret=2;
break;
default:
ret=-1;
}
return (ret);
}

I've put the above code in a C source file called get_transaction_state_c.c

Create the makefile

Again, for the makefile I copied some examples and came up with the following. Please consider this as an example only. I'm not an expert on makefile building and this is just a small project.


include $(INFORMIXDIR)/incl/dbdk/makeinc.linux

MI_INCL = $(INFORMIXDIR)/incl
CFLAGS = -DMI_SERVBUILD $(CC_PIC) -I$(MI_INCL)/public $(COPTS)
LINKFLAGS = $(SHLIBLFLAG) $(SYMFLAG)


all: get_transaction_state.so

clean:
rm -f get_transaction_state.so get_transaction_state_c.o


get_transaction_state_c.o: get_transaction_state_c.c
$(CC) $(CFLAGS) -o $@ -c $?

get_transaction_state.so: get_transaction_state_c.o
$(SHLIBLOD) $(LINKFLAGS) -o $@ $?


Note that this is a GNU Make makefile. The first line includes a makefile that IBM supplies with Informix. It basically contains variables or macro definitions. You should adapt the include directive to your system (the name of the makefile can vary with the platform) and make sure that the variables I use are also defined in your system base makefile.
After that I define some more variables and I create the makefile targets. I just want it to build the get_transaction_state.so dynamically loadable library and for that I'm including the object (get_transaction_state_c.o) generated from my source code (get_transaction_state_c.c). Pretty simple if you have basic knowledge about makefiles

Compile the code

Once we have the makefile we just need to run a simple command to make it compile:


cheetah@pacman.onlinedomus.net:informix-> make
cc -DMI_SERVBUILD -fpic -I/usr/informix/srvr1150uc7/incl/public -g -o get_transaction_state_c.o -c get_transaction_state_c.c
gcc -shared -Bsymbolic -o get_transaction_state.so get_transaction_state_c.o
cheetah@pacman.onlinedomus.net:informix->
The two commands run are the translation of the macros/variables defined in the makefile(s) and they simply compile the source code (1st command) and then generate the dynamic loadable library. If all goes well (as it naturally happened in the output above), we'll have a library on this location, ready for usage by Informix:


cheetah@pacman.onlinedomus.net:informix-> ls -lia *.so
267913 -rwxrwxr-x 1 informix informix 5639 Nov 23 22:06 get_transaction_state.so
cheetah@pacman.onlinedomus.net:informix-> file *.so
get_transaction_state.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, not stripped
cheetah@pacman.onlinedomus.net:informix->

Use SQL to define the function

Now that we have executable code, in the form of a dynamic loadable library, we need to instruct Informix to use it. For that we will create a new function, telling the engine that it's implemented in C language and the location where it's stored. For that I created a simple SQL file:


cheetah@pacman.onlinedomus.net:informix-> ls *.sql
get_transaction_state_c.sql
cheetah@pacman.onlinedomus.net:informix-> cat get_transaction_state_c.sql
DROP FUNCTION get_transaction_state_c;

CREATE FUNCTION get_transaction_state_c () RETURNING INTEGER
EXTERNAL NAME '/home/informix/udr_tests/get_transaction_state/get_transaction_state.so'
LANGUAGE C;
cheetah@pacman.onlinedomus.net:informix->


So, let's run it...:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores get_transaction_state_c.sql

Database selected.


674: Routine (get_transaction_state_c) can not be resolved.

111: ISAM error: no record found.
Error in line 1
Near character position 36

Routine created.


Database closed.

cheetah@pacman.onlinedomus.net:informix->


Note that the -674 error is expected, since my SQL includes a DROP FUNCTION. If I were using 11.7 (due to several tests I don't have it ready at this moment) I could have used the new syntax "DROP IF EXISTS...".

So, after this step I should have a function callable from the SQL interface with the name get_transaction_state_c(). It takes no arguments and returns an integer value.

Test it!

Now it's time to see it working. I've opened a session in stores database and did the following:
  1. Run the function. It returned "0", meaning no transaction was opened.
  2. Than I opened a transaction and run it again. It returned "2", meaning an explicit transaction was opened
  3. I closed the transaction and run the function by the third time. As expected it returned "0"
Here is the output:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores -

Database selected.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

> BEGIN WORK;

Started transaction.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

2

1 row(s) retrieved.

> ROLLBACK WORK;

Transaction rolled back.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

>

We haven't seen it returning "1". That happens when we're inside an implicit transaction. This situation can be seen if we use the function in an ANSI mode database. For that I'm going to use another database (stores_ansi), and naturally I need to create the function there (using the previous SQL statements). Then I repeat more or less the same steps and the result is interesting:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores_ansi -

Database selected.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

> SELECT COUNT(*) FROM systables;


(count(*))

83

1 row(s) retrieved.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

1

1 row(s) retrieved.

>
If you notice it, the first execution returns "0". Since I have not done any operations there is no transaction opened. But just after a simple SELECT, the return is "1", meaning an implicit transaction is opened. This has to do with the nature and behavior of ANSI mode databases.
If you use them and you intend to use this function you must take that into consideration. Or you could simply map the "1" and "2" output of the mi_transaction_state() function return into simply a "1". This would signal that a transaction is opened (omitting the distinction between implicit and explicit transactions).

Final considerations

Please keep in mind that this article serves more as a light introduction to the C language UDRs than to solve a real problem. If you need to know if you're already in transaction (inside a stored procedure for example) you can use this solution, but you could as well try to open a transaction and capture and deal with the error inside an ON EXCEPTION block.

Also note that if this is a real problem for your applications, even if you're inside an already opened transaction, you can make your procedure code work as a unit, by using the SAVEPOINT functionality introduced in 11.50. So, in simple pseudo-code it would be done like this:

  1. Call get_transaction_state_c()
  2. If we're inside a transaction then set TX="SVPOINT" and create a savepoint called "MYSVPOINT" and goto 4)
  3. If we're not inside a transaction than set TX="TX" and create one. Goto 4
  4. Run our procedure code
  5. If any error happens test TX variable. Else goto 8
  6. If TX=="TX" then ROLLBACK WORK. Return error
  7. Else, if TX=="SVPOINT" then ROLLBACK WORK TO SAVEPOINT 'MYSVPOINT'. Return error
  8. Return success
After this introduction, I hope to be able to write a few more articles related to this topic. The basic idea is that sometimes it's very easy to extend the functionality of Informix. And I feel that many customers don't take advantage of this.
Naturally, there are implications on writing C UDRs. The example above is terribly simple, and it will not harm the engine. But when you're writing code that will be run by the engine a lot of questions pop up.... Memory usage, memory leaks, security stability... But there are answers to this concerns. Hopefully some of them (problems and solutions) will be covered in future articles.


VersĂŁo Portuguesa:

Introdução

Acabei de verificar.... Este será o centésimo artigo!!! Nunca estive tão activo no blog... Temos a versão Panther (11.7) (cheia de funcionalidades sobre as quais ainda não escrevi), fiz algum trabalho com tarefas do OAT que quero partilhar, e para além disso tenho andado a testar coisas novas... Sim... Apesar de já trabalhar com Informix há perto de 20 anos (é assustador dizer isto, mas é verdade...) há áreas de funcionalidade com as quais não lido habitualmente. Diria que aquela sobre a qual vou debruçar-me hoje não é usada pela maioria dos utilizadores. E isso é uma pena porque:
  1. Permite resolver problemas que não têm outra solução
  2. Se fosse mais usada seria melhorada mais rapidamente
Adicionalmente, existe muita gente que pensa que isto foi o que marcou o declínio da empresa Informix. Possivelmente já percebeu que estou a falar da extensibilidade. Para relembrar um pouco de história, em 1995, a Informix tinha a arquitectura DSA (Dynamic Scalable Architecture) na versão 7. E adquiriu a empresa Illustra, fundada por Michael Stonebraker e outros. O senhor Stonebraker já tinha um longo passado de inovação (que prossegue ainda actualmente) e permaneceu na Informix durante alguns anos. Toda a tecnologia à volta dos datablades e extensibilidade teve aí a sua origem.... Os críticos da Informix dizem que a companhia ficou tão absorvida pelas funcionalidades de extensibilidade (que acreditava serem a próxima "vaga") que perdeu o foco do mercado. A verdade é que a extensibilidade nunca se tornou em algo generalizado nem no Informix nem em outras bases de dados, e todas elas seguiram o lançamento do Informix Universal Server (1996): Oracle, IBM DB2 etc.

Mas este artigo não irá focar todo o conceito de extensibilidade. Seria impossível e entediante tentar cobrir tudo isso num artigo de blog. Em vez disso vou apenas introduzir um dos seus aspectos: User Defined Routines (UDRs), e em particular rotinas escritas usando linguagem C.

Existe um manual que cobre os UDRs, e eu recomendo vivamente a sua leitura. Mas aqui seguirei outra abordagem: Começarei com um problema muito simples, que sem um UDR em C seria impossível de resolver, definirei uma solução para o mesmo, e prosseguirei até à implementação e utilização da solução com um exemplo.

O problema

Alguma vez esteve numa situação em que estivesse a escrever um procedimento em SPL, e quisesse colocar parte dele dentro de uma transacção, mas tivesse receio que o código que chama o procedimento já estivesse com uma transacção aberta?

Poderia contornar o problema iniciando uma transacção e apanhando o erro (already in transaction) com um bloco de ON EXCEPTION

Mas isto teria outras implicações (os blocos de ON EXCEPTION podem criar problemas se o procedimento for chamado de um trigger). Portanto seria bom poder verificar se a sessão já está no meio de uma transacção. Uma forma natural de o fazer seria recorrer à função DBINFO(...), mas infelizmente as versões actuais (até à 11.7.xC1) não permitem isso. Ou seja, não há nenhum parâmetro desta função que permita obter a informação que necessitamos.

Pesquisa da solução

Uma parte importante da extensibilidade no Informix é a chamada Datable API. É um conjunto de interfaces programáveis que podemos usar dentro de datablades e também dentro de UDRs em C. O infocenter tem um manual de referência das funções do Datablade API. Uma pesquisa rápida por "transaction" faz aparecer uma função: mi_transaction_state()

A documentação indica que quando a chamamos (não requer parâmetros) irá retornar um valor do tipo mi_integer (equivale a um inteiro) com um destes valores:
  • MI_NO_XACT
    significa que não temos uma transacção aberta
  • MI_IMPLICIT_XACT
    significa que temos uma transacção implícita aberta (por exemplo se estivermos conectados a uma base de dados em modo ANSI)
  • MI_EXPLICIT_XACT
    significa que temos uma transacção explícita aberta
Isto é tudo o que necessitamos conceptualmente.... Agora precisamos de transformar uma ideia em código executável!

Começando o código

Para implementarmos um UDR em C necessitamos de efectuar vários passos:
  1. Criar o esqueleto do cĂłdigo C
  2. Criar a função com código C usando o datablade API
  3. Criar um makefile que tenha todas as instruções necessárias para gerar o código executável num formato que possa ser usado pelo motor
  4. Compilar o cĂłdigo
  5. Usar SQL para definir uma nova função, indicando ao motor onde pode encontrar a função, o interface para a chamar bem como a linguagem usada e outros atributos da função
  6. Testar!

Criar o cĂłdigo em C

O Informix fornece uma ferramenta chamada DataBlade Developers Kit (DBDK) que incluí vários componentes: Blade Manager, Blade Pack e Bladesmith. O Blade Manager permite-nos registar datablades em bases de dados, o Blade Pack faz o "empacotamento" de todos os ficheiros de um datablade (bibliotecas executáveis, ficheiros de documentação, ficheiros SQL, etc.). Finalmente o Bladesmith ajuda-nos a criar vários componentes e código fonte. É uma ferramenta de desenvolvimento que apenas corre em Windows mas que pode ser usado para preparar ficheiros para Unix/Linux. Para projectos complexos será boa ideia usar o Bladesmith mas para este exemplo simples farei tudo à mão. Apenas estou a criar um UDR em C. Estas ferramentas destinam-se a lidar com projectos muito mais complexos. Um Datablade pode incluir novos tipos de dados, várias funções etc.
Assim, para o nosso exemplo dei uma espreitadela ao recente Informix Developer's Handbook para copiar alguns exemplos.

Depois de ver os exemplos referidos, foi fácil criar o código em C:
/*
This simple function returns an integer to the calling SQL code with the following meaning:
0 - We're not within a transaction
1 - We're inside an implicit transaction
2 - We're inside an explicit (BEGIN WORK...) transaction
-1 - Something unexpected happened!
*/

#include <milib.h>

mi_integer get_transaction_state_c( MI_FPARAM *fp)
{
mi_integer i,ret;
i=mi_transaction_state();
switch(i)
{
case MI_NO_XACT:
ret=0;
break;
case MI_IMPLICIT_XACT:
ret=1;
break;
case MI_EXPLICIT_XACT:
ret=2;
break;
default:
ret=-1;
}
return (ret);
}

Coloquei o cĂłdigo acima num ficheiro chamado get_transaction_state_c.c


Criar o makefile

Também para o makefile, limitei-me a copiar alguns exemplos e gerei o seguinte. Por favor considere isto apenas como um exemplo. Não sou especialista em construção de makefiles e isto é apenas um pequeno projecto.


include $(INFORMIXDIR)/incl/dbdk/makeinc.linux

MI_INCL = $(INFORMIXDIR)/incl
CFLAGS = -DMI_SERVBUILD $(CC_PIC) -I$(MI_INCL)/public $(COPTS)
LINKFLAGS = $(SHLIBLFLAG) $(SYMFLAG)


all: get_transaction_state.so

clean:
rm -f get_transaction_state.so get_transaction_state_c.o


get_transaction_state_c.o: get_transaction_state_c.c
$(CC) $(CFLAGS) -o $@ -c $?

get_transaction_state.so: get_transaction_state_c.o
$(SHLIBLOD) $(LINKFLAGS) -o $@ $?


Este makefile destina-se ao GNU Make. A primeira linha incluí um makefile fornecido pela IBM com o Informix. Este, basicamente, contém definições de variáveis e macros. Deve adaptar a directiva include ao seu sistema (o nome do makefile pode variar com a plataforma) e garanta que as variáveis que usei estão definidas no makefile base do seu sistema.
Depois disso defini mais algumas variáveis e criei os targets. Apenas quero que gere a biblioteca dinâmica get_transaction_state.so e para isso estou a incluir o objecto (get_transaction_state_c.o) gerado a partir do meu código fonte (get_transaction_state_c.c). Bastante simples se tiver conhecimentos básicos de makefiles.


Compilar o cĂłdigo

Depois de termos o makefile apenas necessitamos de um comando simples para executar a compilação:


cheetah@pacman.onlinedomus.net:informix-> make
cc -DMI_SERVBUILD -fpic -I/usr/informix/srvr1150uc7/incl/public -g -o get_transaction_state_c.o -c get_transaction_state_c.c
gcc -shared -Bsymbolic -o get_transaction_state.so get_transaction_state_c.o
cheetah@pacman.onlinedomus.net:informix->
Os dois comandos executados são a tradução dos macros/variáveis definidos no(s) makefiles(s), e apenas compilam o código fonte (primeiro comando) e depois geram a biblioteca dinâmica. Se tudo correr bem (como naturalmente aconteceu no output acima), teremos a biblioteca nesta localização, pronta a ser usada pelo Informix:
cheetah@pacman.onlinedomus.net:informix-> ls -lia *.so
267913 -rwxrwxr-x 1 informix informix 5639 Nov 23 22:06 get_transaction_state.so
cheetah@pacman.onlinedomus.net:informix-> file *.so
get_transaction_state.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, not stripped
cheetah@pacman.onlinedomus.net:informix->

Usar SQL para definir a função

Agora que temos o código executável, na forma de uma biblioteca dinâmica, precisamos de instruir o Informix para usá-la. Para isso vamos criar uma nova função, dizendo ao motor que está implementada em linguagem C e qual a localização onde está guardada. Faremos isso com um script SQL simples:

cheetah@pacman.onlinedomus.net:informix-> ls *.sql
get_transaction_state_c.sql
cheetah@pacman.onlinedomus.net:informix-> cat get_transaction_state_c.sql
DROP FUNCTION get_transaction_state_c;

CREATE FUNCTION get_transaction_state_c () RETURNING INTEGER
EXTERNAL NAME '/home/informix/udr_tests/get_transaction_state/get_transaction_state.so'
LANGUAGE C;
cheetah@pacman.onlinedomus.net:informix->


Vamos executá-lo...:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores get_transaction_state_c.sql

Database selected.


674: Routine (get_transaction_state_c) can not be resolved.

111: ISAM error: no record found.
Error in line 1
Near character position 36

Routine created.


Database closed.

cheetah@pacman.onlinedomus.net:informix->


Repare que o erro -674 é expectável, dado que o meu SQL incluí a instrução DROP FUNCTION (e ela ainda não existe). Se estivesse a usar a versão 11.7 (devido a vários testes não a tenho operacional agora) podia ter usado a nova sintaxe "DROP IF EXISTS".

Portanto depois deste passo, devo ter uma função que pode ser chamada pela interface SQL com o nome get_transaction_state_c(). Não recebe argumentos e retorna um valor inteiro.


Testar!

Agora Ă© tempo de a ver a trabalhar. Abri uma sessĂŁo na base de dados stores e fiz o seguinte:
  1. Corri a função. Retornou "0", o que significa que não havia transacção aberta
  2. Depois abri uma transacção e executei a função novamente. Retornou "2", o que significa que uma transacção explícita estava aberta
  3. Fechei a transacção e corri a função pela terceira vez. Como esperado retornou "0"
Aqui está o output:


cheetah@pacman.onlinedomus.net:informix-> dbaccess stores -

Database selected.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

> BEGIN WORK;

Started transaction.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

2

1 row(s) retrieved.

> ROLLBACK WORK;

Transaction rolled back.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

>

Não vimos o retorno "1". Isso acontece quando estamos dentro de uma transacção implícita. Esta situação pode ser vista se a função estiver a ser executada numa base de dados em modo ANSI. Para isso vou usar uma outra base de dados (stores_ansi), e naturalmente necessito de criar a função aqui (usando as instruções SQL anteriores). Depois repito mais ou menos os mesmos passos e o resultado é interessante:

cheetah@pacman.onlinedomus.net:informix-> dbaccess stores_ansi -

Database selected.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

0

1 row(s) retrieved.

> SELECT COUNT(*) FROM systables;


(count(*))

83

1 row(s) retrieved.

> EXECUTE FUNCTION get_transaction_state_c();


(expression)

1

1 row(s) retrieved.

>
Se reparar, a primeira execução retornou "0". Como ainda não tinha efectuado nenhuma operação não havia transacção aberta. Mas logo a seguir a um simples SELECT já retorna "1", o que significa que uma transacção implícita estava aberta. Isto prende-se com a natureza e comportamento das bases de dados em modo ANSI.
Se as usa e pretende usar esta função terá de ter isto em consideração. Ou poderá simplesmente mapear o retorno "1" e "2" da função mi_transaction_state() no retorno "1" da função criada por si. Isto sinalizaria que uma transacção estava aberta (omitindo a distinção entre transacção implícita e explícita).

Considerações finais

Relembro que este artigo serve mais como introdução aos UDRs na linguagem C que propriamente para resolver um problema real.
Se necessitar de saber se já está numa transacção (dentro de uma stored procedure por exemplo) pode usar esta solução, mas também podia tentar abrir uma transacção e capturar e gerir o erro dentro de um bloco ON EXCEPTION.

Chamo a atenção também para que se isto é um problema real das suas aplicações, mesmo que esteja já dentro de uma transacção, pode fazer com que o código da sua stored procedure trabalhe como uma unidade, usando a funcionalidade dos SAVEPOINTs, introduzida na versão 11.50. Em pseudo-código seria feito assim:

  1. Chamar a get_transaction_state_c()
  2. Se estamos dentro de uma transacção então estabelecer TX="SVPOINT" e criar um savepoint chamado "MYSVPOINT". Ir para 4)
  3. Se não estamos dentro de uma transacção então estabelecer TX="TX" e criar uma. Ir para 4)
  4. Correr o cĂłdigo da procedure
  5. Se ocorrer algum erro testat a variável TX. Ir para 8)
  6. Se TX =="TX" entĂŁo ROLLBACK WORK. Retornar erro.
  7. SenĂŁo, SE TX=="SVPOINT" entĂŁo ROLLBACK WORK TO SAVEPOINT 'MYSVPOINT'. Retornar erro
  8. Retornar sucesso
Depois desta introdução espero conseguir escrever mais alguns artigos relacionados com este tópico. A ideia base é que algumas vezes é muito fácil estender a funcionalidade base do Informix. E sinto que muitos clientes não tiram partido disto.
Naturalmente há implicações em escrever UDRs em C. O exemplo acima é terrivelmente simples, e não trará prejuízo ao motor. Mas quando escrevemos código que será executado pelo motor surgem uma série de questões... Utilização de memória, fugas de memória, segurança, estabilidade.... Mas existem respostas para estas preocupações. Espero que alguns (problema e soluções) sejam cobertos em artigos futuros.

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Sweet Tomatoes Printable Coupons