記事"SQLite: MQL5 での SQL データベースのネイティブな処理"についてのディスカッション - ページ 8

 

そして質問その2:

ATTACH/DETACH 関数を使ってSQLiteの 組み込みメカニズムを使ってデータベース間でデータを転送しようとすると、トランザクションエラー5601が発生します。

SQLiteStudioで同じトランザクションを実行すると、すべて正常です。

これは意図的に行われているのでしょうか、それとも何かが機能していないのでしょうか?

   m_db.Create("IndiTemp","indi",m_db_main.GetStruct(),true);
   string db_path=StringFormat("%s\\Files\\%s.sqlite",
                               TerminalInfoString(TERMINAL_COMMONDATA_PATH),
                               "Indi");
                               
   string query=StringFormat("ATTACH DATABASE '%s' AS X; ",db_path),
          tables[];
          
   int total=m_db.GetTables(tables);
   if(total>0)
     {
      for(int i=0; i<total; i++)
         StringAdd(query,StringFormat("INSERT OR IGNORE INTO %s SELECT * FROM X.%s; ",tables[i],tables[i]));
     }
     
   StringAdd(query,"DETACH X; ");
   m_db.TransactionExecute(query);
 
Daniil Kurmyshev プログラム実行の キャンセル)が出ます。おそらくMQL関数内のエラーか、私のライブラリのコードの一部でしょう:


残念ながら、DatabaseExport関数はテーブルをエクスポートする機能を持たず(この機能はもともと意図されていたものですが)、現在はクエリのみをサポートしています。

エラー4022については、テスト中に発生するのでしょうか、もしそうであれば、テスターはエクスポート・ファイルのサイズに制限があります - ディスクに書き込まれるデータの合計サイズは1GBですか?

 
Daniil Kurmyshev SQLiteの 内蔵メカニズムでデータベース間のデータ転送を行おうとしているのですが、結果はトランザクションエラー5601です。

SQLiteStudioで同じトランザクションを実行すると、すべて正常です。

これはわざとなのでしょうか、それとも何かがうまくいっていないのでしょうか?

クエリは動作するはずです。
 
Ilyas #:

残念ながら、DatabaseExport関数はテーブルエクスポート機能を持たず(この機能はもともと意図されていたものだが)、現在はクエリーのみをサポートしている。

もしそうなら、テスターはエクスポートファイルのサイズに制限があります。

DatabaseExport関数でテーブル名の代わりにクエリを指定すると、テスターなしでエラー4022が表示されます。

データベースのサイズは10MB未満で、この機能を使ってディスク上のデータベースからメモリ上のデータベースにデータをコピーしようと考えていました。
 
Ilyas #:
クエリは動作するはずですが、パスが正しいか確認してください。

SQLiteStudioでは指定したパスでクエリが動作します。ターミナルログにクエリを出力し、SQLiteStudioでコピーして実行しても問題ありませんでした。

その結果を書いてみます。

 
SQLiteに そのような可能性があることは知っていますが、MT5に含まれているかどうか知りたいです。
 

データベースへのマルチスレッド書き込みをテストするために、スクリプトの複数のコピーを実行する。

#property copyright "Aliaksandr Hryshyn"
#property link      "https://www.mql5.com/ja/users/greshnik1"
#property version   "1.00"
#property script_show_inputs

enum e_E
  {
   e_0,
   e_1,
   e_2,
   e_3,
  };
input e_E expert_id=0;
//+------------------------------------------------------------------+
//| スクリプト番組開始機能|
//+------------------------------------------------------------------+
void OnStart()
  {
   int db_handle=DatabaseOpen("tmp//test.sqlite",DATABASE_OPEN_READWRITE|DATABASE_OPEN_CREATE|DATABASE_OPEN_COMMON);
   const string sql_create=
      "CREATE TABLE IF NOT EXISTS Demo("
      "Id INTEGER PRIMARY KEY AUTOINCREMENT,"
      "Expert_id INTEGER,"
      "demo_0 TEXT(2000),"
      "demo_1 TEXT(2000),"
      "demo_2 TEXT(2000),"
      "demo_3 TEXT(2000),"
      "demo_4 TEXT(2000),"
      "demo_5 TEXT(2000),"
      "demo_6 TEXT(2000),"
      "demo_7 TEXT(2000)"
      ");";
   const string sql_add=
      "INSERT INTO Demo(Expert_id,demo_%s) VALUES(%s,'%s')";
   if(!DatabaseExecute(db_handle,sql_create))//不在の場合はテーブルを作成する
     {
      DatabaseClose(db_handle);
      Print(「エラー,GetLastError());
      Print(「クエリー,sql_create);
      return;
     }
   string s1;
   string sql;
   int err_counter=100;//記録追加エラーカウンタ
   for(int i1=0; i1<1000; i1++)
     {
      s1="";
      for(int i2=0; i2<100; i2++)
        {
         s1+=string(MathRand());
        }
      sql=StringFormat(sql_add,string(MathRand()%8),string(expert_id),s1);
      if(DatabaseExecute(db_handle,sql))//demo_...セットからランダムなカラムにレコードを追加する。
        {
         err_counter=100;
        }
      else
        {
         if(err_counter==0)
           {
            DatabaseClose(db_handle);
            Print(expert_id,": end");
            return;
           }
         else
           {
            Print(expert_id,": ",err_counter);
            err_counter--;
            i1--;
           }
        }
      if(IsStopped())
         break;
      Sleep(1);// 少し眠る
     }
   DatabaseClose(db_handle);
  }

すべて正しく書き込まれます:


しかし、ブロッキングに関するエラーが発生します:

...
2021.09.18 13:08:05.252 Test_sql (EURUSD,M1)    2: 80
2021.09.18 13:08:05.267 Test_sql (EURUSD,M1)    database error, database is locked
2021.09.18 13:08:05.267 Test_sql (EURUSD,M1)    2: 79
2021.09.18 13:08:05.283 Test_sql (EURUSD,M1)    database error, database is locked
2021.09.18 13:08:05.283 Test_sql (EURUSD,M1)    2: 78
2021.09.18 13:08:05.299 Test_sql (EURUSD,M1)    database error, database is locked
2021.09.18 13:08:05.299 Test_sql (EURUSD,M1)    1: 100
2021.09.18 13:08:05.315 Test_sql (EURUSD,M1)    database error, database is locked
2021.09.18 13:08:05.315 Test_sql (EURUSD,M1)    1: 99
...

エラーを返さない条件付きレコード挿入のメカニズムが必要です。

 
Ilyas #:
クエリーは動作するはずですが、パスが正しいことを確認してください。

1.チェックATTACH DATABASEは本当に動作します!

問題は以下の点にあった。RAMに作成したベースにアタッチしようとしたが、この場合物理ベースはATTACH DATABASEが機能しないが、RAMベースを物理ベースにアタッチすれば 機能する!

これは、RAMに基地のコピーを作成し、計算をスピードアップするには十分なことです)))


2.私はさらに踏み込むことにした...。さらにもう一つの可能性をチェックすることにした:

ATTACH DATABASE 'file:memdb1?mode=memory&cache=shared' AS M;

考え方によると、データベースはRAMに作成され、スレッドが閉じられた後に存在しなくなるはずですが、その動作は異なります...

1では、どのMQL5プログラム、Expert Advisor、インジケータ、スクリプト、サービスからでも参加できます、

2では、その中のデータは、再起動した後でも、永久に保存されます。私はすでに...データベースが物理的に作成されているのかもしれないと考えましたが、*memdb1*という名前で検索しても何も見つかりませんでした

追伸:おそらく、インジケータからベースを作成し、共通のスレッドで動作しているからでしょうか?


クールな機能ですが、次のアップデートでターミナルに残るのかどうか、それについての私のメッセージの後に知りたいです:)))。

この場合、問題や遅延なしに、簡単にプログラム間で大量のデータを転送することができ、名前の長さによって制限されるグローバル変数を使用することはありません...。


この実行では、MQL5プログラムの終了後に削除されます:

ATTACH DATABASE ':memory:?cache=shared' AS M;

ATTACH DATABASE ':memory:' AS M

 

こんにちは!

MTの開発者に質問ですが、SQLiteライブラリのShared属性を無効にすることは可能でしょうか?他のプロジェクトでの 経験から、これがデータベース エラー、データベースがロックされて います」というエラーの原因であると判断しました。

異なるスレッドからデータベースにアクセスしている場合は、データベースを開いた直後に以下の2つのクエリを実行することで、データベース自体のレベルですべて解決できます:

1. PRAGMA journal_mode = WAL;

2. PRAGMA busy_timeout = 1000;

PRAGMA journal_mode = WAL; 2. PRAGMA busy_timeout = 1000; しかし、ロック・エラーはベースを非共有に した後でのみ解消されます。

 
Daniil Kurmyshev プロジェクトでの 経験から、これがデータベースエラー、データベースがロックされて います」というエラーの原因であると判断しました。

異なるスレッドからデータベースへのアクセスであれば、データベースを開いた直後に2つのクエリを実行することで、データベース自体のレベルで解決できます:

1. PRAGMA journal_mode = WAL;

2. PRAGMA busy_timeout = 1000;

しかし、ロックエラーがなくなるのは、ベースを共有 しないようにした後だけである。

この場合、クエリーの速度は低下し、必要なメモリは増加します。

でも大丈夫です :-)

SQLiteは、1つのスレッド、または1人のライターと多数のリーダーのために設計されています。SQLiteは1つのスレッド、または1人のライターと多くの読者のために設計されています。

MQLがどうのこうのではなく、本当にどこでもそうなのです。