Здесь было много полезных ответов, в целом достигающих высшей точки в два пункта.
BACKTICKS(
) `используются вокруг имен идентификаторов. QUOTES(')
используются вокруг значений. И как @MichaelBerkowski сказал
Backticks должны использоваться для идентификаторов таблиц и столбцов, но необходимы только тогда, когда идентификатор является
blockquote>MySQL
зарезервированным ключевое слово или когда идентификатор содержит символы пробела или символы за пределами ограниченного набора (см. ниже) Часто рекомендуется избегать использования зарезервированных ключевых слов в качестве идентификаторов столбцов или таблиц, если это возможно, во избежание проблемы с кавычками.Существует случай, когда идентификатор не может быть зарезервированным ключевым словом или содержать символы whitespace или за пределами ограниченного набора , но обязательно требует обратных ссылок вокруг их.
ПРИМЕР
123E10
является допустимым именем идентификатора, а также действительнымINTEGER
литералом.[Не вдаваясь в подробности, как вы могли бы получить такое имя идентификатора] Предположим, что я хочу создать временную таблицу с именем
123456e6
.Нет ОШИБКИ на обратных циклах.
DB [XXX]> create temporary table `123456e6` (`id` char (8)); Query OK, 0 rows affected (0.03 sec)
ОШИБКА, если вы не используете обратные ссылки.
DB [XXX]> create temporary table 123451e6 (`id` char (8)); ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '123451e6 (`id` char (8))' at line 1
Однако
123451a6
[* g15]DB [XXX]> create temporary table 123451a6 (`id` char (8)); Query OK, 0 rows affected (0.03 sec)
Это полностью, потому что
1234156e6
также является показательным номером.
Для того, что это стоит, эта блокировка не ограничена READ-UNCOMMITTED
:
mysql1> show variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
mysql1> BEGIN;
mysql1> SET @x := (SELECT x FROM foo LIMIT 1);
mysql2> UPDATE foo SET x = x+1;
[gets a lock wait]
mysql3> SHOW ENGINE INNODB STATUS;
...
---TRANSACTION 228746, ACTIVE 22 sec
2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 58, OS thread handle 0x7fc262a1c700, query id 8163
192.168.56.1 root cleaning up
TABLE LOCK table `test`.`foo` trx id 228746 lock mode IS
RECORD LOCKS space id 801 page no 3 n bits 80 index `PRIMARY`
of table `test`.`foo` trx id 228746 lock mode S
...
Как обсуждалось в ошибке, которую вы регистрировали, Ошибка # 67452 Установка переменной из select приобретает блокировка при использовании read uncommitted , это поведение, вероятно, по дизайну. Кажется, что она относится к той же категории, что и SELECT
, результаты которой используются для изменения данных, как описано выше:
http://dev.mysql.com/doc/refman/ 5.6 / ru / innodb-locks-set.html
Когда в конструкциях
blockquote>REPLACE INTO t SELECT ... FROM s WHERE ...
илиUPDATE t ... WHERE col IN (SELECT ... FROM s ...)
используется SELECT, InnoDB устанавливает общие блокировки следующих клавиш в строках из таблицыs
.Причина блокировки следующей клавиши - сделать результаты
SELECT
более стабильными. То есть мы не хотим, чтобы строки, сопоставляемыеSELECT
, менялись, когда они используются дляUPDATE
или другого оператора, изменяющего данные.Даже если tx_isolation
REPEATABLE-READ
, это важно, потому что InnoDB не поддерживаетREPEATABLE-READ
для операторовSELECT
, когда они выполняются как часть любого типаUPDATE
.
. Ваш комментарий:
Независимо от документации, вот что происходит:
Когда вы выполняете простой оператор
SELECT
, InnoDB ничего не блокирует в любой изоляции транзакции, кромеSERIALIZABLE
.Если вы выполняете
SELECT ... LOCK IN SHARE MODE
илиSELECT ... FOR UPDATE
, он блокируется, конечно.Но когда вы выполняете
SELECT
как часть инструкции, изменяющей данные, напримерINSERT INTO...SELECT
или в подзапросеUPDATE
или, как вы обнаружили вSET @variable := (SELECT...)
, он использует общую блокировку, чтобы убедиться, что данные не изменяются во время обновления.Документация может быть неполный. Лучше проверить.
Ваш первый оператор выполняет SELECT в таблице, поэтому транзакция получает блокировку чтения в одной строке. Вторая транзакция пытается получить блокировку записи в той же таблице (для всех строк, поскольку нет предложения WHERE
), но не может. Вам необходимо выдать команду COMMIT
(или ROLLBACK
) после SET @x = (...)
, чтобы она освободила блокировку чтения.
Вышеуказанное неверно. Я сохраняю этот пост только потому, что могут быть интересны следующие комментарии.