SQL Server上でのSQLトレースの注意点
SQL Server Profilerを利用しないSQLトレース
SQL ServerのSQLトレースでは、通常 付属のSQL Server Profilerが利用できるが、これをそのまま運用環境で利用するとSQL Server Profiler自体がボトルネックになり、SQL Serverの負荷が上がる。 以下の記事のように、スクリプトからSQLトレースを実行することで、SQL Server Profilerにキャプチャーしたイベントを流し込んで表示する負荷が下がり、SQLトレースの負荷だけになり、だいぶ処理が軽くなる。
「DO’s&DONT’s #1: やらない方がいいこと – 運用環境で、Profiler GUI を使用してトレースする」 https://blogs.msdn.microsoft.com/jpsql/2011/01/25/dosdonts-1-profiler-gui-1237/
「SQL トレーススクリプトの作成、実行 (SQL Server 2005 ~ 2014)」 https://blogs.msdn.microsoft.com/jpsql/2011/01/25/sql-sql-server-2005-2014/
注意
トレースファイルの作成時に以下のエラーが出る場合がある。Windowsのファイル作成権限が足りないらしい。権限をつけるか、SQL Server配下のディレクトリを指定するなどして解消できる。
SP_TRACE_CREATE の実行中に Windows エラーが発生しました。エラー = 0x80070005(アクセスが拒否されました。)。 メッセージ 19062、レベル 16、状態 1、プロシージャ sp_trace_create、行 1 トレース ファイルを作成できませんでした。 (1 行処理されました)
「Sql Server : Error : Could not create a trace file (SP_TRACE_CREATE)」 https://sqltimes.wordpress.com/2014/11/08/sql-server-error-could-not-create-a-trace-file-sp_trace_create/
割り込みによる待機中・処理中スレッドの復帰方法
待機中の復帰方法
Thread.sleep()を利用して待機状態になっているスレッドを停止させるには、Thread.interrupt()を実行する。 Thread.interrupt()を実行すると、InterruptedExceptionが発生するので、InterruptedExceptionをキャッチしてタイムアウトに対するエラーハンドリング処理を行う。
処理中スレッドの復帰方法
待機中のスレッドでない場合はThread.interrupt()を実行しても即時にInterruptedExceptionが発生する訳ではない。 Thread.isInterrupted()によって割り込みがあるかを判断する処理を記述する必要がある。
Thread.isInterrupted()によって割り込みがあった場合は、タイムアウトに対するエラーハンドリング処理を行う。
参考
Entity Framework Npgsqlのメモ
<connectionStrings> <add name="dbContext" connectionString="Server=127.0.0.1;Port=5432;Database=postgres;UserId=postgres;Password=postgres;Timeout=60;" providerName="Npgsql" /> </connectionStrings> <system.data> <DbProviderFactories> <remove invariant="Npgsql" /> <add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql" type="Npgsql.NpgsqlFactory, Npgsql" /> </DbProviderFactories> </system.data> <entityFramework> <providers> <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" /> </providers> </entityFramework>
【C#】PostgreSQLでEntityFrameworkの使用方法#2 | ぷろちゃん
Javaの正規表現
正規表現の復習メモ
メタ文字「.」
なんでもよい1文字を表す。通常は、改行を含めることができない。
改行を含めるには、Pattern.DOTALL オプションを利用する。 https://docs.oracle.com/javase/jp/7/api/java/util/regex/Pattern.html#DOTALL
(例)コード
String str = "before"; str += System.lineSeparator(); str += "after"; String regex = "(before).*(after)"; Pattern p=Pattern.compile(regex,Pattern.DOTALL); Matcher m = p.matcher(str); if(m.find()){ System.out.println(m.group()); }
(例)出力結果
before after
メタ文字「*」「+」「?」
直前の繰り返しを表す文字。 「*」は、直前の文字が1個もないか、1個以上連続することを示す。 「+」は、直前の文字が1個以上連続することを示す。 「?」は、直前の文字が1個だけあることを示す。
(例)コード
String str = "abbbb"; String regex = "ab+"; Pattern p=Pattern.compile(regex); Matcher m = p.matcher(str); if(m.find()){ System.out.println(m.group()); }
(例)出力結果
abbbb
メタ文字「^」
行の先頭にある文字列の検索に利用する。
- 単一行
(例)コード
String str = "first_line_second"; String regex = "^(first).+"; Pattern p=Pattern.compile(regex); Matcher m = p.matcher(str); if(m.find()){ System.out.println(m.group()); }
(例)出力結果
first_line_second
(例)コード
String str = "first_line"; str += System.lineSeparator(); str += "second_line"; String regex = "^(first).+"; Pattern p=Pattern.compile(regex, Pattern.MULTILINE); Matcher m = p.matcher(str); if(m.find()){ System.out.println(m.group()); }
(例)出力結果
first_line
メタ文字「$」
行の最後にある文字列の検索を利用する。
- 単一行
(例)コード
String str = "first_line_second"; String regex = ".+(second)$"; Pattern p=Pattern.compile(regex); Matcher m = p.matcher(str); if(m.find()){ System.out.println(m.group()); }
(例)出力結果
first_line_second
(例)コード
String str = "line_first"; str += System.lineSeparator(); str += "line_second"; String regex = ".+(first)$"; Pattern p=Pattern.compile(regex, Pattern.MULTILINE); Matcher m = p.matcher(str); if(m.find()){ System.out.println(m.group()); }
(例)出力結果
line_first
メタ文字「()」
グループ化の機能。()で囲んだ文字列をグループ化して扱うことができる。
String str = "before_content_after"; String regex = ".(content)."; Pattern p=Pattern.compile(regex); Matcher m = p.matcher(str); if(m.find()){ System.out.println(m.group()); }
(例)出力結果
_content_
メタ文字「[]」
指定された文字のどれらかを表す機能。
エスケープ
\を前につける。「^」
ただし、Javaのコードとして記述する際には、「\」自体をエスケープする必要があり、以下のようになる。
(例)コード
String regex = "\\^";
- 【参考】サルにもわかる正規表現入門
http://www.mnet.ne.jp/~nakama/
文字列の取得
- メタ文字「()」のグループに合致する範囲をMatcher.group()にて取得することができる。
- グループが複数存在する場合は、Matcher.group(int)にて取得することができる。
- 引数のインデックスは、1から始まる。インデックスは、「()」の出現順に振られる。
https://docs.oracle.com/javase/jp/7/api/java/util/regex/Matcher.html#group(int)
(例)コード
String str = "before_test1_content_test2_after"; String regex = "((before).+(content).+(after))"; Pattern p=Pattern.compile(regex); Matcher m = p.matcher(str); if(m.find()){ for(int i=1; i<=m.groupCount(); i++){ System.out.println(m.group(i)); } }
(例)出力結果
before_test1_content_test2_after before content after
- 【参考】パターン内の括弧毎にマッチした部分文字列を取得
L4スイッチとL7スイッチ
ロードバランサ(L4スイッチ)
リバースプロキシ(L7スイッチ)
L7スイッチは、アプリケーション層の中身まで解析して分散先を決定する。
L7スイッチは転送するだけでなく仲介する立場として動作し、TCPコネクションはクライアント・L7スイッチ間とL7スイッチ・転送先サーバ間の2つで張られる。
HTTPリクエストに応じた制御
リバースプロキシは、クライアントからの要求と転送先サーバを仲介するので、その間に様々な前後処理を挟むことができる。 (ex)URLの書き換え。
アプリケーションサーバのメモリ使用効率の向上
URLの書き換えによって、静的コンテンツを返却するWebサーバと動的コンテンツを返却するアプリケーションサーバを分ける。 そうすることで、アプリケーションサーバのメモリ消費量を抑えることができる。
HTTPのKeep-Alive
クライアント - リバースプロキシ間のKeep-Alive
TCPコネクションを新規に作成するには負荷がかかるため、一度作成したら接続を一定時間維持するKeep-Aliveの仕組みが提供されている。
リバースプロキシをアプリケーションサーバの前に配置する場合には、クライアントとリバースプロキシ間でKeep-Aliveが有効となる。
リバースプロキシ - アプリケーションサーバ間のKeep-Alive
「[24時間365日] サーバ/インフラを支える技術」本によると、リバースプロキシ - アプリケーションサーバではKeep-Aliveはオフにするのを薦めている。アプリケーションサーバの前提がマルチプロセス型だから、プロセスを長時間保持してしまうコストの方がTCPコネクションを新規に張るコストより大きいという前提なのかもしれない。
Javaの場合は、マルチスレッドのアプリケーションサーバなので、スレッドを専有するのはそれほど高コストではない。 リバースプロキシ - アプリケーションサーバ間のKeep-Aliveの仕組みが用意されているものもある。
Apache - Tomcat間では、mod_jkというApacheのモジュールが提供されており、こちらではこの2者間のKeep-Aliveをサポートしている。ただ、mod_jkではなく単にmod_proxyでも同じことはできる。
参考
[24時間365日] サーバ/インフラを支える技術 ?スケーラビリティ、ハイパフォーマンス、省力運用 (WEB+DB PRESS plusシリーズ)
- 作者: 安井真伸,横川和哉,ひろせまさあき,伊藤直也,田中慎司,勝見祐己
- 出版社/メーカー: 技術評論社
- 発売日: 2008/08/07
- メディア: 単行本(ソフトカバー)
- 購入: 133人 クリック: 2,270回
- この商品を含むブログ (289件) を見る
トランザクション分離レベル
トランザクションの同時実行制御と分離性
トランザクションの同時実行制御と分離性は、データベースによって異なる。
Oracle : 一時領域を使用した「多バージョン法」
読み取るデータが更新中であっても検索処理が待たされることはない。
SQL Server : 「ロック法」
ロック法による同時実行制御のため、検索時に共有ロックをかける。 読み取るデータが更新中の場合は、すでにそのデータに排他ロックがかかっているため、共有ロックをかけることができない。
更新中のデータに読み手はアクセスできず、検索処理が待たされる。
Oracle
- トランザクション分離レベルのうち、Read Committed・Serializableをサポートしている。
SQL Server
トランザクション分離レベルのうち、Uncommitted Read・Read Committed・Repeatable Read・Serializableをサポートしている。
デフォルトはOracleと同じくRead Committedであるが、実際はREAD_COMMITTED_SNAPSHOT データベースオプションの設定によって動作が異なる。
READ_COMMITTED_SNAPSHOT データベースオプションがOFFの場合は、更新トランザクション中のSELECTはロック待ちとなる。
READ_COMMITTED_SNAPSHOT データベースオプションがONの場合は、通常のRead Committedの動作(多バージョン法)となる。
【参考】
Uncommitted Read
Dirty read・Fuzzy read・Phantom readが発生する。
Read Committed
Fuzzy read・Phantom readが発生する。
Repeatable Read
Phantom readが発生する。
Serializable
トランザクションの同時実行における3つの問題がどれも発生しない。 パフォーマンスを犠牲にして、ロックを行う方式。
【参考】トランザクションの同時実行における3つの問題
Dirty read
まだコミットされていない更新データをSELECT時に取得できてしまう。
Fuzzy read
あるトランザクションの中で別トランザクションによる更新のコミットがあった場合に、 別トランザクションによるコミットの前後でSELECTした場合、異なるデータが取得できてしまう。
Phantom read
あるトランザクションの中で別トランザクションによる更新のコミットがあった場合に、 別のトランザクションがその問い合わせ条件を満たす行を追加した場合、 別トランザクションによるコミットの前後でSELECTする、取得するレコード数も異なる。
参考
「DBMSのロック・分離戦略と同時実行制御」
http://techinfoofmicrosofttech.osscons.jp/index.php?DBMSのロック・分離戦略と同時実行制御#pc81bc15
DBの「トランザクション分離レベル」が必要な理由 (PostgreSQLで,ファントム・リードを防止すべきサンプル事例)
http://language-and-engineering.hatenablog.jp/entry/20110104/p1