MySQL Dati commessi non visualizzati per selezionare la query


13

Contesto: il framework utilizzato è Spring e tutte le query vengono eseguite con JdbcTemplate. La versione di Mysql Server è 5.6.19. Il tableè una InnoDB tablee le impostazioni predefinite, come auto commite livello di isolamento ripetibile-lettura è impostato.

Problema : si Insertverifica un errore all'interno di una transazione e un utente selectche legge gli stessi dati inseriti non li vede. Le selectcorse dopo il inserte dopo l' insertoperazione ha commited.

Ho abilitato il registro bin e il registro generale in mysql. Registri pertinenti di seguito

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/*!*/;

Registro query

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'

Curiosamente, First insert(249935389) non dovrebbe far parte della transazione. È una chiamata API separata e completamente non correlata. Potrebbe essere primavera mescolando con la transazione o sto leggendo il registro sbagliato? AFAIK poiché si trova sullo stesso thread implica che l'inserimento è nella transazione.

I prossimi due insertsfanno parte della transazione e sembra che commetta. (249.936.514). Ora la query di selezione (l'ultima nel registro generale) viene eseguita dopo il commit e non vede i dati. Restituisce 0 righe. Come può succedere considerando i dati committed? O commitnon è sul thread 40? Dal momento che non ha l'id thread.

Per riassumere ho due domande.

  1. Fa il BEGINnell'essere binlog prima della INSERT INTO user_geo_loc(che non fa parte della transazione), è presente un bug con la primavera / JDBC o MySql semplicemente lo fa come sa questa transazione, ha già commesso (come le transazioni vengono scritte binlog quando hanno è riuscito) e quindi non verrà mai eseguito il rollback.

  2. Dato che il commit avviene prima della selezione (commit è alle 14:16:06 e select è alle 14:16:07) come mai la selezione non restituisce la riga inserita dalla transazione?

Questo è estremamente sconcertante. Qualsiasi aiuto sarebbe apprezzato

Nota: le query nel cestino e nel registro delle query sono state modificate per rimuovere informazioni riservate. Ma l'essenza delle domande rimane la stessa

Modifica: aggiornato con il registro generale e il registro delle query con un esempio dettagliato.


L'hai taggato 5.5, ma hai menzionato 5.6; cos'è questo? La replica è coinvolta?
Rick James,

@RickJames mi dispiace, è il 5.6.19. Ho aggiornato la domanda con l'esempio del registro delle query e dei bin. Inoltre non c'è alcuna replica coinvolta ho attivato il registro bin solo dopo aver notato il problema per il debug. Grazie
Ahmed Aeon Axan il

Grazie, aiuta. Non vedo un BEGINo START TRANSACTION. Stai invece usando autocommit=0? (Preferisco iniziare ... commit; chiarisce l'entità della transazione.)
Rick James

Quindi il framework (primavera) gestisce le transazioni e di solito imposta autocommit = 0 e si impegna alla fine. Immagino che non vediamo autocommit = 0 qui perché la connessione era già in quello stato.
Ahmed Aeon Axan,

Risposte:


3

Cerco di fare un'ipotesi sulla seconda domanda:

Dato che il commit avviene prima della selezione (commit è alle 14:16:06 e select è alle 14:16:07) come mai la selezione non restituisce la riga inserita dalla transazione?

Le transazioni sono gestite da Spring. Quindi sarebbe possibile che prima di eseguire la selectprimavera abbia sollevato un start transactiono abbia già usato la connessione per eseguire un'altra query.

Inizio una prima sessione in cui simulo un inserto in una tabella 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)

Creo una nuova sessione, session2, dove autocommitè impostato su 0. In questa nuova sessione, una transazione viene avviata implicitamente quando si esegue una selezione.

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)

Passa alla sessione1 per confermare l'inserimento.

session1> commit;

Ora passa di nuovo a session2:

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

Sessione2 non può vedere la riga appena inserita. Se un commitviene generato in session2 possiamo vedere una nuova riga inserita in session1

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

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

Il registro generale è simile a:

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

La prima riga è correlata alla sessione 2. È quando la sessione 2 apre la transazione.

Non so se questo è ciò che accade nel tuo caso. È possibile controllare nel registro generale se connection_id 36 è stato utilizzato per altre query. Facci sapere.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.