SQL Anywhereは付属するdbtranコマンドでログファイルからSQLを抽出することが出来ます。例えば
insert into tablea values (1,'aaaaa');
commit;
と実行し、その後”コマンドラインから”(Interactive SQLなどではなくOSのコマンドラインです)
と実行します。
dbのログファイル名.sqlというファイルが出力されますので中を見てみます。
--BEGIN TRANSACTION-1016-0000698840
BEGIN TRANSACTION
go
--INSERT-1016-0000698913
INSERT INTO DBA.tablea(col1,col2)
VALUES (1,'aaaaa')
go
--COMMIT-1016-0000698931-2023-10-31 14:59:14.009561
COMMIT WORK
go
このように出力されていることが確認できます。Ver.17ではコミット時の時刻も記載されています。
dbtranコマンドの実行にはデータベースへの接続は必要ありません。ログファイルだけあれば良いです。
このコマンドはログファイルに記載されている内容をSQLとして出力するものです。つまり、出力される内容はログに記述されるものになります。
SELECT文はログに記述されませんので当然含まれません。データベースに変更を行う文はログに記述されますが、LOAD文はLOADが行われたことが記述されても実際にロードされたデータはログには記述されないことに注意して下さい。
このコマンドは何に使うのかというと、アプリケーションのデバッグ用途(INSERTなどのコマンドを実行しているかの確認)やログされた内容を利用してデータベースの手動リカバリなどに使用することが出来ます。
想像したくは無いシチュエーションですが、日にログのリネームを数度行っている環境でディスクが破損し、リネームしたログも一部消失してしまった場合は通常のリカバリ方法ではデータベースファイルのバックアップからその消失してしまったログの前のログまでしかリカバリできません。しかしながらdbtranを使用すれば消失してしまった先のログからも実行されたコマンドを取得する事ができます。整合性の問題がありますが、消失してしまった範囲を狭めることが出来るかもしれません。
さて、デバッグ的な用途でこのdbtranコマンドの出力を使用する場合、注意点があります。
先の例では私はこのようなINSERT文を記述しました。
insert into tablea values (1,'aaaaa');
しかし、実際にdbtranコマンドで出力されたコマンドは以下です。
INSERT INTO DBA.tablea(col1,col2)
VALUES (1,'aaaaa')
意味は同じですが、形が異なります。このようにdbtranコマンドの出力はアプリケーションから実行されたコマンドがそのまま出力されるわけではありません。これは実際にSQL Anywhere上で実行する場合はオプティマイザで整形されたものが使用されます。それがログに記述されます。そのため出力されたファイルの中身を検索する際には注意が必要です。同様の理由でSQL中に/* */などで記述したコメントも出力されません。
特別値などは置換されて記録されます。例えば
insert into tablec values(1,current timestamp)
を実行した場合、ログには
INSERT INTO DBA.tablec(col1,col2)
VALUES (1,'2023-10-31 15:00:52.023127')
と実際に実行した時刻が記述されたSQLとして出力されます。
また、そもそもアプリ上でデータを変更するコマンドを実行してもログに記載されないというパターンも存在します。
例えば
insert into tablea select * from tableb where col1=100;
という文を実行した場合、select * from tableb where col1=100 が1件も該当しなかった場合は挿入するものが存在しないということになりますので、INSERT文自体が実行されず、ログに何も記載されないことになります。また、該当するものがあった場合でも
INSERT INTO DBA.tablea(col1,col2)
VALUES (1,'aaaaa')
のように通常のINSERT文として、該当件数分記載される形で出力されます。そのためログからはINSERT INTO … SELECT文であることは判別が出来ません。
dbtranの出力を利用して分析を行う場合はアプリケーション側の動作を理解しておく必要があります。また、ログの内容を検索する場合も上記のとおり注意が必要です。
ログの出力が多すぎて検索しづらい場合は下記のようなテーブルを作成し
create table forsearch(
"comment"varchar (250),
"time"timestamp
)
アプリケーション側でログから確認したい処理の前後に
INSERT INTO forsearch VALUES("PROCESS START",CURRENT TIMESTAMP);
<確認したい処理>
INSERT INTO forsearch VALUES("PROCESS END",CURRENT TIMESTAMP);
という風にINSERT文を挿入することで「PROCESS START」文字列が出力に含まれます。そこから「PROCESS END」までということになりますので検索が容易になります。
ログを読める形にしてくれるdbtranの機能は開発やディスク破損時の最終手段として役に立つことがあります。あまり積極的に使うものではないですが、覚えておいて損はない機能です。