Это самый полезный вопрос для интервью с Mysql, который я когда-либо видел.

Java
Это самый полезный вопрос для интервью с Mysql, который я когда-либо видел.

Если вы хотите попасть на большую фабрику, если вы не знаете mysql, этого недостаточно.

1. Можете ли вы сказать мне разницу между myisam и innodb?

Механизм myisam является механизмом по умолчанию до версии 5.1, который поддерживает полнотекстовый поиск, сжатие, пространственные функции и т. д., но не поддерживает транзакции и блокировки на уровне строк, поэтому обычно используется в сценариях с большим количеством запросов. и малое количество вставок, и myisam не поддерживает внешние ключи.И индексы и данные хранятся отдельно.

Innodb построен на основе кластеризованных индексов.В отличие от myisam, он поддерживает транзакции, внешние ключи и поддерживает высокий параллелизм через MVCC.Индексы и данные хранятся вместе.

2. Что такое индексы mysql, кластеризованные и некластеризованные индексы?

По структуре данных индекс в основном включает дерево B+ и хэш-индекс.

Предположим, у нас есть таблица со следующей структурой:

create table user(
	id int(11) not null,
  age int(11) not null,
  primary key(id),
  key(age)
);

Дерево B+ представляет собой последовательную структуру хранения с малым левым и большим правым. Узел содержит только столбец индекса id, а конечный узел содержит столбец индекса и данные. Метод индекса, в котором данные и индекс хранятся вместе, называется кластеризованный индекс Таблица может иметь только кластеризованный индекс. Предполагая, что первичный ключ не определен, InnoDB вместо этого выберет уникальный ненулевой индекс, если нет, он неявно определит первичный ключ как кластеризованный индекс.

Это структура хранилища кластеризованного индекса первичного ключа, так как же выглядит структура некластеризованного индекса? Некластеризованный индекс (вторичный индекс) хранит значение идентификатора первичного ключа, которое отличается от адреса данных, хранящегося в myisam.

Наконец, давайте посмотрим на разницу между кластеризованными и некластеризованными индексами InnoDB и Myisam.

3. Знаете ли вы, что такое покрывающий индекс и таблица возврата?

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

Чтобы определить, является ли запрос покрывающим индексом, нам нужно только объяснить оператор sql, чтобы увидеть, является ли результатом Extra «Использование индекса».

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

explain select * from user where age=1; //查询的name无法从索引数据获取
explain select id,age from user where age=1; //可以直接从索引获取

4. Какие бывают замки?

Блокировка MySQL делится наобщий замокиэксклюзивный замок, также известные как блокировки чтения и блокировки записи.

Блокировка чтения является общей и может быть реализована с помощью блокировки в режиме общего доступа, когда она может только читаться, но не записываться.

Блокировка записи является монопольной, она блокирует другие блокировки записи и чтения. По степени детализации его можно разделить наблокировка столаиблокировка строкидва вида.

Блокировка таблицы заблокирует всю таблицу и заблокирует все операции чтения и записи в таблице другими пользователями.Например, когда alter изменяет структуру таблицы, таблица будет заблокирована.

Рядовые замки можно разделить наоптимистическая блокировкаипессимистический замок, пессимистическую блокировку можно реализовать с помощью for update, а оптимистическую блокировку — с помощью номера версии.

5. Можете ли вы описать основные характеристики и уровень изоляции транзакций?

Основные характеристики транзакций ACID:

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

последовательностьЭто означает, что база данных всегда переходит из одного согласованного состояния в другое согласованное состояние. Например, если A переведет 100 юаней B, предполагая, что система выйдет из строя во время выполнения промежуточного SQL, A не потеряет 100 юаней, потому что транзакция не будет отправлена, и модификация не будет сохранена в базе данных.

изоляцияОтносится к модификации транзакции, невидимой для других транзакций, пока она не будет окончательно зафиксирована.

УпорствоЭто означает, что после фиксации транзакции внесенные изменения навсегда сохраняются в базе данных.

Изоляция имеет 4 уровня изоляции, а именно:

read uncommitRead uncommitted, может читать незафиксированные данные других транзакций, также называемые грязным чтением.

Пользователь должен был прочитать, что возраст пользователя с id=1 должен быть 10. В результате читается транзакция, которая не была зафиксирована другими транзакциями, и результатом чтения результата является age=20, что равно грязное чтение.

read commitЧтение зафиксировано, и результаты двух чтений несовместимы, что называется неповторяемым чтением.

Неповторяющееся чтение решает проблему грязных чтений, оно читает только зафиксированные транзакции.

Пользователь открывает транзакцию для чтения пользователя с идентификатором = 1, запрос достигает возраста = 10, и при повторном чтении обнаруживается, что результат равен 20. В одной и той же транзакции один и тот же запрос считывает разные результаты, что называется неповторяемым. читать.

repeatable readПовторяемое чтение, это уровень mysql по умолчанию, то есть результат каждого чтения одинаков, но может вызвать фантомное чтение.

serializableПоследовательный, который обычно не используется, будет блокировать данные, считанные каждой строкой, что приведет к большому количеству тайм-аутов и проблемам с конкуренцией блокировок.

6. На какую гарантию полагается ACID?

Атомарность гарантируется журналом журнала отмены, в который записывается информация журнала, которую необходимо откатить.При откате транзакции успешно выполненный SQL-запрос отменяется.

Согласованность C обычно гарантируется на уровне кода

I изоляция гарантируется MVCC

D Постоянство гарантируется памятью и журналом повторов. MySQL изменяет данные и записывает эту операцию в память и журнал повторов одновременно. не работает.

7. Тогда что вы подразумеваете под фантомным чтением и что такое MVCC?

Чтобы говорить о фантомном чтении, мы должны сначала понять MVCC, MVCC называется контролем параллелизма нескольких версий, который фактически сохраняет снимок данных в определенный момент времени.

На самом деле мы скрываем два столбца на номер строки, номер версии во время создания и номер версии во время истечения срока действия (удаления), и номер версии автоматически увеличивается каждый раз, когда запускается новая транзакция.

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

id name create_version delete_version
1 Чжан Сан 1
2 Ли Си 2

В это время предположим, что Сяо Мин выполняет запрос, в это время current_version=3

select * from user where id<=3;

В то же время Xiaohong запускает транзакцию в это время, чтобы изменить запись с id=1, current_version=4.

update user set name='张三三' where id=1;

Результат после успешного выполнения такой

id name create_version delete_version
1 Чжан Сан 1
2 Ли Си 2
1 Чжан Сансан 4

Если все еще Xiao Hei удаляет данные с id=2, current_version=5, результат после выполнения будет таким.

id name create_version delete_version
1 Чжан Сан 1
2 Ли Си 2 5
1 Чжан Сансан 4

Поскольку принцип MVCC заключается в том, чтобы найти, что созданная версия меньше или равна текущей версии транзакции, а удаленная версия пуста или больше, чем текущая версия транзакции, реальный запрос Сяо Мина должен быть таким

select * from user where id<=3 and create_version<=3 and (delete_version>3 or delete_version is null);

Таким образом, имя id=1, которое наконец запросил Сяомин, по-прежнему «Чжан Сан», и запись с id=2 также может быть запрошена. Делать этоЧтобы гарантировать, что данные, считанные транзакцией, уже существуют до начала транзакции, либо вставлены, либо изменены самой транзакцией..

Поймите принцип MVCC, нам гораздо проще говорить о том, что такое фантомное чтение. В общем сценарии, когда пользователь регистрируется, мы сначала запрашиваем, существует ли имя пользователя, и вставляем его, если оно не существует, предполагая, что имя пользователя является уникальным индексом.

  1. Сяо Мин открыл транзакцию current_version=6, чтобы запросить запись с именем «Ван Ву», и обнаружил, что она не существует.

  2. Xiaohong запускает транзакцию current_version=7 и вставляет часть данных, результат такой:

id Name create_version delete_version
1 Чжан Сан 1
2 Ли Си 2
3 Ван Ву 7
  1. Сяомин выполняет вставку записи с именем «Ван Ву» и обнаруживает, что уникальный индекс конфликтует и не может быть вставлен Это фантомное чтение.

8. Знаете ли вы, что такое гэп-лок?

Гэп-блокировки доступны только на уровне повторяющегося чтения.Сочетание MVCC и гэп-блокировок может решить проблему фантомного чтения. Возьмем в качестве примера пользователя, предполагая, что сейчас в таблице пользователей есть несколько записей.

id Age
1 10
2 20
3 30

Когда мы выполняем:

begin;
select * from user where age=20 for update;

begin;
insert into user(age) values(10); #成功
insert into user(age) values(11); #失败
insert into user(age) values(20); #失败
insert into user(age) values(21); #失败
insert into user(age) values(30); #失败

Только 10 могут быть успешно вставлены, поэтому из-за промежутка между таблицами mysql автоматически генерирует для нас интервал (слева открыт и справа закрыт)

(negative infinity,10],(10,20],(20,30],(30,positive infinity)

Поскольку есть записи с номером 20, интервалы (10,20], (20,30] заблокированы и не могут быть вставлены или удалены.

Что делать, если запрос 21? Он будет помещен в интервал (20,30) по 21 (оба интервала открытые).

Следует отметить, что уникальный индекс не будет иметь индекс разрыва.

9. Какова величина ваших данных? Как сделать подтаблицу подбазы данных?

Во-первых, подбиблиотека и подтаблица делятся на два способа: вертикальный и горизонтальный.Вообще говоря, порядок нашего разбиения сначала вертикальный, а затем горизонтальный.

вертикальная библиотека

Основываясь на текущем разделении микросервисов, они уже создали вертикальную подбиблиотеку.

вертикальный стол

Если полей таблицы много, разделите те, которые обычно не используются, поля с большими данными и т. д.

горизонтальная подтаблица

Во-первых, решите, какое поле использовать в качестве sharding_key в соответствии с бизнес-сценарием. Например, в настоящее время у нас есть 10 миллионов ежедневных заказов. Большинство наших сценариев исходят от C-стороны. Мы можем использовать user_id в качестве sharding_key. Поддерживается запрос данных. до последних 3 месяцев.Если заказ архивируется более 3 месяцев, то количество данных за 3 месяца составляет 900 миллионов, которые можно разделить на 1024 таблицы, таким образом данные каждой таблицы составляют около 1 миллиона.

Например, если id пользователя 100, то мы все проходим через hash(100), а потом берем по модулю 1024, и тогда можем попасть на соответствующую таблицу.

10. Как обеспечить уникальность идентификатора после подтаблицы?

Поскольку наши первичные ключи по умолчанию автоматически увеличиваются, первичные ключи после подтаблиц определенно будут конфликтовать в разных таблицах. Есть несколько способов рассмотреть:

  1. Задаем размер шага, например 1-1024 таблицы, базовый размер шага ставим соответственно 1-1024, чтобы первичный ключ не конфликтовал при попадании на разные таблицы.
  2. Распределенный идентификатор, внедрите набор алгоритмов генерации распределенного идентификатора самостоятельно или используйте открытый исходный код, например алгоритм снежинки.
  3. После разделения таблицы первичный ключ не используется в качестве основы запроса, а в каждую таблицу добавляется отдельное поле в качестве уникального первичного ключа.Например, порядковый номер таблицы порядков уникален.Независимо от того, какая таблица заканчивается в таблице, он будет основан на номере заказа в качестве основы запроса.То же самое.

11. Как быть с запросами без sharding_key после разделения таблиц?

  1. Вы можете создать таблицу сопоставления.Например, что если продавец хочет запросить список заказов в это время? Если вы не сделаете запрос с user_id, вы не сможете просканировать всю таблицу, верно? Поэтому мы можем сделать таблицу отношений сопоставления, чтобы сохранить отношения между продавцами и пользователями.При запросе мы сначала запрашиваем список пользователей через продавца, а затем запрашиваем через user_id.
  2. Для использования широкой таблицы, как правило, на стороне продавца не очень высокие требования к данным в реальном времени.Например, для запроса списка заказов можно синхронизировать таблицу заказов с автономным (в реальном времени) хранилищем данных, а затем сделать широкую таблицу на основе хранилища данных, а затем на основе хранилища данных.Другие, такие как es, предоставляют услуги запросов.
  3. Если объем данных невелик, например, некоторые запросы в фоновом режиме, это также можно сделать, просканировав таблицу несколькими потоками и затем объединив результаты. Или возможна асинхронная форма.
List<Callable<List<User>>> taskList = Lists.newArrayList();
for (int shardingIndex = 0; shardingIndex < 1024; shardingIndex++) {
    taskList.add(() -> (userMapper.getProcessingAccountList(shardingIndex)));
}
List<ThirdAccountInfo> list = null;
try {
    list = taskExecutor.executeTask(taskList);
} catch (Exception e) {
    //do something
}

public class TaskExecutor {
    public <T> List<T> executeTask(Collection<? extends Callable<T>> tasks) throws Exception {
        List<T> result = Lists.newArrayList();
        List<Future<T>> futures = ExecutorUtil.invokeAll(tasks);
        for (Future<T> future : futures) {
            result.add(future.get());
        }
        return result;
    }
}

12. Подскажите, как делается синхронизация master-slave в mysql?

Сначала поймите принцип синхронизации master-slave mysql.

  1. После того, как мастер фиксирует транзакцию, он пишет в бинлог
  2. Слейв подключается к мастеру и получает бинлог
  3. Мастер создает поток дампа и отправляет журнал бингов подчиненному.
  4. Подчиненное устройство запускает поток ввода-вывода для чтения двоичного журнала синхронизированного ведущего устройства и записывает его в журнал реле.
  5. Затем ведомое устройство запускает поток sql, чтобы прочитать событие журнала реле и выполнить его на ведомом устройстве для завершения синхронизации.
  6. подчиненный записывает свой собственный журнал бингинга

Поскольку метод репликации mysql по умолчанию является асинхронным, главной библиотеке все равно, обработала ли подчиненная библиотека журнал после отправки журнала в подчиненную библиотеку.Это вызовет проблему, если главная библиотека зависнет, а обработка подчиненной библиотеки завершится ошибкой. , то ведомая библиотека обновляется После основной библиотеки лог теряется. Отсюда вытекают две концепции.

Полная синхронная репликация

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

полусинхронная репликация

В отличие от полной синхронизации, логика полусинхронной репликации такова, что после того, как подчиненная библиотека успешно записывает журнал, она возвращает подтверждение ACK в главную библиотеку, а главная библиотека считает операцию записи завершенной, когда получает хотя бы одно подтверждение. из рабской библиотеки.

13. Как решить задержку ведущего и ведомого?

Эта проблема кажется нерешенной проблемой.Можно только сказать, что вы можете судить по себе, и вам нужно пойти в основную библиотеку, чтобы заставить запрос основной библиотеки.