Общая база данных Desktop / Webapp перезаписывает данные на дубликате ключа - PullRequest
1 голос
/ 10 мая 2019

Я разрабатываю веб-приложение, которое совместно использует базу данных с рабочим приложением для рабочего стола (иначе я не могу изменить базу данных, только пытаюсь имитировать поведение).Модуль, над которым я сейчас работаю, будет хранить заметки в этой базе данных в таблице notes.Я смог заставить его работать, я добавил заметки, и они появились в настольном приложении, затем через некоторое время я понял, что текст заметок и их описания перезаписываются.Просматривая строки в базе данных, я заметил, что modified_by пользователь был установлен, сообщая, что при вставке был дубликат ключа, а затем обновлено.Первичный ключ для этой таблицы - автоинкремент, поэтому я очень растерялся.После некоторого копания я нашел таблицу с именем counters со столбцом с именем notes, счетчик которого соответствовал текущему индексу таблицы notes.Прежде чем просто +1 счетчик на каждой вставке, я загрузил wireshark на сервер БД и записал трафик на порт БД и обнаружил следующее:

(Процедура добавления заметки из настольного приложения)

UPDATE counters SET in_use = 'Y';
SELECT notes FROM counters WHERE key_col = 1;
/* Desktop app uses current count for new index */
UPDATE counters SET notes = /* current count +1 */ WHERE key_col = 1;
UPDATE counters SET in_use = 'N';
/* ...Inserts new note here with explicit ID = current count ... */

Теперь я еще больше запутался.Зачем вообще устанавливать таблицу с автоинкрементом?Во-вторых, никогда не проверялось in_use до того, как выбрать счетчик и добавить его ... так какой смысл in_use?Может ли этот код привести к перезаписи, если два пользователя будут вставлены одновременно?Разве правильный способ сделать это - заблокировать таблицу counters для каждой операции?Я мог бы попробовать это, но я не уверен, как настольное приложение будет обрабатывать обнаружение блокировки (на основе опыта - фатальная ошибка).

Помимо точного дублирования этой процедуры и надежды на лучшее, яне совсем уверен, куда идти отсюда.Одна мысль состоит в том, чтобы:

<?php
const MAX_ATTEMPTS = 3;
$curKey;

for($i = 0; $i < MAX_ATTEMPTS; $i++){
    /*
    SELECT in_use, notes from counters where key_col = 1;
    ...
    */
    if( 'N' === $result['in_use'] ){
        $curKey = $result['notes'];
        /* INSERT count here - $curKey++ */
        break;
    }
    /* Sleep for .25 seconds to allow for current operation to finish */
    usleep(250000);
}

if( null == $curKey ){
    throw \Exception('Could not insert note because counter table locked after '. MAX_ATTEMPTS .' attempts');
}

/* INSET note code here... */

Это выглядит нормально, но все же возможно может перезаписать, потому что а) время между выбором счетчика и вставкой нового счета б) Кажется, приложение для настольного компьютера не выполняет никакой проверки.

Есть какие-нибудь мысли / предложения?

РЕДАКТИРОВАТЬ : Создана хранимая процедура для проверки во время выбора и вставки.

DELIMITER $$

CREATE DEFINER=`testUser`@`%` FUNCTION `getNextNoteIndex`(appKey INTEGER) RETURNS int(11)
BEGIN
    SELECT IF(`in_use` = 'N', `notes`, NULL) INTO @curIndex FROM `counters` WHERE `app_key` = appKey;
    IF @curIndex IS NOT NULL
    THEN
        SET @newIndex = @curIndex + 1;
        UPDATE `counters` SET `notes` = @newIndex WHERE `app_key` = appKey AND `in_use` = 'N' AND `notes` = @curIndex;
        IF ROW_COUNT() = 1
        THEN
            RETURN @newIndex;
        END IF;
    END IF;
RETURN NULL;
END

Использование:

SELECT testDB.getNextNoteIndex(1) AS $index;

1 Ответ

0 голосов
/ 10 мая 2019

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

Я не совсем понимаю, что вы можете и не можете изменить (БД, внутренний код и т. Д.):

Если вы внутри, не можете ли вы спросить разработчика, который создал эту промежуточную таблицу приращений, для чего она и, возможно, получить ясность или вообще обойти ее?

Если вы снаружи, имеет ли смысл спрашивать у них API и использовать конечные точки, которые они вам дали? Тогда любые проблемы, которые возникают из-за перезаписи, ложатся на их суд.

...