Понимать принцип последовательного неблокирующего чтения MySQL.

MySQL

Текст: Сунь Ченг

Данная статья является оригинальной, просьба указывать автора и источник для перепечатки

Команда общественного бизнеса, к которой я принадлежу, предоставляет базовые бизнес-услуги для Hujiang. Чтобы система могла выдерживать давление высокой параллелизма и большого трафика, мы гарантируем производительность каждого узла системы, включая базу данных, и понимание принцип реализации сделает оптимизацию более эффективной, точной и эффективной. Hujiang завершил вывод из эксплуатации основной системы в прошлом году.Windows, база данных также изменена сSQL Serverпереключился наMySQL. Как широко используемая база данных в отрасли,MySQLНа сегодняшний день это одна из самых популярных реляционных баз данных в мире, но она может быть более знакома разработчикам, которые когда-то были знакомы с экосистемой Microsoft.SQL Server. несмотря на то чтоMySQLа такжеSQL ServerОни похожи в использовании, но все же сильно различаются в деталях реализации. Ниже я поделюсьMySQL InnoDBСвязанный с этим принцип реализации последовательного чтения в механизме хранения.

последовательное чтение

InnoDBСогласованное чтение относится к использованию нескольких версий для запроса моментального снимка базы данных в определенный момент времени. Этот запрос может видеть изменения, сделанные транзакциями, зафиксированными до этого момента времени, и не будет затронут последующими изменениями или незафиксированными транзакциями. Однако это правило не применяется к модификации более ранних операторов в той же транзакции, что приводит к следующему исключению: если вы обновляете некоторые строки в таблице, один разSELECT Можно увидеть последнюю версию обновленной строки или более старую версию любой строки; если другие сеансы одновременно обновляют ту же таблицу, они могут увидеть таблицу в состоянии, которого никогда не было в базе данных.

  • Когда уровень изоляции транзакцииREPEATABLE READВ то же время согласованные операции чтения в одной и той же транзакции считывают моментальный снимок, созданный первым запросом транзакции.

  • Когда уровень изоляции транзакцииREAD COMMITTEDПри согласованном чтении в рамках одной и той же транзакции будет создан и прочитан последний моментальный снимок самого запроса.

Последовательные чтенияInnoDBсуществуетREPEATABLE READа такжеREAD COMMITTEDОбработка в изоляции транзакцииSELECTРежим оператора по умолчанию. Согласованное чтение не устанавливает никаких блокировок для таблицы, поэтому другие сеансы могут читать и записывать в таблицу.

Снимки состояния базы данных доступны в транзакцияхSELECTутверждение, не обязательно применимое кDMLутверждение. Если выполняетсяINSERTилиUPDATEнекоторые строки затем фиксируют транзакцию, затем из другой параллельнойREPEATABLE READвыдается по сделкеDELETEилиUPDATEОператор влияет на те строки данных, которые только что были зафиксированы.

В следующем примере показан этот сценарий:

  1.           Session A                              Session B

  2.           begin;                                   begin;

  3. -------------------------------------------------------------------------------------

  4.           SELECT * FROM t;                        SELECT * FROM t;

  5.           > empty set                             > empty set

  6. -------------------------------------------------------------------------------------

  7.                                                   INSERT INTO t (id) VALUES (1);

  8.                                                    > 1 row affected

  9.                                                    SELECT * FROM t;

  10.                                                    -----------

  11.                                                    |   id    |

  12.                                                    -----------

  13.                                                    |    1    |

  14.                                                    -----------

  15. -------------------------------------------------------------------------------------            

  16.           SELECT * FROM t;        

  17.           > empty set

  18. -------------------------------------------------------------------------------------                                                    

  19.                                                    COMMIT;

  20. -------------------------------------------------------------------------------------

  21.           SELECT * FROM t;

  22.           > empty set

  23. -------------------------------------------------------------------------------------

  24.           DELETE FROM t WAERE id = 1;

  25.           > 1 row affected

  26. -------------------------------------------------------------------------------------

  27.                                                    SELECT * FROM t;

  28.                                                    -----------

  29.                                                    |   id    |

  30.                                                    -----------

  31.                                                    |    1    |

  32.                                                    -----------

  33. -------------------------------------------------------------------------------------

  34.           COMMIT;

  35. -------------------------------------------------------------------------------------

  36.                                                    SELECT * FROM t;

  37.                                                    > empty set

  38. -------------------------------------------------------------------------------------

  39.           SELECT * FROM t;

  40.           -----------

  41.           |   id    |

  42.           -----------

  43.           |    1    |

  44.           -----------

  45. -------------------------------------------------------------------------------------

скопировать код

Непротиворечивое чтение не работает для некоторыхDDLутверждения, такие как:

1) Непротиворечивое чтение не относится кDROP TABLE, потому что таблица былаInnoDBуничтожен. 2) Согласованное чтение не относится кALTER TABLE,потому чтоALTER TABLEФактически создается временная таблица исходной таблицы, а исходная таблица удаляется после завершения построения. При последовательном чтении в транзакции строки в новой таблице не видны, и в этом случае транзакция возвращает значение.ERTABLEDEF_CHANGEDОшибка (определение таблицы изменено, повторите транзакцию).

без указанияFOR UPDATEилиLOCK IN SHARE MODEна случай, еслиINSERT INTO ... SELECT,ОБНОВЛЕНИЕ... (ВЫБРАТЬ)а такжеCREATE TABLE...Существуют следующие различия в чтении в операторе:

  • По умолчанию вродеREAD COMMITTEDАналогичным образом, даже в рамках одной и той же транзакции каждое согласованное чтение создает и считывает свой собственный снимок.

  • еслиinnodblocksunsafe forbinlogустановлен вenableи уровень изоляции транзакций неSERIALIZABLE, операция чтения больше не будет заблокирована для строки.

Многоверсионный контроль параллелизма

Упомянутое выше последовательное чтение (consistend read) в основном основано на реализации MVCC и большинстве типов транзакций в MySQL (таких как:ИнноДБ, Соколи т. д.) механизмы хранения реализуются одновременноMVCC(Multi-Version Concurrency Control).

В настоящее время не толькоMySQL, другие системы баз данных (такие как:Оракл, Постгрес SQL) также реализуютсяMVCC. Стоит отметить, чтоMVCCЕдиного стандарта реализации не существует, поэтому разные базы данных и разные механизмы хранения имеют разные реализации.

Ядром управления несколькими версиями являются моментальные снимки данных, в то время какInnoDBчерезundo logдля хранения моментальных снимков данных.

Следующее показывает без учетаredo logиспользовать в случаеundo logУпрощенный процесс работы:

серийный номер действие
1 начать транзакцию
2 Запись моментального снимка данных строки данных в журнал отмены
3 обновить данные
4 Записать журнал отмены на диск
5 записать данные на диск
6 совершить транзакцию

1) Чтобы обеспечить постоянство данных, данные должны быть сохранены до совершения транзакции. 2) Сохранение журнала отмены должно быть до сохранения данных, чтобы гарантировать, что в случае сбоя системы журнал отмены можно будет использовать для отката транзакции.

Скрытая колонка в Innodb

InnoDBпройти черезundo logСохраняет снимок старой версии информации, которая изменила строки.InnoDBВо внутренней реализации добавлено три скрытых столбца для каждой строки данных для реализацииMVCC.

имя столбца длина (байты) эффект
DBTRXID 6 Идентификатор транзакции последней транзакции, вставившей или обновившей строку. (удаление считается обновлением, отметьте как удаленное)
DBROLLPTR 7 Запись журнала отмены, записанная в сегмент отката (если строка была обновлена, запись журнала отмены содержит информацию, необходимую для восстановления содержимого строки перед ее обновлением).
DBROWID 6 Логотип строки (скрытый монотонный идентификатор самоуспечения)

MVCCтолько вREAD COMMITEDа такжеREPEATABLE READРаботает при двух уровнях изоляции.READ UNCOMMITTEDВсегда читайте последнюю строку данных, а не строку данных, соответствующую текущей версии транзакции. а такжеSERIALIZABLEВсе прочитанные строки блокируются.

SELECT

InnoDBКаждая строка записей проверяется на соответствие двум условиям:

1) InnoDBНайти только версию (DBTRXID) для строк данных, предшествующих текущей версии транзакции (номер системной версии строки<=Номер системной версии транзакции, который гарантирует, что строка данных либо существовала до запуска, либо была вставлена ​​или изменена самой транзакцией). 2) Номер версии удаления строки (DBROLLPTR) либо не определено (не обновляется), либо больше номера версии текущей транзакции (обновляется после запуска текущей транзакции). Это гарантирует, что строки, прочитанные транзакцией, не будут удалены до начала транзакции.

INSERT

InnoDBСохраните текущий номер версии системы в качестве номера версии строки для каждой вновь вставленной строки.

DELETE

InnoDBСохраните номер текущей версии системы в качестве идентификатора удаления строки для каждой удаляемой строки.

UPDATE

InnoDBЧтобы вставить новую строку, сохраните номер текущей версии системы в качестве номера версии строки и сохраните номер текущей версии системы в исходной строке в качестве флага удаления строки.

Undo log

существуетInnoDBВ механизме хранения его основная роль заключается в реализацииMVCCи откат данных,undo logэто логический журнал, он просто регистрирует базу данныхлогикаоткатиться до исходного состояния, все изменения внесенылогически отменить, но структура данных и сама страница данных могли измениться после отката и до него.Цель этого в том, что в БД может быть одновременно несколько параллельных транзакций, и они могут модифицировать другие строки данных на странице в момент в то же время, если из-за отката транзакции, которая откатывает страницы данных до состояния в начале транзакции, повлияет на другие выполняющиеся транзакции.

undo logСуществовать вundo log segmentsсередина,undo log segmentsнаходится вrollback segmentsв, покаrollback segmentsможет существовать в системном табличном пространстве (system tablespace), временное табличное пространство (temporary tablespace), Отменить табличное пространство (undo tablespaces)середина.

сегмент отката

Атрибуты стоимость
формат командной строки --innodb-rollback-segments=#
системная переменная innodbrollbacksegments
Объем Глобальный
Динамическая конфигурация да
тип данных Integer
По умолчанию 128 (макс.)
минимум 1
максимальное значение 128

InnoDBПоддерживает128Каждый сегмент отката может поддерживать до 1023 транзакций модификации данных, и можно задать до 128 сегментов отката.

  1. mysql> show variables like 'innodb_rollback_segments';

  2. +--------------------------+-------+

  3. | Variable_name            | Value |

  4. +--------------------------+-------+

  5. | innodb_rollback_segments | 128   |

  6. +--------------------------+-------+

скопировать код

Конкретная стратегия распределения выглядит следующим образом:

  • Должен быть сегмент отката, выделенный для системного табличного пространства.

  • когда innodbrollbacksegmentsКогда значение меньше или равно 32,InnoDBОдин сегмент отката будет выделен для системного табличного пространства, а 32 сегмента отката будут выделены для временного табличного пространства.

  • когда innodbrollbacksegmentsКогда значение больше 32,InnoDBОдин сегмент отката будет выделен для системного табличного пространства, 32 сегмента отката будут выделены для временного табличного пространства, а оставшиеся сегменты отката будут выделены дляотменить табличное пространство, если нет табличного пространства отмены, оставшиеся сегменты отката будут выделены системному табличному пространству (5.7 По умолчанию).

отменить табличное пространство в5.7.21версия отмечена послеустарелможет быть удален в будущем, в настоящее время (MySQL5.7)innodbundo_tablespacesПо умолчанию0то есть не включен.

фиксация транзакции

в зависимости от поведенияundo logразделен на дваinsert undo log / update undo log.

insert undo logвinsertсгенерированный в процессе эксплуатацииundo log. потому чтоinsertЗапись операции видна только самой транзакции и не видна другим транзакциям, поэтомуinsert undo logМожет быть удален сразу после фиксации транзакции безpurgeработать.

update undo logдаupdateилиdeleteсгенерированный в процессе эксплуатацииundo log, из-за влияния на существующие записи, чтобы обеспечитьMVCCмеханизм, такupdate undo logВы не можете удалить, когда транзакция зафиксирована, но вставить ее, когда транзакция зафиксирована.history listвставай, подождиpurgeПоток выполняет последнюю операцию удаления.

когда бизнесcommit, состояние транзакции должно быть установлено наCOMMITукажите и включите транзакциюUndoнастроены на завершение

  1. Если текущийundo logединственныйpage, и занимаетheader pageнизкорослый3/4, добавьте его вundo cache listвключен, чтобы его можно было выделить для следующей транзакции, а статус установлен наTRXUNDOCACHED

  2. Если текущийundo log Да insertundoЗатем устанавливается статусTRXUNDOTOFREE

  3. если не удовлетворен1а также2Затем укажите, чтоundoможет понадобиться purgeПоток переходит к выполнению операции очистки, и статус устанавливается наTRXUNDOTO_PURG.

MySQL 5.7Временная таблицаundoи обычный столundoобрабатывается отдельно, первый пишетundoЛогирование всегда не требуетсяredo, последний требует записи.

очистить

deleteа такжеupdateОперация не может напрямую удалять исходные данные,deleteОперация просто преобразует столбец кластеризованного индексаdelete flagустановлен в1, запись все еще существует вB+дерево, окончательное удаление находится вpurgeВыполняется в потоке (этот дизайн связан с тем, что другие транзакции могут ссылаться на эту строку, поэтому ее нельзя удалить сразу).

Стоит отметить, чтоinnodbдляupdateФактически обработка состоит из двух этапов: 1. Пометить исходную запись кластеризованного индекса как удаленную. 2. Вставьте новую запись, чтобыpurgeДействия должны быть толькоdelete flagДостаточно записи 1.

history list

history listВ зависимости от порядка совершения сделокundo logПри цепочке транзакция, которая зафиксирована первой, всегда находится вhistory listхвост, тот самыйundo pageсерединаundo logТоже всегда по порядку.

Специфический процесс очисткиinnoDBбудет по умолчанию отhistory listНайдите первые данные, которые нужно очистить вtx1, после успешной очистки поток очистки продолжитtx1на страницеПродолжайте искать журнал __undo, который необходимо очистить.(которыйtx3, обратите внимание, что нетhistory listпродолжай искатьtx2), затем продолжите поиск в обратном направлении, чтобы найтиtx5, нашел в это времяtx5Ссылки, на которые ссылаются другие транзакции, не могут быть очищены (trx noчем текущийpurgeв более просторное место), так что идите сноваhistory listНайдите конечную запись вtx2Повторите вышеуказанные шаги.

Проще говоряInnoDBНепротиворечивое чтение в основном зависит отMVCCпонял, иMVCCЯдром является зависимостьundo logсохранять моментальные снимки транзакций таким образом, чтобыInnoDBПри условии, что блокировки не используются, по-прежнему может быть гарантирована согласованность данных в транзакции, снижены накладные расходы на блокировки и значительно улучшена производительность запросов.

Справочная документация:

  • Справочное руководство MySQL 5.7:

  • https://dev.mysql.com/doc/refman/5.7/en/
  • MySQL Engine поддерживает перемещение журнала отмены InnoDB:

  • http://mysql.taobao.org/monthly/2015/04/01/
  • «Высокопроизводительный Mysql» (третье издание)

  • "Инсайдер технологии Mysql - механизм хранения Innodb"

Рекомендуемое чтение

Вы действительно понимаете A/B-тестирование? (начальство)

Система фактического голосования по разработке DAPP (Часть 2)

От Nest к Nesk — практика модульной структуры Node.

От SQL Server к MySQL (1): миграция гетерогенной базы данных