<?xml version="1.0" encoding="UTF-8"?>
<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/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arkadiusz Kuryłowicz, blog prywatny &#187; MySQL</title>
	<atom:link href="http://www.kurylowicz.info/category/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kurylowicz.info</link>
	<description>Blog prywatny, projekty, PHP, Linux, MySQL</description>
	<lastBuildDate>Thu, 19 Nov 2009 21:40:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Stored procedures czasem sie przydają</title>
		<link>http://www.kurylowicz.info/2009/04/06/stored-procedures-czasem-sie-przydaja/</link>
		<comments>http://www.kurylowicz.info/2009/04/06/stored-procedures-czasem-sie-przydaja/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 13:17:58 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Developer]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/2009/04/06/stored-procedures-czasem-sie-przydaja/</guid>
		<description><![CDATA[Podczas konwersji bazy danych serwisu Poema napotkałem pewien problem. Otóż dane dotyczące przypisania użytkownika do grup dostępu nie były zapisywane w osobnej tabeli jako indywidualne rekordy, lecz w rekordzie użytkownika, w pojedynczym polu o nazwie GID,  jako identyfikatory grup oddzielanych przecinkami, np. '1,3,19,3' lub pojedyncze wartości '8'. Z oczywistych względów dane takie są mało użyteczne. [...]]]></description>
			<content:encoded><![CDATA[<p>Podczas konwersji bazy danych serwisu Poema napotkałem pewien problem. Otóż dane dotyczące przypisania użytkownika do grup dostępu nie były zapisywane w osobnej tabeli jako indywidualne rekordy, lecz w rekordzie użytkownika, w pojedynczym polu o nazwie GID,  jako identyfikatory grup oddzielanych przecinkami, np. '1,3,19,3' lub pojedyncze wartości '8'. Z oczywistych względów dane takie są mało użyteczne. Zatem trzeba je przenieść do osobnej tabeli i powkładać w indywidualne rekordy. Na pierwszy rzut oka MySQL sobie nie poradzi. No to skrypt PHP, ale... leniwy jestem - nie chce mi się pisać skryptu, może zatem jednak MySQL. Rozwiązaniem jest napisanie własnej funkcji. Wygląda ona mniej więcej tak:</p>
<pre class="mysql">delimiter //</pre>
<pre class="mysql"><span style="color: #993333; font-weight: bold;">CREATE FUNCTION</span> create_records_in_poema_uid_group<span style="color: #66cc66;">&#40;</span>p_id <span style="color: #aa9933; font-weight: bold;">INT</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">RETURNS</span> <span style="color: #aa9933; font-weight: bold;">INT</span>
<span style="color: #993333; font-weight: bold;">BEGIN</span>
  <span style="color: #993333; font-weight: bold;">DECLARE</span> gid_set <span style="color: #aa9933; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #aa3399; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">''</span>;
  <span style="color: #993333; font-weight: bold;">DECLARE</span> gid <span style="color: #aa9933; font-weight: bold;">INT</span>;
  <span style="color: #993333; font-weight: bold;">DECLARE</span> pos <span style="color: #aa9933; font-weight: bold;">INT</span>;
&nbsp;
  <span style="color: #993333; font-weight: bold;">SET</span> @done = <span style="color: #cc66cc;">0</span>;
  <span style="color: #993333; font-weight: bold;">SET</span> @num = <span style="color: #cc66cc;">0</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Pobieramy wartość pola do zmiennej gid_set, pole może wyglądać</span>
  <span style="color: #808080; font-style: italic;">-- '1,5,12,16' lub być pojedyncza wartością '10'</span>
  <span style="color: #808080; font-style: italic;">-- dodatkowy warunek w WHERE zapobiega duplikatom</span>
     <span style="color: #993333; font-weight: bold;">SELECT</span> u.GID
       <span style="color: #993333; font-weight: bold;">INTO</span> gid_set
       <span style="color: #993333; font-weight: bold;">FROM</span> poema_users u
  <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> poema_uid_group g ON <span style="color: #66cc66;">&#40;</span>g.intUid = u.ID<span style="color: #66cc66;">&#41;</span>
      <span style="color: #993333; font-weight: bold;">WHERE</span> u.ID = p_id
        <span style="color: #993333; font-weight: bold;">AND</span> g.intUidGroupId <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #aa3399; font-weight: bold;">NULL</span>;
&nbsp;
  IF gid_set &lt;&gt; <span style="color: #ff0000;">''</span> <span style="color: #993333; font-weight: bold;">THEN</span>
    <span style="color: #993333; font-weight: bold;">REPEAT</span>
&nbsp;
      <span style="color: #808080; font-style: italic;">-- Ustalamy pozycję znaku przecinka</span>
      <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">LOCATE</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">','</span>, gid_set<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">INTO</span> pos;
&nbsp;
      IF pos &gt; <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">THEN</span>
        <span style="color: #808080; font-style: italic;">-- jest przecinek, odetnij pierwszą wartość, i usuń ją ze zmiennej gid_set</span>
        <span style="color: #993333; font-weight: bold;">SELECT</span> CAST<span style="color: #66cc66;">&#40;</span>SUBSTR<span style="color: #66cc66;">&#40;</span>gid_set, <span style="color: #cc66cc;">1</span>, pos<span style="color: #66cc66;">&#41;</span> AS <span style="color: #aa3399; font-weight: bold;">UNSIGNED</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">INTO</span> gid;
        <span style="color: #993333; font-weight: bold;">SELECT</span> SUBSTR<span style="color: #66cc66;">&#40;</span>gid_set, pos + <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">INTO</span> gid_set;
      <span style="color: #993333; font-weight: bold;">ELSE</span>
        <span style="color: #808080; font-style: italic;">-- nie znaleziono przecinka, gid_set zawiera wyłącznie cyfrę,</span>
        <span style="color: #808080; font-style: italic;">-- zzutuj ją do zmiennej gid jako</span>
        <span style="color: #808080; font-style: italic;">-- INT i ustaw flagę zakończenia pętli</span>
        <span style="color: #993333; font-weight: bold;">SELECT</span> CAST<span style="color: #66cc66;">&#40;</span>gid_set AS <span style="color: #aa3399; font-weight: bold;">UNSIGNED</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">INTO</span> gid;
        <span style="color: #993333; font-weight: bold;">SET</span> @done = <span style="color: #cc66cc;">1</span>;
      <span style="color: #993333; font-weight: bold;">END</span> IF;
&nbsp;
      <span style="color: #808080; font-style: italic;">-- Można dodać rekord do bazy</span>
      <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> poema_uid_group <span style="color: #66cc66;">&#40;</span>intUid, intGid, intGrantorUid, dtmGranted<span style="color: #66cc66;">&#41;</span>
      <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span>p_id, gid, <span style="color: #cc66cc;">1</span>, <span style="color: #993333; font-weight: bold;">NOW</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
      <span style="color: #993333; font-weight: bold;">SET</span> @num = @num + <span style="color: #cc66cc;">1</span>;
&nbsp;
    UNTIL @done <span style="color: #993333; font-weight: bold;">END</span> <span style="color: #993333; font-weight: bold;">REPEAT</span>;
  <span style="color: #993333; font-weight: bold;">END</span> IF;
&nbsp;
  <span style="color: #808080; font-style: italic;">-- Zwróć ilość dodanych rekordów</span>
  RETURN @num;
<span style="color: #993333; font-weight: bold;">END</span>;
//</pre>
<pre class="mysql">delimiter ;</pre>
<p>Ok, funkcja dodana, teraz wystarczy wywołać ją dla każdego ID użytkownika:</p>
<pre class="mysql"><span style="color: #993333; font-weight: bold;">SELECT</span> create_records_in_poema_uid_group<span style="color: #66cc66;">&#40;</span>ID<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">FROM</span> poema_users;</pre>
<p>Przy odrobinie inwencji będziesz w stanie wykorzystać funkcję do rozwiązania podobnego problemu w Twojej bazie danych.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2009/04/06/stored-procedures-czasem-sie-przydaja/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Efektywne zarządzanie bazą danych serwera wirtualnego z backendem MySQL (część 1)</title>
		<link>http://www.kurylowicz.info/2007/07/24/efektywne-zarzadzanie-baza-danych-serwera-wirtualnego-z-backendem-mysql/</link>
		<comments>http://www.kurylowicz.info/2007/07/24/efektywne-zarzadzanie-baza-danych-serwera-wirtualnego-z-backendem-mysql/#comments</comments>
		<pubDate>Tue, 24 Jul 2007 00:03:02 +0000</pubDate>
		<dc:creator>Arek Kuryłowicz</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.pink.art.pl/2007/07/24/efektywne-zarzadzanie-baza-danych-serwera-wirtualnego-z-backendem-mysql/</guid>
		<description><![CDATA[Wielu   osobom  nieobce  jest  zagadnienie  instalacji  usług  serwera wirtualnego (pDNS, Postfix, SASL, Dovecot, Pureftpd, Amavis, GPS, Apache)  w  oparciu  backend na  bazie  danych MySQL. Rozwiązanie takie jest bardzo elastyczne i bezpieczne stanowiąc jednocześnie punkt wyjścia do efektywnego  zarządzania  usługą.
Do w/w integracji [...]]]></description>
			<content:encoded><![CDATA[<p>Wielu   osobom  nieobce  jest  zagadnienie  instalacji  usług  serwera wirtualnego (pDNS, Postfix, SASL, Dovecot, Pureftpd, Amavis, GPS, Apache)  w  oparciu  backend na  bazie  danych MySQL. Rozwiązanie takie jest bardzo elastyczne i bezpieczne stanowiąc jednocześnie punkt wyjścia do efektywnego  zarządzania  usługą.</p>
<p>Do w/w integracji często stosuje się następujące oprogramowanie:</p>
<ul>
<li>pDNS jako serwer DNS (1)</li>
<li>  Postfix wraz z SASL jako MTA</li>
<li>  Dovecot jako serwer usług POP3/IMAP</li>
<li>  Apache</li>
<li>  pureFTPd (2)</li>
</ul>
<p>1) Bind jest najczęściej stosowanym serwerem DNS, jednakże pDNS oferuje natywne wsparcie MySQL oraz bardzo łatwą (gotowe programy) migrację</p>
<p>2) Zazwyczaj stosuje się proFTPd, którego przez długi czas i ja byłem zwolennikiem - jednakże z uwagi na problematyczną konfigurację z MySQL (problemy z quota) zrezygnowałem z niego.</p>
<p>Dodatkowo stosuję oprogramowanie<br />
- GPS - wspierający MySQL grey-list policy server dla Postfixa<br />
- Amavis jako SMTP proxy wspierające skanowanie antyvirusowe (clamav) i antyspamowe (spamassasin)</p>
<p>Integracja całości jest przedmiotem wielu FAQ oraz całej masy dokumentacji którą można znaleźć w googlach, tak więc nie na tym będę się skupiał. Skupie się na samej strukturze bazy danych.</p>
<p>Otóż zauważyć można podczas integracji pewną nadmiarowość i duplikowanie informacji w wielu tabelach podczas konfigurowania różnych usług dla tego samego klienta.</p>
<p><span id="more-70"></span></p>
<p>I tak aby zgodnie z większością znanych opisów integracji metodą dodać klientowi pełną obsługę wszystkich usług musimy:</p>
<ul>
<li>dodać wpisy w 2 tabelach pDNS</li>
<li>  dodać wpisy w 3 tabelach postfixa</li>
<li>  dodać wpisy w tabeli dla Dovecot jeśli nie używamy tabeli Postfixa</li>
<li>  dodać 1 wpis w tabeli pureFTPd</li>
<li>  dodać 2(?) wpisy w tabeli amavis</li>
</ul>
<p>Większość z informacji, które dodajemy do tych tabel jest duplikowana. W przypadku potrzeby zarządzania tą informacją mamy problem. Co zrobić aby nie duplikować niepotrzebnie informacji. Otóż z pomocą przychodzą nam tutaj mechanizmy view (w dalszej części będę używał nazwy widok) dostępne w MySQL od wersji 5.</p>
<p>Przyjrzyjmy się najpierw tabelą pDNS. Tutaj uwaga. Wszystkie tabele mają format zgodny z powszechnie stosowanymi opisami integracji usługi z MySQL. Różnią się tylko nazwą, którą dla własnej wygody prefixowałem nazwą usługi.</p>
<pre>mysql&gt; desc pdns_domains;
+-----------------+------------------+------+-----+---------+----------------+
| Field           | Type             | Null | Key | Default | Extra          |
+-----------------+------------------+------+-----+---------+----------------+
| id              | int(11)          | NO   | PRI | NULL    | auto_increment |
| name            | varchar(255)     | NO   | UNI |         |                |
| master          | varchar(20)      | YES  |     | NULL    |                |
| last_check      | int(11)          | YES  |     | NULL    |                |
| type            | varchar(6)       | NO   |     |         |                |
| notified_serial | int(11) unsigned | YES  |     | NULL    |                |
| account         | varchar(40)      | YES  |     | NULL    |                |
+-----------------+------------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)</pre>
<pre>mysql&gt; desc pdns_records;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| domain_id   | int(11)      | YES  | MUL | NULL    |                |
| name        | varchar(255) | YES  | MUL | NULL    |                |
| type        | varchar(6)   | YES  |     | NULL    |                |
| content     | varchar(255) | YES  |     | NULL    |                |
| ttl         | int(11)      | YES  |     | NULL    |                |
| prio        | int(11)      | YES  |     | NULL    |                |
| change_date | int(11)      | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
8 rows in set (0.01 sec)</pre>
<p>Otóż tabel pDNS zmieniać nie możemy z tej oto przyczyny, iż pDNS zapisuje samodzielnie informacje do obu tabel, tak więc nie mogą być one przekonwertowane do widoku. Tabela pdns_domains zawiera jednakże istotne informacje, mianowicie AKTYWNE w naszym systemie domeny podstawowe i zapasowe.</p>
<p>Rzućmy okiem na tabele używane przez Postfixa:</p>
<pre>mysql&gt; show tables like 'postfix%';
+------------------------------+
| Tables_in_vserver (postfix%) |
+------------------------------+
| postfix_alias                |
| postfix_domains              |
| postfix_mailbox              |
+------------------------------+
3 rows in set (0.00 sec)</pre>
<pre>mysql&gt; desc postfix_domains;
+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| domain   | varchar(255) | NO   |     |         |       |
| backupmx | tinyint(1)   | NO   |     | 0       |       |
+----------+--------------+------+-----+---------+-------+
2 rows in set (0.01 sec)</pre>
<pre>mysql&gt; desc postfix_mailbox;
+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| username | varchar(255) | NO   | PRI |         |       |
| password | varchar(255) | NO   |     |         |       |
| maildir  | varchar(255) | NO   |     |         |       |
| quota    | int(10)      | NO   |     | 0       |       |
| domain   | varchar(255) | NO   | MUL |         |       |
| active   | tinyint(1)   | NO   | MUL | 1       |       |
+----------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)</pre>
<p>Otóż w tabeli postfix_domains znajduje się lista domen obsługiwanych przez nasz system. Dodatkowo znajdują się tam domeny których backup MX utrzymujemy. Z dużym prawdopodobieństwem założyć można, iż będzie to lista domen których DNS utrzymujemy w pDNS. W tabeli postfix_mailbox znajdują się konta użytkowników, tabela ta może być współdzielona przez SASL oraz Dovecot, aczkolwiek jest to nieefektywne z uwagi do różnego sposobu podejścia do tematu blokowania kont.<br />
Zazwyczaj blokada tymczasowa ma na celu zablokowanie możliwości wysyłania i odbierania poczty przy jednoczesnym braku blokady na pocztę przychodzącą.</p>
<p>Tabela serwera FTP, poniższy schemat jest schematem pochodzącym z dokumentacji:</p>
<pre>mysql&gt; desc ftpd_users;
+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| User     | varchar(16)  | NO   | PRI |         |       |
| Password | varchar(64)  | NO   |     |         |       |
| Uid      | int(11)      | NO   |     | -1      |       |
| Gid      | int(11)      | NO   |     | -1      |       |
| Dir      | varchar(128) | NO   |     |         |       |
+----------+--------------+------+-----+---------+-------+
5 rows in set (0.01 sec)</pre>
<p>Do rzeczy: założenia:</p>
<ul>
<li>  projektowany schemat danych ma mieć zastosowanie w serwerze wirtualnym, który może obsługiwać sporą ilość domen i być punktem wyjścia do zarządzania przy pomocy interfejsu WWW.</li>
<li>  podstawową jednostką przyporządkowania użytkowników do grup będzie domena</li>
<li>  Chcemy mieć na tyle elastyczny system, aby jednym wpisem w odpowiedniej tabeli dało się uaktywnić użytkownikowi cały zestaw usług.</li>
<li>  Chcemy dodatkowo zapewnić minimalną duplikację danych w całym systemie oraz pewne mechanizmy weryfikacji danych na poziomie bazy.</li>
</ul>
<p>Cdn...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kurylowicz.info/2007/07/24/efektywne-zarzadzanie-baza-danych-serwera-wirtualnego-z-backendem-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

