Aktualizacja MySQL zmieniająca wiele kolumn nie jest atomowa?

Mam problem z Django z MySQL 5.5.22.

Biorąc pod uwagę tabelę z identyfikatorami kolumn, poziomem i macierzą 2x2 przechowywaną jako a11, a12, a21, a22, mam ten wiersz:

id   a11   a12   a21   a22   level
324  3     2     5     3     2

Biorąc pod uwagę zestaw zapytań qs, wykonuję następującą aktualizację:

qs.update(
    a11=(b12 * a21 - b11 * a22) * F('a11') + (b11 * a12 - b12 * a11) * F('a21'),
    a12=(b12 * a21 - b11 * a22) * F('a12') + (b11 * a12 - b12 * a11) * F('a22'),
    a21=(b22 * a21 - b21 * a22) * F('a11') + (b21 * a12 - b22 * a11) * F('a21'),
    a22=(b22 * a21 - b21 * a22) * F('a12') + (b21 * a12 - b22 * a11) * F('a22'),
    level=(F('level') - 1)
    )

W przypadku których django generuje następującą kwerendę (pobrano ją z db.connection.queries, usuń klauzulę where dla zwięzłości):

UPDATE `storage` 
SET 
`a21` = (3 * `storage`.`a11`) + (-1 * `storage`.`a21`), 
`a22` = (3 * `storage`.`a12`) + (-1 * `storage`.`a22`), 
`level` = `storage`.`level` - -1, 
`a11` = (2 * `storage`.`a11`) + (-1 * `storage`.`a21`), 
`a12` = (2 * `storage`.`a12`) + (-1 * `storage`.`a22`) 

A mój wiersz wygląda tak po tym:

id   a11   a12   a21   a22   level
324  2     1     4     3     1

Dla każdego rzędua12*a21 - a11*a22 = 1 ma być True i zgodnie z tym wiersz miał być:

id   a11   a12   a21   a22   level
324  1     1     4     3     1

To jest to, co otrzymuję w SQLite, z Django generującym to samo zapytanie, i zajęło mi dużo czasu, aby stwierdzić, że MySQL robi coś innego. Z zapytania wynika, że ​​podczas aktualizowania wielu różnych wierszy MySQL nie traktuje go jako pojedynczej operacji atomowej, a ponieważ kolumny są aktualizowane, wpływają na wartości zależne od nich. Potwierdziłem, że wydaje się, co dzieje się z następującym kodem w wierszu polecenia Pythona:

>>> a11, a12, a21, a22 = (3, 2, 5, 3)
>>> (2 * a11) + (-1 * a21),\
... (2 * a12) + (-1 * a22),\
... (3 * a11) + (-1 * a21),\
... (3 * a12) + (-1 * a22)
(1, 1, 4, 3)

Jeśli kolumny są aktualizowane pojedynczo, w tej samej kolejności co zapytanie:

>>> a11, a12, a21, a22 = (3, 2, 5, 3)
>>> a21 = (3*a11) + (-1*a21)
>>> a22 = (3*a12) + (-1*a22)
>>> a11 = (2*a11) + (-1*a21)
>>> a12 = (2*a12) + (-1*a22)
>>> (a11, a12, a21, a22)
(2, 1, 4, 3)

Jest to naprawdę przerażające zachowanie, ponieważ jest to biblioteka przeznaczona do użytku międzyplatformowego. Moje pytania to:

Który z nich robi to źle, MySQL lub SQLite? Czy można to uznać za błąd?Czego mogę oczekiwać od innych dużych baz danych (Oracle, PostgreSQL i SQLServer)?Co mogę zrobić z ORM Django (bez surowych zapytań), aby znormalizować to zachowanie?

edytować

Problem jest jasny, ale wciąż szukam rozwiązania. Wyciąganie wszystkich wartości i cofanie ich nie jest rozwiązaniem akceptowalnym dla tej konkretnej aplikacji.

questionAnswers(2)

yourAnswerToTheQuestion