Mysql InnoDB - сценарий блокировки - PullRequest
1 голос
/ 25 января 2012

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

Я читал, что InnoDB использует блокировку на уровне строк? Насколько я понимаю, он блокирует определенную строку в транзакции. Что будет с оператором select при обновлении таблицы?

Например, предположим, что есть транзакция и оператор выбора, запущенные из двух разных процессов, и предположим, что Transaction1 запускается до того, как будет выполнен оператор выбора.

Transaction1 : Start
Update table_x set x = y where 1=1
Transaction1 : End

Выбрать запрос

Select x from table_x

Что будет с оператором select. Будет ли он возвращать значения "во время" транзакции 1 или "после" завершения? И если он может начаться только после завершения Transaction1, где блокировка уровня строки на этом рисунке?

Имею ли я смысл или само мое фундаментальное понимание неверно? Пожалуйста, сообщите.

Ответы [ 4 ]

3 голосов
/ 25 января 2012

Зависит от уровня изоляции.

SERIALIZABLE 
REPEATABLE READS 
READ COMMITTED 
READ UNCOMMITTED

Хорошо объяснил Википедия

И MySQL Документ

2 голосов
/ 25 января 2012

Это зависит не только от задействованной блокировки, но и от уровня изоляции, который использует блокировку для обеспечения изоляции транзакции, как определено стандартами ACID. InnoDB использует не только блокировку, но и мультиверсионность строк для ускорения транзакций.

На уровне изоляции serializable при обновлении будет использоваться блокировка чтения, поэтому селекту придется ждать завершения первой транзакции. На более низких уровнях изоляции, однако, блокировка будет записана, а выборки не будут заблокированы. В repeatable read и read committed он будет сканировать журнал отката, чтобы получить предыдущее значение записи, если оно будет обновлено, а в read uncommitted in вернет текущее значение.

Разница между блокировкой на уровне таблицы и блокировкой на уровне строки заключается в том, что у вас есть 2 транзакции, которые выполняют запрос на обновление. При блокировке на уровне таблицы 2-й должен ждать первого, так как вся таблица заблокирована. При блокировке на уровне строк будут блокироваться только строки, которые соответствуют предложению where * (а также некоторые пробелы между ними, но это другая тема), что означает, что различные транзакции могут обновлять разные части таблицы без необходимости ждать друг для друга.

* при условии, что существует индекс, охватывающий предложение where

2 голосов
/ 25 января 2012

Выбор не будет ждать завершения транзакции, вместо этого он вернет текущее значение строк (иначе, до начала транзакции).

Если вы хотите, чтобы оператор ожидал завершения транзакции, вы можете использовать «LOCK IN SHARE MODE»:

Select x from table_x LOCK IN SHARE MODE;

Это заставит select ждать любую строку (строки), которые в данный момент заблокированы транзакцией, для которой установлена ​​исключительная (обновление / удаление) блокировка.

При чтении в режиме LOCK IN SHARE читаются последние доступные данные и устанавливает блокировку общего режима для чтения строк. Блокировка общего режима запрещает другим обновлять или удалять прочитанные строки. Кроме того, если последние данные принадлежат еще не совершенной транзакции другого сеанса, мы ждем, пока эта транзакция не закончится.

http://dev.mysql.com/doc/refman/5.0/en/innodb-lock-modes.html

1 голос
/ 25 января 2012

SELECT, запущенный извне транзакции, увидит таблицу, как она была до начала транзакции. Обновленные значения будут видны только после совершения транзакции.

...