← Назад к вопросам

Что такое D (долговечность) в принципах ACID?

2.2 Middle🔥 171 комментариев
#Базы данных и SQL

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

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

D (Durability) в принципах ACID

Durability - это четвёртый принцип ACID, который гарантирует, что после успешного завершения транзакции данные будут сохранены постоянно и не будут потеряны даже при сбое системы.

Понятие Durability

Долговечность означает, что как только транзакция подтверждена (commit), её данные сохраняются на постоянном хранилище и не могут быть потеряны из-за сбоев питания, отказа оборудования или другого сбоя системы.

// Пример: Перевод денег
public class BankTransfer {
    public void transferMoney(Account from, Account to, BigDecimal amount) 
            throws SQLException {
        try {
            // Начало транзакции
            connection.setAutoCommit(false);
            
            // Операция 1: Снять деньги
            from.withdraw(amount);
            
            // Операция 2: Положить деньги
            to.deposit(amount);
            
            // Commit - данные записаны на диск (Durability)
            connection.commit();
            // После этого даже при сбое питания данные сохранятся
        } catch (SQLException e) {
            connection.rollback();
            throw e;
        }
    }
}

Как БД обеспечивает Durability

1. Write-Ahead Logging (WAL)

БД записывает изменения в журнал логов ДО того, как изменит основные данные. При восстановлении системы логи используются для воссоздания состояния.

Шаг 1: Запись в WAL:  "UPDATE account SET balance = 900 WHERE id = 1"
Шаг 2: Применение изменения в памяти
Шаг 3: Запись на диск
Шаг 4: Подтверждение commit
// Spring Data JPA с Durability
@Service
public class PaymentService {
    @Transactional  // Гарантирует commit после успеха
    public void processPayment(Payment payment) {
        payment.setStatus("PROCESSING");
        paymentRepository.save(payment);
        
        // После @Transactional данные гарантированно на диске
        sendPaymentNotification(payment);
    }
}

2. Флаш на диск (Fsync)

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

-- PostgreSQL: WAL гарантирует durability
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;  -- Данные на диск
-- Теже если сейчас отключить питание, данные сохранятся

Четыре принципа ACID

┌─────────────────────────────────────┐
│          ACID свойства              │
├─────────────────────────────────────┤
│ A - Atomicity (Атомарность)         │
│   Либо всё либо ничего              │
│                                     │
│ C - Consistency (Согласованность)   │
│   БД остаётся в валидном состоянии  │
│                                     │
│ I - Isolation (Изоляция)            │
│   Транзакции не видят друг друга    │
│                                     │
│ D - Durability (Долговечность)      │
│   Данные сохраняются постоянно      │
└─────────────────────────────────────┘

Пример Durability в действии

// Сценарий: Покупка билета в системе Ticketmaster
@Service
public class TicketService {
    @Autowired
    private EventRepository eventRepository;
    
    @Autowired
    private TicketRepository ticketRepository;
    
    @Transactional
    public Ticket buyTicket(Long eventId, User user) {
        // 1. Проверка наличия мест (Consistency)
        Event event = eventRepository.findByIdForUpdate(eventId);
        if (event.getAvailableSeats() <= 0) {
            throw new OutOfSeatsException();
        }
        
        // 2. Все или ничего (Atomicity)
        event.decreaseAvailableSeats();
        eventRepository.save(event);
        
        Ticket ticket = new Ticket(user, event);
        ticketRepository.save(ticket);
        
        // 3. Commit - Durability гарантирует сохранение
        // Даже если после этой строки сервер упадёт,
        // данные уже на диске и не потеряются
        return ticket;
    }
}

Механизмы обеспечения Durability

1. Persistent Storage (постоянное хранилище)

// ПЛОХО: данные только в памяти (не durable)
public class InMemoryDatabase {
    private Map<Integer, String> data = new HashMap<>();
    // При сбое питания всё потеряется
}

// ХОРОШО: данные на диске (durable)
public class PersistentDatabase {
    private Connection dbConnection;  // PostgreSQL, MySQL, Oracle
    // Данные сохраняются на диск через fsync()
}

2. Двойная запись (Replication)

Данные записываются на несколько серверов для надёжности:

Вторичный сервер  ← Репликация ← Первичный сервер
(резервная копия)                (основная запись)
// Spring Data с репликацией
@Configuration
public class DatabaseConfig {
    // Первичная БД
    @Bean
    @Primary
    public DataSource primaryDataSource() {
        // Production PostgreSQL
    }
    
    // Вторичная БД для репликации
    @Bean
    public DataSource replicaDataSource() {
        // Backup server для Durability
    }
}

3. Резервные копии (Backups)

-- MySQL Backup
MYSQL_DUMP -u root -p database > backup.sql

-- PostgreSQL Backup
pg_dump -U user database > backup.sql

-- Восстановление при критическом сбое
psql -U user database < backup.sql

Уровни Durability

1. Синхронная запись (максимальная надёжность, медленнее)

@Transactional
public void saveWithMaxDurability(Data data) {
    // fsync() вызывается сразу
    dataRepository.save(data);
}

2. Асинхронная запись (быстрее, но риск потери)

@Async
@Transactional
public void saveWithAsyncDurability(Data data) {
    // Данные в буфере, записываются позже
    dataRepository.save(data);
}

Примеры Durability в популярных БД

PostgreSQL:

-- Максимальная Durability
SET synchronous_commit = on;
-- Каждый commit ждёт fsync() на диск

-- Баланс между скоростью и надёжностью
SET synchronous_commit = local;
-- Ждёт записи на диск основного сервера

-- Высокая скорость, низкая надёжность
SET synchronous_commit = off;
-- Не ждёт fsync()

MySQL с InnoDB:

-- Максимальная Durability (медленнее)
SET GLOBAL innodb_flush_log_at_trx_commit = 1;
-- Логи пишутся на диск при каждом commit

-- Баланс (по умолчанию)
SET GLOBAL innodb_flush_log_at_trx_commit = 2;

-- Асинхронно (быстро, рискованно)
SET GLOBAL innodb_flush_log_at_trx_commit = 0;

Проблема: Долговечность vs Производительность

   ┌─────────────────────────────────────┐
   │   Синхронный commit (Durability)    │
   │  ✓ Данные 100% сохранены            │
   │  ✗ Медленнее (ожидание fsync)       │
   └─────────────────────────────────────┘

   ┌─────────────────────────────────────┐
   │   Асинхронный commit                │
   │  ✓ Быстрее (нет ожидания)           │
   │  ✗ Риск потери при сбое             │
   └─────────────────────────────────────┘

Реальный пример: Финансовая система

@Service
public class FinancialTransactionService {
    
    @Transactional(
        isolation = Isolation.SERIALIZABLE,  // Максимальная изоляция
        propagation = Propagation.REQUIRED   // Новая транзакция если нужна
    )
    public void transferMoney(
        Long fromAccountId, 
        Long toAccountId, 
        BigDecimal amount) throws Exception {
        
        // 1. Atomicity: либо оба счёта обновятся, либо никакой
        Account from = accountRepository.findByIdForUpdate(fromAccountId);
        Account to = accountRepository.findByIdForUpdate(toAccountId);
        
        // 2. Consistency: балансы останутся корректными
        if (from.getBalance().compareTo(amount) < 0) {
            throw new InsufficientFundsException();
        }
        
        // 3. Isolation: другие транзакции не видят промежуточное состояние
        from.withdraw(amount);
        to.deposit(amount);
        
        accountRepository.save(from);
        accountRepository.save(to);
        
        // 4. Durability: после commit данные гарантированно на диске
        // Даже если падёт сервер, БД восстановит из логов
    }
}

Вывод

Durability (Долговечность) - это гарантия, что после успешного commit данные сохраняются на постоянном хранилище и не будут потеряны при сбое системы. Это достигается благодаря:
  • Write-Ahead Logging (WAL)
  • Синхронной записи на диск (fsync)
  • Репликации на вторичные серверы
  • Резервным копиям

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

Что такое D (долговечность) в принципах ACID? | PrepBro