データベースアクセス時たまにread only mode エラー †
ページ | OpenOffice.org FAQの登録ページ |
---|---|
投稿者 | 匿名希望 |
分類 | |
優先順位 | |
状態 | |
カテゴリー | |
投稿日 | 2010-03-04 15:22:12 (木) |
OS | WindowsXP |
依存するページ | |
バージョン |
メッセージ †
回答ページでは行末に「~」を付加する必要はありません |
- データベースアクセス時たまにread only mode エラー
- メッセージ
- アプリケーションの構成は?
- ロックファイルは消えています。
- 無題
- 1点、確認します
- 質問にお答えします。
- 不思議な現象
- ファイル以外のロック要素
- データベースのシャットダウンのコードは?
- Re: データベースのシャットダウンのコードは?
- シャットダウンのタイミング
- シャットダウン処理を入れてみましたが、効いてないようです。
- 試行願います
- 試行結果
- 検証ありがとうございます
- MySQLにするとしたら
- データベースの選択
- 他のアイデアについて
- calc MySQL間の動作確認方法は?
- MySQL用Baseファイルの作成など
- マクロでの接続
- データーベースにアクセスするとクラッシュします。
- ドライバを変えてみては
- 当方では問題無しです
- 途中経過、接続テストはOKです。
- 無題
- 途中経過報告、DELETE文でクラッシュ
- 無題
- 経過報告
- 経過報告、単純なコードミスでした。
- データベースへの同時アクセスができました。
- みなさまお疲れ様でした
- メッセージ
Sub WorkBook_open Statement = Connection.createStatement() Statement.ResultSetConcurrency = "1008" Statement.ResultSetType = "1005" データベース更新処理 Statement.Close() Connection.Close() Connection.Dispose() ダイアログ表示 End Sub
上記のような処理のCALCを複数の端末にコピーして
処理を実行したときに
片方の端末ではデータベースにアクセスしてはいなく
ダイアログを表示状態で待ちのときに
他方の端末のCALCを開くいて処理を実行すると
The database is in read only mode in statement [DELETE FROM "HinmeiBF"]
というエラーが毎回ではないのですがたまにでます。
アクセスが競合しているわけではないので
ほかの原因があると思いますが
どなたか解決方法を教えて頂けませんか?お願いします。
アプリケーションの構成は? †
M.Kamataki (2010-03-04 16:39:34 (木))
作成されたアプリケーションですが、OpenOffice.orgのBaseで作成したデータベース(DB)を共有されているということで良いのでしょうか。
仮にBase標準のDB形式であるHSQLDBをお使いの場合、〜.odb ファイルに接続している間はロックファイルが作成されると思います。このロックファイルの挙動を確認して、マクロを組んでください。
理想的なのは「ダイアログ表示」の前にロックファイルが消えていることです。Windowsだと隠しファイルになっている可能性があるので、ロックファイルを確認する場合はエクスプローラの設定を変更してチェックしてみてください。
なお、標準のDB形式以外のMySQL、PostgreSQLなどのオープンソースのRDBMSをお使いになれば、確実にDBの共有は可能だと思います。
ロックファイルは消えています。 †
匿名 (2010-03-04 17:55:02 (木))
OpenOfficeのBaseで作成したデータベースを共有しています。
ロックファイルの挙動を確認しました。
一方の端末からCALCのマクロを実行するとbasefile.odbと
同じフォルダにbasefile.odb.lckが作成され
ダイアログ表示時はbasefile.odb.lckは消滅しています。
がしかし、他方の端末からCALCのマクロを実行するとread only modeの
エラーが出ます。Baseのデータベースは共有できないということでしょうか?
無題 †
tani (2010-03-04 20:53:52 (木))
すると、一方の端末のダイアログが消えた(マクロが終了した)時点で、他の端末からマクロを実行してもread only modeじゃなくなるのでしょうか?
ちょっと気になりましたので。
1点、確認します †
M.Kamataki (2010-03-04 21:08:45 (木))
OpenOffice.orgのクイック起動を利用されていますでしょうか。Baseのodbファイルを利用する際は、クイック起動は利用しないようにしましょう。
3.0までは、odbファイルのロックファイルがちゃんと消えるタイミングは、クイック起動を含めてOpenOffice.orgを終了した時でした。3.1からBaseの終了時にロックファイルが消えるようになりましたが、クイック起動を利用されていると結局はOpenOffice.orgのプロセスが残っているので、影響があるかもしれません。
質問にお答えします。 †
匿名 (2010-03-05 17:48:12 (金))
tani様
ご指摘の通りマクロが終了した時点でread only modeではなくなるという
動きをしているようにみえます。
Mkamataki様
クイック起動は利用していません。
不思議な現象 †
匿名 (2010-03-05 19:06:29 (金))
データーベースを更新したマクロ(データベース更新後に別の処理を)
実行中は
他端末からデータベースにアクセスする時にロックファイルは生成されず、
マクロの実行が終了した後に、 同様に他端末からデータベースにアクセスすると
ロックファイルは生成されるという現象になります。
この現象はデータベースが共有できないことと関係があるのでしょうか。
たとえば、read only mode だからロックファイルは生成しないとか。
ファイル以外のロック要素 †
M.Kamataki (2010-03-05 21:24:18 (金))
マクロが動いているということは、OpenOffice.orgのプロセスが残っているので、クイック起動利用時と同じ現象が起こるのかもしれません。
クイック起動利用時、Baseで標準のHSQLDB形式のデータベースの共有が現状難しいことは、faq/5/7「Baseファイルの運用」で回答しています。なお、faq/5/7で紹介しているOpenOffice.orgの不具合・要望データベースであるIssueTrackerに登録されているIssue #21747の修正予定が3.3となっていますから、いずれ共有が可能になる時期はくると思います。
Issue #21747で指摘されている問題は、ファイルではなくディレクトリ単位でロックが掛かるというものです。faq/4b/1075「ネットワークハードディスク上のファイルが更新できていない」という質問の中で、クイック起動利用時のロックファイルの問題を指摘したIssue #48221が、Issue #21747と重複になっていますので、ファイル以外のロック要素としてディレクトリロックが掛かっているのかもしれません。
なお、クイック起動は利用されていないということなので、データベースを明示的にシャットダウンしてみてはどうでしょう。標準のデータベース形式であるHSQLDBのシャットダウンについては、faq/4/1812「マクロからodbファイル内のテーブルを別のodbファイルにコピーするには?」をご覧ください。ダイアログ表示の前に実行すると、データベースを開放してくれる可能性があります。
faq/4/1231「データベースの共有を行うと2台目以降でテーブルにアクセスできません」の最後にも書きましたが、他のRDBMSを使うのが、悩まなくて済む方法かと思います。Issue #21747については、2.0で修正される予定が、3.0に延び、3.1、3.2と延期されているので、あまり楽観的にはなれません。
データベースのシャットダウンのコードは? †
匿名 (2010-03-06 13:12:41 (土))
Execute_SQL("Z:\data\basefile.odb","SHUTDOWN;")
これでいいんでしょうか?
BASICランタイムエラー
SubまたはFunctionプロシージャ−の未定義。
というエラーが出るんですけど。
お世話をおかけします。
Re: データベースのシャットダウンのコードは? †
M.Kamataki (2010-03-06 20:22:15 (土))
今回のケースでは、Statement = Connection.createStatement()で、データベースに接続しているので、
Sql = "COMMIT;" Statement.execute( Sql ) Sql = "SHUTDOWN;" Statement.execute( Sql )を
Connection.Close()の前、あるいは代わりに発行するとどうなりますか。「Connection.Close()」の時点では「COMMIT;」されると思うので、かわりにコミットとシャットダウンを明示的に実行するイメージです。
ちなみに、シャットダウン時のユーザー関数については、faq/5/74「Querie.Command 後に更新できない!」にプログラム例がありますが、odbファイルをhiddonで呼び出しているので、大げさになっちゃいます。
シャットダウンのタイミング †
M.Kamataki (2010-03-07 07:04:16 (日))
現在のマクロはそのままでダイアログ表示の前に再度データベースに接続するようにして、シャットダウンを発行した方が良いかもしれません。その場合はコミットは不要だと思います。この手順が安心ですね。
シャットダウン処理を入れてみましたが、効いてないようです。 †
匿名 (2010-03-10 13:48:42 (水))
下記のコードで
接続したデータベースを一度切り離して、
再度接続したあとの切り離しのところに
シャットダウン処理を入れてみましたが
効いていないのか?現象は変わらずに
read only modeのエラーが出ます。
'データベースを一度切り離す
Statement.Close()
Connection.Close()
Connection.Dispose()
'再度データベース接続
DatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")'
DataSource = DatabaseContext.getByName("basefile")
Connection = DataSource.GetConnection("","")
Statement = Connection.createStatement()
Statement.ResultSetConcurrency = "1008"
Statement.ResultSetType = "1005"
SQL = "SHUTDOWN;"
Statement.execute( SQL )
Statement.Close()
Connection.Close()
Connection.Dispose()
試行願います †
ike@九州 (2010-03-10 16:40:57 (水))
データベース更新処理の後に以下挿入Connection.Parent.DataBaseDocument.store()
データベース接続時に〜 Connection = DataSource.GetConnection("","") If Connection.IsReadOnly Then Msgbox("ReadOnly") Statement = Connection.createStatement() 〜のように挿入して ReadOnly が表示されるのか試行していただけませんか
表示されなくて read only mode になるのかどうかなど…
試行結果 †
匿名 (2010-03-10 19:23:51 (水))
まず、Connection.Parent.DataBaseDocument.store()を
Statement.Close()の前に挿入しましたが、
1台目の端末からマクロを実行後、ダイアログ表示中に
2台目の端末からマクロを実行すると、
BASICランタイムエラー
例外が発生しました
Type:com.sun.star.sdbc.SQLException
Message:General error:org.hsqldb.lib.FileSystemRuntimeException:java.io.IOException:
というエラーがでますので、Connection.Parent〜この一行の挿入はやめて、
IF Connection .IsReadOnly Then Msgbox("ReadOnly")
を挿入してマクロを実行してみると、
必ずReadOnlyのメッセージが出て、
read only mode のエラーが出ます。
検証ありがとうございます †
ike@九州 (2010-03-11 14:35:49 (木))
やはり、Base(HSQLDB) の仕様だと思います。
1台目のPCからマクロにてアクセスした場合、1台目の OOo を終了しないと
2台目以降のマクロでは必ず Connection は ReadOnly になりますね。
2台目以降の GUI ではテーブル表示は接続エラーにてできません。
2台目以降でも更新を行う運用であれば、更新したら一度 OOo の終了をする運用が必須だと思います。
Kamataki さんの提案通り、他のRDBMS(MySQL等)を使い Base はフロントエンド接続としての運用だと、複数アクセス更新で問題が起きないと思います。
(マクロ使用も同じように可能です)
MySQLにするとしたら †
匿名 (2010-03-11 17:19:36 (木))
MySQLを使うとして、MySQLのサーバーをインストールして
MySQLのドライバーを使うようにすれば、
現状のコードで、現状のデータベースで
なにも変更なしに動くということなのでしょうか?
ちなみに、何をダウンロードすればよいのかわからないので、
インストール手順等がありましたらご教授お願いします。
データベースの選択 †
M.Kamataki (2010-03-12 00:00:24 (金))
おすすめはMySQLかPostgreSQLです。PostgreSQLは、今現在インストールして利用しているので、わたしが当Q&Aで回答する分には疑問があれば対応できます。MySQLも比較的よく使われているDBなので、回答できる方もいるかもしれません。まず、ふたつのDBの日本語のユーザ会ページを紹介しておきます。
日本MySQLユーザ会
http://www.mysql.gr.jp/
日本PostgreSQLユーザ会
http://www.postgresql.jp/
両者とも日本語のドキュメントは豊富にあるので、まずはそれぞれのホームページをご覧ください。逆に豊富にありすぎるので、「MySQL インストール」などをキーワードにGoogleなどで検索すると良いページが見つかるかもしれませんが。
なお、MySQLは文字コードの設定がややこしいので、必ずユーザ会のFAQを見ておいてください。その意味では、PostgreSQLのほうが良いかもしれませんが、OpenOffice.orgでのマクロの例が多いのはMySQLです。
マクロでの接続については、以下をご覧ください。
OpenOffice.org Base Basic
http://ja.wikibooks.org/wiki/OpenOffice.org_Base_Basic
ご覧いただければわかりますが、接続してしまえば、Base標準のHSQLDBと変わりません。
いずれもOpenOffice.orgとの接続は、JDBC、ODBC、ネイティブドライバ(OpenOffice.org専用ドライバ)があります。マクロ例が多いのは、JDBCでしょうか。
MySQLのネイティブドライバは、以下にあります。
http://extensions.services.openoffice.org/ja/project/mysql_connector
PostgreSQLのネイティブドライバは、以下にあります。
http://dba.openoffice.org/drivers/postgresql/
ネイティブドライバはSDBC(OpenOffice.orgオリジナルのDB接続規格)で接続するので、HSQLDBと同じcom.sun.star.sdb.DatabaseContextサービスを使えると思いますが、まだ試していないので確約はできません。(時間があったら試してみたいと。。年度末で。。。)
他のアイデアについて †
ike@九州 (2010-03-13 10:41:01 (土))
更新作業を別プロセスにさせると OK かもしれないと思い、マクロから外部のVBSファイルを実行させてみました。(Calcドキュメントとvbsファイル同一フォルダ)
結果は2台目のPCから更新は可能でした…参考までに
Calc 側のマクロSub Main oShellExecute = CreateUnoService("com.sun.star.system.SystemShellExecute" ) sURL = convertFromURL(ThisComponent.URL) sDir = left(sURL,Instr(sURL,Dir(ThisComponent.URL))-1) sUpdateVbs = sDir & "BaseUpdate.vbs" sSQL = "INSERT INTO *テーブルA* VALUES(100,'hogehoge');" oShellExecute.execute(sUpdateVbs,sSQL,0) 'ダイアログ表示 End sub
BaseUpdate.vbs の内容Set oSM = WScript.CreateObject("com.sun.star.ServiceManager") Set args = Wscript.Arguments For Each s in args sSQL = sSQL & s & " " Next sSQL = Replace(sSQL,"*","""") 'Msgbox(sSQL) Set oDatabaseContext = oSM.CreateInstance("com.sun.star.sdb.DatabaseContext") Set oDataSource = oDatabaseContext.getByName("hogehoge") On Error Resume Next Set oConnection = oDataSource.getConnection("","") If Err.Number <> 0 or oConnection.isReadOnly Then MsgBox("読取専用又は他接続中です。") Err.Clear On Error Goto 0 Set oConnection = Nothing Set oSM = Nothing Set args = Nothing Set oDatabaseContext = Nothing Set oDataSource = Nothing WScript.Quit() End If Set oStatement = oConnection.createStatement() oStatement.executeUpdate(sSQL) If Err.Number <> 0 Then MsgBox("書込みエラーです。以下詳細" & chr(13) & Err.Description) End If Err.Clear On Error Goto 0 oStatement.Close() oConnection.Close() Set oConnection = Nothing Set oStatement = Nothing Set oSM = Nothing Set args = Nothing Set oDatabaseContext = Nothing Set oDataSource = Nothing 'スクリプト終了 WScript.Quit()
注意点
渡した SQL 文が vbs 側では以下になってましたのでテーブル名に空白があるとエラーになります。(正常になる渡し方はわかりません)
"INSERT INTO テーブルA VALUES(100,'hogehoge'); "
#上記注意点 Replace 関数を使用してコード修正しました
calc MySQL間の動作確認方法は? †
匿名 (2010-03-25 14:09:43 (木))
かなり日が経ってしまい申し訳ありません。
MySQLを使うことにしました。
とりあえず、MySQLサーバーをインストールして、
ネイティブドライバーを拡張機能マネージャーで追加したのですが、
それだけでいいのか、まだなにかすることがあるのか
動作確認の方法もわかりません。
コードの修正をする必要はないんですよね。
どなたか、ご教授をお願いいたします。
MySQL用Baseファイルの作成など †
M.Kamataki (2010-03-25 14:59:50 (木))
>とりあえず、MySQLサーバーをインストールして、
MySQLにデータベースは作成しましたか。最低限1つのデータベースがないといけないのですが、「test」データベースの存在を確認するか、適当な名前のデータベースを作成してください。
次にBaseを起動して、ネイティブドライバーでMySQLサーバーを指定し、上記の「test」か作成したデータベースに接続したBaseファイルを作成してください。この時のファイル名がMySQL用のデータソース名になります。CalcでF4キーを押下して、データソースペインにMySQL用のデータソース名が表示され、ツリーをたどってテーブルが見えれば設定はOKだと思います。
なお、わたしが以前書いた記事が以下にありました。文字コードあたりは古くなって参考にならないと思いますが、上記の手順の参考にはなると思います。JDBCをMySQLのネイティブドライバーに読み替えてください。
MySQLデータベースとBaseを接続する(その2)
http://www.itmedia.co.jp/enterprise/articles/0508/29/news002.html
マクロでの接続 †
ike@九州 (2010-03-26 16:34:31 (金))
MySQLのネイティブドライバエクステンションにての接続の場合です'"sdbc:mysql:mysqlc: mysqlをインストールしたPCのIPアドレス : 設定したポート番号 / 作成したデータベース名" sURL = "sdbc:mysql:mysqlc:192.168.1.230:3306/sampledb040" 'mysqlが起動していないと以下はエラーとなります Dim aProps(1) as new com.sun.star.beans.PropertyValue aProps(0).Name = "user" 'データベースにアクセス権限のあるユーザー名 aProps(0).value = "pgtop" aProps(1).Name = "password" 'ユーザーのパスワード aProps(1).value = "12345" DatabaseContext = createUnoService("com.sun.star.sdbc.DriverManager") oConnection = DatabaseContext.getConnectionWithInfo(sURL, aProps()) oStatement = oConnection.createStatement() 〜処理〜 oConnection.close() 〜
データーベースにアクセスするとクラッシュします。 †
匿名 (2010-03-26 19:02:01 (金))
baseにMySQLのデーターベースを登録して接続テストも完了しました。
まったくコードの変更なしに、マクロからデータベースにアクセスするとクラッシュしました。
ike@九州さまご教授のコードを参考にしてコードを修正しましたが、
同様にクラッシュします。
情報が少ないかもしれませんが、何かどこか調べるところがありましたら
ご教授お願いいたします。
ドライバを変えてみては †
M.Kamataki (2010-03-26 23:09:32 (金))
ドライバのせいかどうか確認するために、JDBCやODBCのドライバでも確認してみてはどうでしょうか。わたしが紹介したWikiBooksのサイトにサンプルがありますよね。
まだ、MySQL用のネイティブドライバはリリースされて間がないので、バグが枯れていない可能性があります。
当方では問題無しです †
ike@九州 (2010-03-27 09:08:52 (土))
接続はユーザー名、パスワードを使用しますのでそのままでは接続できません。
>baseにMySQLのデーターベースを登録して接続テストも完了しました。
という事ですので問題を切り分ける為に、登録したデータベース名から sURL を表示&接続テストしてみましょう。
Sub test '登録データベースの場合 oDatabaseContext = CreateUnoService("com.sun.star.sdb.DatabaseContext") oDB = oDatabaseContext.getByName(データベース名) msgbox(oDB.URL()) 'sURLになります If oDB.IsPasswordRequired then'MySQL等のユーザ名、パスワードの入力ダイアログ InteractionHandler = createUnoService("com.sun.star.sdb.InteractionHandler") oConnection = oDB.connectWithCompletion(InteractionHandler) Else oConnection = oDB.getConnection("","") End if If Not IsEmpty(oConnection) then Msgbox("接続に成功しました") oConnection.close() End if End sub
上記で問題なければ
SQL文の問題では無いでしょうか。MySQLの規則に沿っての記述が必要になります
sSQL = "INSERT INTO meibo(住所,氏名,電話番号,郵便番号) VALUES('東京都','田中角栄','03-5555-5555','555-5555');
途中経過、接続テストはOKです。 †
匿名 (2010-03-29 13:19:19 (月))
sURL表示は
”sdbc:mysqlc:localhost:3306/nextfile”
となり
Connectionも確立しているようです。
SQL文を確認します。
無題 †
ike@九州 (2010-03-29 15:39:02 (月))
localhost ではなく固定実 IP アドレスに変更しましょう。
MySQL の インストール PC 以外からは接続不可ですね。
途中経過報告、DELETE文でクラッシュ †
匿名 (2010-03-30 19:14:13 (火))
サーバーにMySQLをインストールしなおし、クライアントから
サーバーの固定実IPアドレスで接続するように変更しました。
テスト接続はOKでinsert文もOKですが、
delete文でクラッシュします。
Dim sURL As String Dim aProps(1) as new com.sun.star.beans.PropertyValue sURL = "sdbc:mysql:mysqlc:172.27.20.205:3306/labeldb" aProps(0).Name = "user" aProps(0).value = "root" aProps(1).Name = "password" aProps(1).value = "password" DatabaseContext = CreateUnoService("com.sun.star.sdbc.DriverManager") Connection = DatabaseContext.getConnectionWithInfo(sURL,aProps()) If Not IsEmpty(Connection)Then MsgBox("接続に成功しました") End If Statement = Connection.createStatement() IF( PnameSheet.getCellByPosition(0,0).String <> ResultSet.getString(2) ) then ResultSet = Statement.executeQuery("delete from hinmeib;") i = 1 Do While PnameSheet.getCellByPosition(0,i-1).String <> "" SQL = "" SQL = "insert into HinmeiB(ID,syukkabi,seihinmei,zumiflg) values('" SQL = SQL & CStr(i) & "','" & PnameSheet.getCellByPosition(0,i-1).String & "','" & PnameSheet.getCellByPosition(1,i-1).String & "','" & _ PnameSheet.getCellByPosition(2,i-1).String & "');" nLines = Statement.executeUpdate( SQL ) i = i + 1 Loop End If Connection.close() End sub
無題 †
tani (2010-03-31 09:27:10 (水))
想像ですが、delete文もexecuteUpdateでは?
(delete文の実行でResultsetが必要とは思えないので。)
あと正確なテーブル名がhinmeibなのかHinmeiBなのかよくわかりませんでした。
経過報告 †
匿名 (2010-03-31 13:55:00 (水))
taniさまのご指摘通り
executeUpdateで動きました。ありがとうございます。
新たな問題です。
添付ファイルのエラーメッセージの意味を
教えて頂きたいです。?の部分
経過報告、単純なコードミスでした。 †
匿名 (2010-03-31 16:41:24 (水))
単純なコードミスでした。
申し訳ありません。
とりあえず、base使用時レベルの機能まで回復しました。
あとは、複数クライアントからの同時アクセスができることの
確認です。
データベースへの同時アクセスができました。 †
匿名 (2010-04-01 17:05:56 (木))
当初の問題をクリアーできましたので、
この件は完了とさせていただきます。
みなさま、ご指導ありがとうございました。
みなさまお疲れ様でした †
M.Kamataki (2010-04-01 17:33:20 (木))
約1ヶ月かかりましたね。完了にしました。では。