2015-09-09 34 views
17

Sto usando Laravel 5.1.Come evitare il problema dei blocchi delle tabelle dei DB durante l'uso delle code Laravel?

Le code vengono utilizzate per il recupero/sincronizzazione dei dati tra diversi sistemi.

Uso il driver del database, 3 processi "artisan queue: work --daemon" sono in esecuzione in ogni momento.

I lavori vengono inviati sia dagli utenti di sistema che dallo scheduler (cron). Tre code vengono utilizzate per stabilire la priorità dei lavori.

Tutto sembra funzionare correttamente: la tabella dei lavori viene riempita di record, il sistema si occupa di loro e rimuove quelli che sono stati eseguiti.

questioni Tuttavia, dopo un certo tempo di bloccaggio cominciano ad interferire:

SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction

e

'RuntimeException' with message 'Can't swap PDO instance while within transaction.'

e

SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction

Non ho provato utilizzando un altro driver coda ancora. Mi piacerebbe molto stare con il database però. Il motore è InnoDB, la tabella dei lavori ha struttura e indici predefiniti.

C'è un modo per risolvere questo problema? Quali sono i tuoi pensieri?

Vale la pena ricordare che chiamo lo DB::reconnect() all'interno delle mie classi di lavoro poiché i lavoratori della coda sono in esecuzione come demoni.

I lavori vengono inviati utilizzando il tratto DispatchesJobs come ci si aspetterebbe. Non interferisco nell'algoritmo delle code in nessun altro modo.

+0

Qualsiasi soluzione per questo? –

+1

No. Spostato in beanstalkd per ora. Anche se mi è piaciuto il driver DB perché potevo tenere traccia dei lavori e dei lavori falliti semplicemente guardando le tabelle DB ... – MaGnetas

+0

Studia come Laravel si occupa delle "transazioni" di MySQL. Sembra che tu abbia iniziato una transazione, quindi ti sei seduto per molto tempo. Transazioni 'COMMIT' non appena possibile. Controlla l'uso di 'autocommit'. –

risposta

0

È possibile passare a MyISAM e rimuovere gli errori di transazione; ma allo stesso tempo perdi un sacco di grandi funzionalità e affidabilità con innoDB.

* Questo non è un'opzione se le tabelle hanno chiavi esterne e si fa affidamento su cose come le eliminazioni a cascata e aggiornamenti che si trovano solo in InnoDB

+1

, suppongo che le chiavi esterne non siano un problema in questo caso. La tabella non ha relazioni. E la migrazione che crea la tabella "jobs" non specifica il motore. Questa potrebbe essere la soluzione. Tuttavia, non avere transazioni potrebbe significare collisioni che sono appena tracciabili ... – MaGnetas

1

Questo non può essere la risposta, ma alcune informazioni.

Quando si utilizzano le istruzioni SELECT ... FOR UPDATE, è possibile osservare contesa di blocco (blocchi morti ecc.).

select … for update where x <= y 

sua che intervallo di scansione con < = i blocchi del database tutte le righe < = y, comprese eventuali lacune quindi se si hanno righe con y come questo: 1, 3, 5 Si blocca anche lo spazio vuoto tra 1 e 3 nell'indice sua chiamata gap bloccaggio

può vedere il problema con questo comando:

SHOW ENGINE INNODB STATUS; 

---TRANSACTION 72C, ACTIVE 755 sec 
4 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 1 
MySQL thread id 3, OS thread handle 0x7f84a78ba700, query id 163 localhost msandbox 
TABLE LOCK table test.t trx id 72C lock mode IX 
RECORD LOCKS space id 19 page no 4 n bits 80 index age of table test.t trx id 72C lock_mode X 
RECORD LOCKS space id 19 page no 3 n bits 80 index GEN_CLUST_INDEX of table test.t trx id 72C lock_mode X locks rec but not gap 
RECORD LOCKS space id 19 page no 4 n bits 80 index age of table test.t trx id 72C lock_mode X locks gap before rec 

ultima riga

Se si dispone di molte lacune blocca nelle transazioni che interessano la concorrenza e le prestazioni è possibile disattivarli in due modi diversi:

1- Change the ISOLATION level to READ COMMITTED. In this isolation level, it is normal and expected that query results can change during a transaction, so there is no need to create locks to prevent that from happening. 

2- innodb_locks_unsafe_for_binlog = 1. Disables the gap locks except for foreign-key constraint checking or duplicate-key checking. 

https://www.percona.com/blog/2012/03/27/innodbs-gap-locks/

+0

tutto questo potrebbe essere utile, grazie. Ma odio davvero fare confusione con il nucleo di laravel. Credo che questo dovrebbe essere in qualche modo risolto "fuori dagli schemi". Anche se potrei fare alcune "buone pratiche" modifiche al mio codice o flusso di lavoro per evitare il problema. – MaGnetas