Блокировка строк таблицы в распределенном приложении, вся таблица блокируется при запуске select..for update в mysql 5.6 [duplicate]

Для получения ввода из командной строки, например Console.ReadLine ... Chalkers имеет решение следующим образом.

func input() -> String {
    var keyboard = NSFileHandle.fileHandleWithStandardInput()
    var inputData = keyboard.availableData
    return NSString(data: inputData, encoding:NSUTF8StringEncoding) as! String
}

, пожалуйста, спросите, если это не так работа Винод.

19
задан Matt Fenwick 9 May 2012 в 18:53
поделиться

5 ответов

MySQL использует только блокировку на уровне таблицы из таблиц MyISAM. Если вы можете, переключитесь на InnoDB для блокировки на уровне строк.

Вот ссылка на сайт MySQL, описывающий блокировки, установленные таблицами SQL для таблиц InnoDB. http://dev.mysql.com/doc/refman/5.0/en/innodb-locks-set.html

23
ответ дан belwood 18 August 2018 в 18:15
поделиться
  • 1
    Эта блокировка работает только для этой транзакции или является постоянной для всей базы данных? – Juan Carlos 27 April 2017 в 17:19
  • 2
    Иногда для транзакций, иногда глобальных. Перед использованием внимательно прочитайте и поймите. Например, существуют различные типы блокировок, такие как «глобальная блокировка чтения». Иногда блокировки автоматически освобождаются при фиксации, другие могут быть выпущены в начале транзакции. Ваши требования должны диктовать какой тип блокировки вы должны использовать и как ее использовать. – belwood 1 May 2017 в 13:11

Лучше обходным путем является создание столбца, содержащего метку времени. Всякий раз, когда вы хотите заблокировать строку, вы обновляете ее до текущего времени. Чтобы разблокировать обновление до времени не менее x минут в прошлом. Затем, чтобы проверить, не заблокирована ли эта отметка, что отметка времени не менее ста лет.

Таким образом, если процесс завершается с ошибкой (или пользователь никогда не завершает свою работу), блокировка эффективно заканчивается через x минут.

-2
ответ дан Barnaby Dawson 18 August 2018 в 18:15
поделиться
  • 1
    Нет ничего хорошего - поскольку проверка и обновление не являются одной операцией, это позволяет двум соединениям блокировать одну и ту же строку, не зная друг о друге. (Вероятно, есть способ сделать это правильно, но было бы сложно и легко запутаться.) – Brilliand 5 May 2014 в 21:10
  • 2
    Никогда не используйте время в качестве замены для блокировки. – Ryan Yoosefi 8 May 2015 в 09:15

В качестве обходного пути вы можете добавить столбец в свою таблицу, например locked TINYINT(1) - всякий раз, когда вы хотите, чтобы строка была заблокирована, вы установите ее на 1. Когда вы пытаетесь получить доступ к этой строке, первое, что вы делаете, это проверить, установлены ли поля locked.

Чтобы разблокировать строку, просто установите ее на 0 еще раз. Нехорошо, но очень просто обходное решение.

1
ответ дан dhh 18 August 2018 в 18:15
поделиться
  • 1
    Если соединение закрыто, как закрыть браузер или т. Д. Если он автоматически разблокируется для других? Я думаю, что это не будет сделано. Правильно ли я? – svk 7 October 2010 в 06:35
  • 2
    Нет, конечно, нет. Вы могли бы предоставить какую-то работу, которая периодически проверяет, существует ли открытый сеанс для пользователя, который вызвал блокировку строк. Конечно, вы должны добавить некоторую пользовательскую информацию в таблицу. – dhh 7 October 2010 в 14:35
  • 3
    Но это похоже на плохой семафор, который не устраняет условия гонки. Если 2 параллельных запроса думают LOCK=0, они оба переходят в критический раздел, оба устанавливают LOCK=1, и у вас есть ошибка скрытого состояния гонки. – bobobobo 6 June 2013 в 17:20
  • 4
    обновляет и записывает блокировку внутри MySQL. Только один будет на самом деле писать одновременно, поэтому, если ваш UPDATE имеет предложение where для lock = 0, он не должен создавать условие гонки. – JRL 9 June 2014 в 18:28
  • 5
    @JRL это неверно. Я испытал это. – majidarif 17 January 2017 в 01:46

Поздно, но надеюсь, что это кому-то поможет:

UPDATE user SET lastusedecnumber = LAST_INSERT_ID(lastusedecnumber + 1);
SELECT LAST_INSERT_ID();

даст вам атомный приращение lastusedecnumber и возможность читать новое значение поля lastusedecnumber (после увеличения) с помощью SELECT LAST_INSERT_ID() .

2
ответ дан DontVoteMeDown 18 August 2018 в 18:15
поделиться
  • 1
    Непонятно, как это связано с блокировкой строки ... – Brilliand 5 May 2014 в 21:16
  • 2
    Это хорошее предложение, так как оно позволяет вам обновлять строку и читать значение (хотя в настоящее время она читает обновленное значение, а не старое). В том, что он не упоминает, так это то, что, поскольку это запись в таблицу, она блокирует всю таблицу, пока она обновляет строку, поскольку это то, что делает MyISAM - этого нельзя избежать. – davidsheldon 13 April 2015 в 09:41

Мне не хотелось конвертировать всю мою базу данных из myisam. Поэтому я просто пытаюсь создать новую таблицу с именем на основе идентификатора записи, которую я хочу заблокировать. Если создать таблицу успешно, выполните мою работу и удалите таблицу в конце. Если создать таблицу не удалось, остановитесь.

0
ответ дан oyvey 18 August 2018 в 18:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: