<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/wordpress-mu-1.2.5" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>procself &#187; database</title>
	<link>http://blogs.fe.up.pt/mpadilha</link>
	<description>cat /proc/self/cmdline</description>
	<pubDate>Wed, 14 Oct 2009 17:36:32 +0000</pubDate>
	<generator>http://wordpress.org/?v=wordpress-mu-1.2.5</generator>
	<language>en</language>
			<item>
		<title>JBoss + Hibernate + MySQL sem perder ligações</title>
		<link>http://blogs.fe.up.pt/mpadilha/2008/11/28/jboss-hibernate-mysql-sem-perder-ligacoes/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2008/11/28/jboss-hibernate-mysql-sem-perder-ligacoes/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 10:29:58 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[mysql]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[open-source]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2008/11/28/jboss-hibernate-mysql-sem-perder-ligacoes/</guid>
		<description><![CDATA[Existem essencialmente duas formas distintas de usar Hibernate com MySQL (ou qualquer outra base-de-dados, para este ponto em concreto é indiferente), definindo todas as propriedades da ligação no próprio ficheiro de configuração do Hibernate, ou dizendo apenas que se pretende usar uma datasource JNDI pré-existente.
A primeira opção é a escolha típica numa aplicação stand-alone, mas [...]]]></description>
			<content:encoded><![CDATA[<p>Existem essencialmente duas formas distintas de usar Hibernate com MySQL (ou qualquer outra base-de-dados, para este ponto em concreto é indiferente), definindo todas as propriedades da ligação no próprio ficheiro de configuração do Hibernate, ou dizendo apenas que se pretende usar uma datasource JNDI pré-existente.</p>
<p>A primeira opção é a escolha típica numa aplicação stand-alone, mas a opção de utilizar uma datasource JNDI é a que faz mais sentido para <em>application servers</em>. Portanto, o ficheiro de configuração do Hibernate há-de ter, parcialmente, este aspecto:</p>
<p><code>&lt;hibernate-configuration&gt;<br />
&lt;session-factory&gt;<br />
&lt;property name="hibernate.connection.datasource"&gt;<br />
java:my_app_name<br />
&lt;/property&gt;<br />
&lt;property name="hibernate.setup"&gt;true&lt;/property&gt;<br />
&lt;property name="hibernate.dialect"&gt;<br />
org.hibernate.dialect.MySQLInnoDBDialect<br />
&lt;/property&gt;<br />
&lt;property name="transaction.factory_class"&gt;<br />
org.hibernate.transaction.JDBCTransactionFactory<br />
&lt;/property&gt;<br />
&lt;property name="current_session_context_class"&gt;<br />
thread<br />
&lt;/property&gt;<br />
&lt;/session-factory&gt;<br />
&lt;/hibernate-configuration&gt;</code></p>
<p>Depois basta definir a datasource com o nome JNDI correspondente, por exemplo assim:</p>
<p><code>&lt;datasources&gt;<br />
&lt;local-tx-datasource&gt;<br />
&lt;jndi-name&gt;my_app_name&lt;/jndi-name&gt;<br />
&lt;connection-url&gt;jdbc:mysql://host_or_ip/db_name&lt;/connection-url&gt;<br />
&lt;driver-class&gt;com.mysql.jdbc.Driver&lt;/driver-class&gt;<br />
&lt;user-name&gt;username&lt;/user-name&gt;<br />
&lt;password&gt;password&lt;/password&gt;<br />
&lt;min-pool-size&gt;5&lt;/min-pool-size&gt;<br />
&lt;max-pool-size&gt;20&lt;/max-pool-size&gt;<br />
&lt;/local-tx-datasource&gt;<br />
&lt;/datasources&gt;</code></p>
<p>Agora que está tudo montado como manda a documentação, sugiro uma experiência:</p>
<ol>
<li>Ligar servidor BD.</li>
<li>Ligar application server.</li>
<li>Testar aplicação que se liga à base de dados (funciona)</li>
<li>Reiniciar servidor BD (ou esperar 8 horas).</li>
<li>Testar aplicação que se liga à base de dados (não funciona!)</li>
</ol>
<p>Então&#8230; tanto trabalho para abstrair a ligação a base de dados e um simples restart da base de dados deixa as ligações geridas pelo Hibernate todas inválidas? E, pior, não há recuperação automática?</p>
<p>Pois&#8230; parece que não. E acrescentar o parâmetro <code>autoReconnect=true</code> ao URL JDBC também não resolve, aliás, a utilização desse parâmetro até é desaconselhada, como se pode ver pelo que diz no manual:</p>
<blockquote><p>Should the driver try to re-establish stale and/or dead connections? If enabled the driver will throw an exception for a queries issued on a stale or dead connection, which belong to the current transaction, but will attempt reconnect before the next query issued on the connection in a new transaction. The use of this feature is not recommended, because it has side effects related to session state and data consistency when applications don&#8217;t handle SQLExceptions properly, and is only designed to be used when you are unable to configure your application to handle SQLExceptions resulting from dead and stale connections properly. &#8212; <a href="http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html">MySQL 5.0 Reference Manual</a></p></blockquote>
<p>A solução que encontrei para MySQL (e que também funciona para MS SQL Server), é acrescentar a seguinte linha ao ficheiro de configuração da datasource:</p>
<p><code>&lt;check-valid-connection-sql&gt;SELECT 1&lt;/check-valid-connection-sql&gt;</code></p>
<p>Esta opção faz mesmo aquilo que parece fazer, ou seja, antes de usar uma ligação, a query ali especificada é executada como forma de verificar se a ligação é usável. Se não ocorrer nenhum erro, a instrução SQL que realmente se pretende executar é enviada pela mesma ligação, se houver um erro, a ligação é descartada e é criada uma nova.</p>
<p>Claro que isto tem um impacto sério na performance uma vez que se está a duplicar o número de queries, o que pode ser particularmente grave se o acesso à base de dados for feito através de um canal de elevada latência (rede, por exemplo).</p>
<p>Aparentemente existem soluções melhores para outras bases de dados, como o seguinte comentário parece sugerir:</p>
<p class="post-text">&nbsp;</p>
<blockquote><p>Whilst you can use the old &#8220;select 1 from dual&#8221; trick, the downside with this is that it issues an extra query each and every time you borrow a connection from the pool. For high volumes, this is wasteful.</p>
<p>JBoss provides a special connection validator which should be used for Oracle:</p>
<p>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</p>
<p>This makes use of the proprietary ping() method on the Oracle JDBC Connection class, and uses the driver&#8217;s underlying networking code to determine if the connection is still alive. &#8212; <a href="http://stackoverflow.com/questions/128527/is-there-any-way-to-have-the-jboss-connection-pool-reconnect-to-oracle-when-con#145889">stackoverflow.com</a></p></blockquote>
<p>Alguém conhece uma alternativa semelhante para MySQL?</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=96&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_96" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2008/11/28/jboss-hibernate-mysql-sem-perder-ligacoes/feed/</wfw:commentRss>
		</item>
		<item>
		<title>No TDS_RET_STATUS was found</title>
		<link>http://blogs.fe.up.pt/mpadilha/2008/10/31/no-tds_ret_status-was-found/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2008/10/31/no-tds_ret_status-was-found/#comments</comments>
		<pubDate>Fri, 31 Oct 2008 22:29:36 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[database]]></category>

		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2008/10/31/no-tds_ret_status-was-found/</guid>
		<description><![CDATA[Se alguma vez se depararem com este erro:

 No TDS_RET_STATUS was found

ao inserir dados numa tabela em SQL Server. Ficam a saber que a causa pode ser esta:

Microsoft® SQL Server™ 2000 retains the 900-byte limit for the maximum size of an index key (&#8230;)

De facto a criação de um índice com um chave que exceda os [...]]]></description>
			<content:encoded><![CDATA[<p class="lf secttl"><span>Se alguma vez se depararem com este erro:</span></p>
<blockquote>
<p class="lf secttl"><span> No TDS_RET_STATUS was found</span></p>
</blockquote>
<p class="lf secttl"><span>ao inserir dados numa tabela em SQL Server. Ficam a saber que a causa pode ser esta:</span></p>
<blockquote>
<p class="lf secttl"><span>Microsoft® SQL Server™ 2000 retains the <strong>900-byte limit</strong> for the maximum size of an index key (&#8230;)</span></p>
</blockquote>
<p class="lf secttl">De facto a criação de um índice com um chave que exceda os 900 bytes em comprimento já resulta num aviso, mas sucede se os dados existentes na tabela no momento da criação do índice não ultrapassarem o tal limite dos 900 bytes.</p>
<p class="lf secttl">No entanto, quando tentarem inserir dados que façam ultrapassar este limite podem ter um erro que, do outro lado de um ligação ODBC, pode ser tão pouco elucidativo como este <img src='http://blogs.fe.up.pt/mpadilha/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=77&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_77" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2008/10/31/no-tds_ret_status-was-found/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MySQL Clone database schema</title>
		<link>http://blogs.fe.up.pt/mpadilha/2008/01/09/mysql-clone-database-schema/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2008/01/09/mysql-clone-database-schema/#comments</comments>
		<pubDate>Wed, 09 Jan 2008 14:52:30 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[mysql]]></category>

		<category><![CDATA[open-source]]></category>

		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2008/01/09/mysql-clone-database-schema/</guid>
		<description><![CDATA[Neste artigo descobri uma forma de criar tabelas que dá muito jeito:
CREATE TABLE newtable LIKE mytable;
Pensei que devia existir algo equivalente para copiar as definições de uma base de dados inteira, mas aparentemente não existe.
A forma mais fácil de conseguir o mesmo resultado é provavelmente usar o mysqldump com a seguinte opção:

--no-data

No entanto, já há [...]]]></description>
			<content:encoded><![CDATA[<p>Neste <a href="http://www.phpdiary.org/articles/how-to-clone-a-mysql-table-schema/">artigo</a> descobri uma forma de criar tabelas que dá muito jeito:</p>
<blockquote><p><code>CREATE TABLE newtable LIKE mytable;</code></p></blockquote>
<p>Pensei que devia existir algo equivalente para copiar as definições de uma base de dados inteira, mas aparentemente não existe.<br />
A forma mais fácil de conseguir o mesmo resultado é provavelmente usar o <a href="http://dev.mysql.com/doc/mysql/en/mysqldump.html">mysqldump</a> com a seguinte opção:</p>
<blockquote>
<pre>--no-data</pre>
</blockquote>
<p>No entanto, já há bastante tempo que queria experimentar os <em>stored procedures</em> do MySQL, por isso aproveitei a oportunidade para escrever o meu primeiro:</p>
<blockquote><p><code> delimiter //</code><br />
<code> DROP PROCEDURE IF EXISTS copySchema //</code><br />
<code> CREATE PROCEDURE copySchema(IN schemaname CHAR(64))</code><br />
<code> BEGIN</code><br />
<code> DECLARE done INT DEFAULT 0;</code><br />
<code> DECLARE table_a CHAR(64) default 'testing';</code><br />
<code> DECLARE cur1 CURSOR FOR SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA = schemaname;</code><br />
<code> DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;</code><br />
<code> OPEN cur1;</code><br />
<code> REPEAT</code><br />
<code> FETCH cur1 INTO table_a;</code><br />
<code> IF NOT done THEN</code><br />
<code> SELECT CONCAT('CREATE TABLE ', table_a, ' LIKE ', schemaname, '.', table_a) into @sqlstr;</code><br />
<code> PREPARE stmt FROM @sqlstr;</code><br />
<code> EXECUTE stmt;</code><br />
<code> END IF;</code><br />
<code> UNTIL done END REPEAT;</code><br />
<code> CLOSE cur1;</code><br />
<code> END</code><br />
<code> //</code><br />
<code> delimiter ;</code><br />
<code></code><br />
<code>CALL mydb.copySchema('mysql');</code></p></blockquote>
<p>Referências:</p>
<ul>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html">Create Procedure</a></li>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/cursors.html">Cursors</a></li>
<li><a href="http://dev.mysql.com/doc/refman/5.0/en/sqlps.html">Prepared Statements</a></li>
</ul>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=67&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_67" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2008/01/09/mysql-clone-database-schema/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SQLServer Create Database if it doesn&#8217;t exist</title>
		<link>http://blogs.fe.up.pt/mpadilha/2007/12/10/sqlserver-create-database-if-it-doesnt-exist/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2007/12/10/sqlserver-create-database-if-it-doesnt-exist/#comments</comments>
		<pubDate>Mon, 10 Dec 2007 11:24:44 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[database]]></category>

		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2007/12/10/sqlserver-create-database-if-it-doesnt-exist/</guid>
		<description><![CDATA[good: 
if not exists(select * from sys.databases where name = &#8216;Testing&#8217;)
    create database testing
better:
if db_id(&#8217;dbname&#8217;) is null
    create database testing
best?&#8230;
Source: Microsoft Forums
Partilhar
]]></description>
			<content:encoded><![CDATA[<p><strong>good:</strong> </p>
<blockquote><p>if not exists(select * from sys.databases where name = &#8216;Testing&#8217;)<br />
    create database testing</p></blockquote>
<p><strong>better:</strong></p>
<blockquote><p>if db_id(&#8217;dbname&#8217;) is null<br />
    create database testing</p></blockquote>
<p><strong>best?&#8230;</strong></p>
<p>Source: <a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=95570&amp;SiteID=1">Microsoft Forums</a></p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=59&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_59" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2007/12/10/sqlserver-create-database-if-it-doesnt-exist/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MySQL sliding window archive</title>
		<link>http://blogs.fe.up.pt/mpadilha/2007/12/02/mysql-sliding-window-archive/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2007/12/02/mysql-sliding-window-archive/#comments</comments>
		<pubDate>Sun, 02 Dec 2007 04:05:56 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[mysql]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[storage]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2007/12/02/mysql-sliding-window-archive/</guid>
		<description><![CDATA[O objectivo
Já aqui falei sobre logs centralizados. O objectivo que se pretende atingir é concentrar todos os logs de um datacenter num único sítio para consulta fácil e arquivo histórico. Mais concretamente, é importante:

Guardar todos os logs durante pelo menos 5 anos.
Manter os últimos meses rapidamente acessíveis e passíveis de serem consultados de forma flexível e rápida.
Garantir [...]]]></description>
			<content:encoded><![CDATA[<p><strong>O objectivo</strong><br />
Já aqui falei sobre <a href="http://blogs.fe.up.pt/mpadilha/2007/04/23/centralized-logs/">logs centralizados</a>. O objectivo que se pretende atingir é concentrar todos os logs de um datacenter num único sítio para consulta fácil e arquivo histórico. Mais concretamente, é importante:</p>
<ul>
<li>Guardar todos os logs durante pelo menos 5 anos.</li>
<li>Manter os últimos meses rapidamente acessíveis e passíveis de serem consultados de forma flexível e rápida.</li>
<li>Garantir que em caso de avaria grave não se perdem mais do que 1 ou dois dias de logs.</li>
</ul>
<p>Noutro post falei da possibilidade de <a href="http://blogs.fe.up.pt/mpadilha/2007/04/25/centralized-logs-todo-list/">usar o <em>Archive storage engine</em></a> como forma de reduzir o espaço ocupado e, simultaneamente, dificultar o encobrimento de acções ilegítimas através da eliminação de logs.<strong> </strong></p>
<p><strong>Os problemas</strong><br />
Ao tentar usar o Archive storage engine como repositório de todos os logs, tentanto tirar partido da compresão e da durabilidade inerentes, surgem alguns problemas, nomeadamente:</p>
<ul>
<li>A compressão/descompressão de dados, associada à <a href="http://forums.mysql.com/read.php?112,41737,41737#msg-41737">inexistência de índices</a> torna as consultas com critérios complexos muito mais demoradas do que em MyISAM.</li>
<li>O recurso a <a href="http://dev.mysql.com/tech-resources/articles/mysql_5.1_partitions.html">partições</a> para acelerar as consultas (que são sempre limitadas a um determinado intervalo de tempo, e por isso prestam-se a <a href="http://dev.mysql.com/doc/refman/5.1/en/partitioning-pruning.html">partition pruning</a>) é uma boa ideia, mas há <a href="http://forums.mysql.com/read.php?106,143188,143293#msg-143293">limites</a>&#8230;</li>
</ul>
<p><strong>A solução</strong><br />
A conjugação dos requisitos anteriores aponta quase directamente para uma solução heterogénea que combine o melhor de dois mundos: a rapidez de acesso e a flexibilidade do storage engine MyISAM, com a durabilidade e compressão do Archive.<br />
A solução final tem os seguintes componentes:</p>
<ul>
<li>Uma base de dados em que os logs são guardados em tabelas MyISAM. As tabelas são particionadas <a target="_blank" href="http://dev.mysql.com/doc/refman/5.1/en/partitioning-range.html">por intervalo</a>, usando a data do evento como chave de particionamento. Cada partição irá conter um dia dados, ou seja uma média de 300.000 registos. As tabelas são criadas vazias com duas partições, uma para o dia actual e outra para o dia seguinte.</li>
<li>Uma base de dados em que os logs são guardados em tabelas Archive, sem recurso a partições, porque são conhecidos <a target="_blank" href="http://www.google.com/search?q=archive+partitions+site%3Abugs.mysql.com&amp;rls=com.microsoft:en-US&amp;ie=UTF-8&amp;oe=UTF-8&amp;startIndex=&amp;startPage=1">vários problemas</a> com essa combinação, e já tive oportunidade de experimentar alguns deles. As tabelas são criadas vazias.</li>
<li>Um script executado diariamente que verifica a existência de dados na base de dados MyISAM com mais de 60 dias e, caso existam, os copia para a base de dados Archive, eliminando de seguida a partição correspondente (e os dados nela contidos) da base de dados MyISAM.</li>
</ul>
<p>Desta forma mantém-se sempre 2 meses de logs que são muito rápidos de consultar, graças ao uso de partições e do storage engine MyISAM é fácil e rápido fazer backup, e assegura-se o armazenamento a longo prazo com taxas de ocupação adequadas.</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=45&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_45" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2007/12/02/mysql-sliding-window-archive/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Database Disaster Resilience (3/3)</title>
		<link>http://blogs.fe.up.pt/mpadilha/2007/05/27/database-disaster-resilience-33/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2007/05/27/database-disaster-resilience-33/#comments</comments>
		<pubDate>Sun, 27 May 2007 22:58:07 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[open-source]]></category>

		<category><![CDATA[mysql]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[networking]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[storage]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2007/05/27/database-disaster-resilience-33/</guid>
		<description><![CDATA[(Continuação deste outro post)
Para encerrar este tema, a solução final passou por replicar duas partições de alguns GBs usando DRBD 0.7, e montar o /var/lib/mysql lá em cima.
Como storage engine ficou o InnoDB, mas com tablespaces individuais por cada tabela, para ser mais fácil gerir o espaço em disco (e também dá jeito para backup/restore [...]]]></description>
			<content:encoded><![CDATA[<p>(Continuação deste outro <a href="http://blogs.fe.up.pt/mpadilha/2007/04/15/database-disaster-resilience-23/">post</a>)</p>
<p>Para encerrar este tema, a solução final passou por replicar duas partições de alguns GBs usando <a href="http://www.drbd.org/">DRBD 0.7</a>, e montar o /var/lib/mysql lá em cima.</p>
<p>Como storage engine ficou o <a href="http://dev.mysql.com/doc/refman/5.0/en/innodb.html">InnoDB</a>, mas com <a href="http://dev.mysql.com/doc/mysql/en/Multiple_tablespaces.html">tablespaces individuais por cada tabela</a>, para ser mais fácil gerir o espaço em disco (e também dá jeito para <em>backup/restore</em> binário).</p>
<p>Ainda não simulei desastres com o sistema em carga, mas conto fazê-los em breve, se houver novidades dignas de registo, avisarei.</p>
<p>Só mais uma nota, durante o <em>setup</em> foi necessário sincronizar a partição entre duas localizações remotas e fiquei agradavelmente surpreendido com o desempenho de rede do DRBD.</p>
<p>PS: A história das maçãs serve apenas para facilitar a escrita e evitar mencionar o objectivo real da aplicação que está em cima desta infra-estrutura. Como é ortogonal em relação aos temas discutidos, julgo que ninguém sai lesado.</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=28&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_28" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2007/05/27/database-disaster-resilience-33/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Gestão de dados hierárquicos em (My)SQL</title>
		<link>http://blogs.fe.up.pt/mpadilha/2007/05/02/gestao-de-dados-hierarquicos-em-mysql/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2007/05/02/gestao-de-dados-hierarquicos-em-mysql/#comments</comments>
		<pubDate>Wed, 02 May 2007 21:33:11 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[mysql]]></category>

		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2007/05/02/gestao-de-dados-hierarquicos-em-mysql/</guid>
		<description><![CDATA[A Diana escreveu recentemente sobre este tema, chamando-me à atenção este artigo de Mike Hillier.
O artigo é muito bom, obrigado pelo link Diana.
A grande sedução do modelo da lista de adjacências vem da facilidade com que se implementam as operações de inserção de nós (por onde normalmente se começa) e só se perde quando se [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://dianasoares.blogspot.com/2005/08/gesto-de-dados-hierrquicos-em-mysql.html">Diana escreveu</a> recentemente sobre este tema, chamando-me à atenção este <a href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html">artigo</a> de <a href="http://www.openwin.org/mike/">Mike Hillier</a>.<br />
O artigo é muito bom, obrigado pelo link Diana.</p>
<p>A grande sedução do modelo da lista de adjacências vem da facilidade com que se implementam as operações de inserção de nós (por onde normalmente se começa) e só se perde quando se chega ao ponto de precisar de alguma recursividade para percorrer convenientemente uma árvore com profundidade arbitrária.</p>
<p>Por oposição, o modelo dos &#8220;conjuntos encaixados&#8221; torna a operação de inserção bem mais difícil de escrever, mas, em contrapartida, facilita muito a tarefa de percorrer a árvore.</p>
<p>Em aplicações OLTP convencionais do tipo loja on-line, a árvore (de produtos e categorias) é criada uma vez e depois raramente é mexida. Mesmo que surjam novos produtos, estes irão usualmente encaixar em categorias pré-existentes, portanto a necessidade de criar novos nós intermédios na árvore é realmente baixa. Pelo contrário, a necessidade de apresentar uma lista de categorias com vários níveis de indentação que possam ser progressivamente expandidos até se chegarem aos produtos é crucial. Todos os clientes da loja on-line terão que passar por lá várias vezes durante a sua visita.</p>
<p>Nesta perspectiva, é bem mais compensador recorrer ao modelo dos conjuntos encaixados. Como também é normal, provavelmente o inverso é verdade se estivermos a falar de aplicações OLAP&#8230;</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=22&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_22" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2007/05/02/gestao-de-dados-hierarquicos-em-mysql/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Centralized Logs - ToDo List</title>
		<link>http://blogs.fe.up.pt/mpadilha/2007/04/25/centralized-logs-todo-list/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2007/04/25/centralized-logs-todo-list/#comments</comments>
		<pubDate>Wed, 25 Apr 2007 02:50:31 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[mysql]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[security]]></category>

		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2007/04/25/centralized-logs-todo-list/</guid>
		<description><![CDATA[(continuação deste outro post)
Encriptação
Encriptar a transmissão dos logs para garantir confidencialidade dos dados transmitidos. Como a transmissão é feita sobre UDP, não basta usar um túnel de SSH. Uma possibilidade é usar a funcionalidade de Datagram TLS (DTLS) que o openssl também fornece, mas ainda não consegui pôr isso a funcionar em Windows&#8230;
Host-based Auth
Neste momento [...]]]></description>
			<content:encoded><![CDATA[<p>(continuação deste outro <a href="http://blogs.fe.up.pt/mpadilha/2007/04/23/centralized-logs/">post</a>)</p>
<p><strong>Encriptação</strong><br />
Encriptar a transmissão dos logs para garantir confidencialidade dos dados transmitidos. Como a transmissão é feita sobre UDP, não basta usar um túnel de SSH. Uma possibilidade é usar a funcionalidade de <a href="http://crypto.stanford.edu/~nagendra/projects/dtls/dtls.html">Datagram TLS</a> (DTLS) que o <a href="http://www.openssl.org/">openssl</a> também fornece, mas ainda não consegui pôr isso a funcionar em Windows&#8230;</p>
<p><strong>Host-based Auth</strong><br />
Neste momento qualquer host que tenha acesso ao servidor onde corre o rsyslogd pode enviar logs para lá. Já com a escrita dos logs para ficheiros isto podia ser usado para <a href="http://en.wikipedia.org/wiki/Denial-of-service_attack">ataques DoS</a>, mas com o <em>overhead</em> adicional da escrita para base de dados, começa a ser preocupante. Se não houver uma alternativa mais <em>application-level</em>, posso usar o <a href="http://www.netfilter.org/">iptables</a> para limitar os <em>hosts</em> que têm acesso à porta 514/udp.</p>
<p><strong>Storage Engine Archive</strong><br />
Na versão 5.0 o MySQL suporta um novo tipo de storage engine, o <a href="http://dev.mysql.com/tech-resources/articles/storage-engine.html">Archive</a>. Descrição abreviada retirada do site:</p>
<blockquote><p>In addition to its compression and ease-of-use capabilities, the Archive storage engine is ideal for data auditing uses. Archive tables only support SELECT and INSERT operations, which should cause every data security officer or auditor to smile. Why? Because auditing restrictions require that, once created, audit data should not be manipulated in any way. Archive tables support just these types of restrictions since data cannot be updated or selectively removed - in other words, no tampering allowed.</p></blockquote>
<p>Para este tipo de aplicação isto é ouro sobre azul&#8230; Só é preciso ter cuidado com a versão do servidor MySQL que se usa, até à 5.0.15 havia um <a href="http://forums.mysql.com/read.php?112,63662,63686#msg-63686">bug na Zlib</a> que impedia que os ORDER BY funcionassem devidamente.</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=21&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_21" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2007/04/25/centralized-logs-todo-list/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Centralized Logs</title>
		<link>http://blogs.fe.up.pt/mpadilha/2007/04/23/centralized-logs/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2007/04/23/centralized-logs/#comments</comments>
		<pubDate>Mon, 23 Apr 2007 00:28:36 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[open-source]]></category>

		<category><![CDATA[mysql]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[security]]></category>

		<category><![CDATA[networking]]></category>

		<category><![CDATA[windows]]></category>

		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2007/04/23/centralized-logs/</guid>
		<description><![CDATA[Objectivo
O objectivo era criar um repositório centralizado para os logs de todos os equipamentos existentes dentro do Datacenter.
A resposta óbvia para quem vem do Linux é syslog-ng + MySQL, mas é preciso ver que nem só de Linux é o mundo feito, neste caso, nem tudo o que está no Datacenter corre Linux 
A solução [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Objectivo</strong><br />
O objectivo era criar um repositório centralizado para os logs de todos os equipamentos existentes dentro do Datacenter.<br />
A resposta óbvia para quem vem do Linux é <a href="http://www.balabit.com/products/syslog_ng/">syslog-ng</a> + MySQL, mas é preciso ver que nem só de Linux é o mundo feito, neste caso, nem tudo o que está no Datacenter corre Linux <img src='http://blogs.fe.up.pt/mpadilha/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /><br />
A solução final tem vários componentes, que explico já a seguir. A forma como se interligam é fácil de ver na figura seguinte.</p>
<p><a href='http://blogs.fe.up.pt/mpadilha/files/2007/04/centralized_logs.PNG' title='Logs Centralizados'><img src='http://blogs.fe.up.pt/mpadilha/files/2007/04/centralized_logs.thumbnail.PNG' alt='Logs Centralizados' /></a></p>
<p><strong>Syslogd</strong><br />
O <a href="http://linux.about.com/od/commands/l/blcmdl8_syslogd.htm">syslogd</a> vem de base com tudo o que é distro Linux e também se encontra para Unix. A consola do <a href="http://www.vmware.com/products/vi/esx/">VMware ESX</a>, sendo baseada em RHEL 3, também usa obviamente syslog.<br />
Basta acrescentar ao /etc/syslog.conf (ou substitui-lo por inteiro) a seguinte linha para se conseguir enviar todas as mensagens para um servidor syslog central:</p>
<p><code>*.*      @endereço-ip</code></p>
<p><strong>Winlogd</strong><br />
O <a href="http://www.edoceo.com/products/winlogd.php">winlogd</a> é um executável que se adiciona aos serviços do Windows e que envia, com as prioridades adequadas, todos os eventos que apareçam no Event Viewer para um <em>syslog server</em> remoto. A parametrização do endereço IP é feita no sítio do costume:</p>
<p><code>HKLM\System\CurrentControlSet\Services\Winlogd</code></p>
<p><strong>Snmptrapd + snmptt</strong><br />
É vulgar encontrar UPS&#8217;s, unidades de A/C, geradores e demais equipamentos periféricos que enviam alertas através de <a href="http://en.wikipedia.org/wiki/Snmp#SNMPv2_and_Structure_of_Management_Information">TRAPs SNMP</a>. As mensagens reportadas por um TRAP não são muito informativas se não forem traduzidas a partir de uma <a href="http://en.wikipedia.org/wiki/Snmp#Management_Information_Base_.28MIBs.29">MIB</a>. Uma boa forma de o fazer automaticamente e ainda guardar as mensagens num syslog é usar o <a href="http://www.snmptt.org">SNMPTT</a>.</p>
<p><strong>Logs Domino</strong><br />
Os servidores Lotus Domino guardam os seus logs numa base de dados&#8230; adivinhem&#8230; Domino! Felizmente, se estiverem a correr em Linux, também enviam os logs para a consola. Se se acrescentar o seguinte pipe à invocação do servidor, consegue-se ter a consola disponível numa tty e, simultaneamente, enviar todos os logs para o syslog local:</p>
<p><code>$domino_server | tee /dev/tty8 | logger -p local3.info</code></p>
<p>É pena perder-se o conceito de <em>priority</em>, mas como o Domino não o suporta internamente, não há nada a fazer&#8230;</p>
<p><strong>Rsyslogd</strong><br />
Em vez de syslog-ng como concentrador de logs, resolvi usar o <a href="http://www.rsyslog.com/">rsyslogd</a>. Na altura foi uma escolha do momento, mas veio a revelar-se oportuna, essencialmente porque o Phplogcon é melhorzinho que o <a href="http://www.phpwizardry.com/php-syslog-ng.php">php-syslog-ng</a>.<br />
O ficheiro de configuração é compatível com o do syslog, o que torna a migração muito fácil e rápida. Tal como o syslog-ng, a configuração é feita através de templates, e há vários <a href="http://www.rsyslog.com/module-Static_Docs-view-f-/sample.conf.html.phtml">exemplos</a> no site que tornam o <em>setup</em> inicial coisa de segundos&#8230;<br />
Com uma linha (grandita, é verdade&#8230;) define-se o template para inserir registos na base de dados:</p>
<p><code>$template dbFormat,"insert into SystemEvents (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%',%syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')",sql</code></p>
<p>E com outra linha, diz-se que se quer tudo lá dentro <img src='http://blogs.fe.up.pt/mpadilha/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><code>*.*      &gt;localhost,rsyslog,rsyslog,rsyslog;dbFormat</code></p>
<p><strong>Phplogcon</strong><br />
Finalmente, o <a href="http://www.phplogcon.org/">Phplogcon</a> é uma aplicação web para explorar os dados que o rsyslog guarda na base de dados. Não é o supra-sumo das ferramentas de exploração de dados, mas é bem rápida e suficientemente flexível para aquilo que normalmente se pretende destas ferramentas.<br />
Para análises mais elaboradas, há uma ferramenta proprietária feita pela <a href="http://www.adiscon.com/en/">Adiscon</a> (a empresa que faz o rsyslog e o phplogcon, já agora). Não cheguei a <a href="http://www.mwconsole.com/en/">experimentá-la</a>, mas parece valer a pena&#8230;</p>
<p><strong>MySQL</strong><br />
Não há muito a dizer aqui. Usei um servidor MySQL completamente <em>vanilla</em>, com tabelas MyISAM, que para o caso servem perfeitamente.</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=17&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_17" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2007/04/23/centralized-logs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Database Disaster Resilience (2/3)</title>
		<link>http://blogs.fe.up.pt/mpadilha/2007/04/15/database-disaster-resilience-23/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2007/04/15/database-disaster-resilience-23/#comments</comments>
		<pubDate>Sun, 15 Apr 2007 23:40:46 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[open-source]]></category>

		<category><![CDATA[mysql]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[networking]]></category>

		<category><![CDATA[ibm]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[storage]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2007/04/15/database-disaster-resilience-23/</guid>
		<description><![CDATA[(Continuação deste outro post)
O problema da dispersão geográfica pode ser resolvido em várias camadas.

Pode ser a própria aplicação a assumir a necessidade de manter toda a informação em bases de dados distintas.
Pode ser o servidor de base de dados a manter repositórios distintos para a mesma base de dados.
Por fim, podemos ter algum tipo de [...]]]></description>
			<content:encoded><![CDATA[<p>(Continuação deste outro <a href="http://blogs.fe.up.pt/mpadilha/2007/04/08/database-disaster-resilience-12/">post</a>)</p>
<p>O problema da dispersão geográfica pode ser resolvido em várias camadas.</p>
<ol>
<li>Pode ser a própria aplicação a assumir a necessidade de manter toda a informação em bases de dados distintas.</li>
<li>Pode ser o servidor de base de dados a manter repositórios distintos para a mesma base de dados.</li>
<li>Por fim, podemos ter algum tipo de <em>storage</em> inteligente que seja capaz de manter discos em sítios diferentes sincronizados.</li>
</ol>
<p>A primeira abordagem é muito pouco elegante do ponto de vista da Arquitectura. Porque é que uma aplicação que lida com maçãs há-de ter que se preocupar com o facto de eu dar muita importância às minhas maçãs e querer tê-las guardadas em dois sítios diferentes? Para além disso, é frequente que as aplicações sejam consideradas <em>off-premises</em> no que a estes problemas diz respeito&#8230; Vou esquecer esta hipótese.</p>
<p>A segunda abordagem faz mais sentido. Há várias bases de dados (proprietárias ou open-source) que lidam com o problema através de mecanismos de replicação e <em>clustering</em>. Umas fazem-no de forma síncrona, outras de forma assíncrona, há muitas alternativas por onde escolher e é um mundo bem conhecido de muita gente.</p>
<p>A terceira hipótese é, na minha opinião, aquela que faz mais sentido de todas. O problema que descrevi não me obriga, por si só, a ter duas bases de dados, não me obriga a balancear carga, nem sequer me impõe requisitos de alta disponibilidade. A única coisa que está em causa é mesmo a recuperação de um desastre. Para conseguir fazer isso basta-me, de facto, ter uma cópia permanentemente actualizada dos discos onde guardo a base de dados num sítio longínquo.</p>
<p>Sabendo isto, que alternativas tenho?</p>
<p><strong>Replicação de Base de Dados</strong><br />
Se me quiser manter dentro das soluções open-source (é sempre uma preferência), a opção clara é pelo MySQL. Ora o MySQL oferece duas formas de manter uma ou mais cópias da informação de uma base de dados em dois ou mais sítios. Uma é através dos mecanismos normais de <a href="http://dev.mysql.com/doc/refman/5.0/en/replication.html">replicação</a>, a outra é através de um produto mais ou menos autónomo, que é o <a href="http://dev.mysql.com/doc/refman/5.0/en/mysql-cluster.html">MySQL Cluster</a>.</p>
<p>A replicação do MySQL é sempre <strong>assíncrona</strong> e é feita através da replicação de um <em>binary log</em> serializado de todas as transacções executadas sobre a base de dados. Isto não serve. Como a replicação é assíncrona, um desastre na localização que tivesse a cópia <em>master</em> da base de dados fazia-me perder as maçãs que estivessem <em>in flight</em>. Isto não é aceitável, vou ter que descartar esta opção.</p>
<p>O MySQL Cluster é síncrono! É verdade que faz muito mais do que aquilo do que preciso, mas pelo menos é síncrono. Tem no entanto um problema inesperado: pelo menos na versão actual obriga a que toda a base de dados caiba em memória! Alguns testes feitos com a aplicação levaram-me a ter bases de dados de maçãs com vários gigabytes, e estavamos apenas em testes. É verdade que podia comprar servidores com muita memória, transformar todo o disco em <em>swap space</em>, mas a verdade é que me pareceu que estava a tentar resolver o problema com a ferramenta errada. Se não houvesse alternativas até podia ser, mas&#8230;</p>
<p>Não seria justo não falar das alternativas proprietárias. A Microsoft lançou com o SQL Server 2005 uma nova tecnologia denominada <a href="http://www.microsoft.com/technet/prodtechnol/sql/2005/dbmirror.mspx">database mirroring</a>, que faz precisamente o que se pretende. O <em>downside</em> desta hipótese são as duas licenças de Windows 2003 + duas licenças de SQL Server 2005, que levam a solução para cerca de 12 K€&#8230; Ouch!<br />
Claro que Oracle e DB2 também têm respostas para este problema, mas o preço é ainda superior.</p>
<p><strong>Replicação de Storage</strong><br />
No capítulo da replicação de storage, as soluções mais badaladas são todas proprietárias. As que conheço melhor são as da IBM, mas outros <em>vendors</em> têm soluções semelhantes. Copiando directamente de um PDF da IBM, existem as seguintes opções:</p>
<blockquote><p><em>Enhanced Remote Mirroring consists of Global Mirror, Global Copy, and Metro Mirror and is designed to provide the ability to mirror data from one storage system to another over extended distances. It is<br />
designed to control synchronization from within the storage system so that it is nearly transparent to the host application servers. Unlike FlashCopy, Enhanced Remote Mirroring is designed to provide continuous updates from the primary logical drive to the secondary. This is designed to provide data availability, and is a key technology for implementing Disaster Recovery and Business Continuity plans. The Metro Mirror mode is designed to provide synchronous mirroring for logical drives. Global Mirror mode is designed to provide asynchronous mirroring and includes the write-order consistency option. </em></p></blockquote>
<p>O grande problema desta solução é que obriga a ter não uma, mas duas SAN IBM, pelo menos da gama 4000 e, dependendo dos modelos, pode ser ainda necessária uma licença específica para activar a feature de <em>Enhanced Remote Mirroring</em>. Usando preços de equipamentos usados disponíveis para encomendar na net, a brincadeira dificilmente ficaria por menos de 50K€&#8230; <em>way too much</em>!</p>
<p>Mas a ideia é boa e felizmente o mundo <em>open-source</em> tem uma palavra a dizer. Um dos componentes mais usados para construir <em>clusters</em> linux, logo a seguir ao <a href="http://www.linux-ha.org/Heartbeat">heartbeat</a>, é o <a href="http://www.linux-ha.org/DRBD">DRBD</a> - Distributed Remote Block Device. Simplificando muito, pode pensar-se no DRBD como uma espécie de RAID 1 entre dois discos que estão em servidores diferentes, e em que o meio usado para sincronização dos discos é uma rede IP em fez de um <em>backplane</em> SCSI.<br />
Felizmente o DRBD tem um modo de funcionamento em que a replicação é síncrona, isto é, uma escrita em disco só é <em>ack&#8217;ed</em> depois de a escrita no disco remoto o ter sido: exactamente o pretendido!</p>
<p>Parece ter sido identificado o melhor candidato. Como o post vai longo, reservo para a próxima a apresentação da solução completa.</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=18&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_18" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2007/04/15/database-disaster-resilience-23/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
