Ответ
Ключевым набором требований для реляционных баз данных является соответствие принципам ACID, которые гарантируют надежность транзакций.
ACID — это акроним, обозначающий четыре свойства:
-
Atomicity (Атомарность): Транзакция — это неделимая единица работы. Она либо выполняется полностью, либо не выполняется совсем. Если любая часть транзакции завершается сбоем, все изменения, сделанные в её рамках, откатываются.
-
Consistency (Согласованность): Транзакция переводит базу данных из одного валидного состояния в другое. Данные всегда должны соответствовать всем установленным правилам и ограничениям (например,
NOT NULL
,UNIQUE
,FOREIGN KEY
). -
Isolation (Изолированность): Параллельно выполняемые транзакции не должны влиять друг на друга. Результат параллельного выполнения должен быть таким же, как если бы они выполнялись последовательно. Для управления этим поведением существуют уровни изоляции транзакций (например,
Read Uncommitted
,Read Committed
,Repeatable Read
,Serializable
). -
Durability (Долговечность): Если транзакция успешно завершена (закоммичена), её результаты должны быть сохранены и не потеряются даже в случае сбоя системы (например, отключения питания). Обычно это достигается за счет записи изменений в журнал упреждающей записи (Write-Ahead Log, WAL).
Другие важные характеристики SQL баз данных:
- Структурированность: Данные хранятся в таблицах со строго определенной схемой.
- Поддержка индексов: Механизмы для ускорения поиска и выборки данных.
- Масштабируемость: Возможности вертикального (увеличение мощности сервера) и горизонтального (репликация, шардинг) масштабирования.
- Безопасность: Управление правами доступа пользователей к данным.
- Резервное копирование и восстановление: Инструменты для создания бэкапов и восстановления данных после сбоев.
Пример транзакции в Go:
// Начинаем транзакцию
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
// Выполняем первую операцию
_, err = tx.Exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
if err != nil {
// Если ошибка, откатываем все изменения
tx.Rollback()
return
}
// Выполняем вторую операцию
_, err = tx.Exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2")
if err != nil {
// Если ошибка, откатываем все изменения
tx.Rollback()
return
}
// Если все успешно, фиксируем изменения
err = tx.Commit()
if err != nil {
log.Fatal(err)
}