Что произойдет, когда ключ автоинкремента InnoDB и row_id закончатся?

задняя часть MySQL

Ярлыки: Статьи официального аккаунта


Что происходит, когда ключ автоинкремента израсходован?

Когда мы строим таблицу, мы устанавливаем столбец индекса (Примечание. Должен быть индексным столбцом.)Добавить кAUTO_INCREMENTсвойства, например:

CREATE TABLE t (
    c1 TINYINT AUTO_INCREMENT,
    c2 TINYINT,
    KEY idx_c1 (c1)
) ENGINE=InnoDB;

поверхностьtсодержит столбец индексаc1, столбец добавленAUTO_INCREMENTАтрибуты. Сначала вставляем запись в таблицу:

mysql> INSERT INTO t(c1, c2) VALUES(126, 1);
Query OK, 1 row affected (0.02 sec)

После этого мы больше неINSERTЯвно вставляется в операторc1Значение столбца, его значение по умолчанию будет увеличено с текущего вставленного наибольшего значения, например:

mysql> INSERT INTO t(c2) VALUES(1);
Query OK, 1 row affected (0.01 sec)

Давайте посмотрим на это расписаниеtданные в:

mysql> SELECT * FROM t;
+-----+------+
| c1  | c2   |
+-----+------+
| 126 |    1 |
| 127 |    1 |
+-----+------+
2 rows in set (0.02 sec)

так какc1столбецTINYINTВведите, используя 1 байт для хранения данных, максимальное значение, которое он может хранить, равно127, если когда значение столбца достигает127После этого продолжаем вставлять данные в таблицу, автоинкрементируя столбцыc1Какова будет стоимость?

mysql> INSERT INTO t(c2) VALUES(1);
Query OK, 1 row affected (0.01 sec)

После успешной вставки посмотрим на данные в таблице:

mysql> SELECT * FROM t;
+-----+------+
| c1  | c2   |
+-----+------+
| 126 |    1 |
| 127 |    1 |
| 127 |    1 |
+-----+------+
3 rows in set (0.01 sec)

Очевидно, автоинкрементc1Значение больше не будет продолжать расти, но возьметTINYINTМаксимальное значение, которое можно сохранить.

Здесь следует отметить, что в текущем примере мы просто автоматически увеличиваемc1Общий вторичный индекс установлен вышеidx_c1, поэтому нет проблем с повторяющимися значениями ключей. Однако мы, как правило,AUTO_INCREMENTАтрибут применяется к первичному ключу таблицы.В это время, если значение столбца автоинкремента достигает максимального значения, которое может быть сохранено типом данных, соответствующим первичному ключу, будет сообщено об ошибке (поскольку значение первичного ключа повторяется), все должны быть внимательны!

Что происходит, когда row_id заканчивается?

в нашем использованииInnoDBКогда механизм хранения создает таблицу, если мы не создадим первичный ключ явно, механизм хранения найдетNOT NULLСтолбец уникального вторичного индекса атрибута действует как первичный ключ, если мы не пишем таблицу сNOT NULLЕдинственный вторичный столбец индекса для атрибута, извините, механизм хранения добавит нам новый по умолчанию с именемrow_idстолбец первичного ключа.

этоrow_idРазмер столбца по умолчанию составляет 6 байт, стоит отметить, что дизайнInnoDBДядя не для каждой пользовательской таблицы, которая явно не создает первичный ключrow_idСтолбцы поддерживают отдельный счетчик, но все таблицы совместно используют глобальный счетчик. Допустим, у нас нет соответствующей таблицыt1иt2Явно создайте первичные ключи, механизм хранения создаст один для них обоих.row_idстолбец, если мы добавим таблицуt1В таблицу вставляется запись, затем из глобального счетчика выделяется значение, чтобы сделать таблицуrow_idзначение столбца, затем увеличиваем глобальный счетчик на 1, затем добавляем в таблицуt2Вставьте запись в таблицу, затем присвойте значение из глобального счетчика, чтобы сделать таблицуrow_idзначение столбца, а затем увеличить глобальный счетчик на 1.

У многих студентов возникают сомнения, что произойдет, если значение этого глобального счетчика превысит максимальное значение, которое может быть представлено 6 байтами?

Ха-ха 😄, не так. Несмотря на то чтоrow_idсостоит из 6 байт, но конструкцияInnoDBДядя использует 8 байт для хранения значения глобального счетчика, и они записывают эти 8 байт за два разаrow_id, первые четыре байта справа записываются вrow_id4 байта справа, затем запишите 4 байта слеваrow_id2 байта слева, вот так:

image_1dtsbdgl250r7ue10c3f8qmd9.png-25.4kB

Затем запишите четыре байта слева от глобального счетчика.row_id2 байта слева При использовании следующей функции:

UNIV_INLINE
void
mach_write_to_2(
/*============*/
	byte*	b,	/*!< in: pointer to two bytes where to store 也就是row_id值前2个字节所在的内存地址*/
	ulint	n)	/*!< in: ulint integer to be stored 也就是全局计数器的左4个字节值*/
{
	ut_ad(b);
	ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);

	b[0] = (byte)(n >> 8);
	b[1] = (byte)(n);
}

Вы можете увидеть эту строку в коде:

ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);

Это функция утверждения, эта строка кода означает левое 4-байтовое значение глобального счетчика.nОно не должно быть больше максимального значения, которое может храниться в 2 байтах, иначе ассертерия завершится ошибкой, и тогда MySQL будет зависать, зависать и зависать~

То есть, еслиrow_idПосле того, как он израсходуется, MySQL зависнет, и такая программа зависнет сразу.Но 6 байт достаточно.Вы можете посчитать, сколько записей нужно вставить, если вы хотите, чтобы MySQL завис?

Ссылки на другие статьи

Сверхполноценный анализ блокировки операторов MySQL (Часть 1)

Сверхполноценный анализ блокировки операторов MySQL (Часть 2)

Сверхполноценный анализ блокировки операторов MySQL (Часть 2)

Не по теме

Написание статей очень утомительно, и иногда вы чувствуете, что чтение идет очень гладко, что на самом деле является результатом бесчисленных правок за ним. Если вы думаете, что это хорошо, пожалуйста, помогите переслать его.Большое спасибо~ Вот мой публичный аккаунт "Мы все маленькие лягушки".