Использование Node.js для создания базы данных, поддерживающей распространённые SQL-запросы.
Клонируйте репозиторий:
git clone https://gitee.com/onlyyyy/AvenirSQL
Перейдите в папку AvenirSQL:
cd AvenirSQL
Установите инструмент управления процессами PM2:
npm i pm2 -g
Запустите AvenirSQL с помощью PM2:
pm2 start AvenirSQL
Обратите внимание на файл конфигурации run.ini, который определяет настройки базы данных.
Для обновления конфигурации необходимо перезапустить базу данных:
pm2 restart AvenirSQL
Рекомендуется использовать последнюю версию Node.js (v14+), используя менеджер версий n:
В настоящее время n поддерживает только Mac и Linux.
npm i n -g
n lts// скачать последнюю версию Nodejs
./database/: реализация ядра AvenirSQL.
./AvenirSQL.js: программа запуска AvenirSQL.
./curl.js: CLI-программа.
./dtest.js: тестовая программа.
./jmeter/: файлы тестовых случаев Jmeter.
./db/: данные базы данных и таблицы.
./run.ini: файл конфигурации базы данных.
./AvenirSQL/: библиотека операций AvenirSQL для Nodejs.
В проекте используются следующие модули Node, разработанные Avenir Open Source Organization:
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();
}
}
Файл данных: первая строка содержит определение структуры таблицы, вторая строка начинается с шестнадцатеричного числа в сжатом виде, представляющего, является ли элемент строки пустым, а последующие элементы хранятся в виде разделенных элементов.
Файл хеш-индекса: объект, ключ — первичный ключ, значение — номер строки в файле.
B+ дерево: хранит структуру B+ дерева.
Управление соединениями. Для различения различных операций пользователей с базой данных, таких как несколько запросов от одного процесса в секунду, AvenirSQL генерирует подпись, которую пользователь должен использовать после входа в систему.
Блокировка строк. Перед выполнением операции устанавливается блокировка, которая снимается после завершения операции, и кэш обновляется (исключая 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]);
}
}
}
}
Кэширование. В настоящее время существует пять типов кэшей, которые не обновляются при изменении файла конфигурации базы данных или структуры таблицы, но хэш-индекс, табличные данные и B+ дерево обновляются через определённые промежутки времени.
Анализ 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);
}
}
}
Операция отката непосредственно очищает кэш, операция фиксации записывает в файл, снимает блокировку и также освобождает кэш.
Автоматическое снятие блокировки по тайм-ауту предотвращает взаимоблокировки базы данных.
Журналы. На данный момент поддерживается только запись журналов, без реализации журналов undolog, binlog и других, с использованием класса Trace и модуля avenir-log.
Программа 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"
}
Запрос:
{
sign:"ef3d843f26c4e900e9ab4979f324d5571a4cb5f5c011278b36985b2802c828185ad0bdd7e19390cfffe479afe1b09d1c",
type:"sql",
data:"select * from test"
}
Ответ:
{
code : 0,
message:"success",
data:[{
name:"test",
id:"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 )