mysql REPEATABLE_READ и еще не существующая строка - PullRequest
1 голос
/ 16 января 2011

В MySQL с модом изоляции REPEATABLE_READ моя транзакция выглядит следующим образом: выберите строку с помощью pk, если она не существует, затем вставьте ее:

SELECT * FROM users, где user_id = 10;INSERT INTO users (user_id) VALUES (10);

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

Ответы [ 2 ]

3 голосов
/ 16 января 2011

В зависимости от того, что вам действительно нужно сделать с записью, вот несколько вариантов:

  1. Если вам нужно только выполнить «Если существует, то обновить, в противном случае вставить», лучшим вариантом будет использовать INSERT users(user_id, visits) VALUES (10,1) ON DUPLICATE KEY UPDATE visits = visits + 1, поскольку эта операция является атомарной.

  2. Попробуйте вставить новую строку, используя INSERT IGNORE, и проверьте функцию ROW_COUNT(), чтобы выяснить, была ли вставлена ​​строка, это лучше, чем вариант # 3, поскольку он позволяет избежать взаимоблокировок.

  3. Добавьте FOR UPDATE к вашему оператору выбора и положитесь на следующие блокировки ключа InnoDB.

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

InnoDB использует блокировки «пробела», которые регистрируют пустой пробел в индексе.

В вашем примере, если есть пользователи 8 и 12, InnoDB заблокирует пространство между 8 и 12, не давая другим транзакциям вставить user_id 10.

Из документов: http://dev.mysql.com/doc/refman/5.1/en/innodb-next-key-locking.html

Вы можете использовать блокировку следующего ключа для реализовать проверку уникальности в вашем приложение: если вы читаете ваши данные в режим обмена и не вижу дубликат для строки, которую вы собираетесь вставить, тогда вы можете спокойно вставить свой ряд и знаю, что блокировка следующего ключа установлена ​​на преемник вашего ряда во время читать мешает тем временем вставив дубликат для вашего ряда. Таким образом, блокировка следующего ключа позволяет вам «заблокировать» небытие что-то в вашем столе

Также читайте http://dev.mysql.com/doc/refman/5.1/en/innodb-record-level-locks.html

0 голосов
/ 16 января 2011

почему вы даже не пытаетесь повторно использовать user_ids (заполнение пробелов) - как вы думаете, у вас кончатся ключевые значения ??

create table users
(
user_id int unsigned not null auto_increment primary key,
...
)
engine=innodb;

int unsigned имеет возможный диапазон от 0 до 4294,967,295 (4 миллиарда) или, иначе говоря, в 8 раз больше пользователей, чем в настоящее время. facebook или половина всего населения планеты.

если вы думаете, что ваше приложение будет работать с такой скоростью, вы можете использовать bigint unsigned, который достаточно велик, чтобы хранить количество секунд, прошедших с начала времени (большой взрыв)

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