Контекст: Рамка, що використовується, є Spring і всі запити виконуються з JdbcTemplate. Версія сервера Mysql - 5.6.19. Значення " table
є" InnoDB table
та "за замовчуванням" auto commit
та встановлюється рівень повторного читання рівня ізоляції.
Проблема : Insert
трапляється всередині транзакції, і той, select
хто читає ті самі вставлені дані, не бачить даних. У select
пробігах післяinsert
і після того , як insert
угода має commited
.
Я ввімкнув журнал бін, а також загальний журнал у mysql. Відповідні журнали нижче
bin-log:
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'
Цікаво, що Перший 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
? (Я вважаю за краще починати ... вчиняти; це дозволяє зрозуміти масштаби транзакції.)