2012-04-14 5 views
2

Я читаю documentation для Google App Engine и наткнулся на то, что я не совсем понимаю:Google App Engine оптимистичный параллелизм

Хранилище данных использует оптимистичный параллелизм для управления транзакциями. Когда два или более экземпляра приложения пытаются одновременно сменить одну и ту же группу сущностей (либо путем обновления существующих объектов, либо путем создания новых), первое приложение для фиксации его изменений будет выполнено успешно , а все остальные не будут выполнены при фиксации , Эти другие приложения могут затем снова попробовать свои транзакции, чтобы применить их к обновленным данным. Примечание , что, поскольку хранилище данных работает таким образом, использование групп объектов ограничивает количество одновременных операций записи, которые вы можете сделать любому объекту в данной группе .

Означает ли это, что если два разных пользователя из двух разных устройств попытаются изменить один и тот же объект, только один из них будет успешным? Является ли это типичным поведением базы данных или просто ограничением GAE? Как другие базы данных обычно обрабатывают такие ситуации, когда два или более пользователя пытаются изменить один и тот же объект?

И что это значит из-за того, что, когда два или более экземпляра приложения пытаются создать новые сущности, только один из них будет успешным. Я понимаю это неправильно? Нет двух экземпляров приложения, которые могут добавить новый объект в одну и ту же таблицу?

+1

обратите внимание на дизайн вашего кода: добавление нескольких записей в одну группу лиц делает запросы быстрее, но имеет несколько ограничений для проблемы параллелизма –

ответ

5

Хотя я не могу говорить о таких документах, как MongoDB и т. П. (Aka NoSQL), могу сказать, что реляционные базы данных позволят только операции вступить в силу. Однако это сводится к тому, что операции являются.

Например, скажем, что два пользователя попытались изменить один и тот же объект. Если их модификации изменяют только подмножество столбцов, скажем ...

Пользователь 1:

update MyTable set Col1 = '1', Col2 = '2' where ID = 'abc' 

Пользователь 2:

update MyTable set Col2 = 'x', Col3 = 'y' where ID = 'abc' 

Вы можете быть уверены, что Col1 будет '1' и Col3' will be 'y', as those two columns were only updated in one statement. The value of Col2` будет определяться любой командой, выполненной последним.

Аналогичным образом, если один пользователь обновил строку, а другой удалил ее, то строка будет удалена независимо от того, что. Если команда пользователя обновления была первой, тогда обновление будет успешным, и затем строка будет удалена. Если команда удаления была первой, тогда строка сначала будет удалена, и обновление ничего не сделает, поскольку строка не существует (предложение where не будет соответствовать ни одному строчку).

Тем не менее,, очень мало приложений действительно беспокоит выпуск обновлений базы данных командами, которые включают только измененные столбцы. Почти во всех приложениях команды создаются на уровне таблицы, и они обновляют все столбцы, а затем текущие (измененные или нет) значения передаются в эти команды. Это является причиной использования оптимистического параллелизма.

Предполагая, что ряд abc в настоящее время имеет следующие значения:

ID = 'abc' 
Col1 = '1_original' 
Col2 = '2_original' 
Col3 = '3_original' 

И что оба пользователя извлекаться строку в то же время, наши выше команды будут более реалистично выглядеть следующим образом:

Пользователь 1:

update MyTable set Col1 = '1', Col2 = '2', Col3 = '3_original' where ID = 'abc' 

Пользователь 2:

update MyTable set Col1 = '1_original', Col2 = 'x', Col3 = 'y' where ID = 'abc' 

Теперь у нас есть проблема; хотя наша вторая команда действительно не заботится о значении в Col1, она может перезаписать значение, заданное пользователем 1. Аналогично, если пользователь 2 первым ударил, тогда Пользователь 1 перепишет значение, записанное пользователем Col3.

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

Таким образом, учитывая те же условия, наши команды будут выглядеть следующим образом:

пользователя 1:

update MyTable set Col1 = '1', Col2 = '2', Col3 = '3_original' where ID = 'abc' 
     and Col1 = '1_original' and Col2 = '2_original' and Col3 = '3_original' 

пользователя 2:

update MyTable set Col1 = '1_original', Col2 = 'x', Col3 = 'y' where ID = 'abc' 
     and Col1 = '1_original' and Col2 = '2_original' and Col3 = '3_original' 

Это означает, что в зависимости от того команда попадает в базу данных последнего на самом деле ничего не сделает, поскольку столбцы больше не будут иметь своих исходных значений.

5

API-запросы для транзакций несколько раз повторяются (по умолчанию 3 раза, в общей сложности 4 попытки). Предполагая, что ваша транзакционная функция делает что-то вроде чтения объекта, обновляет свойство, записывает его обратно, повторная попытка также перечитывается и т. Д. Таким образом, вы не заметите сбоев, если не будет тяжелой конкуренции.

Вы неправильно читаете о вставках; обычно вставки используют разные ключи, поэтому не будет никаких конфликтов. (Они будут использовать один и тот же ключ только в том случае, если это явно указано в приложении.)

Смежные вопросы