Discussão do artigo "SQLite: trabalho nativo com bancos de dados SQL em MQL5" - página 7

 
Renat Fatkhullin:

Será 2840 na versão beta amanhã:

  • Versão SQLite 2.35.2

  • Modo WAL permanente, permitindo trabalhar com um banco de dados aberto a partir de diferentes aplicativos (anteriormente, o MetaEditor não podia trabalhar em paralelo com o terminal).

Muito feliz, obrigado
 
Edgar Akhmadeev:
Muito feliz, obrigado

O Beta 2840 está disponível, experimente-o.

 
Renat Fatkhullin:

Será 2840 na versão beta amanhã:

  • Versão SQLite 2.35.2

  • Modo WAL permanente, permitindo trabalhar com um banco de dados aberto a partir de diferentes aplicativos (anteriormente, o MetaEditor não podia trabalhar em paralelo com o terminal)

  • extensão das funções estatísticas
    exemplo:
  • novas funções matemáticas
  • O suporte a JSON também foi incluído

    Incluiremos um novo tipo de json no assistente de criação de banco de dados posteriormente.



Renat, muito obrigado!!!
Não esperava que fosse tão rápido, estou muito satisfeito))))))
 
fxsaber:

Se você tiver descoberto isso, mostre a implementação dessa tarefa.

  1. Há dois terminais.
  2. É necessário transferir cotações em tempo real de um símbolo do Terminal1 para o símbolo personalizado correspondente do Terminal2.
fxsaber:

No âmbito dessa tarefa, entendo corretamente que em ambos os casos (ao ler a base no Terminal2 e gravar na base do Terminal1) ela deve ser bloqueada por meio do mecanismo de transação?

Qual é a maneira mais econômica de determinar que o banco de dados foi atualizado?

Fundamentalmente errado. Você está descrevendo um aplicativo cliente-servidor distribuído, com um esquema de 1 escritor, n leitores. Ao projetar esses sistemas (e qualquer sistema distribuído em geral), você deve tentar evitar bloqueios usando formas de organização de dados e acesso a eles sem bloqueios. Se a tecnologia usada não permitir que você passe sem bloqueio, talvez ela não seja a melhor solução para a sua tarefa. No entanto, para outras tarefas, a tecnologia pode ser excelente.
No seu caso, é melhor implantar um servidor completo (você pode fazer isso no mesmo computador que o cliente) e gravar as cotações na fila de mensagens, como no Kafka, por exemplo. O cliente lerá essas citações do índice necessário. Esse é um esquema de acesso a dados sem bloqueio.

fxsaber:

Então, a troca de dados tem menos possibilidades do que via arquivos?

Categoricamente, não. O compartilhamento por meio de arquivos não é atômico, portanto, requer bloqueios tanto no lado do leitor quanto do gravador. Essa é a maneira mais segura de obter um impasse e se perder na captura de erros difíceis de encontrar e incompreensíveis.

 
Vasiliy Sokolov:

Fundamentalmente errado. Você está descrevendo um aplicativo cliente-servidor distribuído com um esquema de 1 escritor, n leitores. Ao projetar esses sistemas (e qualquer sistema distribuído em geral), você deve tentar evitar bloqueios, usando formas de organização de dados e acesso a eles sem bloqueios. Se a tecnologia usada não permitir que você passe sem bloqueio, talvez ela não seja a melhor solução para a sua tarefa. No entanto, para outras tarefas, a tecnologia pode ser excelente.
No seu caso, é melhor implantar um servidor completo (você pode fazer isso no mesmo computador que o cliente) e gravar as cotações na fila de mensagens, como no Kafka, por exemplo. O cliente lerá essas citações do índice necessário. Esse é um esquema de acesso a dados sem bloqueio.

Categoricamente, não. O compartilhamento por meio de arquivos não é atômico de forma alguma, portanto, requer bloqueios no lado do leitor e do gravador. Essa é a maneira mais segura de obter um deadlock e se perder na captura de erros difíceis de ver e incompreensíveis.

Obrigado por uma resposta tão detalhada! Infelizmente, esqueci completamente o problema que estava resolvendo na época. É por isso que não posso compartilhar minhas ideias sobre o assunto.

 
Renat Fatkhullin:

O Beta 2840 está disponível, experimente-o.

Renat, bom dia!

Também notei um problema no StringFormat, quando uma string de dados de entrada bastante grande é colocada nele, por exemplo, de um arquivo de recurso com 3-4 instruções, por exemplo, %d, %s, %lld, %s, verifiquei várias variantes de substituição, é apenas uma questão de uma grande quantidade de dados de entrada, o que resulta no erro 4003.

Mudei temporariamente para a função StringReplace nos projetos, que funciona corretamente com dados grandes na string de entrada.
 
Aprendi muito, obrigado por compartilhar.
 
No arquivo DataBasePrepare, há um erro. Eu substituiria o "pair" por string, certo?
 

Perguntas sobre essa solução

- Há algum problema com o fato de vários EAs usarem o mesmo banco de dados sqlite simultaneamente?

- Se o MT5 travar, alguns dados poderão ser perdidos? Com que frequência ele grava dados no disco?

 

Boa tarde, caros desenvolvedores!

A função "DatabaseExport" não quer funcionar de forma alguma... dá o erro 5601 (erro de execução de consulta, mas não executo a consulta) quando especifico o nome da tabela nos parâmetros,

e quando eu especifico a consulta SQL, ele dá o erro 4022 (cancelamento da execução do programa), provavelmente um erro dentro da função MQL, parte do código da minha biblioteca:


//+------------------------------------------------------------------+
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();
  }
//+------------------------------------------------------------------+