1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/onlyyyy-AvenirSQL

Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

AvenirSQL

Введение

Использование Node.js для создания базы данных, поддерживающей распространённые SQL-запросы.

Установка и использование

  1. Клонируйте репозиторий:

    git clone https://gitee.com/onlyyyy/AvenirSQL
  2. Перейдите в папку AvenirSQL:

    cd AvenirSQL
  3. Установите инструмент управления процессами PM2:

    npm i pm2 -g
  4. Запустите AvenirSQL с помощью PM2:

    pm2 start AvenirSQL

Обратите внимание на файл конфигурации run.ini, который определяет настройки базы данных.

Для обновления конфигурации необходимо перезапустить базу данных:

pm2 restart AvenirSQL

Рекомендуется использовать последнюю версию Node.js (v14+), используя менеджер версий n:

В настоящее время n поддерживает только Mac и Linux.

npm i n -g
n lts// скачать последнюю версию Nodejs

Технические особенности

  • Поддержка операций INSERT, UPDATE, DELETE и SELECT.
  • Точный поиск с использованием хеш-индекса, диапазонный поиск с использованием B+ дерева.
  • Интеллектуальное кэширование для повышения производительности QPS.
  • Предоставление функций управления пользователями, CLI-программа (curl.js).
  • Реализация функции блокировки строк.
  • Гибкая конфигурация стратегий.

Структура кода

./database/: реализация ядра AvenirSQL.

./AvenirSQL.js: программа запуска AvenirSQL.

./curl.js: CLI-программа.

./dtest.js: тестовая программа.

./jmeter/: файлы тестовых случаев Jmeter.

./db/: данные базы данных и таблицы.

./run.ini: файл конфигурации базы данных.

./AvenirSQL/: библиотека операций AvenirSQL для Nodejs.

В проекте используются следующие модули Node, разработанные Avenir Open Source Organization:

  1. Библиотека общих методов для Nodejs libcu.
  2. Библиотека журналов Avenir avenir-log.
  3. Библиотека работы с файлами Nodejs nth-file.
  4. Реализация многоветвевого дерева и словаря для Nodejs multiple-tree.

Поддерживаемые типы данных

  1. number — число, по умолчанию длиной 10.
  2. int — фактически также число, но не обязательно целое, по умолчанию длиной 10.
  3. bignumber — число без ограничения длины.
  4. varchar — символьный тип, по умолчанию длиной 20.
  5. string — символьный тип, по умолчанию длиной 20.
  6. bigstring — символьный тип без ограничения длины.

Конкретная техническая реализация

  1. Единая функция обработки ошибок нижнего уровня позволяет избежать передачи повторяющихся параметров.
async response(type, client) {
        let res = null;
        if (typeof type == 'string') {
            res = getError(type);
            if (!res) {
                res = unknown;
            }
        } else {
            let code = type.code;
            let data = type.data;
            res = getError(code);
            if (!res) {
                res = unknown;
            }
            res.data = data;
        }
        client.write(JSON.stringify(res));
        //если нет конфигурации по умолчанию короткое соединение

        if( ini.db.keepAlive != true) {
            toLog("активно отключить клиентское соединение");
            client.end();
        }
    }
  1. Структура базы данных: база данных — имя папки, таблица — файл данных, файл хеш-индекса и файл B+ дерева (агрегированный индекс).

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

Файл хеш-индекса: объект, ключ — первичный ключ, значение — номер строки в файле.

B+ дерево: хранит структуру B+ дерева.

  1. Управление соединениями. Для различения различных операций пользователей с базой данных, таких как несколько запросов от одного процесса в секунду, AvenirSQL генерирует подпись, которую пользователь должен использовать после входа в систему.

  2. Блокировка строк. Перед выполнением операции устанавливается блокировка, которая снимается после завершения операции, и кэш обновляется (исключая SELECT-запрос, который не обновляет кэш).

//автоматическое снятие блокировки предотвращает взаимоблокировку базы данных
    async releaseLock() {
        let now = moment().valueOf();
        let releaseLockTime = ini.db.releaseLockTime;
        releaseLockTime = releaseLockTime > ini.db.checkLockTime ? releaseLockTime : ini.db.checkLockTime;
        for(let key in this.table) {
            let tables = this.table[key];
            for(let subKey in tables) {
                let times = tables[subKey];
                if(moment(now).diff(moment(times),'seconds') > releaseLockTime) {
                    delete tables[subKey];
                    toLog("автоматически снята блокировка ",tables[subKey]);
                }
            }
        }
    }
  1. Кэширование. В настоящее время существует пять типов кэшей, которые не обновляются при изменении файла конфигурации базы данных или структуры таблицы, но хэш-индекс, табличные данные и B+ дерево обновляются через определённые промежутки времени.

  2. Анализ SQL. Здесь мы благодарим анализатор SQL от Alibaba node-sqlparser.

AvenirSQL имеет собственный синтаксис SQL, который сначала анализируется, а затем передаётся анализатору SQL для анализа.

//включает собственный SQL и может быть распознан синтаксисом AvenirSQL
    async parse(sql, sign) {
        //сначала проанализировать специфический для AvenirSQL синтаксис, затем проанализировать собственный SQL
        toLog("необходимо проанализировать sql как ", sql);
        let raw = this.getArray(sql);
        if (raw.length === 0 || !sql) {
            throw ('SQL_PARSE_ERROR');
        } else {
            //анализ AvenirSQL завершился неудачно, не сообщая об ошибке, передавая анализ анализатору, анализируя ошибку напрямую throw
            try {
                await this.parseAvenirSql(raw, sql, sign);
            } catch (error) {
                //не является внутренней ошибкой, указывающей на то, что программа обработала ошибку
                toLog('error = ', error);
                if (error == SUCCESS || error != 'error') {
                    throw (error);
                }

                //нет необходимости в try catch, нижний уровень будет перехватывать ошибки
                let par = this.parseSql(sql);
                await this.doSql(par, sign);

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

Операция отката непосредственно очищает кэш, операция фиксации записывает в файл, снимает блокировку и также освобождает кэш.

Автоматическое снятие блокировки по тайм-ауту предотвращает взаимоблокировки базы данных.

  1. Журналы. На данный момент поддерживается только запись журналов, без реализации журналов undolog, binlog и других, с использованием класса Trace и модуля avenir-log.

  2. Программа CLI. Предоставляет инструмент для взаимодействия с AvenirSQL, реализует функцию автоматического повторного подключения, при обнаружении ошибки с кодом 2 немедленно повторно подключается.

//проверка возвращаемого значения, если время ожидания истекло, автоматически повторите отправку
async function checkError(response) {
    if (response && response.code == 2) {
        //возвращаемое значение равно 2, указывая на то, что подпись недействительна, просто повторно войдите в систему
        let data = ```
await safeConnect();
if (data.code === 0) {
    data = data.data;
} else {
    //说明重新登录也报错了 数据库故障
    return {
        code: -1,
        data: null,
    };
}
return {
    code: 1,
    data
};

Иначе если ответ равен 0:

} else if (response.code == 0) {
    return {
        code: 0,
        data: null
    };
} else {
    return {
        code: -1,
        data: null,
    };  //其他错误 其实返回这个没啥用 只需要判断1 就行
}

Функция обработки distinct от 2021-02-22 с использованием многовходового дерева:

let mulTree = new MultipleTree();
if (columns.length == 1 && columns[0].expr.column == tableDetail.key) {
    toLog("优化器跳过distinct");
    return data;
}

for (let i = 0; i < data.length; i++) {
    let line = data[i];
    if(mulTree.insert(line) === false) {
        data.splice(i,1);
        i--;
    } else {
        continue;
    }
}
return data;
}```

*Импорт и экспорт:*

Экспорт — это выполнение операции select и преобразование SQL-запроса в insert.
Импорт — это выполнение SQL-запросов по разделителю.

Формат имени файла для экспорта: dump[table || database]_dbname_tableName_YYYYMMDDHHmmss.sql

*Интерфейс:*

Используется TCP-соединение для подключения к базе данных, данные передаются в формате JSON.

1. *Вход в систему:*

Запрос:
```js
{
user:"root",
password:"123456"
type:"login"
}

Ответ:

{
code:0,
message:"success",
data:"ef3d843f26c4e900e9ab4979f324d5571a4cb5f5c011278b36985b2802c828185ad0bdd7e19390cfffe479afe1b09d1c"
}
  1. SQL-операции:

Запрос:

{
sign:"ef3d843f26c4e900e9ab4979f324d5571a4cb5f5c011278b36985b2802c828185ad0bdd7e19390cfffe479afe1b09d1c",
type:"sql",
data:"select * from test"

}

Ответ:

{
code : 0,
message:"success",
data:[{
name:"test",
id:"1",
}]
}
  1. Транзакции:

Запрос:

{
sign:"ef3d843f26c4e900e9ab4979f324d5571a4cb5f5c011278b36985b2802c828185ad0bdd7e19390cfffe479afe1b09d1c",
id:"transID"            //事务执行流程: begin->sql->commit,begin的时候会给id 后续用id来执行sql
type:"trans",
data:"delete from test",
}

Ответ:

{
code : 0,
message:"success",
}

Разделитель строк — символ ∫. Все столбцы не должны содержать этот символ, иначе будет ошибка.

Таблица кодов ошибок:

Код ошибки Описание
UNKNOWN_CMD Неизвестная команда
SYSTEM_BUSY Система занята
BAD_REQUEST Плохой запрос (невозможно сериализовать запрос в JSON)
UNKNOWN_ERROR Неизвестная ошибка
AVENIR_SUCCESS Успех
SQL_PARSE_ERROR Ошибка синтаксического анализа SQL
NOT_CONNECTED Нет соединения, необходимо сначала войти в систему
FILE_NOT_EXIST Файл не существует
GEN_SIGN_ERROR Ошибка генерации подписи
SET_SIGN_EXIT Подпись вышла из строя
LACK_OF_SIGN Недостаток подписи, необходимо сначала авторизоваться
INVALID_NAME Недопустимое имя
BAD_USER Ошибка пользователя или пароля
PERMISSION_DENIED Отказано в доступе
DATABASE_NOT_FOUND База данных не найдена
DATABASE_EXIST База данных уже существует
TABLE_NOT_FOUND Таблица не найдена
TABLE_EXIST Таблица уже существует
INVALID_SQL_ERROR Недопустимый SQL или ошибка синтаксического анализа
TOO_MANY_COLUMNS Слишком много столбцов
[dump]
path=./dump

Следует ли сначала удалить таблицу, а затем импортировать её (по умолчанию сначала удаляется, а потом импортируется)

notForce=false

Конфигурация системы журналов

[log]

Каталог вывода журнала

logPath=./log

Период записи в журнал (в секундах)

loopTime=10

Имя файла журнала

logName=AvenirSQL

Резюме

В технологиях нет различий между высоким и низким, важным и неважным. Если у нас есть идея в голове, мы должны её реализовать.

Путь программирования далёк и извилист, я буду искать решения как сверху, так и снизу.

Спасибо.

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Используя Node.js, спроектируйте базу данных. Развернуть Свернуть
GPL-2.0
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/onlyyyy-AvenirSQL.git
git@api.gitlife.ru:oschina-mirror/onlyyyy-AvenirSQL.git
oschina-mirror
onlyyyy-AvenirSQL
onlyyyy-AvenirSQL
master