Контекст: используется среда 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? Так как у него нет идентификатора потока.
Подводя итог, у меня есть два вопроса.
Имеет ли место
BEGIN
в binlog передINSERT INTO user_geo_loc
(который не является частью транзакции), это ошибка в Spring / Jdbc или MySql просто делает это, поскольку он знает, что эта транзакция уже зафиксирована (поскольку транзакции записываются в binlog, когда они удалось) и поэтому никогда не будет откат.Если фиксация происходит до выбора (фиксация в 14:16:06, а выбор в 14:16:07), как получается, что выбор не возвращает строку, вставленную транзакцией?
Это очень сложно. Любая помощь будет оценена
Примечание. Запросы в корзине и журнале запросов были отредактированы для удаления конфиденциальной информации. Но суть запросов остается прежней
Изменить: Обновлен общий журнал и журнал запросов с подробным примером.
источник
BEGIN
илиSTART TRANSACTION
. Вы вместо этого используетеautocommit=0
? (Я предпочитаю начинать ... фиксировать; это ясноОтветы:
Я пытаюсь выдвинуть гипотезу о втором вопросе:
Сделки управляются весной. Таким образом, возможно, что перед запуском
select
пружина поднялаstart transaction
или уже использовала соединение для выполнения другого запроса.Я начинаю первый сеанс, где я имитирую вставку в таблицу
t
:Я создаю новый сеанс session2, где
autocommit
установлено значение 0. В этот новый сеанс транзакция неявно запускается при выполнении выбора.Перейдите к session1, чтобы зафиксировать вставку.
Теперь перейдите снова к session2:
Session2 не может видеть только что вставленную строку. Если a
commit
поднимается в session2, мы можем видеть новую строку, вставленную в session1Общий журнал выглядит так:
Первая строка связана с сеансом 2. Это когда сеанс 2 открывает транзакцию.
Я не знаю, так ли это в вашем случае. Вы можете проверить в своем общем журнале, использовался ли connection_id 36 для других запросов. Дайте нам знать.
источник