記事"SQLite: MQL5 での SQL データベースのネイティブな処理"についてのディスカッション - ページ 8 123456789101112 新しいコメント Daniil Kurmyshev 2021.09.06 01:33 #71 そして質問その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); Ilyas 2021.09.06 15:21 #72 Daniil Kurmyshev プログラム実行の キャンセル)が出ます。おそらくMQL関数内のエラーか、私のライブラリのコードの一部でしょう: 残念ながら、DatabaseExport関数はテーブルをエクスポートする機能を持たず(この機能はもともと意図されていたものですが)、現在はクエリのみをサポートしています。 エラー4022については、テスト中に発生するのでしょうか、もしそうであれば、テスターはエクスポート・ファイルのサイズに制限があります - ディスクに書き込まれるデータの合計サイズは1GBですか? Ilyas 2021.09.06 18:20 #73 Daniil Kurmyshev SQLiteの 内蔵メカニズムでデータベース間のデータ転送を行おうとしているのですが、結果はトランザクションエラー5601です。 SQLiteStudioで同じトランザクションを実行すると、すべて正常です。これはわざとなのでしょうか、それとも何かがうまくいっていないのでしょうか? クエリは動作するはずです。 Daniil Kurmyshev 2021.09.10 03:39 #74 Ilyas #:残念ながら、DatabaseExport関数はテーブルエクスポート機能を持たず(この機能はもともと意図されていたものだが)、現在はクエリーのみをサポートしている。もしそうなら、テスターはエクスポートファイルのサイズに制限があります。DatabaseExport関数でテーブル名の代わりにクエリを指定すると、テスターなしでエラー4022が表示されます。 データベースのサイズは10MB未満で、この機能を使ってディスク上のデータベースからメモリ上のデータベースにデータをコピーしようと考えていました。 Daniil Kurmyshev 2021.09.10 03:42 #75 Ilyas #: クエリは動作するはずですが、パスが正しいか確認してください。 SQLiteStudioでは指定したパスでクエリが動作します。ターミナルログにクエリを出力し、SQLiteStudioでコピーして実行しても問題ありませんでした。 その結果を書いてみます。 Daniil Kurmyshev 2021.09.10 03:50 #76 SQLiteに そのような可能性があることは知っていますが、MT5に含まれているかどうか知りたいです。 Aliaksandr Hryshyn 2021.09.18 12:35 #77 データベースへのマルチスレッド書き込みをテストするために、スクリプトの複数のコピーを実行する。 #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 ... エラーを返さない条件付きレコード挿入のメカニズムが必要です。 Daniil Kurmyshev 2021.09.27 11:39 #78 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; Daniil Kurmyshev 2021.11.20 17:40 #79 こんにちは! MTの開発者に質問ですが、SQLiteライブラリのShared属性を無効にすることは可能でしょうか?他のプロジェクトでの 経験から、これが「データベース エラー、データベースがロックされて います」というエラーの原因であると判断しました。 異なるスレッドからデータベースにアクセスしている場合は、データベースを開いた直後に以下の2つのクエリを実行することで、データベース自体のレベルですべて解決できます: 1. PRAGMA journal_mode = WAL; 2. PRAGMA busy_timeout = 1000; PRAGMA journal_mode = WAL; 2. PRAGMA busy_timeout = 1000; しかし、ロック・エラーはベースを非共有に した後でのみ解消されます。 Discussion of article "SQLite: Linux上のMetaTrader 5のC++マルチスレッドサポートを備えた概念実証DLLを開発する Maxim Kuznetsov 2021.11.20 19:08 #80 Daniil Kurmyshev プロジェクトでの 経験から、これが「データベースエラー、データベースがロックされて います」というエラーの原因であると判断しました。 異なるスレッドからデータベースへのアクセスであれば、データベースを開いた直後に2つのクエリを実行することで、データベース自体のレベルで解決できます:1. PRAGMA journal_mode = WAL;2. PRAGMA busy_timeout = 1000;しかし、ロックエラーがなくなるのは、ベースを共有 しないようにした後だけである。 この場合、クエリーの速度は低下し、必要なメモリは増加します。でも大丈夫です :-)SQLiteは、1つのスレッド、または1人のライターと多数のリーダーのために設計されています。SQLiteは1つのスレッド、または1人のライターと多くの読者のために設計されています。 MQLがどうのこうのではなく、本当にどこでもそうなのです。 123456789101112 新しいコメント 取引の機会を逃しています。 無料取引アプリ 8千を超えるシグナルをコピー 金融ニュースで金融マーケットを探索 新規登録 ログイン スペースを含まないラテン文字 このメールにパスワードが送信されます エラーが発生しました Googleでログイン WebサイトポリシーおよびMQL5.COM利用規約に同意します。 新規登録 MQL5.com WebサイトへのログインにCookieの使用を許可します。 ログインするには、ブラウザで必要な設定を有効にしてください。 ログイン/パスワードをお忘れですか? Googleでログイン
そして質問その2:
ATTACH/DETACH 関数を使ってSQLiteの 組み込みメカニズムを使ってデータベース間でデータを転送しようとすると、トランザクションエラー5601が発生します。
SQLiteStudioで同じトランザクションを実行すると、すべて正常です。
これは意図的に行われているのでしょうか、それとも何かが機能していないのでしょうか?
残念ながら、DatabaseExport関数はテーブルをエクスポートする機能を持たず(この機能はもともと意図されていたものですが)、現在はクエリのみをサポートしています。
エラー4022については、テスト中に発生するのでしょうか、もしそうであれば、テスターはエクスポート・ファイルのサイズに制限があります - ディスクに書き込まれるデータの合計サイズは1GBですか?
SQLiteStudioで同じトランザクションを実行すると、すべて正常です。
これはわざとなのでしょうか、それとも何かがうまくいっていないのでしょうか?
残念ながら、DatabaseExport関数はテーブルエクスポート機能を持たず(この機能はもともと意図されていたものだが)、現在はクエリーのみをサポートしている。
もしそうなら、テスターはエクスポートファイルのサイズに制限があります。
DatabaseExport関数でテーブル名の代わりにクエリを指定すると、テスターなしでエラー4022が表示されます。
データベースのサイズは10MB未満で、この機能を使ってディスク上のデータベースからメモリ上のデータベースにデータをコピーしようと考えていました。クエリは動作するはずですが、パスが正しいか確認してください。
SQLiteStudioでは指定したパスでクエリが動作します。ターミナルログにクエリを出力し、SQLiteStudioでコピーして実行しても問題ありませんでした。
その結果を書いてみます。
データベースへのマルチスレッド書き込みをテストするために、スクリプトの複数のコピーを実行する。
すべて正しく書き込まれます:
しかし、ブロッキングに関するエラーが発生します:
エラーを返さない条件付きレコード挿入のメカニズムが必要です。
クエリーは動作するはずですが、パスが正しいことを確認してください。
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; しかし、ロック・エラーはベースを非共有に した後でのみ解消されます。
異なるスレッドからデータベースへのアクセスであれば、データベースを開いた直後に2つのクエリを実行することで、データベース自体のレベルで解決できます:
1. PRAGMA journal_mode = WAL;
2. PRAGMA busy_timeout = 1000;
しかし、ロックエラーがなくなるのは、ベースを共有 しないようにした後だけである。
この場合、クエリーの速度は低下し、必要なメモリは増加します。
でも大丈夫です :-)
SQLiteは、1つのスレッド、または1人のライターと多数のリーダーのために設計されています。SQLiteは1つのスレッド、または1人のライターと多くの読者のために設計されています。
MQLがどうのこうのではなく、本当にどこでもそうなのです。