Атомные преобразования в нетранзакционных таблицах

0

У меня есть 2 таблицы без транзакций. Я хочу выполнить "вставку" на один и "обновить" на другой.

Я хочу сделать это атомарно, оба должны пройти или оба не должны.

Как это сделать для не транзакционных таблиц? Я использую MySql

  • 0
    Не могли бы вы обновить движок для InnoDB?
  • 0
    Любой нетранзакционный движок
Теги:
transactions
atomicity

2 ответа

1
Лучший ответ

Используйте блокировка:

LOCK TABLES t1, t2 WRITE;
...
UNLOCK TABLES;

ПРИМЕЧАНИЕ:, если какой-либо из запросов завершился неудачей, вам придется вручную отменить их! Поэтому убедитесь, что вы собрали INSERT_ID() или некоторые другие способы определения строк, которые вы вставляете. (10x ring0)

Если это слишком часто происходит в вашем приложении - вы получите ужасную производительность. В этом случае вам лучше переключиться на InnoDB со своей функцией блокировки строк и транзакциями.

И убедитесь, что вы ВСЕГДА либо отключите сразу после этой операции, либо выполните запрос UNLOCK TABLES! В противном случае (например, забыть разблокировать/умереть с исключением при использовании постоянного соединения с БД - в итоге вы столкнулись с тупиком!)

  • 0
    как это сделать на InnoDB?
  • 1
    Это не работает Что произойдет, если INSERT работает, а UPDATE не работает?
Показать ещё 4 комментария
2

Без механизма транзакций вам необходимо защитить код чтения и записи, который будет обращаться к базе данных.

Некоторые псевдокоды для выполнения операций записи и чтения в критических разделах, защищенных с помощью семафора:

Semaphore sem;

bool method write (data) {
  lock(sem);
  ok  = do (insert data into table);
  prevdata = do (select olddata from table2);
  ok2 = do (update data into table2);
  if (ok && !ok2) do (delete date from table);
  else if (!ok && ok2) do (update olddata into table2);
  unlock(sem);
  return (ok && ok2);
}

datacontainer method read () {
  lock (sem);
  data = do (select data from table);
  unlock(sem);
  return data;
}

datacontainer method read2 () {
  lock (sem);
  data = do (select data from table2);
  unlock(sem);
  return data;
}

Синхронизация может быть оптимизирована в зависимости от ваших потребностей.

Если вы можете использовать InnoDB, это намного проще: в коде MySQL

START TRANSACTION;
INSERT INTO table (...) VALUES (...);
UPDATE table2 SET data=... WHERE ...;
COMMIT;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню