Discussione sull’articolo "SQLite: Gestione nativa dei database SQL in MQL5" - pagina 7

 
Renat Fatkhullin:

Domani sarà 2840 in beta:

  • versione di SQLite 2.35.2

  • modalità WAL permanente, che consente di lavorare con un database aperto da diverse applicazioni (in precedenza MetaEditor non poteva lavorare in parallelo con il terminale).

Molto soddisfatto, grazie
 
Edgar Akhmadeev:
Molto soddisfatto, grazie

La beta 2840 è disponibile, provatela.

 
Renat Fatkhullin:

Domani sarà 2840 in beta:

  • versione di SQLite 2.35.2

  • modalità WAL permanente, che consente di lavorare con un database aperto da diverse applicazioni (in precedenza MetaEditor non poteva lavorare in parallelo con il terminale)

  • estensione delle funzioni statistiche
    esempio:
  • nuove funzioni matematiche
  • È stato incluso ancheil supporto JSON

    In seguito includeremo il nuovo tipo json nella creazione guidata del database.



Renat, grazie mille!!!
Non me l'aspettavo così veloce, molto soddisfatto))))))
 
fxsaber:

Chi l'ha capito, è pregato di mostrare l'implementazione di tale compito.

  1. Ci sono due terminali.
  2. È necessario trasferire le quotazioni in tempo reale di un simbolo dal Terminale1 al corrispondente simbolo personalizzato del Terminale2.
fxsaber:

Nell'ambito di questo compito, ho capito bene che in entrambi i casi (quando si legge la base sul Terminal2 e si scrive sulla base nel Terminal1) dovrebbe essere bloccato attraverso il meccanismo delle transazioni?

Qual è il modo più economico per determinare che il database è stato aggiornato?

Fondamentalmente sbagliato. State descrivendo un'applicazione client-server distribuita, con uno schema di 1 scrittore, n lettori. Quando si progettano sistemi di questo tipo (e in generale tutti i sistemi distribuiti) si dovrebbe cercare di evitare i blocchi, utilizzando modalità di organizzazione dei dati e di accesso agli stessi prive di blocchi. Se la tecnologia utilizzata non consente di fare a meno dei blocchi, forse non è la soluzione migliore per il vostro compito. Tuttavia, per altri compiti la tecnologia potrebbe essere ottima.
Nel vostro caso è meglio implementare un server completo (potete farlo sulla stessa macchina del client) e scrivere le citazioni sulla coda di messaggi, ad esempio Kafka. Il client leggerà queste citazioni dall'indice richiesto. Si tratta di uno schema di accesso ai dati privo di lock.

fxsaber:

Quindi risulta che lo scambio di dati ha meno possibilità rispetto ai file?

Categoricamente no. La condivisione tramite file non è affatto atomica, quindi richiede blocchi sia sul lato del lettore che su quello dello scrittore. Questo è il modo più sicuro per ottenere un deadlock e perdersi nella cattura di errori difficili da trovare e incomprensibili.

 
Vasiliy Sokolov:

Fondamentalmente sbagliato. Si sta descrivendo un'applicazione client-server distribuita con uno schema di 1 scrittore, n lettori. Quando si progettano sistemi di questo tipo (e qualsiasi altro sistema distribuito in generale) si dovrebbe cercare di evitare qualsiasi blocco, utilizzando modalità di organizzazione dei dati e di accesso agli stessi prive di blocchi. Se la tecnologia utilizzata non consente di fare a meno dei blocchi, forse non è la soluzione migliore per il vostro compito. Tuttavia, per altri compiti la tecnologia potrebbe essere ottima.
Nel vostro caso è meglio implementare un server completo (potete farlo sulla stessa macchina del client) e scrivere le citazioni nella coda di messaggi, ad esempio Kafka. Il client leggerà queste citazioni dall'indice richiesto. Si tratta di uno schema di accesso ai dati privo di lock.

Categoricamente no. La condivisione tramite file non è in alcun modo atomica, quindi richiede blocchi sia sul lato del lettore che su quello dello scrittore. Questo è il modo più sicuro per ottenere un deadlock e perdersi nella cattura di errori difficili da vedere e incomprensibili.

Grazie per la risposta così dettagliata! Sfortunatamente, ho completamente dimenticato il problema che stavo risolvendo in quel momento. Per questo motivo non posso condividere i miei pensieri sull'argomento.

 
Renat Fatkhullin:

La beta 2840 è disponibile, provatela.

Renat, buongiorno!

Ho notato anch'io un problema in StringFormat, quando viene inserita una stringa di dati di input piuttosto grande, ad esempio da un file di risorse con 3-4 dichiarazioni, ad esempio %d, %s, %lld, %s, ho controllato diverse varianti di sostituzione, è solo una questione di una grande quantità di dati di input, che risulta nell'errore 4003.

Sono passato temporaneamente alla funzione StringReplace nei progetti, che funziona correttamente con dati grandi nella stringa di input.
 
Imparato, grazie per averlo condiviso.
 
Nel file DataBasePrepare c'è un errore. Dovrei sostituire la "coppia" con una stringa, è corretto?
 

Domande su questa soluzione

- Ci sono problemi se più EA utilizzano lo stesso database sqlite contemporaneamente?

- Se MT5 si blocca, alcuni dati possono andare persi? Con quale frequenza vengono scritti i dati su disco?

 

Buon pomeriggio, cari sviluppatori!

La funzione "DatabaseExport" non vuole funzionare in nessun modo...dà errore 5601 (errore di esecuzione della query, ma non eseguo la query) quando specifico il nome della tabella nei parametri,

e quando specifico la query SQL, dà l'errore 4022 (annullamento dell'esecuzione del programma), probabilmente un errore all'interno della funzione MQL, parte del codice della mia libreria:


//+------------------------------------------------------------------+
void CSQLite::DataBaseToFile(void)
  {
   uint flags=DATABASE_EXPORT_COMMON_FOLDER | DATABASE_EXPORT_QUOTED_STRINGS;

   long count_rows=0;

   string tables[],
          file_name,
          separator=";",
          query="SELECT name FROM sqlite_master WHERE tbl_name <> 'sqlite_sequence' AND type='table'";

   int total=GetValuesFromDataBase(query,tables); // ТУТ ВСЕ ОК, СПИСОК ТАБЛИЦ ИЗ БАЗЫ ПОЛУЧЕН.

   if(m_handle==NULL)
      Open();

   for(int i=0; i<total; i++)
     {
      file_name=StringFormat("%s.%s",m_name,tables[i]);
      count_rows=DatabaseExport(m_handle,tables[i],file_name,flags,separator); // ОШИБКА ПОСЛЕ ВЫПОЛНЕНИЯ ДАННОЙ ФУНКЦИИ
      Print(StringFormat("Export file: %s, rows: %lld",file_name,count_rows));

      if(count_rows<0)
         Print("DB: ", m_name,", Table: ",tables[i], ", Import failed with code ", GetLastError());
      else
         if(count_rows>0)
            Print(StringFormat("Import file: %s, rows: %lld",file_name,count_rows));
     }

   Finalize();
  }
//+------------------------------------------------------------------+