Дані MySQL Commited не відображаються для вибору запиту


13

Контекст: Рамка, що використовується, є 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? Оскільки він не має ідентифікатора потоку.

Підводячи підсумок, у мене є два питання.

  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? (Я вважаю за краще починати ... вчиняти; це дозволяє зрозуміти масштаби транзакції.)
Рік Джеймс,

Таким чином, фреймворк (весна) управляє транзакціями, і він зазвичай встановлює autocommit = 0 і здійснює в кінці. Я здогадуюсь, що тут ми не бачимо autocommit = 0, оскільки з'єднання вже було в такому стані.
Ахмед Еон Аксан

Відповіді:


3

Я намагаюся зробити гіпотезу щодо другого питання:

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

Операціями керує Весна. Тому можливо, що перед запуском selectпружина підняла a 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)

Перейдіть до сесії1, щоб зробити вставку.

session1> commit;

Тепер знову переходимо до session2:

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

Сесія2 не може побачити щойно вставлений рядок. Якщо 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 сеанс відкриває транзакцію.

Я не знаю, чи це трапиться у вашому випадку. Ви можете перевірити у своєму загальному журналі, чи використовувався з'єднання_id 36 для інших запитів. Дайте нам знати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.