Данные MySQL Commited не видны для выбора запроса


13

Контекст: используется среда Spring, и все запросы выполняются с помощью JdbcTemplate. Версия Mysql Server - 5.6.19. tableЭто InnoDB tableи по умолчанию , как auto commitи уровень изоляции повторяемое-чтение установлено.

Проблема : Событие Insertпроисходит внутри транзакции, и a, selectкоторый читает те же самые вставленные данные, не видит данные. В selectпробегах послеinsert и после того , как insertсделка имеет commited.

Я включил журнал бина, а также общий журнал в MySQL. Соответствующие журналы ниже

бен-журнал:

SET TIMESTAMP=1438265764/*!*/;
BEGIN
/*!*/;
# at 249935389
#150730 14:16:04 server id 1  end_log_pos 249935606 CRC32 0xa6aca292    Query   thread_id=40    exec_time=0     error_code=0
SET TIMESTAMP=1438265764/*!*/;
insert into user_geo_loc_latest(user_id, lat, lng) values(x,y,z) on duplicate key update lat=y, lng=z
/*!*/;
# at 249935606
#150730 14:16:06 server id 1  end_log_pos 249936255 CRC32 0x2a52c734    Query   thread_id=40    exec_time=0     error_code=0
SET TIMESTAMP=1438265766/*!*/;
INSERT INTO table(txnid) VALUES ('885851438265675046')
/*!*/;
# at 249936255
#150730 14:16:06 server id 1  end_log_pos 249936514 CRC32 0x6cd85eb5    Query   thread_id=40    exec_time=0     error_code=0
SET TIMESTAMP=1438265766/*!*/;
INSERT INTO table2(x) VALUES (y)
/*!*/;
# at 249936514
#150730 14:16:06 server id 1  end_log_pos 249936545 CRC32 0xceb9ec56    Xid = 9406873
COMMIT/*!*/;

Журнал запросов

150730 14:16:04    40 Query ...
....
40 Query     select count(*) from table where txnid = '885851438265675046'
                   40 Query     select @@session.tx_read_only
                   40 Query     INSERT INTO table(txnid) VALUES ('885851438265675046')
                   40 Query     select @@session.tx_read_only
                   40 Query     INSERT INTO table2(x) values(y)
                   40 Query     commit
....
150730 14:16:07    36 Query     select pp.*, b.create_date from table pp left join bill b on pp.bill_id = b.bill_id where pp.txnid = '885851438265675046'

Любопытно, что First insert(249935389) вообще не должен участвовать в транзакции. Это отдельный вызов API и совершенно не связанный. Это может быть весна, смешивающая это с транзакцией, или я читаю журнал неправильно? AFAIK, поскольку он находится в том же потоке, это означает, что вставка находится в транзакции.

Следующие два insertsявляются частью транзакции, и похоже, что она фиксируется. (249936514). Теперь запрос на выборку (последний в общем журнале) выполняется после коммита и не видит данных. Возвращает 0 строк. Как это может произойти, учитывая данные committed? Или commitне в теме 40? Так как у него нет идентификатора потока.

Подводя итог, у меня есть два вопроса.

  1. Имеет ли место BEGINв binlog перед INSERT INTO user_geo_loc(который не является частью транзакции), это ошибка в Spring / Jdbc или MySql просто делает это, поскольку он знает, что эта транзакция уже зафиксирована (поскольку транзакции записываются в binlog, когда они удалось) и поэтому никогда не будет откат.

  2. Если фиксация происходит до выбора (фиксация в 14:16:06, а выбор в 14:16:07), как получается, что выбор не возвращает строку, вставленную транзакцией?

Это очень сложно. Любая помощь будет оценена

Примечание. Запросы в корзине и журнале запросов были отредактированы для удаления конфиденциальной информации. Но суть запросов остается прежней

Изменить: Обновлен общий журнал и журнал запросов с подробным примером.


Вы отметили это 5.5, но упомянули 5.6; что он? Вовлечена ли репликация?
Рик Джеймс

@RickJames извините, это 5.6.19. Я обновил вопрос с примером из журнала запросов и журнала. Также нет никакой репликации, я включил журнал бина только после того, как заметил проблему, чтобы отладить это. Спасибо
Ахмед Эон Аксан

Спасибо, это помогает. Я не вижу BEGINили START TRANSACTION. Вы вместо этого используете autocommit=0? (Я предпочитаю начинать ... фиксировать; это ясно
Рик Джеймс

Таким образом, framework (spring) управляет транзакциями и обычно устанавливает autocommit = 0 и фиксирует в конце. Я предполагаю, что мы не видим autocommit = 0 здесь, потому что соединение уже было в этом состоянии.
Ахмед Эон Аксан

Ответы:


3

Я пытаюсь выдвинуть гипотезу о втором вопросе:

Если фиксация происходит до выбора (фиксация в 14:16:06, а выбор в 14:16:07), как получается, что выбор не возвращает строку, вставленную транзакцией?

Сделки управляются весной. Таким образом, возможно, что перед запуском selectпружина подняла start transactionили уже использовала соединение для выполнения другого запроса.

Я начинаю первый сеанс, где я имитирую вставку в таблицу t:

session1> create table t (i int auto_increment primary key);
Query OK, 0 rows affected (0,32 sec)

session1> insert into t values();
Query OK, 1 row affected (0,00 sec)

session1> select * from t;
+---+
| i |
+---+
| 1 |
+---+
1 row in set (0,00 sec)

session1> start transaction;
Query OK, 0 rows affected (0,00 sec)

session1> insert into t values();
Query OK, 1 row affected (0,00 sec)

Я создаю новый сеанс session2, где autocommitустановлено значение 0. В этот новый сеанс транзакция неявно запускается при выполнении выбора.

session2> set autocommit = 0;
Query OK, 0 rows affected (0,00 sec)

session2> select * from t;  -- this starts a transaction
+---+
| i |
+---+
| 1 |
+---+
1 rows in set (0,00 sec)

Перейдите к session1, чтобы зафиксировать вставку.

session1> commit;

Теперь перейдите снова к session2:

session2> select * from t;
+---+
| i |
+---+
| 1 |
+---+
1 row in set (0,00 sec)

Session2 не может видеть только что вставленную строку. Если a commitподнимается в session2, мы можем видеть новую строку, вставленную в session1

session2> commit
1 row in set (0,00 sec)

session2> select * from t;
+---+
| i |
+---+
| 1 |
| 2 |
+---+
2 rows in set (0,00 sec)

Общий журнал выглядит так:

150804 14:04:10     2 Query select * from t

150804 14:04:30     1 Query start transaction
150804 14:04:39     1 Query insert into t values ()
150804 14:04:44     1 Query commit
150804 14:04:51     2 Query select * from t

150804 14:05:07     2 Query commit
150804 14:05:10     2 Query select * from t

Первая строка связана с сеансом 2. Это когда сеанс 2 открывает транзакцию.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.