Discusión sobre el artículo "SQLite: trabajo nativo con bases de datos en SQL en MQL5" - página 7

 
Renat Fatkhullin:

Mañana será 2840 en beta:

  • Versión SQLite 2.35.2

  • modo WAL permanente, que permite trabajar con una base de datos abierta desde diferentes aplicaciones (antes MetaEditor no podía trabajar en paralelo con el terminal).

Muy contento, gracias
 
Edgar Akhmadeev:
Muy contento, gracias

Beta 2840 está disponible, por favor pruébela.

 
Renat Fatkhullin:

Mañana será 2840 en beta:

  • versión SQLite 2.35.2

  • modo WAL permanente, que permite trabajar con una base de datos abierta desde diferentes aplicaciones (antes MetaEditor no podía trabajar en paralelo con el terminal)

  • ampliación de las funciones estadísticas
    ejemplo:
  • nuevas funciones matemáticas
  • También se incluyesoporte para JSON

    Más adelante incluiremos el nuevo tipo json en el asistente de creación de bases de datos.



¡¡¡Renat, muchas gracias!!!
No me lo esperaba tan rápido, muy contento))))))
 
fxsaber:

Quien lo haya resuelto, por favor que muestre la implementación de dicha tarea.

  1. Hay dos Terminales.
  2. Es necesario transferir las cotizaciones en tiempo real de un símbolo del Terminal1 al símbolo personalizado correspondiente del Terminal2.
fxsaber:

En el marco de esta tarea, ¿entiendo correctamente que en ambos casos (al leer la base en Terminal2 y escribir en la base en Terminal1) se debe bloquear a través del mecanismo de transacción?

¿Cuál es la forma más económica de determinar que la base de datos ha sido actualizada?

Fundamentalmente erróneo. Estás describiendo una aplicación cliente-servidor distribuida, con un esquema de 1 escritor, n lectores. Cuando se diseñan este tipo de sistemas (y cualquier sistema distribuido en general) se debe intentar evitar cualquier bloqueo utilizando formas de organización de datos y de acceso a los mismos sin bloqueos. Si la tecnología utilizada no permite prescindir de los bloqueos, quizá no sea la mejor solución para su tarea. Sin embargo, para otras tareas la tecnología puede ser estupenda.
En tu caso es mejor desplegar un servidor completo (puedes hacerlo en la misma máquina que el cliente) y escribir citas en la cola de mensajes, mira Kafka, por ejemplo. El cliente leerá estas citas desde el índice requerido. Este es un esquema de acceso a datos libre de bloqueos.

fxsaber:

Entonces, ¿resulta que el intercambio de datos tiene menos posibilidades que a través de ficheros?

Categóricamente no. El intercambio a través de ficheros no es atómico en absoluto, por lo que requiere bloqueos tanto en el lado del lector como en el del escritor. Esta es la forma más segura de llegar a un punto muerto y perderse en la captura de errores difíciles de encontrar e incomprensibles.

 
Vasiliy Sokolov:

Fundamentalmente erróneo. Estás describiendo una aplicación cliente-servidor distribuida con un esquema de 1 escritor, n lectores. Cuando se diseñan este tipo de sistemas (y cualquier sistema distribuido en general) se debe intentar evitar cualquier bloqueo, utilizando formas libres de bloqueos para la organización de los datos y el acceso a ellos. Si la tecnología utilizada no permite prescindir de los bloqueos, quizá no sea la mejor solución para su tarea. Sin embargo, para otras tareas la tecnología puede ser estupenda.
En tu caso es mejor desplegar un servidor completo (puedes hacerlo en la misma máquina que el cliente) y escribir citas en la cola de mensajes, mira Kafka, por ejemplo. El cliente leerá estas citas desde el índice requerido. Se trata de un esquema de acceso a datos sin bloqueo.

Categóricamente no. Compartir a través de archivos no es atómico de ninguna manera, por lo que requiere bloqueos tanto en el lado del lector como del escritor. Esta es la forma más segura de llegar a un punto muerto y perderse en la captura de errores difíciles de ver e incomprensibles.

Gracias por una respuesta tan detallada. Por desgracia, olvidé por completo qué problema estaba resolviendo en ese momento. Por eso no puedo compartir mis ideas sobre el tema.

 
Renat Fatkhullin:

Beta 2840 está disponible, por favor pruébala.

Renat, ¡buenos días!

Yo también he notado un problema en StringFormat, cuando se coloca en él una cadena de datos de entrada bastante grande, por ejemplo de un archivo de recursos con 3-4 declaraciones, por ejemplo %d, %s, %lld, %s, he comprobado varias variantes de sustitución, es sólo una cuestión de una gran cantidad de datos de entrada, lo que resulta en el error 4003.

He cambiado temporalmente a la función StringReplace en los proyectos, funciona correctamente con grandes datos en la cadena de entrada.
 
Aprendido, gracias por compartir.
 
En el archivo DataBasePrepare hay algún error. Yo sustituiría el "par" por cadena ¿es correcto?
 

Preguntas sobre esta solución

- ¿Hay algún problema si varios EAs utilizan la misma base de datos sqlite simultáneamente?

- Si MT5 se bloquea, ¿pueden perderse algunos datos? ¿Con qué frecuencia se escriben los datos en el disco?

 

¡Buenas tardes, estimados desarrolladores!

La función "DatabaseExport" no quiere funcionar de ninguna manera...da error 5601 (error de ejecución de la consulta, pero no ejecuto la consulta) cuando especifico el nombre de la tabla en los parámetros,

y cuando especifico la consulta SQL, da error 4022 (cancelación de la ejecución del programa), probablemente error dentro de la función MQL, parte del código de mi librería:


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