【MySQL】DBをOracleからMySQLへ移行する件について ~その2~
Java製アプリケーションを
別の環境でトレースするときに
オリジナルはDBがOracleだったけど
MySQLに無理やり変更してみたときの話
Auto Commitの設定
MySQLではAuto Commitがデフォルト
一方、OracleではCommitありがデフォルト
なのでOracleを前提にしたプログラムでは
TransactionやらRollbackがどうこうという
エラーがでる可能性が高い
なのでAutoCommitをOFFにする
SET autocommit=0;
検証や研究用の環境ならむしろ
AutoCommit便利だけど、本番の環境では
やっぱりCommitありのほうが安心だと思う
カラムのデフォルト制約のこと
データをインサートするとき
デフォルト値が設定してあると
CREATE TABLE AAA ( BBB int , CCC int default 0 );
例えば↑のようにテーブルを作成した場合、
insert into AAA values(1);
とインサートすると
BBBカラムに1、CCCカラムには
デフォルト値の0が入る(はず)
こともあろうにJavaのプログラムのなかで
こんな記載がされていたわけで、、
Workbenchとかで手動でSQLを書いて
データを入れ込むのであれば
CCCカラムには何も指定されてないよ!
と警告がでるだけで処理自体はされる
で、JavaでDBを使うとなると
ドライバーを使用することになるはず
現行のはOracleのJDBCドライバーを
使用していてこちらは上記のSQLに対応して
問題なく使えていた
同様にMySQLのJDBCドライバーを使った場合
警告がでるだけでなくException Error
つまりエラーでプログラムが中断する…
これはMySQLのドライバーのプログラムを
書いた人がそういう仕様にしたらしく
どうしようもない様子
(英文サイトを読むと多分そんな意味あい)
確かに処理としては正しいのだろうけど、、
まぁ、無償のDBを便利に使えるドライバーを
善意で提供してくれているのだから文句など
言えるはずもなく
と、いうわけで、
根本的な解決方法は
Javaのプログラムを修正するしかない
ROWIDについて
OracleにはROWIDという隠し列があり
SELECTで呼び出すことができる
中身はというとランダムにふられた
18桁の英数字で行を特定できる
早い話がキー項目
なのでMySQLでこれを実現するには
キー項目の列を作ってやればいいことになるが
問題はSQL文がプログラムに
組み込まれている場合
ROWIDを絞り込み条件にした
SELECT文なんかがあったりしたら
独自に設定したキー項目に書き換えないといけない
ちなみにOracleのROWIDは
行を削除してバックアップから戻す場合など
変わることがあるので
あまり使わないほうがいいみたい
まだ他にもいくつかあるので
また次回に
【MySQL】DBをOracleからMySQLへ移行する件について ~その1~
OracleとMySQLはDBの仲間
Oracleは有料、MySQLは無料
という知識だけ持っている人が
「Oracleは高いからMySQLにしようぜ」
とか言い出したため、
「そんなに簡単にいくわけないだろ!」
と思ったけど、
実際にやってみたらやっぱり
一筋縄ではいかなかった話
TimeZone(タイムゾーン)の設定
まず、TimeZoneの設定値が不正です
というエラーがでた
???? (?W????)
なんとなくJISをUTFで表示してしまったときの
文字化けに見えるので
とりあえずデータベースやテーブルなど
文字コードをUTF-8にセット
しかし解消されず
実はMySQLをWindowsで使う場合に、
OSにタイムゾーンが存在しないから
起こるエラーらしく
Oracle⇒MySQL移行とは関係ないんだけど
ためになったので記載しておく次第
MySQLの設定ファイル、my.iniの
[mysqld]項目に
default-time-zone='Asia/Tokyo'
を追記
このmy.iniの場所が曲者で
MySQLをインストールした場所
(C:\Program Files\Mysql\あたり)
の下にあったファイルにだまされたのだけど
正しくは「C:\ProgramData\MySQL\あたり」
にあるmy.iniファイルを編集する必要がある
データ型のちがい
このへんは真っ先に直面する課題
OracleのDBからDDLを出力して
MySQLでSQLを流すと
データ型がちがうものがエラーになる
今回、ほとんどは
Varchar2 ⇒ Varchar Number ⇒ int
でなんとかなったけど
ほぼほぼ同一のものはない様子
関数のちがい
このへんもスタンダードな課題
よく見かけるのが
NVL ( a , b ) で a が null なら b に置き換え
MySQLでは
Case文で対応しなければいけない
のかと思っていたけど
IfNull( a , b )
で代用できる
しかしNVL2は
Case文で対応するしかないのか…
VIEWで使われているだけだったので
ソースの書き換えだけで完了
MySQLにはシーケンス機能がない
こともあろうにJavaプログラムのなかに
セッションのカウントとして組み込まれていた
たしかにネットでサンプルを見てても
セッションIDを振るのに使われていることが
多いので自然な成り行きかもしれない
シーケンスの機能自体はファンクションで代用
DELIMITER $ CREATE FUNCTION session() RETURNS int(8) DETERMINISTIC BEGIN DECLARE value int(8); SET value = 0; SELECT id INTO value FROM session_id; UPDATE session_id SET id = (CASE WHEN value = 99999999 THEN 1 ELSE value + 1 END); RETURN value + 1; END
ただ、シーケンスの呼び出しではなく
あくまでファンクションの呼び出しなので
SQLの構文が変わる
Oracleでは空のテーブルを読み込むのに
from Dualを使うけどMySQLでは
そんな仕様はないので
SELECT SESSION_ID.SESSION FROM DUAL; ↓ select session();
と変更
実は前述の2つについては
OracleからMySQLの移行を
自動でしてくれるツールがあるらしく
おそらくそれで対応可能
便利なものがあるもんだ
しかしこのシーケンスの機能や
SQLとしてプログラムに入り込んでいる
ものはさすがに移行できないのだろう
と思う
JavaのClassファイルを逆コンパイルして
javaファイルを作りなおしたのち
Classファイルに再コンパイルして、と
その辺の話はまた別の機会に記載
長くなったので今回はここまで
続きはまた次回に
【Webサーバー】レンタルサーバーでphpをバージョンアップしたら文字化けした
相変わらず脆弱性の対応に追われている
ところどころでセキュリティの観点で
ものを見れるようになったことや
そもそも覚えることが多いので
役に立っているのはいいが
そのうち君セキュリティ担当な!
とか言われたらイヤだなぁ…
Webサーバーに文字化け発生
サーバーで使っているphpのバージョンが
古すぎる (5シリーズ) ということで
セキュリティにひっかかり、
バージョンを7シリーズまであげる
羽目になった
たしかに今になるとバージョン低いことが
リスクだと感じるようになったので
バージョンをあげるにこしたことはない
しかし、このバージョンアップにより
サーバー上の一部のhtmlに文字化けが発生
php5.5までならデフォルト文字コードの
設定は"デフォルト値"が"なし"でもよく
要するにどんな文字コードでも受け入れて
くれる設定だったということらしい
ところがphp5.6より新しいバージョンでは
デフォルト文字コードが"なし"は
許されず何かしら設定しないといけない
これもセキュリティの一環らしい
デフォルトでは"UTF-8"が設定されている
.htaccessまたはhost.conf?あたりに
以下の記述がされていると
(Apacheの場合)
拡張子が.phpのものと.htmlのものは
phpの設定が適用される
つまりUTF-8が適用される
AddHandler application/x-httpd-php .php .html
文字化けへの対策
文字化けしているhtmlのコードを見てみる
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP"> <title></title> </head>
思った通り、
meta情報がEUC-JPになっている
これをUTF-8に変えれば
楽勝だろうと思いきや
変わらない…
サクラエディタあたりの
エディタソフトで開くと
htmlファイルの文字コード自体が
EUC-JPで保存されていることが
確認できる
なのでこれをUTF-8に変更して
上書き保存してやると
文字化けがなおった!
ちなみにmeta情報は変更しても
しなくても変わらず
phpinfoのdefault_charsetと
htmlファイル自体の文字コードが
一致することのほうが優先されるの
だと思う
php.iniにて
default_charset = "UTF-8"
の記述があるのでこれを
default_charset = "EUC-JP"
に変えてやれば
もちろん文字コードは
変更される
けど、
php5.5以下の環境で
文字コードが混在したphpファイルや
htmlファイルが存在していた場合は
どちらかに統一するしかない
ちなみに前述のとおり
デフォルトが"なし"は許されないので
;default_charset = "UTF-8"
デフォルト文字コードを指定しなかった
場合はUTF-8が設定される
php やら DB をさわっていると文字コード
ってなにかとネックになる気がする
英語圏ならこんな悩みはないのか。。
と、ちょっとだけ欧米人がうらやましい
【Windows】ファイヤーウォールのポートを閉じてリモートデスクトップで接続できない
いろいろあって、
FTPSの通信に使われているポートの
検証のためにWindowsサーバーの
ファイヤーウォールのポート
1024から65536までを閉じる設定をして
ファイヤーウォールを有効にする
ボタンを押した瞬間、
「ブツッ」
リモートデスクトップが切断される…
リモートデスクトップで使用されている
3389ポートを閉じてしまったのだから
当然だが、途方もないやっちまった感と
素人丸出し感に多少の自虐を覚える
きっと誰もが通る道だ
と言い聞かせながら解決策をさぐる
その1 net use と sc コマンド
コマンドプロンプトからサービスの
制御ができる net コマンドと
sc コマンドがあるらしい
どうやらnetコマンドは自身のみ
scコマンドはネットワークのPCの
サービスを制御できるっぽい
でもネットワーク上のPCに
ログインするためには
net use コマンドを使う
このへんはよく理解してない
まずネットワーク上のPCにadmin権限でログイン net use \\192.168.0.10 /user:[ユーザー名] [パスワード] PCを指定してサービスをストップ sc \\192.168.0.10 stop mpssvc (mpssvcはファイヤーウォールのサービス名) ログアウトする net use \\192.168.0.10 /delete
意外と簡単にリカバリできたじゃん
と思いきや
通信ができなくなる
pingも通らない
電源はON
つまりハングってる状態
AWSのようなクラウド環境だったので
コンソールからの再起動で
最悪の状態からは復帰できたが
しかし、原因は不明
たまたまだったのか
サービスを起動するときの
アカウントが
LocalServiceになっていることが
関係しているのだろうか…
その2 Telnet
なんとなく古風な通信方式のイメージ
しかしポートはLinuxのSSHでおなじみの
22ポート、ということはわりと
何でもできるのでは?と期待大
telnet 192.168.0.10
が、事前にサーバーにTelnetをインストール
しておく必要があるらしく
NG
その3 PowerShell (WinRM)
名前はよく聞くけど実は理解していない
「今どきはbatchじゃなくてpowershell
だよな!」なんて話を聞いた
batchよりもっと複雑な処理ができる、
みたいなイメージなんだけど
合ってるだろうか
こんなかんじでリモートでbatchを起動できるようだ
PS> Invoke-Command -ComputerName 192.168.0.10 -Credential [user] {C:\test.bat}
が、これも事前にファイヤーウォールの
Windows リモート管理 (HTTP 受信)
を有効にしておく必要があるらしい
しかもポートは5985…
どちらにしてもNG
その4 WMI
わりと簡単な手順とコマンドで
いろんなことができそうなサービス
以前に別のところで使ったことがあるので
いけるのではないかと思ったが
WMIC /NODE:192.168.0.10 /user:[user] /password:[pass] process call create "C:\test.bat"
これも事前にファイヤーウォールの
Windows Management Instrumentation (WMI)
グループを有効化しておく必要がある
やむなくNG
その4 PsExec
Windows純正のソフトをクライアントに
入れて実行するといろいろできるらしい
が、使用するのは
135ポート
445ポート
1025~65535ポート
ということでNG
使用する場合には
PsExec.exe -u [user] -p [pass] \\192.168.0.10 C:\test.bat
のようにするみたい
その5 タスクスケジューラ
atコマンド
at \\192.168.0.10 09:00 C:\test.bat
のようなかんじで
タスクスケジューラを外部から
操作できるらしい
しかし事前にファイヤーウォールの
ファイルとプリンターの共有
グループを有効化しておく必要がある
ファイルの共有自体はできていたので
グループのなかの必要な項目が
有効になっていなかったのだと思われる
atコマンドより高機能なschtasksコマンドが
あるらしい
schtasks /Create /S 192.168.0.10 /U [user] /P [pass] /TN sample /SC ONCE /SD 1900/01/01 /ST 00:00 /TR C:\test.bat schtasks /Run /S 192.168.0.10 /U [user] /P [pass] /TN sample
のように使う
こちらもファイヤーウォールの
スケジュールされたリモート タスク管理
グループを有効化しておく必要があり
やっぱりNG
しかしまだタスクスケジューラを
あきらめない、あきらめたら試合終了だ
幸いにもファイル共有はいきているので
net use \\192.168.0.10 /user:[ユーザー名] [パスワード]
でログインしたあと
エクスプローラーのアドレスバーに
\\192.168.0.10\C$
と打ち込むとサーバーの
ディレクトリが表示されて
読み込みも書き込みもできる
タスクスケジューラのタスクは
下記のフォルダにxml形式で
保存されているので
開いて中身を確認できる
C:\Windows\System32\Tasks
たまたま毎日定時に実行している
どうでもいいbatchがあった
(ちなみにここのファイルを直接編集しても
反映されずエラーになるので都合のいい
タスクがないとお手上げ)
batchファイルの最初の行に
netsh advfirewall set allprofiles state off
を追加してbatchが起動したら
ファイヤーウォールをすべて
無効化するように仕込む
これでスケジューラが起動したら
ファイヤーウォールが無効化されて
復旧完了、と翌朝ウキウキして
確認すると
batchがうごいていない…
こればっかりは謎のまま
それはともかくとして
万策が尽きてくる
その6 リモートでレジストリを変更
レジストリエディタを開き、
ファイル⇒ネットワークレジストリへの接続 "選択するオブジェクト名を選択してください"に \\192.168.0.10を入力⇒OK
これでサーバーのレジストリを開ける
これもおそらくファイヤーウォールで
リモートレジストリを受け付けるか
どうかの設定があるのだろうけど
意外にも有効になっていたらしい
\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\SharedAccess\Parameters\FirewallPolicy\PublicProfile \HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\SharedAccess\Parameters\FirewallPolicy\DomainProfile \HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile
がそれぞれファイヤーウォールの
・パブリックプロファイル
・ドメインプロファイル
・プライベートプロファイル
に相当すると思われる
それぞれの
EnableFirewallのデータ値を(0)に設定
することでファイヤーウォールが
無効になる
ただし設定値を有効にするには
再起動が必要
実はいろいろあって再起動しておらず
というのは結局クラウドのコンソールから
復旧できたりしたので顛末は不明のまま
しかし、不測の事態に備えて
リモートデスクトップ以外でも
ある程度操作できるようにしておいた
ほうがいいのではと思う反面、
セキュリティホールにもなり得るので
ある意味ジレンマなのだと思う
(今回の件もどうにかして侵入して
ファイヤーウォールを無効化とか
ハッキングにも通ずる気がするし)
ともあれ
トラブルの対策がいちばん技術の
上達に役立つという話
【iOS】iPad・iPhoneでFacetimeがつながらないというか、つながるけど20秒で切れるときの対応
iPadでFacetimeをつなごうとしたとき
途中で切れてしまうときの対応
事象: Facetimeをかけるといったんつながるが、19秒経つと突然強制的に通話が切断される
そもそもつながらないとかいう事象は
ググるとけっこうでてくるけど
上記の対応は見つけられなかった
原因究明までの道のり
我が家で以前使っていたおさがりのiPad2を
義母に預け使用している
↓
義母からFacetimeで通話ができないと
相談を受ける
↓
内容はいったんつながるけどすぐ切れる
通話相手は我が家ともうひとり
↓
ここであやしいと思われるのは
iPad本体か回線
↓
我が家にiPadを持ってきてもらい検証
↓
同一LAN内でiPad2から我が家のiPad Air2に
Facetimeしてみる
↓
結果はいったんつながるものの
19秒経過すると切断される
↓
ここでハードの問題と特定し
古い筐体であることから
Facetimeの再インストール
iOSをギリギリまでアップデート
iPadの再起動など
考えらえることをすべて試す
↓
が、状況変わらず
↓
そのままお帰りいただくが
後日、義母宅からもう一方とは
Facetimeできたとの連絡
↓
しかし、我が家との通信は
相変わらず途中で切断
↓
ここで我が家の回線を疑う
↓
↓
結果、同じように途中で切断される
↓
この時点では回線状況と特定
いつ買ったかもあまり覚えていない
古い安物のルーター
こいつに疑いの目を向ける
↓
今回iPadということで
有線と無線の切り分けはできない
ルーターの設定画面から設定項目を
見てみるも関係ありそうなものは
見当たらない
↓
しばらく悩んだ末、
そもそも回線が原因ではないのでは?
と頭を切り替える
↓
我が家のはまだまだ新しい機種という
先入観と(実際はそんなに新しくもないが)
これまでの経緯により除外していたが
↓
Facetimeの再インストールと
iPadの再起動を実施
おそらく効果があったのは再起動のほう
↓
なんなくつながるようになる…
教訓
障害が起こった際の切り分けは有効だけど
そこで除外したからと言って
すべて可能性なしとするのではなく
結果が行き詰った際には頭を切り替えて
もう一度疑ってみることが大切
不具合が起こっている原因として
あり得るものはすべて試してみること
というか後から考えると原因が我が家の
iPad本体にあったことに気づくチャンスは
けっこうあったことに気づく
もうひとつ
パソコンとちがいスマホやタブレットって
意外と再起動していないことに気づく
昔からトラブルの7割は再起動で治ると
言われている(?)ようにまずはこれ
トラブルじゃなくても
キャッシュのクリアや更新などなど
感覚的にたまには再起動してあげたほうが
何かといい結果を生むんじゃないかという
気がする
余談:
なんで19秒で切れるのかは結局不明だけど
よくあるアプリの設定画面で通話をかけた
際のタイムアウト設定等々を探すも
そもそも設定画面らしい画面が見当たらない
iOSのコンセプトとして
シンプルに誰でも直感的に使えるように
という配慮なのだと思うが
いろいろ設定をいじってみたくなる
衝動にかられるタイプの人間には
物足りなく感じてしまう今日この頃
【Webサーバー(IIS)】CookieにSecure属性を設定する
CookieにSecure属性がついていないという
脆弱性の指摘を受けたのでその対策
今回の環境はWebサーバーがIISで
APサーバーがtomcatという構成
tomcat側でもSecure属性の設定は
できるんだけど、サイトの構成上
httpとhttpsが混在している場合、
Cookieの情報を見にいったりしてると
うまく動かないことがあるので
アプリケーションの外側で動いていて
やりとりをオーバーラップしているような
Webサーバー側で設定してあげるのが
正解らしい
というわけで今回はIISへ設定
IISでの設定方法
設定するにはURL書き換えから設定するか
web.configの記載を修正する
GUIが売りのIISの場合、
たいがいのことはアイコンから
設定でき、その操作が
自動的にweb.configに記述されるので
ほとんどの操作はいちいちweb.configを
書き換える必要はないが敢えて
web.configと一言で言っても
IIS全体のマスター?configと
その下位に位置するサイトごとの
web.configが存在し、
通常はサイトごとのほうを編集する
サイト名を右クリックしてフォルダを開く
web.configが見当たらない場合は
なんでもいいので設定をすれば
自動的にweb.configが作成されるらしい
web.configを開いたら
以下の通り設定を記載する
<configuration> <system.webServer> <rewrite> <outboundRules> <rule name="cookie secure"> <match serverVariable="RESPONSE_SET_COOKIE" pattern=".*" ignoreCase="false" /> <action type="Rewrite" value="{R:0}; secure" /> </rule> </outboundRules> </configuration>
writeはURL書き換え
outboundRulesは出る側の通信のルール
"リクエストのあったすべてのファイルに
対するCookieの末尾にsecureをつけなさい"
という記述
前回の記事でも書いたとおり
セキュリティ上の脆弱性ということで
たびたび指摘される件だけど
これを設定することで完璧!というよりも
やらないよりやったほうがいいよね
くらいのもの
しかしながらセキュリティは高すぎるから
困るということはないものなので
設定しておくにこしたことはない
【セキュリティ】CookieのSecure属性について詳しく調べてみる
CookieにSecure属性がついてないという
ありがたーい脆弱性の指摘を受けた
Secur属性とは何かと言うと、
https通信じゃないとCookieを発行しない
というものらしい
暗号化されていないhttp通信で
Cookieでよく使われるセッションID
なんかが漏えいしたら
セッションを乗っ取られて
やりたい放題されるということかと
http通信下でのCookie secure属性の検証
いろんなサイトを読むと
httpsじゃないとCookieを発行しない
とあるので検証してみる
まずはhttpでsecure属性なし
当然Cookie情報が表示される
続いてhttpでsecure属性あり
上記の理論通りなら
Cookie情報が表示されないはず
が
思いっきり表示されてんじゃん…
(secure属性がついていることは確認できる)
待てよ、ブラウザ上は表示されてるけど
通信上ではちゃんと隠されてるのでは?
ということでパケットキャプチャを確認
ちゃんと表示されている
そりゃそうだ
Apacheの設定(検証にはApacheを使用)
が間違っているのかとかなり当惑したが
調べたところ、
secure属性があると
http通信のときは
Cookieをブラウザに保存しない
という挙動になるらしい
本当にCookieが保存されないのか検証
まずはhttpでsecure属性なしの場合
しっかりCookieがブラウザに保存されてる
続いてhttpでsecure属性ありの場合
Cookieが保存されていないことを確認
つまり正確に言うと
http通信でsecure属性があると secure属性つきでcookieは発行されるが ブラウザには保存されない
ということになる
考察、というか疑問
で、これの悪用のしかたはというと
・偽サイトを用意して脆弱性のある
サイトへのリンクを踏ませて
Cookieを搾取
・アクセスポイントを偽造するなどして
流れてくるCookieを搾取
…つまり通信上のCookieを盗聴してる
わけだから、被害者のブラウザに
Cookieが保存されようがされまいが
どっちでもよくて
Secure属性がついてたとしても
盗聴されるのは上記の通り
Secureどうこうよりも
通信が暗号化されているかどうかの
ほうが重要で、
・httpでのアクセスを受け付けない
・サイト内にhttp・httpsを混在させず
すべてhttpsに統一
といったことのほうが大事なんだと思う
それでもブラウザにCookieが保存されるか
されないかの違いはあるので
設定しておいたほうがいいんじゃない?
くらいのものだと認識している
大いに勘違いしているかもしれないので
間違っていたら誰か指摘してください[]