Archive for wrzesień, 2006

RT i konwersja SQLite do MySQL

czwartek, wrzesień 28th, 2006 by Paweł Rutkowski

Po dość długiej przerwie, nowy wpis :)

Wstęp

Ostatnio wdrażałem w jednej firmie system obsługi zgłoszeń serwisowych - tzw. ticketów. Mój wybór padł na RT: Request Tracker. Jest to narzędzie open-source, oparte o interface webowy. Zdecydowałem się na nie ze względu na łatwą integrację z mailami, co bardzo ułatwiło wdrożenie (szczególnie ze strony Klientów firmy) i nie narażało na koszty szkoleń. Wkońcu każdy potrafi wysłać maila na określony adres :)

Prognozy… mylne…

Przy instalacjach tego typu ruch zazwyczaj jest mały, jak i ilość danych w systemie nie jest oszołomiająca. Dlatego też zdecydowałem się użycie bazy SQLite co by niepotrzebnie nie instalować nowych usług na serwerze. Niestety… popełniłem błąd. Po miesiącu już można było odczuć dyskomfort przy pracy z systemem, natomiast po trzech była to prawdziwa katorga. Ilość danych która się pojawiła w systemie, całkowicie mnie zaskoczyła.

Trzeba sobie radzić…

Troche czasu mi zajeło wymyślenie sposbu migracji. Nie udało mi się znaleźć żadnych gotowych narzędzi do konwersji tak dużych baz sqlite do mysqla, a po mimio że to SQL to jednak dialekty troche inne. Rozwiązanie było dość trywialne:

  1. Zainstalowanie MySQL i skonfigurowanie go (założenie bazy, usera, itp)
  2. Załadowanie schema.mysql z dystrybucji RT do bazy
  3. Napisanie prostego skryptu w ruby, który dla każdej tabeli w bazie wyciągnął wszystkie rekordy i na ich podstawie stworzył inserty.
  4. Załadowanie insertów do bazy

skryt wyglada w następujący sposób

      1 require 'sqlite3'
      2 class String
      3    def escape
      4       x = self.gsub(/\\'/,"' ").gsub(/\\/, "\\\\\\").gsub(/[']/,"' '")
      5    end
      6 end
      7 tabele = ['ACL', 'Attachments', 'Attributes',
      8     'CachedGroupMembers', 'CustomFieldValues',
      9     'CustomFields', 'GroupMembers', 'Groups',
     10     'Links', 'ObjectCustomFieldValues', 'ObjectCustomFields',
     11     'Principals', 'Queues', 'ScripActions', 'ScripConditions',
     12     'Scrips', 'Templates', 'Tickets', 'Transactions', 'Users']
     13
     14 db = SQLite3::Database.new("/usr/local/rt3/var/rt3")
     15    puts "begin;"
     16    tabele.each { |t|
     17    rows = db.execute("select * from #{t}")
     18    rows.each { |row|
     19       d =[]
     20       row.each { |col|
     21          if col.nil?
     22             d << '\'\''
     23          else
     24             d << '\'' + col.escape + '\''
     25          end
     26       }
     27       puts sprintf("insert into #{t} values (%s);\n", d.join(','))
     28    }
     29 }
     30 puts "commit;"

Po tym zabiegu, RT dostało ogromnego przyśpieszenia. Ja natomiast chyba już nigdy więcej nie wybiore SQLite jako bazy do jakiegokolwiek produkcyjnego systemu…