セージ の メモ書き

メモこそ命の恩人だ

Java - Log4j2

Log4j2

Log4j – Apache Log4j 2

Log4j - Wikipedia

  • Java 用のロギングライブラリ。
  • log4j2 は log4j の後継。バージョン2。
  • ライセンス:Apache2.0
  • 2021年:脆弱性が見つかる。
    • Log4Shell
    • なので最新版を使うこと。

使い方

pom.xml

https://search.maven.org/artifact/org.apache.logging.log4j/log4j-slf4j2-impl/2.19.0/jar

  • log4j2 と log4j-core を指定する。
  • log4j2 のみでは以下のエラーが発生した。
    • ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j2-impl</artifactId>
  <version>2.19.0</version>
</dependency>

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.19.0</version>
</dependency>

設定ファイル

https://logging.apache.org/log4j/log4j-2.4/manual/configuration.html#Properties

(log4j2.properties)

appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS}, %level, %m%n

rootLogger.level = debug
rootLogger.appenderRef = stdout
rootLogger.appenderRef.stdout.ref = STDOUT
  • log4j2 の設定ファイルが必要。
  • 以下、用意する。
    • ファイル名:log4j2.properties
    • パス:src/main/resources
  • appender.console
    • コンソールの出力設定。
    • layout で出力形式を指定できる。
    • %d:日時
    • %level:ログレベル
    • %m:ログメッセージ
    • %n:改行
  • rootLogger.level
    • 指定レベル以上を出力する。
  • 補足
    • プロパティの形式をメモする。
    • xml の方法もある。

コード

  • LogManager.getLogger() でロガーを取得。
  • 設定ファイルをもとにログ出力できる。
  • 設定ファイル未定義の場合、error レベル以上を出力できる。
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public static void main( String[] args )
{
    Logger logger = LogManager.getLogger();
    logger.fatal("fatalです");
    logger.error("errorです");
    logger.warn("warnです");
    logger.info("infoです");
    logger.debug("debugです");
    logger.trace("traceです"); // 設定ファイルで debug 指定の場合、出力されない。
}



以上

Azure - KQL

KQL

Kusto 照会言語 (KQL) の概要 - Azure Data Explorer | Microsoft Learn

  • KQL:Kusto Query Language
  • 診断ログから検索する際に使用する。
  • メソッドチェーンで条件を記述。LINQSQL のような使用感。

よく使うメソッドをメモ。

メソッド 内容 備考
project 指定カラムの抽出 カラムの表示順序や表示有無を設定できる
where フィルタリング project で許可したカラムに適用できる
order by ソート desc で降順にできる
top by ソート+指定件数の取得 desc も使用できる

サンプル

  • TimeGenerated は UTC の形式。
    • 日本時間で検索する場合、"-9" 時間で考える。
  • has で文字列検索できる。
    • 基本、部分一致で検索できてる。
    • 前方一致のケースもある。どのログでそうなるか切り分けできていない。
      • 前方一致でも試してみること!!!

SQL Database

  • Diagnostics:ダイアグノスティクス
AzureDiagnostics
| project TimeGenerated, Category, Message 
| where TimeGenerated between (datetime(2022-1-1 00:00:00) .. datetime(2022-1-1 9:00:00))
| top 1000 by TimeGenerated desc

AKS

ContainerLog
| project TimeGenerated, ContainerID, LogEntry 
| where TimeGenerated between (datetime(2022-1-1 00:00:00) .. datetime(2022-1-1 09:00:00))
//| where LogEntry has "aaa"
//| order by TimeGenerated desc
| top 1000 by TimeGenerated desc



以上

Azure - マネージドID

マネージドID

Azure リソースのマネージド ID - Microsoft Entra | Microsoft Learn

  • Azure Active Directory の機能の一つ。
  • マネージド ID により、資格情報のハードコードが不要になる。
  • マネージド ID は追加コストなしで利用できる。(2022/11時点)
  • マネージド ID は以下の2種類。
    • システム割り当てマネージドID
    • ユーザー割り当てマネージドID

システム割り当てマネージドID

  • Azure リソース自体を識別するID。
  • Azure リソースに対し、1つのみ作成できる。
  • ↑のリソース削除で、IDも削除される。
  • 用途
    • ユーザー割り当てマネージドIDの方に記載した用途でない場合、こちらを使用する。

ユーザー割り当てマネージドID


Functions から SQL Database への接続

Azure Functions間でManaged Identityの認証を構成する – Logico Inside

Functions マネージドIDの有効化

  • Azure Portal の ID メニューより有効化する。
  • システム or ユーザー 割り当てマネージドIDを追加。一方でも両方でもよい。

Functions コード修正

チュートリアル: マネージド ID を使用して Azure データベースにアクセスする - Azure App Service | Microsoft Learn

  • ↑ "コードを変更する" の "Java" の部分を参照。
  • システム割り当てマネージドIDの場合...
    • new DefaultAzureCredentialBuilder().build();
  • ユーザー割り当てマネージドIDの場合...
    • new DefaultAzureCredentialBuilder().managedIdentityClientId(クライアントID).build();
    • クライアントIDは以下のような形式の文字列。
      • 1234abcd-1234-1234-1234-1234abcd1234
      • マネージドIDの Portal から確認できる。

pom.xml に依存関係を追加。

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
    <version>1.4.6</version>
</dependency>
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>10.2.0.jre11</version>
</dependency>

以下で認証用のトークンを取得して、DB 接続に使用する。

// Uncomment one of the two lines depending on the identity type
// system-assigned identity
//DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().build();
// user-assigned identity
//DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().managedIdentityClientId(クライアントID).build();

// Get the token  
TokenRequestContext request = new TokenRequestContext();
request.addScopes("https://database.windows.net//.default");
AccessToken token = creds.getToken(request).block();

コネクションを生成する。

SQLServerDataSource ds = new SQLServerDataSource();
ds.setServerName("<server-name>.database.windows.net");
ds.setDatabaseName("<database-name>");
ds.setAccessToken(token.getToken());

DefaultAzureCredential

DefaultAzureCredential Class | Microsoft Learn

  • 環境の認証情報がある場所を順に探索し、一致した情報を使用する。
  • 例:環境変数 -> マネージドID -> ...
  • 認証情報を探索を部分的に除外することもできる。
    • DefaultAzureCredential クラスのインスタンス時に Options を指定。
    • 例:ExcludeVisualStudioCredential = true

SQL Database ユーザー登録

CREATE USER [<app-name>] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [<app-name>];
ALTER ROLE db_datawriter ADD MEMBER [<app-name>];
ALTER ROLE db_ddladmin ADD MEMBER [<app-name>];
GO
  • EXTERNAL PROVIDER:外部管理ユーザーであることを指定。
  • 必要な権限を付与する。
    • 例:db_datareader etc.
  • システムユーザーの場合、リソース名と同じ名前。

    • Functions のリソース名を設定する。
  • システム割り当てマネージドIDの場合...

    • ユーザー名は、Azure Functions のリソース名を設定する。
  • ユーザー割り当てマネージドIDの場合...
    • ユーザー名は、マネージドIDの名称を設定する。
    • ※ ここはクライアントIDではないので注意。
<identity-name> は、Azure AD のマネージド ID の名前です。 
ID がシステムによって割り当てられる場合は常に、App Service アプリと同じ名前になります。

接続確認

SELECT * FROM sys.dm_exec_sessions WHERE host_name is not NULL;
  • 接続中のセッション情報を確認できる。
  • ユーザー割り当てマネージドIDの場合...
    • ソースで指定したクライアントIDで接続されたことを確認済み。
  • システム割り当てマネージドIDの場合...
    • ソースでクライアントIDは指定しない。
    • Azure リソース側で登録されたクライアントIDで接続されたことを確認。


トーク

Azure リソースのマネージド ID と Azure 仮想マシンの連携 - Microsoft Entra | Microsoft Learn

  • ↑ ここに認証の流れが記載されている。
  • トークンの有効期間は、24 時間。
  • 有効期間切れの場合、認証に失敗する。

Azure Functions の以下のコードでトークンの動作確認を行う。
Azure Functions のシステムマネージドID を有効化する。

@FunctionName("HttpExample")
public HttpResponseMessage run(
        @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS)
        HttpRequestMessage<Optional<String>> request,
        final ExecutionContext context) {

    long startTime = System.currentTimeMillis();

    DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().build();
    TokenRequestContext trequest = new TokenRequestContext();
    trequest.addScopes("https://database.windows.net//.default");
    AccessToken token = creds.getToken(trequest).block();
    String tokenString = token.getToken();

    long endTime = System.currentTimeMillis();
    long diffTime = endTime - startTime;

    return request.createResponseBuilder(HttpStatus.OK).body("time:"+ diffTime + "ms, token:" + tokenString).build();

}

トークン有効期間

  • 前述のコードを複数回実行し、同じトークンを取得できるか確認。
  • 結果:キャッシュされたデータを取得している。
    • 1回目:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1...
    • 2回目:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1...
    • 3回目:eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1...
  • 12時間後に実行すると、まだ同じデータ

  • 24時間後に実行すると、別のコード

    • 1回目:
    • 2回目:...
    • 3回目:...

トークン取得時間

  • 前述のコードでトークン取得時間を計測する。
  • キャッシュ状態の場合、0~30ミリ秒。
  • 以下の場合、約1秒の取得時間がかかる。
    • 初回取得時
    • 有効期間後の再取得時
試行回数 キャッシュにない場合 キャッシュにある場合
1 938 31
2 954 32
3 984 16



以上

SQL Server - コネクション/セッション

コネクション

sys.dm_exec_connections (Transact-SQL) - SQL Server | Microsoft Learn

  • DB と DB使用アプリの接続情報。
  • sys.dm_exec_connections でコネクションを確認できる。
  • 以下、取得カラム(抜粋)
    • コネクションID
    • セッションID
    • クライアントIPアドレス
    • 接続時刻

SSMS で新しいクエリを確認するごとに、コネクションが増えることを確認。

SELECT * FROM sys.dm_exec_connections;


セッション

sys.dm_exec_sessions (Transact-SQL) - SQL Server | Microsoft Learn

  • 1コネクションで、1セッションが通常。
  • MARS により、1コネクションで、n セッションを使用できる。
    • MARS : Multiple Active Result Set
    • 対応:SQL Server 2005 以降
    • 既定:無効化された状態
    • 有効化する場合、接続文字列で指定する。
      • MultipleActiveResultSets=True
  • sys.dm_exec_sessions でセッションを確認できる。
  • 以下、取得カラム(抜粋)
    • ホスト名
    • ログイン名
    • ログイン時刻
    • トランザクション分離レベル
      • 1 = ReadUncommitted
      • 2 = ReadCommitted
      • 3 = RepeatableRead
      • 4 = Serializable
  • 内部セッションの場合、いくつかのカラムが NULL になる。
    • host_name, program_name, host_process_id etc.

現在のセッション情報を確認できた。

SELECT * FROM sys.dm_exec_sessions WHERE host_name is not NULL;

KILL コマンドでセッションを削除することもできる。

KILL セッションID;


関連情報

@@SPID

@@SPID (Transact-SQL) - SQL Server | Microsoft Learn

  • SPID:サーバープロセスID
  • 現在接続中のセッションIDを取得できる。
SELECT @@SPID;

SUSER_ID()/SUSER_NAME()

SUSER_NAME (Transact-SQL) - SQL Server | Microsoft Learn

SUSER_NAME (Transact-SQL) - SQL Server | Microsoft Learn

  • 接続中のユーザーID/ユーザー名
SELECT SUSER_ID(), SUSER_NAME();



以上

Java - JMeter

インストール&起動

シナリオ作成#2_JMeterのインストールと初期設定 - pTune.jp

rem set JMETER_LANGUAGE=-Duser.language="en" -Duser.region="EN"
set JMETER_LANGUAGE=-Duser.language="ja" -Duser.region="JP"
  • jmeter.bat を実行する。
    • JMeter の UI が表示される。



以上

Java - HikariCP

HikariCP

GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last.

(2022/11時点の情報)

SQL Server を使う場合、こんな感じ。

(pom.xml)

Maven Central Repository Search

<dependency>
  <groupId>com.microsoft.sqlserver</groupId>
  <artifactId>mssql-jdbc</artifactId>
  <version>11.2.1.jre11</version>
</dependency>

<dependency>
  <groupId>com.zaxxer</groupId>
  <artifactId>HikariCP</artifactId>
  <version>5.0.1</version>
</dependency>
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.Connection;
public HikariConfig createConfig() {

    HikariConfig config = new HikariConfig();

    // dataSourceClassName
    config.setDataSourceClassName("com.microsoft.sqlserver.jdbc.SQLServerDataSource");

    // 接続先
    // ※ Azure Portal => 接続文字列 [JDBC] の各項目をセット
    // ※ addDataSourceProperty で何の項目を設定できるかは後述参照
    config.addDataSourceProperty("serverName", "***.database.windows.net");
    config.addDataSourceProperty("portNumber", "1433");
    config.addDataSourceProperty("databaseName", "+++");
    config.addDataSourceProperty("encrypt", "true");
    config.addDataSourceProperty("trustServerCertificate", "false");
    config.addDataSourceProperty("hostNameInCertificate", "*.database.windows.net");
    config.addDataSourceProperty("loginTimeout", "30");

    // 接続ユーザー(ID・パスワード)
    // config.setUsername("sa");
    // config.setPassword("1234");

    // 接続ユーザー(マネージドID)
    DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().managedIdentityClientId("ClientId").build();
    TokenRequestContext request = new TokenRequestContext();
    request.addScopes("https://database.windows.net//.default");
    AccessToken token = creds.getToken(request).block();
    config.addDataSourceProperty("accessToken", token.getToken());

    // 接続プール名
    config.setPoolName("SampleHikariPool");

    // 接続プール数
    config.setMaximumPoolSize(5);

    return config;
}
HikariConfig config = createConfig();
HikariDataSource dataSource = new HikariDataSource(config);

Connection connection = dataSource.getConnection();
//----------
// SQL実行
//----------
connection.close();


addDataSourceProperty


設定メモ

dataSourceClassName

This is the name of the DataSource class provided by the JDBC driver. 
  • DataSource の名称を設定する。

jdbcUrl

This property directs HikariCP to use "DriverManager-based" configuration.
We feel that DataSource-based configuration (above) is superior for a variety of reasons (see below), 
but for many deployments there is little significant difference.
  • jdbcUrl は、DriverManagerベースのプロパティ。
  • DataSourceベースの方が優れているとのこと。
    • なので、addDataSourceProperty を使用する。
  • driverClassName は最初は指定なしで試せと公式ドキュメントに記載あり。
  • dataSourceClassName とは "or" となっている。
    • なので、addDataSourceProperty 指定の場合、jdbcUrl と dataSourceClassName は併用しないこと。

maximumPoolSize

  • 既定:10
  • コネクションプールの最大数を設定する。

minimumIdle

  • 既定:maximumPoolSize と同じ
  • 最小:0
  • アイドル接続の最小数を設定する。
  • 既定の場合
    • 最大数分のコネクションが一度に生成される。
  • 0 の場合
    • 接続時に都度コネクションが生成される。
    • idleTimeout 経過後にコネクションが終了する。
    • アイドル状態が続くと、コネクションが0件になる。
  • maximumPoolSize 未満の場合
    • minimumIdle 分のコネクションが一度に生成される。
    • idleTimeout 経過後にコネクションが終了する。
    • アイドル状態が続くと、コネクションがminimumIdle件になる。
    • コネクションが不足する場合、maximumPoolSize まで増加する。

idleTimeout

This setting only applies when minimumIdle is defined to be less than maximumPoolSize

minimumIdle が maximumPoolSize 未満のときに適用される。
  • 既定:600000 (10 分)
  • 最小:10000 (10 秒)
  • コネクションを終了する時間を設定する。
  • minimumIdle と依存関係のある設定。
    • minimumIdle < maximumPoolSizeの場合、idleTimeout が有効になる。


実装例

Azure Functions

azure-java-sample-functions-with-hikaricp/Function.java at master · m-moris/azure-java-sample-functions-with-hikaricp · GitHub

  • HikariDataSource を static で保持し、使い回す仕掛け。
  • 初回参照時に HikariConfig を設定する。
  • ※ もし都度生成すると...
    • アクセスのたびにコネクションが増えていく。
    • コネクションプールする意味がない状態。

Spring Boot

Spring Boot HikariCP Connection Pool Example | MySQL

  • application.properties で接続プールを設定する。


ログ

SLF4J

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.

http://www.slf4j.org/codes.html#noProviders

  • HikariCP のみを使うと...
    • "SLF4J プロバイダーが見つからない" と表示される。
    • SLF4J プロバイダーがクラスパスにあれば表示されない。
  • SLF4J
    • Simple Logging Facade For Java
    • Facade:ファサード
    • Facade パターンでログの実装を抽象化
    • ログ実装ライブラリの例:log4j2, logback etc.
  • 警告解消のため...
    • log4j2 を使用する。後述参照。

log4j2

  • まず、セージメモ書きを参照 (log4j2)
    • log4j2.properties の追加
    • pom.xml に log4j2 を追加
  • 注意
    • pom.xml の log4j2 の書き順によってはエラーになるので注意。
    • HikariCP よりも log4j2 を先に指定すること。
Unexpected problem occured during version sanity check
Reported exception:
java.lang.AbstractMethodError: Receiver class org.apache.logging.slf4j.
SLF4JServiceProvider does not define or inherit an implementation of 
the resolved method 'abstract java.lang.String getRequesteApiVersion()' of interface org.slf4j.spi.SLF4JServiceProvider.

こんな感じ。

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j2-impl</artifactId>
  <version>2.19.0</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.19.0</version>
</dependency>
<dependency>
  <groupId>com.microsoft.sqlserver</groupId>
  <artifactId>mssql-jdbc</artifactId>
  <version>11.2.1.jre11</version>
</dependency>
<dependency>
  <groupId>com.zaxxer</groupId>
  <artifactId>HikariCP</artifactId>
  <version>5.0.1</version>
</dependency>
  • log4j2.properties に HikariCP のログレベルを設定できる。
  • log4j2.properties の rootLogger より下に追記。
  • logger.hikari を追記する。未指定の場合、rootLogger.level が反映される。
logger.hikari.name = com.zaxxer.hikari
logger.hikari.level = debug

HikariCP (Info ログ)

  • dataSource 生成時、以下を確認できる。
    • コネクション生成の開始・処理完了の情報
    • コネクションID
HikariDataSource dataSource = new HikariDataSource(config);
2022-11-26 15:31:26.690, INFO, SampleHikariPool - Starting...
2022-11-26 15:31:27.112, INFO, SampleHikariPool - Added connection ConnectionID:1 ClientConnectionId: 57d4acfb-f83b-42e3-a0f6-284ae94b5042
2022-11-26 15:31:27.113, INFO, SampleHikariPool - Start completed.
  • dataSource クローズ時、以下を確認できる。
    • コネクションの終了・処理完了の情報
dataSource.close(); 
2022-11-26 15:59:51.966, INFO, SampleHikariPool - Shutdown initiated...
2022-11-26 15:59:51.971, INFO, SampleHikariPool - Shutdown completed.

HikariCP (Debug ログ)

  • コネクションプールの状況を確認できる。
  • 30 秒ごとに表示される。
  • total:コネクションプールの最大数
  • active:使用中のコネクション数(closeしない場合、active のままになる)
  • idle:使用可能なコネクション数
  • waiting:待機数のコネクション数(タイムアウトすると減る)
// コネクションを取得した時点で、active が増加
// idle が 0 で実行した場合、waiting が増加(タイムアウト後、例外が発生)
Connection connection = dataSource.getConnection();
// --------------------
// SQL を実行
// --------------------
// close した時点で、active が減少
connection.close();
2022-11-26 15:46:50.845, DEBUG, SampleHikariPool - Pool stats (total=5, active=1, idle=4, waiting=0)
2022-11-26 15:46:50.845, DEBUG, SampleHikariPool - Fill pool skipped, pool has sufficient level or currently being filled (queueDepth=0).

例外情報

コネクションプールが満杯

  • 最大コネクションプール数1の状態で確認。
  • 1つ目のコネクションを解放せずに2つ目を接続すると例外発生。
java.sql.SQLTransientConnectionException: SampleHikariPool - Connection is not available, request timed out after 30018ms.
Connection connection1 = null;
Connection connection2 = null;
try {
    connection1 = dataSource.getConnection();
} catch (SQLException ex) {
    logger.error(ex.getMessage());
}
try {
    // 2つ目のため、ここで例外発生
    connection2 = dataSource.getConnection();
} catch (SQLException ex) {
    logger.error(ex.getMessage());
}

if (connection1 != null) connection1.close();
if (connection2 != null) connection2.close();

データソースのクローズ済み

  • トランザクション中、データソースをクローズ。
    • トランザクション中の場合も、例外は発生しない。
    • コネクションの有無を確認する方法がほしい。。。
  • この状態で、コネクションをクローズするとエラー発生。
Exception in thread "main" com.microsoft.sqlserver.jdbc.SQLServerException: 接続は閉じられています。
Connection connection = connection = dataSource.getConnection();
connection.setAutoCommit(false);
PreparedStatement ps = connection.prepareStatement("UPDATE SampleTable1 SET Data1 += 1 WHERE Id = 1;");
ps.executeUpdate();
ps.close();

// トランザクション中にクローズしても、例外は発生しない
dataSource.close();

try {
    // クローズ済みのため、ここで例外発生
    connection.commit();
} catch (SQLException ex) {
    logger.error(ex.getMessage());
}
connection.close();



以上

SQL Server - 並列クエリ (パラレルクエリ)

並列クエリ

クエリ処理アーキテクチャ ガイド - SQL Server | Microsoft Learn

  • 複数コアで並列してクエリを処理する。
  • 利点
    • 処理時間が小さくなる。
  • 欠点
    • CPU負荷が大きくなる。
  • 動作条件
    • Express エディション以外であること。
    • コア数が複数あること。
    • MAX-DOP が、2以上であること。
    • コストが閾値以上であること。
      • 基本は閾値以上で動作する。
      • 閾値未満でも並列になるケースがあるらしい...


並列クエリの設定

  • コマンドで設定の表示・変更を行う場合...
    • sp_configure の詳細情報を有効する。0→1。
    • 終了時は 1→0 に戻しておく。
    • SSMS で行う場合は不要。
EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO

並列処理の閾値

cost threshold for parallelism サーバー構成オプションの構成 - SQL Server | Microsoft Learn

  • 5 が既定値。
  • SSMS の場合
  • コマンドの場合
    • 詳細設定を有効化して確認・設定を行う。
-- 確認方法
-- cost threshold for parallelism の run_value を確認
sp_configure;
-- 設定方法
EXEC sp_configure 'cost threshold for parallelism', 10;
GO
RECONFIGURE;
GO

並列処理のコア数

max degree of parallelism サーバー構成オプションの構成 - SQL Server | Microsoft Learn

  • 8 が既定値。
  • SSMS の場合
    • "インスタンス -> プロパティ -> 詳細設定" より...
    • "並列処理の最大限度" で設定できる。
  • コマンドの場合
    • 詳細設定を有効化して確認・設定を行う。
-- 確認方法
-- max degree of parallelism の run_value を確認
sp_configure;
-- 設定方法
EXEC sp_configure 'max degree of parallelism', 16;
GO
RECONFIGURE;
GO


並列クエリの確認

以下のテーブルで確認する。

USE SampleDb;
IF object_id(N'SampleTable1') is not null DROP TABLE SampleTable1;
CREATE TABLE SampleTable1 (Id INT PRIMARY KEY, Data1 CHAR(10));
GO
DECLARE @Count INT = 1;
WHILE @Count <= 30000 BEGIN
    INSERT INTO SampleTable1 (Id, Data1) VALUES (@Count, 'xxx');
    SET @Count += 1;
END
GO

実行プランの表示

USE SampleDb;
SET STATISTICS PROFILE ON
SELECT COUNT(Id) FROM SampleTable1;
SET STATISTICS PROFILE OFF
  • "Parallelism" があれば、並列クエリ。
  • SSMS で表示しても良い。

コストの確認

USE SampleDb;
SET STATISTICS PROFILE ON
SELECT COUNT(Id) FROM SampleTable1 OPTION (RECOMPILE, QUERYTRACEON 3604, QUERYTRACEON 8675);
SET STATISTICS PROFILE OFF
  • OPTION句を指定する。
  • SSMS の場合、メッセージタブにコストが表示される。
  • "end search(), cost: " でコストを確認できる。
  • 複数あれば、並列処理されている。

一方の処理が "cost 51" だった。閾値を調整し、並列処理になるか試す。

End of simplification, time: 0 net: 0 total: 0 net: 0
end exploration, tasks: 30 no total cost time: 0 net: 0 total: 0 net: 0
end search(1),  cost: 51.1452 tasks: 62 time: 0 net: 0 total: 0 net: 0
end exploration, tasks: 63 Cost = 51.1452 time: 0 net: 0 total: 0 net: 0
end search(1),  cost: 6.48538 tasks: 126 time: 0 net: 0 total: 0 net: 0
  • 結果
    • 閾値 51 の場合:並列処理で動作した。
    • 閾値 52 の場合:並列処理で動作しなかった。


補足

並列クエリにならない理由

https://learn.microsoft.com/ja-jp/sql/relational-databases/query-processing-architecture-guide#parallel-query-processing

  • 実行プランの以下で確認できる。
    • NonParallelPlanReason
    • 表示できない時もある...

CPU負荷の疑似的な増加

DBCC SETCPUWEIGHT(1000);
  • CPU負荷を大きくできる。
  • 数値通りにCPUコストが大きくなるわけではなさそう...
  • 値を大きくすることで並列処理になる。いつ使う?



以上

SQL Server - 同時接続数/接続プール

サーバー側の設定

user connections サーバー構成オプションの構成 - SQL Server | Microsoft Learn

  • SSMS or コマンドで変更できる。
  • 0 の場合、制限なし。(既定値)
  • 最大 32,767 まで設定できる。

注意事項

  • 同時接続数を小さな値にしないこと。
  • 同時接続数 "3" にした場合、SSMS を使用する際に下記エラーが発生。
  • クエリを使用できない状況に... 面倒なことに。
サーバーとの接続を正常に確立しましたが、ログイン前のハンドシェイク中にエラーが発生しました。 
(provider: Shared Memory Provider, error: 0 - パイプの他端にプロセスがありません。) (.Net SqlClient Data Provider)

SSMS の使用

  • インスタンスの"プロパティ→接続" メニューを選択
  • "コンカレント接続の最大数" で値を設定
  • 変更後、SQL Server を再起動する。

コマンドの使用

sp_configure (Transact-SQL) - SQL Server | Microsoft Learn

show advanced options サーバー構成オプション - SQL Server | Microsoft Learn

  • sp_configure で user connections (同時接続数) を確認できる。
  • sp_configure の詳細情報を表示 or 設定する場合、オプションを有効化する。
  • show advanced option を 0 → 1 にする。

設定を確認する場合

EXEC sp_configure 'show advanced option', '1';
GO
RECONFIGURE;
GO
sys.sp_configure;
GO
-- run_value が動作中の値

設定を変更する場合

EXEC sp_configure 'show advanced option', '1';
GO
RECONFIGURE;
GO
EXEC sp_configure 'user connections', 10;
GO  
RECONFIGURE;
GO
-- 変更後、SQL Server サービスの再起動
  • 試しに "10" に設定
    • SSMS で "新しいクエリ" を複数立ち上げると...
    • ↑のエラーメッセージが表示された。
    • これが接続数エラー???


クライアント側の設定(接続プール)

  • クライアントは接続プールの設定になる。
    • コネクションプールとも呼ぶ。
  • DBアクセスの処理をプールする。接続・切断を都度行わない。
  • プールしたオブジェクトを再利用し、パフォーマンスを上げる。

ADO.NET

SQL Server の接続プール - ADO.NET | Microsoft Learn

  • ADO.NET の場合、既定で接続プールが有効。
  • 一意の接続文字列ごとに 1 つの接続プールが作成される。
    • 接続文字列に差異があると、新たな接続となる。
  • 接続文字列で接続プールを設定できる。

JDBC ドライバー

接続プールの使用 - JDBC Driver for SQL Server | Microsoft Learn

  • JDBC の接続プールの情報あり。
  • [実装] はインターフェースの情報。
    • javax.sql.ConnectionPoolDataSource
    • javax.sql.XADataSource
  • [クラス] は "接続プールに対応したクラス" の情報。
    • SQLServerXADataSource
    • SQLServerConnectionPoolDataSource
  • 注意:このクラス単体で接続プールは使用できない。
    • つまり、最大プール数や、未使用時のタイムアウトなどの設定はない。
    • 上位層のモジュールがこれらのクラスを利用し、接続プールの機能を実現する。
  • つまり...
    • JDBC ドライバー単体で接続プールの機能は実現できない。
    • ミドルウェアが接続プール機能に対応していれば、そちらを使用する。
    • 未対応なら、別途ライブラリを導入する。



以上

SQL Server - 行ロック

事前知識

更新ロック

共有ロック 更新ロック 排他ロック
共有ロック ×
更新ロック × ×
排他ロック × × ×
  • 更新ロック中
    • 共有ロックOK
    • 更新ロックNG
    • 排他ロックNG
  • 共有ロック中
    • 更新ロックOK
  • 排他ロック中
    • 更新ロックNG
  • 用途
    • 更新を予約するときに使う。
    • 共有ロックと更新ロックの中間っぽい?

行ロック

テーブル ヒント (Transact-SQL) - SQL Server | Microsoft Learn

-- 行ロック(更新ロック)
SELECT * FROM テーブル名 WITH(UPDLOCK, ROWLOCK) WHERE ***;
-- 行ロック(排他ロック)
SELECT * FROM テーブル名 WITH(XLOCK, ROWLOCK) WHERE ***;
  • WITH(*, ROWLOCK) で行ロックできる。
  • 行ロックとは
    • ロックの範囲が "行" の方式。
    • そのほか、テーブルロックなどがある。

以下で試す。

USE SampleDb;
IF object_id(N'SampleTable1') is not null DROP TABLE SampleTable1;
CREATE TABLE SampleTable1 (Id INT PRIMARY KEY, Data1 CHAR(10));
GO
INSERT INTO SampleTable1 (Id, Data1) VALUES (1, 'xxx');
INSERT INTO SampleTable1 (Id, Data1) VALUES (2, 'xxx');
INSERT INTO SampleTable1 (Id, Data1) VALUES (3, 'xxx');
GO

更新ロック (UPDLOCK)

行(Id=1)に更新ロックで行ロックする。

USE SampleDb;
BEGIN TRANSACTION;
SELECT * FROM SampleTable1 WITH(UPDLOCK, ROWLOCK) WHERE Id = 1;
WAITFOR DELAY '00:00:30';
COMMIT;

この状態で他のクエリを実行してみる。

-- 行ロックなし SELECT はできた。予想通り。
USE SampleDb;
SELECT * FROM SampleTable1 WHERE Id = 1;
-- 行ロックあり SELECT はロック待ち発生。予想通り。
USE SampleDb;
SELECT * FROM SampleTable1 WITH(UPDLOCK, ROWLOCK) WHERE Id = 1;
-- UPDATE はロック待ち発生。予想通り。
USE SampleDb;
UPDATE SampleTable1 SET Data1 = 'zzz' WHERE Id = 1;

排他ロック (XLOCK)

行(Id=1)に排他ロックで行ロックする。

USE SampleDb;
BEGIN TRANSACTION;
SELECT * FROM SampleTable1 WITH(XLOCK, ROWLOCK) WHERE Id = 1;
WAITFOR DELAY '00:00:30';
COMMIT;

この状態で他のクエリを実行してみる。

-- 行ロックなし SELECT はできた。予想外 ( ゚Д゚) 排他ロック中では???
USE SampleDb;
SELECT * FROM SampleTable1 WHERE Id = 1;
-- 行ロックあり SELECT はロック待ち発生。予想通り。
USE SampleDb;
SELECT * FROM SampleTable1 WITH(UPDLOCK, ROWLOCK) WHERE Id = 1;
-- UPDATE はロック待ち発生。予想通り。
USE SampleDb;
UPDATE SampleTable1 SET Data1 = 'zzz' WHERE Id = 1;


ロックタイムアウト

SET LOCK_TIMEOUT (Transact-SQL) - SQL Server | Microsoft Learn

SET LOCK_TIMEOUT ミリ秒;
  • ロックタイムアウト待ちの時間を設定できる。
  • 既定は無期限に待機する。
  • 元に戻すなら -1 を指定する。
USE SampleDb;
BEGIN TRANSACTION;
SELECT * FROM SampleTable1 WITH(XLOCK, ROWLOCK) WHERE Id = 1;
WAITFOR DELAY '00:00:30';
COMMIT;

以下、1秒でタイムアウトしたことを確認。

SET LOCK_TIMEOUT 1000;

USE SampleDb;
UPDATE SampleTable1 SET Data1 = 'zzz' WHERE Id = 1;
-- メッセージ 1222、レベル 16、状態 51、行 4
-- ロック要求がタイムアウトしました。


ロック状態の確認

sys.dm_tran_locks (Transact-SQL) - SQL Server | Microsoft Learn

SQL Serverでロックを確認する方法 | .NETコラム

どのクエリでロックをかけているか確認できる。

USE SampleDb;

SELECT t.text, l.request_session_id, l.*
FROM sys.dm_tran_locks AS l
LEFT JOIN sys.dm_exec_requests AS r ON l.request_session_id = r.session_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
WHERE resource_type <> 'DATABASE';

ロック状態の解除

kill セッションID;
  • 前述の request_session_id を指定する。
  • ロック中のクエリを中断できたことを確認。


注意:ヒープテーブル

  • ヒープテーブルの場合...
    • 行ロックがかからない。
    • テーブルロックになる。
USE SampleDb;
IF object_id(N'SampleTable1') is not null DROP TABLE SampleTable1;
CREATE TABLE SampleTable1 (Id INT, Data1 CHAR(10));
GO
INSERT INTO SampleTable1 (Id, Data1) VALUES (1, 'xxx');
INSERT INTO SampleTable1 (Id, Data1) VALUES (2, 'xxx');
INSERT INTO SampleTable1 (Id, Data1) VALUES (3, 'xxx');
GO

行(Id=1)に排他ロックで行ロックする。

USE SampleDb;
BEGIN TRANSACTION;
SELECT * FROM SampleTable1 WITH(XLOCK, ROWLOCK) WHERE Id = 1;
WAITFOR DELAY '00:00:30';
COMMIT;

行(Id=2)を更新できない。テーブルロックになっている。。。

USE SampleDb;
UPDATE SampleTable1 SET Data1 = 'zzz' WHERE Id = 2;



以上

IntelliJ - ショートカット

pleiades.io

ファイル編集

内容 コマンド
Ctrl + / コメントアウトコメントアウト解除
Ctrl + Alt + L 自動整形
Ctrl + Alt + T 選択箇所を try や if で囲む
Ctrl + Shift + V クリップボードの履歴から貼り付け
Ctrl + Shift + ↑↓ 選択行を移動

ファイル参照

内容 コマンド
Ctrl + Shift + F 検索。検索画面以外の選択で画面クローズ
Ctrl + B 定義へ移動
Alt + F7 使用箇所の検索、どこから参照されているか

デバッグ

内容 コマンド
F7 ステップイン実行
F8 デバッグ一つずつ実行
F9 次のブレークポイントまで実行
Ctrl + F8 ブレークポイントをセット/解除
Alt + Enter ヒントによる修正



以上

Docker Desktop - インストール

環境準備

インストール

初期設定

プロキシ

  • プロキシを設定する。(必要な場合)
  • 右上の歯車ボタンより設定する。
    • "Resources -> Proxies" メニューを選択。
    • "Manual proxy configuration" を有効にする。
    • HTTP と HTTPS の内容を入力し、"Apply & restart" をクリック。
  • Docker Desktop を再起動。

ログイン

  • 右上のログインアイコンをクリック。

注意

Docker Desktop requires the Server service to be enabled.
  • インストーラー起動時にこのエラーが出た場合...
    • サービス管理を表示。以下のサービスが有効であることを確認。
      • 名前:LanmanServer
      • 説明:Server
    • "無効" の場合、有効化する。



以上

Azure SQL Database - バックアップ/リストア

自動バックアップ

自動の geo 冗長バックアップ - Azure SQL Database | Microsoft Learn

  • データは自動バックアップされる。
    • 手動バックアップ操作は行えない。
    • データ管理もフルマネージド。便利。
  • バックアップ頻度
  • 以下で頻度を設定できる。
    • "SQL Server -> バックアップ" メニュー
    • ログバックアップは設定不可


バックアップデータの復元(リストア)

バックアップからデータベースを復元する - Azure SQL Database | Microsoft Learn

  • 復旧時間について
    • 大規模DBの場合、数時間かかることがある。
    • 12 時間未満で大抵のDBは復旧が完了するらしい。
  • 既存DBは上書きできない。
    • 新規に環境を作成する。
    • 復旧後は、DB名を変更する必要がある。
元のデータベースのコンピューティング サイズとサービス レベルを指定する必要があります。
次に、T-SQL の ALTER DATABASE コマンドを使用して、元のデータベース名を変更し、
復元されたデータベースに元の名前を付けます。
ALTER DATABASE [OldDbname] MODIFY NAME = [NewDbname]


バックアップサイズの確認

https://learn.microsoft.com/ja-jp/azure/azure-sql/database/automated-backups-overview?view=azuresql#backup-storage-consumption

  • 診断設定が必要。"Basic" を有効にしておく。
  • メトリックより確認できる。

バックアップデータの冗長性

データの冗長性 - Azure Storage | Microsoft Learn

https://learn.microsoft.com/ja-jp/azure/azure-sql/database/automated-backups-overview?view=azuresql#backup-storage-redundancy

  • 以下の3パターン。詳細は↑のサイトに載っている。
    • ローカル冗長ストレージ (LRS)
    • ゾーン冗長ストレージ (ZRS)
    • geo 冗長ストレージ (GRS)


バックアップデータのコスト

https://learn.microsoft.com/ja-jp/azure/azure-sql/database/automated-backups-overview?view=azuresql#backup-storage-costs

(仮想コアモデルの場合 上記サイトより)

単一データベースの場合は、データベースの最大データ ストレージ サイズの
100% に等しいバックアップ ストレージ容量が、追加料金なしで提供されます。 
課金対象のバックアップ ストレージ合計使用量の計算には、次の式が使用されます。

Total billable backup storage size = 
(size of full backups + size of differential backups + size of log backups) – maximum data storage
  • バックアップデータの冗長性によりコストが変わる
    • LRS = published price
    • ZRS = published price x 1.25
    • GRS = published price x 2
  • 最大データストレージは、コア数により変わる。
  • 追加料金なしで、↑ これだけのストレージを使用できる。


自動バックアップの履歴

sys.dm_database_backups - SQL Server | Microsoft Learn

  • 自動バックアップの履歴を表示できる。
  • backup_type でバックアップの種類がわかる。
SELECT TOP 10 * 
FROM sys.dm_database_backups 
ORDER BY backup_finish_date DESC;



以上

Azure SQL Database - コスト/サービスレベル/ハードウェア

コスト計算

料金計算ツール | Microsoft Azure

  • ↑のサイトで "Azure SQL Database" を選択。
  • コストの要素がわかる。
  • 課金の単位
    • プロビジョニング済みの場合:時間単位で請求
    • サーバーレスの場合:稼働中の秒単位で請求

価格 - Azure SQL Database Single Database | Microsoft Azure

SQL Database のプロビジョニング コンピューティング レベルでは、
時間単位で請求される固定価格で、固定量のコンピューティング リソースが提供されます。
SQL Database サーバーレス コンピューティング レベルでは、コンピューティングの自動スケーリングと、
1 秒あたりのコンピューティング使用量に対する請求により、使用量が断続的で予測不可能な単一データベースに対して、
価格パフォーマンスが最適化され、パフォーマンスの管理が簡素化されます。

試しに、見積もりしてみる。(2022/10時点)

  • 以下、固定
    • リージョン:Japan East
    • タイプ:単一データベース
    • 購入モデル:vCore
    • サービスレベル:汎用
    • コンピューティングレベル:プロビジョニング済み
    • ハードウェアの種類:Standard(Gen5)
    • インスタンス:8仮想コア
    • コンピューティング冗長性:ローカル冗長
    • データ:32GB
    日数 料金
    1 $48.42
    31 $1,500.99
    365 $17,672.98


タイプ

単一データベース

単一データベースとは - Azure SQL Database | Microsoft Learn

エラスティックプール

エラスティック プールを使用して複数のデータベースを管理する - Azure SQL Database | Microsoft Learn

  • 複数DBのリソースが管理される。
  • 特定DBが高負荷になった場合、低負荷のDBのリソースを共有し、負荷を平坦化する。
  • 使用パターンが予測しづらい場合、選択する。
  • 複数リージョンの場合、有効かも。。。使用する時間帯が異なるため。


購入モデル

モデルの購入 - Azure SQL Database | Microsoft Learn

vCore(仮想コア)

仮想コア購入モデル - Azure SQL Database | Microsoft Learn

DTU

DTU ベースの購入モデル - Azure SQL Database | Microsoft Learn


サービスレベル

General Purpose

汎用のサービス階層 - Azure SQL Database & Azure SQL Managed Instance | Microsoft Learn

Business Critical

Business Critical サービス レベル - Azure SQL Database & Azure SQL Managed Instance | Microsoft Learn

  • General Purpose の2倍ちょっとのコストが必要。
  • IO性能が良い。
    • General Purpose のバッファプールにページ情報がキャッシュされた時と同等の速度がだせそう。
    • SELECT での IO や、フラッシュの IO で性能がいる際に使用する。
  • メモリ最適化テーブルを使用できる。

ハイパースケール

Hyperscale サービス レベルとは - Azure SQL Database | Microsoft Learn

Hyperscale の分散機能のアーキテクチャ - Azure SQL Database | Microsoft Learn

  • 他のサービスレベルとアーキテクチャが異なる。
    • 運用中に切り替えることができないため注意。
    • General Purpose・Business Critical なら切替可。
  • スケールアウトを重視する際に使用する。

各サービスレベルの可用性

高可用性 - Azure SQL Database and SQL Managed Instance | Microsoft Learn

  • リンク先の絵に、稼働データやバックアップデータのアーキテクチャが記載されている。


コンピューティングレベル

プロビジョニング済み

  • Provision:準備
  • 自動停止しない。常に稼働する。

サーバレス

サーバーレス コンピューティング レベル - Azure SQL Database | Microsoft Learn

  • 稼働中の場合にのみ課金される。
  • 設定した時間で自動停止する。
  • ※ 稼働に時間がかかる。これが許容できるサービスは?


ハードウェア

ハードウェアの種類

  • 以下の3つ(2022/10時点)
    • Standardシリーズ(Gen5)
    • Mシリーズ
    • DCシリーズ
  • 日本のリージョンで使用できるハードウェア
    • Standardシリーズ(Gen5)のみ
    • ↑全世界のリージョンに対応

リソースの制限情報

単一データベースの仮想コア リソースの制限 - Azure SQL Database | Microsoft Learn

単一データベースに対する DTU リソースの制限 - Azure SQL Database | Microsoft Learn

CPU/メモリ

仮想コア購入モデル - Azure SQL Database | Microsoft Learn

(Gen5+プロビジョニング済みの場合)

  • CPU
  • CPUの割り当て
    • リソース構築時、ランダムに割り当てられる。
    • ※ 常に変化するわけではない。
  • メモリ
    • 5.1 GB/仮想コア
    • 最大 408 GB



以上

SQL Server - トランザクションログ

トランザクションログ

トランザクション ログ (SQL Server) - SQL Server | Microsoft Learn

仮想ログ ファイル (VLF)

トランザクション ログのアーキテクチャと管理ガイド - SQL Server | Microsoft Learn

sys.dm_db_log_info

sys.dm_db_log_info (Transact-SQL) - SQL Server | Microsoft Learn

  • VLF 単位の情報を確認できる。
  • DBCC LOGINFO 相当(← Azure SQL DB では使用不可)
SELECT l.* 
FROM sys.databases AS d 
CROSS APPLY sys.dm_db_log_info(d.database_id) AS l
WHERE d.name = 'SampleDb';
  • vlf_active:VLF 使用中の有無
    • 0:未使用
    • 1:使用中
  • vlf_status:VLF の状態
    • 0:非アクティブ
    • 1:初期化されているが、未使用
    • 2:アクティブ

sys.dm_db_log_stats

sys.dm_db_log_stats (Transact-SQL) - SQL Server | Microsoft Learn

  • VLF 全体の概要を確認できる。
SELECT l.* 
FROM sys.databases AS d 
CROSS APPLY sys.dm_db_log_stats(d.database_id) AS l
WHERE d.name = 'SampleDb';


トランザクションログのサイズ確認

トランザクション ログ ファイルのサイズの管理 - SQL Server | Microsoft Learn

sys.dm_db_log_space_usage

sys.dm_db_log_space_usage (Transact-SQL) - SQL Server | Microsoft Learn

  • 以下がわかる。
    • ldf ファイルのサイズ(バイト)
    • 使用中ログのサイズ(バイト)
  • USE で対象 DB を指定する。(Azure では不要)
  • 後述の sys.database_files と異なり、使用中サイズもわかる。
  • なのでログの肥大化チェックするなら、この DMV を使う。
USE SampleDb;
SELECT * FROM sys.dm_db_log_space_usage;

sys.database_files

sys.database_files (Transact-SQL) - SQL Server | Microsoft Learn

  • 以下がわかる。
    • ldf ファイルのサイズ(8K単位)
    • ldf ファイルの最大サイズ(8K単位)
    • 拡張方法・拡張サイズ
  • USE で対象 DB を指定する。(Azure では不要)
USE SampleDb;
SELECT * FROM sys.database_files;


トランザクションログの圧縮

以下の2つを満たせば、圧縮できる。

圧縮条件1

  • ログバックアップ処理により、圧縮可能な状態となる。
  • Azure SQL Database の場合...
    • 10分に1回、バックアップ処理が動作する。
    • 手動でのバックアップ処理は行えない。
    • 処理の履歴は sys.dm_databese_backups でわかる。後述参照。

圧縮条件2

USE SampleDb;
DBCC SHRINKFILE ('SampleDb', 0);
DBCC SHRINKFILE ('SampleDb_log', 0);
DBCC SHRINKFILE ('SampleDb_log', 0, TRUNCATEONLY);

DBCC SHRINKFILE

DBCC SHRINKFILE (Transact-SQL) - SQL Server | Microsoft Learn

USE SampleDb;
DBCC SHRINKFILE ('SampleDb_log', 0);
DBCC SHRINKFILE ('SampleDb_log', 0, TRUNCATEONLY);
  • TRUNCATEONLY なし:ページ移動によるデータ圧縮。
  • TRUNCATEONLY あり:ファイル末尾の空きページを切り捨て。

sys.dm_databese_backups

sys.dm_database_backups - SQL Server | Microsoft Learn

  • 自動バックアップの履歴を表示できる。
  • backup_type でバックアップの種類がわかる。
SELECT TOP 10 * 
FROM sys.dm_database_backups 
ORDER BY backup_finish_date DESC;

注意

ログサイズの増加チェック

高速データベース復旧 - Azure SQL | Microsoft Learn

  • ADR(高速データベース復旧)の機能に注意が必要。
  • Azure SQL Database の場合、ADR を無効化できない。
  • ADR はログバックアップ処理のタイミングで動作する。
  • 問題
    • トランザクション中でコミットしていない状況であっても、ADR でログの切り捨てが行われる。
    • ログサイズがどれだけ増加したか把握できない。
  • 対策
    • sys.dm_databese_backups でログバックアップ処理の完了を確認して、サイズ増加のチェックを行う。
    • トランザクションが短時間で終わるようにする。(例:スケールアップ etc.)
  • 補足
    • ADR でログの切り捨てが発生しても、ロールバックなど問題なく行えるらしい。。。



以上

SQL Server - T-SQL オートコミット/トランザクション

オートコミット(自動コミット)

  • 既定は "有効" で動作する。
  • INSERT・UPDATE・DELETE を実行すると、即時にコミットされる。

以下のテーブルで試す。

USE SampleDb;
IF object_id(N'SampleTable1') is not null DROP TABLE SampleTable1;
CREATE TABLE SampleTable1 (Id INT PRIMARY KEY, Data1 CHAR(10));

以下のINSERTを試す。ID3 が重複した状態。

USE SampleDb;

INSERT INTO SampleTable1 (Id, Data1) VALUES (1, 'xxx');
INSERT INTO SampleTable1 (Id, Data1) VALUES (2, 'xxx');
INSERT INTO SampleTable1 (Id, Data1) VALUES (3, 'xxx');

-- 重複データを登録
INSERT INTO SampleTable1 (Id, Data1) VALUES (3, 'xxx');
  • 結果
    • ID3 の重複部分はエラーが表示された。
    • ID1~3 のデータを登録できた。コミットされた。


トランザクション

明示的なトランザクション

BEGIN TRANSACTION (Transact-SQL) - SQL Server | Microsoft Learn

USE SampleDb;
IF object_id(N'SampleTable1') is not null DROP TABLE SampleTable1;
CREATE TABLE SampleTable1 (Id INT PRIMARY KEY, Data1 CHAR(10));
GO

BEGIN TRY
    BEGIN TRANSACTION;
    
    INSERT INTO SampleTable1 (Id, Data1) VALUES (1, 'xxx');
    INSERT INTO SampleTable1 (Id, Data1) VALUES (2, 'xxx');
    INSERT INTO SampleTable1 (Id, Data1) VALUES (3, 'xxx');
    
    -- 重複データ
    --INSERT INTO SampleTable1 (Id, Data1) VALUES (3, 'xxx');
    -- ↑このクエリの有無で、コミット or ロールバックされることを確認。

    COMMIT;

END TRY
BEGIN CATCH
    ROLLBACK;
    PRINT ERROR_MESSAGE();
END CATCH

暗黙的なトランザクション

SET IMPLICIT_TRANSACTIONS (Transact-SQL) - SQL Server | Microsoft Learn

USE SampleDb;
IF object_id(N'SampleTable1') is not null DROP TABLE SampleTable1;
CREATE TABLE SampleTable1 (Id INT PRIMARY KEY, Data1 CHAR(10));
GO

SET IMPLICIT_TRANSACTIONS ON;

BEGIN TRY
    --暗黙的なトランザクション
    --BEGIN TRANSACTION;
    
    INSERT INTO SampleTable1 (Id, Data1) VALUES (1, 'xxx');
    INSERT INTO SampleTable1 (Id, Data1) VALUES (2, 'xxx');
    INSERT INTO SampleTable1 (Id, Data1) VALUES (3, 'xxx');
    
    -- 重複データ
    --INSERT INTO SampleTable1 (Id, Data1) VALUES (3, 'xxx');
    -- ↑このクエリの有無で、コミット or ロールバックされることを確認。
    
    COMMIT;

END TRY
BEGIN CATCH
    ROLLBACK;
    PRINT ERROR_MESSAGE();
END CATCH

SET IMPLICIT_TRANSACTIONS OFF;



以上