использовать несколько go подпрограмм для различных операций на mysql - PullRequest
0 голосов
/ 15 февраля 2020

У меня есть фрагмент кода Go с 3 различными функциями: insertInto Mysql, updateRow Mysql и deleteRow mysql. Я проверяю тип операции и запускаю одну из этих функций по мере необходимости.

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

Но вот в чем проблема:
Если я преобразую в процедуры, я потеряю последовательность операций.

Например, операции вставки выполняются гораздо чаще, чем операции удаления и Операции вставки ставятся в очередь в канале вставки, пока канал удаления пуст, поэтому мой код может попытаться удалить строку до того, как она будет вставлена ​​(например, вставлена ​​строка и удалено 1 se c позже).

Любые идеи о том, как убедиться, что последовательность моих операций на mysql совпадает с полученными операциями.

вот код:


    go insertIntoMysql(insertChan, fields, db, config.DestinationTable)
    go updatefieldMysql(updateChan, fields, db, config.DestinationTable)
    go deleteFromMysql(deleteChan, fields, db, config.DestinationTable)


    for !opsDone {
        select {
        case op, open := <-mysqlChan:
            if !open {
                opsDone = true
                break
            }

            switch op.Operation {
            case "i":
                //fmt.Println("got insert operation")
                insertChan <- op
                break
            case "u":
                fmt.Println("got update operation")
                updateChan <- op
                break
            case "d":
                fmt.Println("got delete operation")
                deleteChan <- op
                break
            case "c":
                fmt.Println("got command operation")
                //no logic yet
                break
            }

            break
        }
    }
    close(done)
    close(insertChan)
    close(deleteChan)
    close(updateChan)

}

Ответы [ 3 ]

0 голосов
/ 15 февраля 2020

Как тот, кто вызывает delete, узнает о строке? С точки зрения SQL: если он не зафиксирован, он не существует. Что-то вызывает ваш код на insert. Ваш код должен вернуться только после завершения транзакции. В этот момент вызывающая сторона может начать select, update или delete.

Например, на веб-сервере: только клиент, вызвавший insert, изначально знает о существовании записи. Другие клиенты узнают о его существовании только после запуска select. Этот select вернет новую запись, только если она была зафиксирована в транзакции, которая ее редактировала. Теперь они могут решить upsert или delete.

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

Обратите внимание, что net/http уже запускает подпрограмму Go для каждого запроса. Как и большинство других серверных интерфейсов для Go. Если вы пишете что-то совсем другое, например, пользовательский прослушиватель TCP, вы можете инициировать собственную подпрограмму Go для каждого запроса.

0 голосов
/ 15 февраля 2020

Просмотр вашего кода и вашего вопроса / требования: оставайтесь в порядке, поскольку исходный канал go доставил данные. Оставаться в курсе c и при этом запускать несколько go подпрограмм для обработки данных можно сделать так:

func processStatements(mysqlChan chan *instructions) {
    var wg sync.WaitGroup
    prevOp := "" // Previous operation
    for {
        op, open := <-mysqlChan
        if !open {
            break
        }
        if prevOp!=op.Operation {
            // Next operation type, unknown side effects on previous operations, 
            // wait for previous to finish before continuing
            wg.Wait()
        }

        switch op.Operation {
        case "i":
            wg.Add(1)
            go processInsert(op,wg)
            break
        case "u":
            wg.Add(1)
            go processUpdate(op,wg)
            break
        case "d":
            wg.Add(1)
            go processDelete(op,wg)
            break
        case "c":
            break
        }
        prevOp = op.Operation
    }
    // Previous go routines might still be running, wait till done
    wg.Wait()
    // Close any channels
}

func processInsert(c chan *sqlCall,wg *sync.WaitGroup) {
    defer wg.Done()
    // Do actual insert etc
}

Основные отличия вашей программы:

  • Обработка в порядке, безопасна для вашего базового сценария
  • Процесс следующего типа операции будет ожидать завершения предыдущего типа операции
  • Несколько одинаковых операций выполняются параллельно (как в код одной операции для каждого типа будет выполняться параллельно). В зависимости от распределения данных любой из них может быть быстрее или медленнее (i, i, i, d, u = 3 ожидания в этом коде, в то время как в вашем коде также будет 3 ожидания, однако в вашем коде 3 i будет выполняться последовательно, здесь они запускаются параллельно) (Смотрите для вставки или обновления для mysql, так как теперь ваши вставки могут внезапно обновляться в зависимости от ваших данных).
0 голосов
/ 15 февраля 2020

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

  1. Вызовите процедуры вставки, удаления или обновления как go, и они будут выполняться одновременно и выполнять все эти операции.

  2. Убедитесь, что у вас есть блокировка на уровне строк в вашей MySQL БД (я уверен, что InnoDb обеспечивает это)

  3. Для ваши операции удаления и обновления, имеют проверку isExist, чтобы проверить, существует ли строка, которую вы обновляете / удаляете, перед удалением и обновлением строки, это допускает некоторый уровень контроля.

  4. Вы можете внедрить механизм повторных попыток в вашем канале (желательно с джиттером), чтобы гарантировать, что даже если операция удаления будет выполняться до операции вставки, она не пройдет проверку на существование, а затем может быть повторена (через секунду, 0,5 секунды или некоторую конфигурацию), и это обеспечит вставка записи уже выполнена до повторной попытки удаления или обновления.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...