Статьи

Phabricator и NuoDB: перенос приложения PHP в распределенную базу данных

Эта статья была первоначально написана Филиппом Стоевым

Вступление

Чтобы удостовериться, что NuoDB является полнофункциональным продуктом базы данных, который можно использовать для поддержки существующих приложений корпоративного уровня, мы часто переносим различные части программного обеспечения для работы на NuoDB.

Недавно мы сделали это с Phabricator , который представляет собой набор инструментов для совместной работы по разработке с открытым исходным кодом, включая браузер репозитория исходного кода, обзоры, систему отслеживания ошибок и вики. Phabricator написан на PHP, а его архитектура включает уровень абстракции базы данных, хотя ранее он работал только на MySQL. В процессе мы усвоили некоторые уроки, которые помогут разработчикам создавать переносимые приложения баз данных или переносить существующие в распределенную базу данных, такую ​​как NuoDB.

Регистр и регистр чувствительности идентификаторов базы данных

По умолчанию MySQL преобразует все идентификаторы в нижний регистр:

mysql> create table t1 (f1 integer);
mysql> insert into t1 values (123);
mysql> select * from t1;
+------+
| f1   |
+------+
|  123 |
+------+

Имя поля возвращается в  f1 нижнем регистре, поэтому если у вас есть уровень абстракции базы данных, который преобразует результаты запроса в хэши, значение  123 будет храниться в f1 нижнем регистре ключа хеша  .

В NuoDB и других продуктах баз данных имена таблиц и столбцов по умолчанию преобразуются в верхний регистр:

SQL> select * from t1;
 F1
 ---
 123

поэтому значение  123 будет храниться в F1 верхнем регистре ключа хеша  .

Для преодоления разрыва можно использовать два подхода:

Заставить NuoDB использовать строчные идентификаторы

Это достигается путем указания имен таблиц и полей в двойных кавычках при создании таблиц. Например:

SQL> create table "t1" ("f1" integer);
SQL> insert into t1 values (123);
SQL> select * from t1;
 f1
 ---
 123

NuoDB Migrator также можно использовать для переноса схемы базы данных таким образом, сохраняющим регистр.

Если в  SELECT запросе используются псевдонимы столбцов, их также необходимо заключить в двойные кавычки:

SQL> select f1 + f1 as "sum" from t1;
 sum
 ----
 246

Принудительно драйвер PHP PDO возвращает имена столбцов в нижнем регистре в наборе результатов

Драйвер PDO предоставляет атрибут, который можно использовать для управления регистром идентификаторов.

// Set the case in which to return column_names.
$dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
...
// The $result associative array will contain lowercase key names
$result = $sth->fetch(PDO::FETCH_ASSOC);

Все имена столбцов в наборе результатов, включая те, которые могли быть в смешанном регистре, будут преобразованы в строчные.

Работа с MySQL-специфическим синтаксисом

Чтобы упростить перенос приложений, NuoDB уже поддерживает специфичные для MySQL функции, функции и фрагменты синтаксиса. Например, NuoDB поддерживает  ENUM тип данных.

По умолчанию синтаксис запросов MySQL имеет некоторые странности и является более разрешающим по отношению к недействительным или неоднозначным запросам. NuoDB стремится быть более совместимым со стандартами, поэтому он работает как база данных MySQL, работающая в следующих режимах SQL:

PIPES_AS_CONCAT,
ANSI_QUOTES,
NO_BACKSLASH_ESCAPES,
STRICT_ALL_TABLES,
ONLY_FULL_GROUP_BY,
ERROR_FOR_DIVISION_BY_ZERO,
NO_ZERO_DATE.

Строковые литералы

В NuoDB строковые литералы заключаются в одинарные кавычки. Символ обратной косой черты не используется для экранирования. Чтобы избежать одиночной кавычки, укажите ее дважды:

SQL> select 'it''s' from dual;
----
it's

Конкатенация строк

В NuoDB символ канала используется для объединения строк:

SQL> select 'this ' | 'string' from dual;
-----------
this string

Неверные значения

NuoDB не позволяет вставлять недопустимые значения в таблицу. Например, вы не можете вставить строку, такую ​​как ‘ ABC‘ в  INTEGER столбец

SQL> создать таблицу t1 (целое число f1);
SQL> вставить в значения t1 (‘abc’);
невозможно преобразовать строку «abc» в тип «integer»

Нулевые значения даты и времени

Значения даты, например,  0000-00-00 и значения времени, например  00:00:00 , не допускаются. Попробуйте использовать  NULL вместо этого другое значение-заполнитель. NuoDB Migrator имеет возможность перезаписывать такие даты на лету во время процесса миграции.

SQL> create table t1 (f1 date);
SQL> insert into t1 values ('0000-00-00');
error converting to date from 0000-00-00

Незавершенный GROUP BY

Запросы, такие как:

SQL> select f1, f2, min(f3) from t1 group by f1;
column TEST.T1.F2 must appear in the GROUP BY clause or be used in an aggregate function

отклонены NuoDB, так как предложение GROUP BY не содержит все неагрегированные столбцы из списка SELECT. MySQL принимает такие запросы, но они не соответствуют стандарту SQL, поскольку значение, возвращаемое для столбца f2, не полностью определено.

Вы можете рассмотреть возможность переписывания таких запросов, добавив соответствующие столбцы в предложение GROUP BY:

SQL> select f1, f2, min(f3) from t1 group by f1, f2;

Получение последнего автоматически сгенерированного значения

NuoDB не предоставляет синтаксис для получения последнего значения автоинкремента с помощью функции SQL, такой как  LAST_INSERT_ID() . Вместо этого значение получается с помощью метода драйвера:

$dbh->execute();
print $dbh->lastInsertId();

Блокировка стола

NuoDB не предоставляет эту  LOCK_TABLE() функцию, но часто код, основанный на этой функции, можно переписать для использования стандартных транзакций.

Рассмотрим этот упрощенный пример, который генерирует непрерывно увеличивающиеся целые числа:

CREATE TABLE counter (value INTEGER);
INSERT INTO counter VALUES (0);
LOCK TABLE counter;
UPDATE counter SET value = value + 1;
SELECT value FROM counter;
UNLOCK TABLES;

В NuoDB эта функциональность доступна с использованием последовательностей:

SQL> create sequence counter;
SQL> select next value for counter from dual;
COUNTER
--------
1

Вывод

Даже если вы столкнулись с приложением, написанным только для конкретной базы данных SQL, попробуйте портировать его на NuoDB, чтобы воспользоваться преимуществами современных функций базы данных, таких как геораспределение и избыточность. NuoDB поддерживает широкий спектр функций и функций SQL, что делает возможным перенос, позволяя переносить устаревшие приложения в облачную эпоху.