ITエンジニアの成長ブログ

ITエンジニアとして行う勉強の発信&日々の生活で体験した楽しいことをゆるく発信

SQL Serverの暗黙的トランザクションに注意する

先日、SQL Serverであるテーブルに登録されている不要なテーブルを大量に削除するクエリを作成しました。

かなり省いておりますが、以下のような感じのクエリです。

DECLARE @delete_row INTEGER;
SET @delete_row = 0;

WHILE 1 = 1
BEGIN
  BEGIN TRAN
    DELETE TOP (50000) FROM dbo.Sample WHERE created_date < '2024-01-01';
    SELECT @delete_row = @@ROWCOUNT;
  COMMIT TRAN

  IF @delete_row = 0
  BEGIN
    BREAK
  END

END


やっていることは、「dbo.Sample」というテーブルから「created_date」が'2024-01-01'より古いデータを50,000件ずつ削除して、削除する行が0件になったらループが終了するという感じです。

一度に大量データを削除すると、たとえ復旧モデルが「単純」でもトランザクションログが大変なことになりますので、少しずつ分けてコミットするようにしています。

そして、ここからが本題なのですが、上記クエリを実行してみたら、予想に反してトランザクションログがどんどん膨れ上がり、結果的にとんでもないサイズになってしまいました。

何故だろうと思って少し調べたら、原因はそのセッションで「暗黙的トランザクション」がONに設定されていたからでした。

以前、SSMSで以下の設定をしていたことを忘れておりました。

SET IMPLICIT_TRANSACTIONSの設定

上記の設定をすると、暗黙的にトランザクションが開始されます。そのため、上記SQLのBEGIN TRAN~COMMIT TRANはネストしたトランザクションになっていたのです。

そのため、実際にはコミットが完了されておらず、結局すべての削除の処理が暗黙的トランザクションにより、まとめて処理される形になってしまっていたのでした。

原因が判明したので、上記クエリの冒頭に以下のSET句を追加しました。

SET IMPLICIT_TRANSACTIONS OFF


これで、再実行してみると以前のようなトランザクションログの肥大化がなくなりました。

暗黙的トランザクションの設定は思わぬデータ削除などを防ぎますが、注意して使わないと予想外の挙動が発生してしまうので注意が必要だと思いました。

最後までお読みいただきありがとうございました。今回はこの辺で失礼いたします。

Javaのリモートデバッグの方法

今更ですが、個人的にいつも忘れるJavaのリモートデバッグの方法をメモしておきます。

今回試した環境は、以下の通りです。Windows 11 Proで試しました。

Javaバージョン

デバッグを実行するのは、Eclipseです。以下の環境で試しました。

Eclipseバージョン

それでは、さっそくためしてみます。

まずは、適当なJavaプロジェクトを作成して以下の簡単なJavaのプログラムを作成します。

Javaプロジェクト

Javaのプログラムは以下です。bbbパッケージのSampleというクラスにしました。そうしたら、Javaのプログラムの「System.out~」の行にブレークポイントを設定しておきます。

Javaプログラム

Eclipseではコンパイルされると、デフォルトではプロジェクト直下の「bin」ディレクトリにclassファイルが作成されると思います。

classファイルの場所

コマンドプロンプトでbinディレクトリまで移動して、以下のコマンドを実行します。

java -agentlib:jdwp=transport=dt_socket,server=y,address="8200" bbb.Sample


私の環境で実行してみると以下のような感じになりました。

デバッグ用でJavaを起動する

実行してみると分かりますが、以下のメッセージが表示されて実行は一旦Stopしている状況です。

Listening for transport dt_socket at address: 8200

それでは、準備ができたのでEclipseに戻り、Javaプログラムを右クリック、「デバッグ」-「デバッグの構成」を押下します。

Eclipseデバッグの構成を起動

デバッグ構成画面が開きましたら、「リモートJavaアプリケーション」-「新規作成」を押下します。

Eclipseデバッグの構成を起動2

右の方に設定の詳細を記入できます、ポートのところを先ほどJavaコマンド実行時に指定した「8200」にします。そしたら、画面下の「デバッグ」を押下します。

Eclipseデバッグの構成を起動3

すると、以下の通りEclipse側で先ほど設定したブレークポイントで停止してます。

ブレークポイントで止まっている様子

良い感じです。こんな形で、いつも忘れるので軽くメモしておきました。
最後までお読みいただきありがとうございました。今回はこの辺で失礼いたします。

log4j-1.2-apiについて

少し前にlog4jにかなり重大な脆弱性が存在することが発覚して、log4jライブラリを脆弱性を対応した最新のバージョンに入れ替えしなければならなくなった人は多いと思います。

私もその対応をしたのですが、そのときに「log4j-api-2.xx.0.jar」と「log4j-core-2.xx.0.jar」のメインのjarファイル以外にもう一つ「log4j-1.2-api-2.xx.0.jar」というライブラリも合わせて交換しました。

実際にライブラリを交換する際には、たいして意識していなかったのですが「log4j-1.2-api-2.xx.0.jar」って結局何の意味があったのか、気になったので今回調べました。

結論から言うと、log4j1.x系で実装されたJavaソースコードでも、実装をLog4j 2に差し替えることができるためのライブラリとのことでした。

なるほど、ソースコードは変えたくないけど、これからは新しいlog4j 2を使いたいといった要望に応えるために、用意されている仕組みのようです。たしかに、Javaソースにはlog4j1.x系のクラスを使っていたのでこのライブラリが必要であったようです。

因みに、「log4j-1.2-api-2.xx.0.jar」のライブラリのみあればOKかというと、もちろんそうではなく、Log4j 2の「log4j-api-2.xx.0.jar」と「log4j-core-2.xx.0.jar」のライブラリは必要になります(クラスパスにないとエラーになります)。

今回はこの辺で失礼いたします。最後までお読みいただきありがとうございました。

EclipseのJavaプロジェクトでコミット対象にすべきファイル

EclipseJavaプロジェクトでバージョン管理システムにコミット対象にすべきファイルについて、迷うことがありましたので個人的なメモを書いておきます。

様々な意見があるようですが、基本的な考えとしては当たり前のことではありますが「環境毎に異なる設定をすることがありえるファイル」はコミット対象にすべきではないということです。

これは逆に、「環境毎に同じ設定であるべきファイル」はコミット対象にすべきということになります。

補足としては、開発環境を揃えるようなプロジェクトの場合は「環境毎に異なる設定をすることがありえるファイル」はあまりないと思われるので、このような設定ファイルはコミット対象にすることで、環境毎の差異がなくなり、ある環境では動く動かない等の問題はなくなると思います。

上記のような前提を元に以下のようなEclipse特有のファイルを、必要に応じてコミット対象にする/しないを選択することが良いと思います。
 ・[ProjectDir]/.project
 ・[ProjectDir]/.classpath
 ・[ProjectDir]/.settings/*

私の携わったプロジェクトでは、開発環境を揃えることが多かったので上記の3つのファイルもコミット対象にされていました。

ちなみに、mavenプロジェクトの場合は上記の原則には当てはまらないようで、mavenの設定ファイルであるpom.xmlに必要な設定をすべて記載しておくことで、他のEclipse固有の設定ファイルはコミットしないようにするそうです(ここは正直、自分はあまり分かっていないのです)

上記はIDE統合開発環境)をEclipseとして特定してお話していますが、IntelliJ IDEAなどを使う人がいる場合はそれも考慮する必要がありますね。どちらにしても、環境ごとに必要に応じて選択しなくてはなりません。

SQL Serverで年月カラムを定義する際についてのメモ

SQL Serverで年月カラムを定義する際についてのメモを、個人的な備忘録として残しておこうと思います。

今回の記事を書こうと思った出来事について

以前、SQL Serverを使用しているシステムで年月を管理するテーブルがありました。

このテーブルでは、処理したタイミングの年月を抽出して「処理年」、「処理月」といった形でカラムを定義していました。

それぞれ、各カラムは以下のように定義していました。

  • 「処理年」

カラム名:「ProcessYear」
データ型:「decimal(4, 0)」

  • 「処理月」

カラム名:「ProcessMonth」
データ型:「decimal(2, 0)」

本来ならば、整数の値のみを取りうる「年」と「月」に、decimal型を使用しているのにとても違和感を覚えました。

今回は、このシステムのように年月を別々にカラム定義して保持するケースにおいて、他の例ではどのように定義しているのかを簡単に調査したメモです。

SQL Serverのサンプルデータベースはどうしているか?

SQL Serverはサンプルデータベースを提供しているので、そのなかで年月カラムを保持しているテーブルを調べてみました。データベース名は、「AdventureWorks2016」です。

その中に似たようなカラム定義をしているテーブルを見つけました。
「Sales.CreditCard」テーブルです(クレジットカードを保持するテーブルのようですね)。

AdventureWorks2016のSales.CreditCardテーブル

上記の通り、以下のようにカラムを定義していました。

  • 「ExpYear」(有効期限、年)※クレジットカードの有効年

データ型:「smallint」

  • 「ExpMonth」(有効期限、月)※クレジットカードの有効月

データ型:「tinyint」

なるほど、整数型をそれぞれ使っていて取りうる値に応じて適切なデータ型を選択しているということが分かりました。

データ型によるストレージ容量について

decimal型と、smallint型、tinyint型をそれぞれ使った場合のストレージ容量を調べてみました。公式サイトを参考にしたところ、以下の通りでした。

データ型 ストレージ(Byte) 備考
decimal 5 定義によるが今回のケースではこの容量となる
smallint 2
tinyint 1

decimal型は、小数点以下を扱うことができるデータ型のため少し容量を多く使うようです。ストレージで見た場合には、decimal型ではなく年月それぞれで適切な整数のデータ型を使用する方がより望ましいと思われます。

調べてみて

年月カラムは結論としては、サンプルデータベースのように適切な数値型を使用する方が良さそうです。

整数しかとりうる値がない場合は、意図も含めて整数型で定義すべきに思えます。

整数しかとりうる値がないのに「decimal(4, 0)」という定義をしている場合、何か意味があるのかと使用する人を惑わせることになるので、不要な混乱を避けるためにも、正しいデータ型を選択したいと思います。

経験や知識がないだけなのかもしれませんが、現時点で調べた感じだとこのような結論になりそうです。

また、上記では触れませんでしたがデータ型を大きく定義してしまうことにより、アプリケーションのパフォーマンスにも影響が発生するなどの記事もいくつか見かけました。実際に試してないので、確証はないですが無駄な領域を定義することにより、メモリもその分使ってしまい遅くなるのは容易に想像できるので、なんとなく正しい意見のような気がします。

今回はこの辺で失礼いたします。最後までお読みいただきありがとうございました。

Eclipseのplugins、features、dropinsフォルダの意味を調べた

Eclipseで手動でプラグインをインストールするときによく目にする、plugins、features、dropinsという3つのフォルダの意味が分からなかったので、それらを私なりに調べて整理したことをメモします。

3つのフォルダの用語の概要を整理する

インストールしたEclipseのフォルダ配下に存在する3つのフォルダの概要を簡単に説明すると以下の通りです。

  • plugins

文字通り、Eclipseプラグインを格納するためのフォルダ。

  • features

フィーチャーを格納するためのフォルダ。

  • dropins

プラグイン及び、フィーチャーを格納するためのフォルダ。

フィーチャーとは?

最初にフィーチャーを説明しておきます。フィーチャーは、複数のプラグインをまとめるためのもの。Eclipseでは更新サイト経由でプラグインをインストールすることもできるが、その場合にはフィーチャーが必要らしい。

このような特徴であるため、別にフィーチャーが必ず必要なわけではない(プラグインだけでも機能する)。

plugins、features、dropinsフォルダの使い分け

結論としては、手動でプラグインを導入する場合は、とりあえずdropinsフォルダを使用するのが良いらしいです。

元々は、pluginsフォルダにプラグインを置くのが基本だったが、そうなると複数あるプラグインの管理が煩雑になり、訳が分からなくなる。

そのため、プラグイン管理を効率化するために、dropinsフォルダで管理する仕組みができたらしい(色々と記事を見ていくと、バージョン3.4からのよう)。

一応今でもプラグインは、plugins、dropinsどちらに入れても動作するそうだけど、上記で説明した理由などにより後発のdropinsに入れた方がより良いということみたい。

dropinsフォルダへのプラグイン及びフィーチャーの置き方

とりあえず、プラグインやフィーチャーはdropinsフォルダへ置けば良いみたいだけど、その置き方が決まっているみたい。

私の環境(4.5.2)では、以下がとりあえず動いたので紹介しておきます(LimyはJavaのプロパティエディタとして使えるプラグインの名前です)。

  • dropins/${AS_YOU_LIKE}/以下に配置
eclipse
  +--- dropins
    +--- Limy
       +--- features
       +--- plugins

dropinsフォルダ配下にプラグイン毎に任意の名前でフォルダを作成して、その配下にfeatures、pluginsフォルダを格納していく方法。これが一番分かりやすく整理されるので良いと思う。

  • dropins/${AS_YOU_LIKE}/eclipse/以下に配置
eclipse
  +--- dropins
    +--- Limy
       +--- eclipse
         +--- features
         +--- plugins

過去の記事では、この構造でなければ動かないと記載されているのが多かったけど、私の環境では先に紹介した構造でも動きました。

この構造はeclipseフォルダが冗長だし、eclipseフォルダの名前を一文字でも間違えると、正しくプラグインを認識してくれないようです(例えば、eclipsだとダメでした)。

おわりに

Eclipseプラグインの格納方法について、もやもやしていたので少しスッキリしました。

因みに、プラグインを格納した後にプラグインが反映されていない場合は、eclipse起動時に「-clean」オプションを付けると良いそうです。

色々と紹介しましたが、基本的にプラグインEclipse Marketplaceや更新サイトからインストールした方が良さそうです。

使いたいプラグインが上記どちらも対応していないときだけ、手動でインストールする方法を選択する必要があるということですね。

今回はこの辺で失礼いたします。最後までお読みいただきありがとうございました。

Webページを検索エンジンで検索されないようにするための方法

IPAの情報処理安全確保支援士の試験で、タイトルの通りWebページをインターネットのGoogleなどの検索エンジンで、検索されないようにする方法が問われた問題があったのですが、全く知らなかったのでメモを残しておきます。

htmlのheadセクションに以下のタグを配置すると、検索エンジンで検索されないようになるようです。

<meta name="robots" content="noindex" />

因みに、contentの値は"none"でも同じ意味になるそうです。