ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

ติดตั้ง SQL Server Express และตั้งสำรองข้อมูลอัตโนมัติ
Home ติดตั้ง SQL Server Express และตั้งสำรองข้อมูลอัตโนมัติ

ติดตั้ง SQL Server Express และตั้งสำรองข้อมูลอัตโนมัติ

SQL Server Express เป็นรุ่นที่ใช้งานได้ฟรีโดยไม่มีค่าลิขสิทธิ์ เหมาะกับระบบงานขนาดเล็กถึงกลาง โดยมีข้อจำกัดที่ต้องรู้ก่อนวางแผน ฐานข้อมูลละไม่เกิน 10 GB ใช้หน่วยความจำได้ 1410 MB และใช้ CPU ได้ไม่เกิน 4 คอร์หรือ 1 ซ็อกเก็ต

ข้อจำกัดที่กระทบงานดูแลระบบมากที่สุดคือไม่มี SQL Server Agent จึงตั้งงานสำรองข้อมูลตามเวลาจากในตัวโปรแกรมไม่ได้ คู่มือนี้แก้ด้วยการใช้สคริปต์ร่วมกับ Task Scheduler ซึ่งใช้งานได้ดีไม่แพ้กัน

สิ่งที่ต้องเตรียม

  • Windows Server 2019 ขึ้นไป
  • หน่วยความจำอย่างน้อย 4 GB และพื้นที่ดิสก์ 10 GB
  • สิทธิ์ Administrator

ขั้นตอนที่ 1: ติดตั้ง

ดาวน์โหลดตัวติดตั้งจากเว็บไซต์ของ Microsoft แล้วติดตั้งแบบไม่ต้องโต้ตอบ

.\SQLEXPR_x64_ENU.exe /qs /ACTION=Install /FEATURES=SQLEngine `
  /INSTANCENAME=SQLEXPRESS `
  /SQLSVCACCOUNT="NT AUTHORITY\NETWORK SERVICE" `
  /SQLSYSADMINACCOUNTS="BUILTIN\Administrators" `
  /TCPENABLED=1 `
  /SECURITYMODE=SQL /SAPWD="รหัสผ่านที่แข็งแรง" `
  /IACCEPTSQLSERVERLICENSETERMS

ตรวจว่าติดตั้งสำเร็จ

Get-Service | Where-Object Name -like "MSSQL*"
sqlcmd -S .\SQLEXPRESS -Q "SELECT @@VERSION;"

ติดตั้งเครื่องมือบรรทัดคำสั่งเพิ่มหากยังไม่มี

sqlcmd -?

ขั้นตอนที่ 2: เปิดการเชื่อมต่อจากเครือข่าย

SQL Server Express ปิดการเชื่อมต่อผ่าน TCP/IP ไว้ตามค่าเริ่มต้น ต้องเปิดเองผ่าน SQL Server Configuration Manager หรือด้วยคำสั่ง

$wmi = New-Object 'Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer'
$tcp = $wmi.GetSmoObject("ManagedComputer[@Name='$env:COMPUTERNAME']/ServerInstance[@Name='SQLEXPRESS']/ServerProtocol[@Name='Tcp']")
$tcp.IsEnabled = $true
$tcp.Alter()

# ตั้งพอร์ตคงที่แทนพอร์ตแบบสุ่ม
$tcp.IPAddresses | Where-Object Name -eq 'IPAll' | ForEach-Object {
  $_.IPAddressProperties['TcpDynamicPorts'].Value = ''
  $_.IPAddressProperties['TcpPort'].Value = '1433'
}
$tcp.Alter()

Restart-Service 'MSSQL$SQLEXPRESS' -Force

เปิด Firewall

New-NetFirewallRule -DisplayName "SQL Server Express" `
  -Direction Inbound -Protocol TCP -LocalPort 1433 -Action Allow `
  -RemoteAddress 10.0.0.0/24

ทดสอบจากเครื่องอื่น

Test-NetConnection 10.0.0.61 -Port 1433

ขั้นตอนที่ 3: สร้างฐานข้อมูลและผู้ใช้

sqlcmd -S .\SQLEXPRESS -Q "CREATE DATABASE myapp;"

sqlcmd -S .\SQLEXPRESS -Q "
CREATE LOGIN myapp_user WITH PASSWORD = 'รหัสผ่านที่แข็งแรง';
USE myapp;
CREATE USER myapp_user FOR LOGIN myapp_user;
ALTER ROLE db_datareader ADD MEMBER myapp_user;
ALTER ROLE db_datawriter ADD MEMBER myapp_user;
"

อย่าให้แอปใช้บัญชี sa ให้สิทธิ์เท่าที่จำเป็นเสมอ และปิดบัญชี sa หากไม่ได้ใช้

sqlcmd -S .\SQLEXPRESS -Q "ALTER LOGIN sa DISABLE;"

ขั้นตอนที่ 4: ตั้งโหมดการกู้คืนให้เหมาะสม

sqlcmd -S .\SQLEXPRESS -Q "
SELECT name, recovery_model_desc, state_desc FROM sys.databases;
"

โหมด SIMPLE ไม่เก็บ Transaction Log ไว้ จึงกู้ย้อนเวลาไม่ได้แต่ Log ไม่โต ส่วนโหมด FULL กู้ย้อนเวลาได้แต่ต้องสำรอง Log เป็นระยะ ไม่เช่นนั้นไฟล์ Log จะโตจนดิสก์เต็ม

-- สำหรับระบบที่ยอมให้ข้อมูลหายได้ถึงรอบสำรองล่าสุด
ALTER DATABASE myapp SET RECOVERY SIMPLE;

-- สำหรับระบบที่ต้องกู้ย้อนเวลาได้
ALTER DATABASE myapp SET RECOVERY FULL;

ขั้นตอนที่ 5: เขียนสคริปต์สำรองข้อมูล

notepad C:\Scripts\sql-backup.ps1
$ErrorActionPreference = 'Stop'

$server = '.\SQLEXPRESS'
$dest   = 'D:\Backups\SQL'
$stamp  = Get-Date -Format 'yyyyMMdd-HHmm'
$keep   = 14

New-Item -ItemType Directory -Path $dest -Force | Out-Null

$dbs = Invoke-Sqlcmd -ServerInstance $server -Query "
  SELECT name FROM sys.databases
  WHERE database_id > 4 AND state = 0;"

foreach ($db in $dbs) {
  $n    = $db.name
  $file = Join-Path $dest "$n-$stamp.bak"
  Invoke-Sqlcmd -ServerInstance $server -QueryTimeout 0 -Query "
    BACKUP DATABASE [$n] TO DISK = N'$file'
    WITH COMPRESSION, CHECKSUM, INIT, STATS = 10;"
  Write-Output "สำรอง $n แล้ว: $file"
}

# ตรวจความถูกต้องของไฟล์ที่เพิ่งสร้าง
Get-ChildItem $dest -Filter "*-$stamp.bak" | ForEach-Object {
  Invoke-Sqlcmd -ServerInstance $server -Query "RESTORE VERIFYONLY FROM DISK = N'$($_.FullName)';"
  Write-Output "ตรวจสอบผ่าน: $($_.Name)"
}

# ลบไฟล์เก่า
Get-ChildItem $dest -Filter '*.bak' |
  Where-Object LastWriteTime -lt (Get-Date).AddDays(-$keep) |
  Remove-Item -Force

ติดตั้งโมดูลที่ต้องใช้

Install-Module -Name SqlServer -Scope AllUsers -Force -AllowClobber

สังเกตคำสั่ง RESTORE VERIFYONLY ซึ่งตรวจว่าไฟล์สำรองอ่านได้จริง ควรมีเสมอเพราะไฟล์สำรองที่เสียหายจะรู้ตัวก็ต่อเมื่อต้องกู้จริง

ขั้นตอนที่ 6: ตั้งเวลาด้วย Task Scheduler

$action  = New-ScheduledTaskAction -Execute 'powershell.exe' `
             -Argument '-NoProfile -ExecutionPolicy Bypass -File C:\Scripts\sql-backup.ps1'
$trigger = New-ScheduledTaskTrigger -Daily -At 1:30am

Register-ScheduledTask -TaskName "SQL Express Backup" `
  -Action $action -Trigger $trigger `
  -User "SYSTEM" -RunLevel Highest -Force

Start-ScheduledTask -TaskName "SQL Express Backup"
Get-ScheduledTaskInfo -TaskName "SQL Express Backup"

สำหรับฐานข้อมูลที่ใช้โหมด FULL ให้เพิ่มงานสำรอง Transaction Log ทุกชั่วโมงด้วย

BACKUP LOG [myapp] TO DISK = N'D:\Backups\SQL\myapp-log.trn' WITH COMPRESSION, INIT;

ขั้นตอนที่ 7: กู้คืน

-- ดูเนื้อหาของไฟล์สำรอง
RESTORE FILELISTONLY FROM DISK = N'D:\Backups\SQL\myapp-20260925-0130.bak';

-- กู้ไปยังชื่อใหม่เพื่อตรวจสอบก่อน
RESTORE DATABASE myapp_test
FROM DISK = N'D:\Backups\SQL\myapp-20260925-0130.bak'
WITH MOVE 'myapp'     TO 'D:\Data\myapp_test.mdf',
     MOVE 'myapp_log' TO 'D:\Data\myapp_test_log.ldf',
     REPLACE, RECOVERY;

ขั้นตอนที่ 8: เฝ้าดูขีดจำกัดของรุ่นฟรี

SELECT DB_NAME(database_id) AS db,
       CAST(SUM(size) * 8.0 / 1024 AS DECIMAL(10,1)) AS size_mb
FROM sys.master_files
WHERE type = 0
GROUP BY database_id
ORDER BY size_mb DESC;

เมื่อฐานข้อมูลใกล้ 10 GB ต้องวางแผนล่วงหน้า ทางเลือกคือย้ายข้อมูลเก่าออกไปฐานข้อมูลอื่น แยกตารางใหญ่ไปคนละฐานข้อมูล หรืออัปเกรดเป็นรุ่นที่มีลิขสิทธิ์

ปัญหาที่พบบ่อย

เชื่อมต่อจากเครื่องอื่นไม่ได้

ตรวจสี่ข้อ TCP/IP เปิดแล้ว พอร์ตตั้งเป็น 1433 คงที่ Firewall เปิดแล้ว และบริการ SQL Server Browser ทำงานหากเชื่อมต่อด้วยชื่ออินสแตนซ์

Set-Service SQLBrowser -StartupType Automatic
Start-Service SQLBrowser

ไฟล์ Log โตจนดิสก์เต็ม

ฐานข้อมูลอยู่ในโหมด FULL แต่ไม่ได้สำรอง Transaction Log เลย แก้โดยเปลี่ยนเป็น SIMPLE หากไม่ต้องกู้ย้อนเวลา หรือเพิ่มงานสำรอง Log ตามขั้นตอนที่ 6

ฐานข้อมูลถึงขีดจำกัด 10 GB

จะได้ข้อผิดพลาดเมื่อพยายามเขียนเพิ่ม ตรวจขนาดตามขั้นตอนที่ 8 และย้ายข้อมูลเก่าออกก่อนจะถึงจุดนั้น

Task Scheduler รันแล้วไม่สำเร็จ

ตรวจว่าบัญชี SYSTEM มีสิทธิ์ทั้งบน SQL Server และโฟลเดอร์ปลายทาง และใส่ -NoProfile ในพารามิเตอร์เสมอ ดูผลลัพธ์ได้จาก Task Scheduler ในแท็บ History

ต้องการวางระบบฐานข้อมูลบน Windows พร้อมการสำรองข้อมูลที่ตรวจสอบได้ ติดต่อ THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security