一、SQL Admin与CentOS环境概述
SQL Admin是用于管理SQL Server和其他数据库的Web管理工具,在CentOS环境中部署SQL Admin可以提供统一的数据库管理界面。版本兼容性测试是确保SQL Admin在CentOS上稳定运行的关键步骤,正确的兼容性测试能避免生产环境中的意外故障。
在CentOS上进行SQL Admin版本兼容性测试需要考虑多个维度:操作系统版本、数据库版本、依赖组件版本、网络配置等。本指南将详细介绍完整的测试流程和最佳实践,帮助运维人员在部署前全面评估兼容性风险。
本章核心知识点:
- SQL Admin支持的操作系统和数据库版本
- CentOS与SQL Admin的版本对应关系
- 测试环境规划与资源准备
- 测试数据的准备与清理
二、测试环境准备
2.1 CentOS系统要求
在进行兼容性测试前,需要确保CentOS系统满足SQL Admin的运行要求。
操作系统版本支持:
| CentOS版本 | SQL Admin 1.x | SQL Admin 2.x | SQL Admin 3.x |
|---|---|---|---|
| CentOS 7 | ✅ 支持 | ✅ 支持 | ⚠️ 部分支持 |
| CentOS Stream 8 | ✅ 支持 | ✅ 支持 | ✅ 支持 |
| CentOS Stream 9 | ⚠️ 兼容 | ✅ 支持 | ✅ 支持 |
系统资源要求:
| 组件 | 最低配置 | 推荐配置 |
|---|---|---|
| CPU | 2核 | 4核+ |
| 内存 | 4GB | 8GB+ |
| 磁盘空间 | 20GB | 50GB+ |
| 网络 | 100Mbps | 1Gbps+ |
系统依赖包安装:
# CentOS 7 安装依赖
sudo yum install -y \
curl \
wget \
unzip \
git \
python3 \
python3-pip \
libffi \
gcc \
openssl-devel
# CentOS Stream 8/9 安装依赖
sudo dnf install -y \
curl \
wget \
unzip \
git \
python3 \
python3-pip \
libffi-devel \
gcc \
openssl-devel \
redhat-rpm-config
# 安装SQL Server命令行工具(用于测试连接)
sudo curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | \
sudo gpg --dearmor -o /usr/share/keyrings/microsoft.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] \
https://packages.microsoft.com/ubuntu/22.04/prod \
jammy main" | sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y mssql-tools unixodbc-dev
echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc
source ~/.bashrc
2.2 SQL Admin安装
根据CentOS版本选择合适的SQL Admin安装方式:
方式一:Docker容器部署(推荐)
# 安装Docker
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
# 拉取SQL Admin镜像(选择稳定版本)
docker pull sqladmin:3.2
# 运行容器
docker run -d \
--name sqladmin \
-p 8080:8080 \
-p 8443:8443 \
-e DB_HOST=your_sql_server_host \
-e DB_PORT=1433 \
-e DB_USER=your_username \
-e DB_PASSWORD=your_password \
--restart unless-stopped \
sqladmin:3.2
# 验证容器运行状态
docker ps | grep sqladmin
docker logs sqladmin
方式二:直接安装
# 下载SQL Admin安装包(v3.2)
cd /opt
sudo wget https://github.com/sqladmin/releases/download/v3.2/sqladmin-3.2-linux-amd64.tar.gz
sudo tar -xzf sqladmin-3.2-linux-amd64.tar.gz
cd sqladmin-3.2
# 创建运行用户
sudo useradd -m -s /bin/bash sqladmin
sudo chown -R sqladmin:sqladmin /opt/sqladmin-3.2
# 创建systemd服务文件
sudo cat > /etc/systemd/system/sqladmin.service << 'EOF'
[Unit]
Description=SQL Admin Service
After=network.target
[Service]
Type=simple
User=sqladmin
WorkingDirectory=/opt/sqladmin-3.2
ExecStart=/opt/sqladmin-3.2/bin/sqladmin server
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# 启动服务
sudo systemctl daemon-reload
sudo systemctl start sqladmin
sudo systemctl enable sqladmin
# 检查服务状态
sudo systemctl status sqladmin
2.3 测试数据库准备
创建用于兼容性测试的数据库环境:
# 连接到SQL Server测试实例
/opt/mssql-tools18/bin/sqlcmd -S your_test_server -U test_user -P test_password
# 创建测试数据库
CREATE DATABASE CompatibilityTestDB;
GO
# 创建测试表
USE CompatibilityTestDB;
GO
CREATE TABLE TestUsers (
UserID INT PRIMARY KEY IDENTITY(1,1),
UserName NVARCHAR(50) NOT NULL,
Email NVARCHAR(100),
CreatedDate DATETIME DEFAULT GETDATE(),
Status TINYINT DEFAULT 1
);
GO
CREATE TABLE TestOrders (
OrderID INT PRIMARY KEY IDENTITY(1,1),
UserID INT FOREIGN KEY REFERENCES TestUsers(UserID),
OrderDate DATETIME DEFAULT GETDATE(),
TotalAmount DECIMAL(10,2),
Status NVARCHAR(20)
);
GO
CREATE TABLE TestProducts (
ProductID INT PRIMARY KEY IDENTITY(1,1),
ProductName NVARCHAR(100),
Price DECIMAL(10,2),
Stock INT,
CategoryID INT
);
GO
-- 插入测试数据
DECLARE @i INT = 1;
WHILE @i <= 100
BEGIN
INSERT INTO TestUsers (UserName, Email)
VALUES ('User_' + CAST(@i AS VARCHAR), 'user' + CAST(@i AS VARCHAR) + '@test.com');
SET @i = @i + 1;
END;
GO
SELECT COUNT(*) FROM TestUsers;
GO
三、版本兼容性测试矩阵
3.1 组件版本兼容性矩阵
在进行兼容性测试前,需要明确各组件之间的版本对应关系:
SQL Admin与SQL Server版本兼容:
| SQL Admin版本 | SQL Server 2017 | SQL Server 2019 | SQL Server 2022 |
|---|---|---|---|
| 1.x | ✅ 完全支持 | ✅ 完全支持 | ⚠️ 部分支持 |
| 2.x | ✅ 完全支持 | ✅ 完全支持 | ✅ 完全支持 |
| 3.x | ⚠️ 兼容 | ✅ 完全支持 | ✅ 完全支持 |
操作系统版本兼容性:
| 操作系统 | SQL Admin 1.5 | SQL Admin 2.3 | SQL Admin 3.2 |
|---|---|---|---|
| CentOS 7.9 | ✅ 通过 | ✅ 通过 | ⚠️ 警告 |
| CentOS Stream 8 | ✅ 通过 | ✅ 通过 | ✅ 通过 |
| CentOS Stream 9 | ⚠️ 警告 | ✅ 通过 | ✅ 通过 |
依赖组件版本要求:
| 组件 | 最低版本 | 推荐版本 | 最高版本 |
|---|---|---|---|
| Python | 3.8 | 3.10 | 3.12 |
| Node.js | 14.x | 18.x | 20.x |
| OpenSSL | 1.1.1 | 3.0.x | 3.2.x |
| Glibc | 2.17 | 2.35 | 2.38 |
3.2 功能模块兼容性测试项
根据SQL Admin的功能模块,制定兼容性测试清单:
核心功能测试项:
| 功能模块 | 测试用例数 | 优先级 | 预期通过率 |
|---|---|---|---|
| 用户认证 | 15 | P0 | 100% |
| 数据库连接 | 20 | P0 | 100% |
| 查询执行 | 25 | P0 | 100% |
| 数据导出 | 10 | P1 | 95% |
| 备份管理 | 12 | P1 | 95% |
| 性能监控 | 8 | P1 | 90% |
| 日志查看 | 6 | P2 | 85% |
| API接口 | 18 | P1 | 95% |
浏览器兼容性:
| 浏览器 | 支持版本 | 注意事项 |
|---|---|---|
| Chrome | 90+ | 推荐使用 |
| Firefox | 88+ | 完全支持 |
| Safari | 14+ | 可能有小问题 |
| Edge | 90+ | 完全支持 |
四、连接兼容性测试
4.1 SQL Server连接测试
验证SQL Admin与SQL Server的连接兼容性:
测试脚本 – 连接测试(Python):
#!/usr/bin/env python3
"""
SQL Admin连接兼容性测试脚本
"""
import os
import sys
import time
import logging
from datetime import datetime
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('/tmp/sqladmin_test.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
class SQLConnectionTester:
def __init__(self, host, port, username, password):
self.host = host
self.port = port
self.username = username
self.password = password
self.connection = None
def test_connection(self):
"""测试SQL Server连接"""
try:
import pyodbc
conn_str = f"DRIVER={{ODBC Driver 18 for SQL Server}};\
SERVER={self.host},{self.port};\
DATABASE=master;\
UID={self.username};\
PWD={self.password};\
TrustServerCertificate=yes;"
logger.info(f"尝试连接 {self.host}:{self.port}")
self.connection = pyodbc.connect(conn_str, timeout=30)
logger.info("✅ SQL Server连接成功")
return True
except ImportError:
logger.error("缺少pyodbc驱动,请先安装: pip3 install pyodbc")
return False
except Exception as e:
logger.error(f"❌ 连接失败: {str(e)}")
return False
def test_query_execution(self):
"""测试查询执行"""
if not self.connection:
logger.error("未建立连接,跳过查询测试")
return False
try:
cursor = self.connection.cursor()
# 测试简单查询
cursor.execute("SELECT @@VERSION")
version = cursor.fetchone()
logger.info(f"✅ 查询执行成功: SQL Server版本 - {version[0][:50]}...")
# 测试系统数据库查询
cursor.execute("SELECT name, state_desc FROM sys.databases")
databases = cursor.fetchall()
logger.info(f"✅ 系统数据库查询成功,共 {len(databases)} 个数据库")
# 测试用户数据库查询
cursor.execute("USE CompatibilityTestDB")
cursor.execute("SELECT COUNT(*) FROM TestUsers")
count = cursor.fetchone()[0]
logger.info(f"✅ 用户数据库查询成功,TestUsers表有 {count} 条记录")
cursor.close()
return True
except Exception as e:
logger.error(f"❌ 查询执行失败: {str(e)}")
return False
def test_data_modification(self):
"""测试数据修改操作"""
if not self.connection:
return False
try:
cursor = self.connection.cursor()
# 测试INSERT
test_username = f"test_user_{int(time.time())}"
cursor.execute(
"INSERT INTO TestUsers (UserName, Email) VALUES (?, ?)",
(test_username, f"{test_username}@test.com")
)
self.connection.commit()
logger.info(f"✅ INSERT测试成功: 插入用户 {test_username}")
# 测试UPDATE
cursor.execute(
"UPDATE TestUsers SET Status = 2 WHERE UserName = ?",
(test_username,)
)
self.connection.commit()
logger.info(f"✅ UPDATE测试成功: 更新用户 {test_username}")
# 测试DELETE
cursor.execute(
"DELETE FROM TestUsers WHERE UserName = ?",
(test_username,)
)
self.connection.commit()
logger.info(f"✅ DELETE测试成功: 删除用户 {test_username}")
cursor.close()
return True
except Exception as e:
logger.error(f"❌ 数据修改失败: {str(e)}")
return False
def test_transaction_rollback(self):
"""测试事务回滚"""
if not self.connection:
return False
try:
cursor = self.connection.cursor()
# 开始事务
cursor.execute("BEGIN TRANSACTION")
# 插入测试数据
test_username = f"rollback_test_{int(time.time())}"
cursor.execute(
"INSERT INTO TestUsers (UserName, Email) VALUES (?, ?)",
(test_username, f"{test_username}@test.com")
)
# 回滚事务
cursor.execute("ROLLBACK TRANSACTION")
# 验证数据未被插入
cursor.execute(
"SELECT COUNT(*) FROM TestUsers WHERE UserName = ?",
(test_username,)
)
count = cursor.fetchone()[0]
if count == 0:
logger.info(f"✅ 事务回滚测试成功")
else:
logger.error(f"❌ 事务回滚失败,数据已提交")
cursor.close()
return count == 0
except Exception as e:
logger.error(f"❌ 事务测试失败: {str(e)}")
return False
def test_stored_procedure(self):
"""测试存储过程执行"""
if not self.connection:
return False
try:
cursor = self.connection.cursor()
# 创建测试存储过程
cursor.execute("""
CREATE OR ALTER PROCEDURE sp_TestCompatibility
@InputParam INT
AS
BEGIN
SELECT @InputParam AS InputValue,
GETDATE() AS CurrentTime,
@@VERSION AS ServerVersion
END
""")
self.connection.commit()
# 调用存储过程
cursor.execute("EXEC sp_TestCompatibility @InputParam = 42")
result = cursor.fetchone()
if result and result[0] == 42:
logger.info(f"✅ 存储过程测试成功")
else:
logger.error(f"❌ 存储过程返回结果异常")
cursor.close()
return True
except Exception as e:
logger.error(f"❌ 存储过程测试失败: {str(e)}")
return False
def close(self):
"""关闭连接"""
if self.connection:
self.connection.close()
logger.info("连接已关闭")
# 执行测试
def run_all_tests():
tester = SQLConnectionTester(
host=os.environ.get('TEST_DB_HOST', 'localhost'),
port=os.environ.get('TEST_DB_PORT', '1433'),
username=os.environ.get('TEST_DB_USER', 'sa'),
password=os.environ.get('TEST_DB_PASSWORD', '')
)
results = {
'connection': tester.test_connection(),
'query': tester.test_query_execution() if tester.connection else False,
'modification': tester.test_data_modification() if tester.connection else False,
'rollback': tester.test_transaction_rollback() if tester.connection else False,
'procedure': tester.test_stored_procedure() if tester.connection else False
}
tester.close()
logger.info("=" * 50)
logger.info("测试结果汇总:")
for test_name, passed in results.items():
status = "✅ 通过" if passed else "❌ 失败"
logger.info(f" {test_name}: {status}")
all_passed = all(results.values())
logger.info(f"总体结果: {'✅ 全部通过' if all_passed else '❌ 部分失败'}")
return all_passed
if __name__ == '__main__':
success = run_all_tests()
sys.exit(0 if success else 1)
测试执行命令:
# 安装依赖
pip3 install pyodbc
# 设置环境变量
export TEST_DB_HOST=your_sql_server_host
export TEST_DB_PORT=1433
export TEST_DB_USER=your_username
export TEST_DB_PASSWORD=your_password
# 运行测试
python3 /tmp/sqladmin_connection_test.py
# 查看测试日志
cat /tmp/sqladmin_test.log
4.2 连接参数兼容性测试
测试不同连接参数组合的兼容性:
连接参数测试矩阵:
| 参数 | 值1 | 值2 | 值3 | 预期结果 |
|---|---|---|---|---|
| 加密模式 | Mandatory | Optional | Strict | 根据服务器配置决定 |
| 证书验证 | True | False | – | False时应有警告 |
| 连接超时 | 5s | 30s | 60s | 超时应返回错误 |
| 查询超时 | 10s | 30s | 120s | 超时应中断查询 |
| 自动提交 | On | Off | – | Off时应支持事务 |
批量连接测试脚本:
#!/bin/bash
# 连接池压力测试脚本
TEST_HOST=${1:-localhost}
TEST_PORT=${2:-1433}
TEST_USER=${3:-sa}
TEST_PASS=${4:-password}
echo "开始连接兼容性测试..."
echo "目标服务器: $TEST_HOST:$TEST_PORT"
# 连续连接测试
for i in {1..50}; do
/opt/mssql-tools18/bin/sqlcmd -S $TEST_HOST,$TEST_PORT -U $TEST_USER -P $TEST_PASS -Q "SELECT 1" -b
if [ $? -eq 0 ]; then
echo "[$i/50] 连接成功"
else
echo "[$i/50] 连接失败"
fi
done
# 并发连接测试
echo "开始并发连接测试..."
for i in {1..10}; do
/opt/mssql-tools18/bin/sqlcmd -S $TEST_HOST,$TEST_PORT -U $TEST_USER -P $TEST_PASS -Q "SELECT @@SPID" -b &
done
wait
echo "连接测试完成"
五、查询兼容性测试
5.1 SQL语法兼容性测试
验证SQL Admin对不同SQL语法特性的支持:
语法兼容性测试用例:
-- 测试CTE(公用表表达式)
WITH MonthlySales AS (
SELECT
YEAR(OrderDate) AS Year,
MONTH(OrderDate) AS Month,
SUM(TotalAmount) AS TotalSales
FROM TestOrders
GROUP BY YEAR(OrderDate), MONTH(OrderDate)
)
SELECT * FROM MonthlySales ORDER BY Year, Month;
-- 测试窗口函数
SELECT
UserID,
COUNT(*) AS OrderCount,
SUM(TotalAmount) AS TotalSpent,
AVG(TotalAmount) OVER (PARTITION BY UserID) AS AvgOrderValue,
RANK() OVER (ORDER BY SUM(TotalAmount) DESC) AS SpendingRank
FROM TestOrders
GROUP BY UserID;
-- 测试JSON函数
SELECT
UserID,
UserName,
JSON_VALUE(Metadata, '$.preference.language') AS Language,
JSON_QUERY(Orders, '$') AS OrdersJson
FROM TestUsers;
-- 测试PIVOT/UNPIVOT
SELECT * FROM (
SELECT UserID, YEAR(OrderDate) AS OrderYear, TotalAmount
FROM TestOrders
) AS SourceTable
PIVOT (
SUM(TotalAmount)
FOR OrderYear IN ([2024], [2025], [2026])
) AS PivotTable;
-- 测试MERGE语句
MERGE INTO TestProducts AS target
USING (SELECT 1 AS ProductID, 99.99 AS NewPrice) AS source
ON target.ProductID = source.ProductID
WHEN MATCHED THEN
UPDATE SET Price = source.NewPrice
WHEN NOT MATCHED THEN
INSERT (ProductName, Price, Stock, CategoryID)
VALUES ('New Product', source.NewPrice, 100, 1);
执行测试脚本:
#!/bin/bash
# SQL语法兼容性测试脚本
SQL_FILE="/tmp/sql_compatibility_test.sql"
# 创建测试SQL文件
cat > $SQL_FILE << 'EOF'
-- 第1组:CTE测试
WITH RankedUsers AS (
SELECT
UserID,
UserName,
COUNT(*) OVER () AS TotalUsers,
ROW_NUMBER() OVER (ORDER BY UserID) AS RowNum
FROM TestUsers
)
SELECT * FROM RankedUsers WHERE RowNum <= 10;
-- 第2组:窗口函数测试
SELECT
ProductID,
ProductName,
Price,
LAG(Price, 1) OVER (ORDER BY Price) AS PreviousPrice,
LEAD(Price, 1) OVER (ORDER BY Price) AS NextPrice,
Price - LAG(Price, 1) OVER (ORDER BY Price) AS PriceDiff
FROM TestProducts
ORDER BY Price;
-- 第3组:递归CTE测试
WITH RecursiveCTE AS (
SELECT 1 AS Level, 'Root' AS Node
UNION ALL
SELECT Level + 1, Node + '->Child'
FROM RecursiveCTE
WHERE Level < 5
)
SELECT * FROM RecursiveCTE;
-- 第4组:临时表测试
CREATE TABLE #TempResults (
ProductID INT,
TotalSold INT
);
INSERT INTO #TempResults
SELECT ProductID, COUNT(*)
FROM TestOrders
GROUP BY ProductID;
SELECT * FROM #TempResults ORDER BY TotalSold DESC;
DROP TABLE #TempResults;
EOF
# 执行测试
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "${DB_PASSWORD}" -i $SQL_FILE -b
# 清理
rm -f $SQL_FILE
5.2 编码兼容性测试
测试不同字符编码的处理能力:
编码测试用例:
-- 测试UTF-8编码
INSERT INTO TestUsers (UserName, Email) VALUES
(N'中文用户名', 'chinese@test.com'),
(N'日本語ユーザー', 'japanese@test.com'),
(N'한국어사용자', 'korean@test.com'),
(N'🔒加密用户🔑', 'emoji@test.com'),
(N'عربي用户名', 'arabic@test.com');
-- 验证编码存储
SELECT
UserID,
UserName,
LEN(UserName) AS CharLength,
DATALENGTH(UserName) AS ByteLength,
UNICODE(LEFT(UserName, 1)) AS FirstCharCode
FROM TestUsers
WHERE UserName LIKE N'%用户%'
OR UserName LIKE N'%ユーザー%'
OR UserName LIKE N'%사용자%';
-- 测试特殊字符处理
INSERT INTO TestUsers (UserName, Email) VALUES
(N'SQL''Injection''Test', 'sqli@test.com'),
(N'Backslash\\Test', 'backslash@test.com'),
(N'Tab Character', 'tab@test.com'),
(N'NewLine
Test', 'newline@test.com');
-- 验证特殊字符
SELECT
UserID,
UserName,
REPLACE(REPLACE(UserName, CHAR(9), '[TAB]'), CHAR(10), '[LF]') AS CleanUserName
FROM TestUsers
WHERE UserName LIKE '%Test%';
编码检测脚本:
#!/usr/bin/env python3
"""字符编码兼容性测试"""
import sys
def test_encoding_compatibility():
test_strings = [
'中文测试',
'English Test',
'日本語テスト',
'한국어 테스트',
'العربية اختبار',
'emoji 😄👍🎉',
'special chars: \' \" \\ / @ # $ % ^ & * ( )',
'mixed: 中文ABC123日本語',
]
encodings = ['utf-8', 'gbk', 'gb2312', 'latin-1']
print("字符编码兼容性测试")
print("=" * 60)
for test_str in test_strings:
print(f"\n测试字符串: {test_str}")
print(f"原始长度: {len(test_str)}")
for encoding in encodings:
try:
encoded = test_str.encode(encoding)
decoded = encoded.decode(encoding)
status = "✅" if decoded == test_str else "⚠️"
print(f" {status} {encoding}: 编码成功 ({len(encoded)} bytes)")
except Exception as e:
print(f" ❌ {encoding}: 编码失败 - {str(e)}")
print("\n编码测试完成")
if __name__ == '__main__':
test_encoding_compatibility()
六、性能与压力测试
6.1 响应时间测试
测量SQL Admin在不同操作下的响应时间:
性能测试脚本(Python):
#!/usr/bin/env python3
"""SQL Admin性能测试脚本"""
import time
import statistics
import pyodbc
class PerformanceTester:
def __init__(self, connection_string):
self.conn = pyodbc.connect(connection_string)
def measure_query_time(self, query, iterations=10):
"""测量查询执行时间"""
times = []
cursor = self.conn.cursor()
for i in range(iterations):
start = time.time()
cursor.execute(query)
cursor.fetchall()
end = time.time()
times.append((end - start) * 1000) # 转换为毫秒
cursor.close()
return {
'mean': statistics.mean(times),
'median': statistics.median(times),
'min': min(times),
'max': max(times),
'stdev': statistics.stdev(times) if len(times) > 1 else 0
}
def test_connection_pool(self):
"""测试连接池性能"""
cursor = self.conn.cursor()
# 测试批量查询性能
queries = [
"SELECT COUNT(*) FROM TestUsers",
"SELECT * FROM TestUsers WHERE UserID <= 100",
"SELECT * FROM TestOrders WHERE OrderDate >= '2026-01-01'",
"SELECT * FROM TestProducts WHERE Price > 100",
]
print("查询性能测试结果:")
print("-" * 60)
for query in queries:
result = self.measure_query_time(query, iterations=5)
print(f"\n查询: {query[:60]}...")
print(f" 平均: {result['mean']:.2f}ms")
print(f" 中位数: {result['median']:.2f}ms")
print(f" 最小: {result['min']:.2f}ms")
print(f" 最大: {result['max']:.2f}ms")
print(f" 标准差: {result['stdev']:.2f}ms")
cursor.close()
def stress_test(self, duration_seconds=60):
"""压力测试"""
print(f"\n开始压力测试(持续 {duration_seconds} 秒)...")
cursor = self.conn.cursor()
start_time = time.time()
request_count = 0
error_count = 0
while time.time() - start_time < duration_seconds:
try:
cursor.execute("SELECT @@SPID")
cursor.fetchone()
request_count += 1
except Exception as e:
error_count += 1
print(f"错误: {str(e)}")
cursor.close()
elapsed = time.time() - start_time
print(f"\n压力测试结果:")
print(f" 总请求数: {request_count}")
print(f" 错误数: {error_count}")
print(f" QPS: {request_count / elapsed:.2f}")
print(f" 错误率: {error_count / request_count * 100:.2f}%")
def close(self):
self.conn.close()
# 使用示例
conn_str = "DRIVER={ODBC Driver 18 for SQL Server};SERVER=localhost;DATABASE=CompatibilityTestDB;UID=sa;PWD=password;TrustServerCertificate=yes"
tester = PerformanceTester(conn_str)
tester.test_connection_pool()
tester.stress_test(duration_seconds=30)
tester.close()
6.2 并发兼容性测试
测试SQL Admin在高并发场景下的表现:
并发测试脚本:
#!/usr/bin/env python3
"""并发兼容性测试脚本"""
import threading
import queue
import time
from datetime import datetime
class ConcurrentTester:
def __init__(self, db_config, num_threads=10, requests_per_thread=20):
self.db_config = db_config
self.num_threads = num_threads
self.requests_per_thread = requests_per_thread
self.results = queue.Queue()
self.errors = queue.Queue()
def worker(self, thread_id):
"""工作线程"""
import pyodbc
try:
conn_str = f"DRIVER={{ODBC Driver 18 for SQL Server}};\
SERVER={self.db_config['host']};\
DATABASE={self.db_config['database']};\
UID={self.db_config['user']};\
PWD={self.db_config['password']};\
TrustServerCertificate=yes;"
conn = pyodbc.connect(conn_str)
cursor = conn.cursor()
for i in range(self.requests_per_thread):
start = time.time()
try:
cursor.execute("SELECT @@SPID")
cursor.fetchone()
elapsed = (time.time() - start) * 1000
self.results.put({
'thread': thread_id,
'request': i,
'time_ms': elapsed,
'success': True
})
except Exception as e:
self.errors.put({
'thread': thread_id,
'request': i,
'error': str(e)
})
cursor.close()
conn.close()
except Exception as e:
print(f"线程 {thread_id} 连接失败: {str(e)}")
def run(self):
"""运行并发测试"""
print(f"启动 {self.num_threads} 个并发线程,每个执行 {self.requests_per_thread} 个请求")
print("-" * 60)
start_time = time.time()
threads = []
for i in range(self.num_threads):
t = threading.Thread(target=self.worker, args=(i,))
t.start()
threads.append(t)
for t in threads:
t.join()
elapsed = time.time() - start_time
# 统计结果
result_list = []
while not self.results.empty():
result_list.append(self.results.get())
error_list = []
while not self.errors.empty():
error_list.append(self.errors.get())
# 输出结果
print(f"\n并发测试完成,耗时 {elapsed:.2f} 秒")
print(f"总请求数: {len(result_list)}")
print(f"总错误数: {len(error_list)}")
print(f"平均QPS: {len(result_list) / elapsed:.2f}")
if result_list:
times = [r['time_ms'] for r in result_list]
avg_time = sum(times) / len(times)
max_time = max(times)
print(f"平均响应时间: {avg_time:.2f}ms")
print(f"最大响应时间: {max_time:.2f}ms")
if error_list:
print(f"\n错误详情(前10条):")
for i, error in enumerate(error_list[:10]):
print(f" [{error['thread']}][{error['request']}] {error['error']}")
if __name__ == '__main__':
config = {
'host': 'localhost',
'database': 'CompatibilityTestDB',
'user': 'sa',
'password': 'password'
}
tester = ConcurrentTester(config, num_threads=10, requests_per_thread=20)
tester.run()
七、版本升级兼容性测试
7.1 数据迁移测试
在进行版本升级前,需要测试数据迁移的兼容性:
数据迁移测试脚本:
-- 创建迁移测试表
USE CompatibilityTestDB;
GO
-- 源表结构
CREATE TABLE SourceTable (
ID INT IDENTITY(1,1) PRIMARY KEY,
Col1 VARCHAR(50),
Col2 NVARCHAR(100),
Col3 DATETIME,
Col4 DECIMAL(10,2),
Col5 BIT DEFAULT 0,
Col6 XML,
Col7 VARBINARY(100)
);
-- 目标表结构(可能因版本不同而改变)
CREATE TABLE TargetTable (
ID INT,
Column1 VARCHAR(50),
Column2 NVARCHAR(100),
Column3 DATETIME,
Column4 DECIMAL(10,2),
Column5 BIT,
Column6 XML,
Column7 VARBINARY(100),
MigrationDate DATETIME DEFAULT GETDATE()
);
-- 插入测试数据
DECLARE @i INT = 1;
WHILE @i <= 1000
BEGIN
INSERT INTO SourceTable (Col1, Col2, Col3, Col4, Col5, Col6, Col7)
VALUES (
'Value_' + CAST(@i AS VARCHAR),
N'测试数据_' + CAST(@i AS NVARCHAR),
DATEADD(DAY, @i, '2026-01-01'),
@i * 1.5,
CASE WHEN @i % 2 = 0 THEN 1 ELSE 0 END,
'<Root><Item>Item' + CAST(@i AS VARCHAR) + '</Item></Root>',
CAST('TestData' + CAST(@i AS VARCHAR) AS VARBINARY(100))
);
SET @i = @i + 1;
END;
-- 执行迁移
INSERT INTO TargetTable (ID, Column1, Column2, Column3, Column4, Column5, Column6, Column7)
SELECT ID, Col1, Col2, Col3, Col4, Col5, Col6, Col7
FROM SourceTable;
-- 验证迁移结果
SELECT
'Source' AS TableName, COUNT(*) AS RowCount
FROM SourceTable
UNION ALL
SELECT
'Target' AS TableName, COUNT(*) AS RowCount
FROM TargetTable;
-- 数据完整性检查
SELECT
'Mismatch' AS CheckType,
COUNT(*) AS Count
FROM SourceTable s
LEFT JOIN TargetTable t ON s.ID = t.ID
WHERE t.ID IS NULL
UNION ALL
SELECT
'Data Difference' AS CheckType,
COUNT(*) AS Count
FROM SourceTable s
INNER JOIN TargetTable t ON s.ID = t.ID
WHERE s.Col1 <> t.Column1
OR s.Col2 <> t.Column2;
7.2 配置文件迁移测试
测试配置文件在不同版本间的兼容性:
配置文件迁移检查脚本:
#!/bin/bash
# 配置文件版本兼容性检查脚本
echo "SQL Admin配置文件版本兼容性检查"
echo "=================================="
# 检查当前配置文件
CONFIG_DIR="/opt/sqladmin/conf"
BACKUP_DIR="/opt/sqladmin/conf_backup"
if [ ! -d "$BACKUP_DIR" ]; then
mkdir -p "$BACKUP_DIR"
cp -r "$CONFIG_DIR"/* "$BACKUP_DIR/"
echo "配置文件已备份到 $BACKUP_DIR"
fi
# 检查关键配置文件
echo ""
echo "检查配置文件版本兼容性..."
# 检查database.json
if [ -f "$CONFIG_DIR/database.json" ]; then
echo "✅ database.json 存在"
# 检查必需字段
if grep -q '"host"' "$CONFIG_DIR/database.json" && \
grep -q '"port"' "$CONFIG_DIR/database.json" && \
grep -q '"database"' "$CONFIG_DIR/database.json"; then
echo "✅ database.json 字段完整"
else
echo "⚠️ database.json 缺少某些字段,可能需要调整"
fi
else
echo "❌ database.json 不存在"
fi
# 检查app.json
if [ -f "$CONFIG_DIR/app.json" ]; then
echo "✅ app.json 存在"
# 检查版本字段
if grep -q '"version"' "$CONFIG_DIR/app.json"; then
VERSION=$(grep '"version"' "$CONFIG_DIR/app.json" | cut -d'"' -f4)
echo " 当前版本: $VERSION"
fi
else
echo "❌ app.json 不存在"
fi
# 检查SSL配置
if [ -f "$CONFIG_DIR/ssl.json" ]; then
echo "✅ ssl.json 存在"
# 检查证书配置
if grep -q '"cert"' "$CONFIG_DIR/ssl.json" && \
grep -q '"key"' "$CONFIG_DIR/ssl.json"; then
echo "✅ SSL证书配置完整"
else
echo "⚠️ SSL配置可能不完整"
fi
else
echo "⚠️ ssl.json 不存在(可选)"
fi
# 输出迁移建议
echo ""
echo "配置文件迁移建议:"
echo "- 备份当前配置文件"
echo "- 检查新版本配置文件模板"
echo "- 逐一对比字段,添加缺失字段"
echo "- 测试配置文件加载"
echo "- 验证服务启动"
echo ""
echo "检查完成"
八、兼容性测试报告
8.1 测试结果汇总模板
生成测试报告是兼容性测试的重要环节:
测试报告模板:
# SQL Admin CentOS兼容性测试报告
## 测试信息
- 测试日期: 2026-05-11
- 测试人员: [姓名]
- SQL Admin版本: 3.2
- CentOS版本: CentOS Stream 9
- SQL Server版本: SQL Server 2022
## 测试环境
| 组件 | 版本 | 说明 |
|------|------|------|
| 操作系统 | CentOS Stream 9 | 64位 |
| Python | 3.10 | 系统默认 |
| Node.js | 18.x | 通过nvm安装 |
| SQL Admin | 3.2.0 | 最新稳定版 |
| SQL Server | 2022 | Ubuntu 22.04 |
## 测试结果汇总
| 测试项 | 通过 | 失败 | 通过率 |
|--------|------|------|--------|
| 连接兼容性 | 20 | 0 | 100% |
| 查询兼容性 | 25 | 1 | 96% |
| 数据操作 | 12 | 0 | 100% |
| 性能测试 | 8 | 1 | 89% |
| 编码测试 | 6 | 0 | 100% |
| 压力测试 | 3 | 0 | 100% |
## 详细测试结果
### 连接兼容性测试
- [x] 基本连接测试
- [x] 连接池测试
- [x] 加密连接测试
- [x] 超时设置测试
### 查询兼容性测试
- [x] DDL语句测试
- [x] DML语句测试
- [x] CTE测试
- [x] 窗口函数测试
- [ ] 递归查询测试(需进一步调试)
### 性能测试结果
| 操作类型 | 平均响应时间 | 最大响应时间 | 评价 |
|---------|-------------|-------------|------|
| SELECT | 15ms | 45ms | 优秀 |
| INSERT | 22ms | 68ms | 良好 |
| UPDATE | 25ms | 72ms | 良好 |
| DELETE | 18ms | 55ms | 优秀 |
## 发现的问题
### 问题1: 递归CTE执行失败
- 严重程度: 中
- 描述: 递归深度超过100时出现内存溢出
- 解决方案: 限制递归深度或升级SQL Server版本
### 问题2: XML数据类型处理延迟
- 严重程度: 低
- 描述: 大型XML文档查询响应较慢
- 解决方案: 优化XML索引或使用JSON替代
## 兼容性结论
**总体评估**: ✅ 通过
SQL Admin 3.2在CentOS Stream 9上与SQL Server 2022的兼容性测试基本通过,仅发现少量非关键问题。建议在生产环境中使用上述配置。
## 建议
1. 生产环境建议使用CentOS Stream 8以获得更好的兼容性
2. 定期执行兼容性测试以监控版本变化
3. 保持SQL Admin和SQL Server版本同步更新
8.2 自动化测试执行
使用自动化脚本定期执行兼容性测试:
自动化测试计划(cron):
#!/bin/bash
# SQL Admin兼容性自动化测试脚本
# 建议添加到cron: 0 2 * * * /opt/sqladmin/scripts/auto_compatibility_test.sh
LOG_DIR="/var/log/sqladmin"
DATE=$(date +%Y%m%d_%H%M%S)
REPORT_FILE="$LOG_DIR/compatibility_test_$DATE.html"
# 创建日志目录
mkdir -p $LOG_DIR
# 执行测试
echo "开始SQL Admin兼容性测试 - $DATE" | tee -a $LOG_DIR/compatibility_test.log
# 运行Python测试脚本
python3 /opt/sqladmin/scripts/sqladmin_compatibility_test.py \
--output $REPORT_FILE \
--db-host localhost \
--db-port 1433 \
--db-user sa \
--db-password "$SQLADMIN_DB_PASSWORD" \
2>&1 | tee -a $LOG_DIR/compatibility_test.log
# 发送报告(如果配置了邮件)
if [ -f "$REPORT_FILE" ]; then
echo "测试报告已生成: $REPORT_FILE"
# 可选:发送邮件通知
# mail -s "SQL Admin兼容性测试报告 - $DATE" admin@example.com < $REPORT_FILE
fi
# 清理旧报告(保留30天)
find $LOG_DIR -name "compatibility_test_*.html" -mtime +30 -delete
echo "测试完成 - $DATE" | tee -a $LOG_DIR/compatibility_test.log
九、常见问题与解决方案
9.1 连接问题
问题一:无法连接到SQL Server
# 排查步骤
# 1. 检查SQL Server服务状态
systemctl status mssql-server
# 2. 检查端口监听
netstat -tlnp | grep 1433
# 3. 测试端口连通性
telnet localhost 1433
curl -v telnet://localhost:1433
# 4. 检查防火墙规则
firewall-cmd --list-ports
firewall-cmd --add-port=1433/tcp --permanent
firewall-cmd --reload
# 5. 验证ODBC驱动
odbcinst -q -d
问题二:TLS/SSL连接失败
# 检查SSL配置
# 1. 查看SQL Server SSL配置
grep -i ssl /var/opt/mssql/mssql.conf
# 2. 测试加密连接
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P password -C # -C表示信任服务器证书
# 3. 检查OpenSSL版本
openssl version
# 4. 验证证书
openssl s_client -connect localhost:1433 -starttls sql
9.2 性能问题
问题:查询响应缓慢
-- 检查执行计划
SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT * FROM TestUsers WHERE UserID > 500
-- 检查索引
EXEC sp_helpindex 'TestUsers'
-- 检查统计信息
UPDATE STATISTICS TestUsers WITH FULLSCAN
-- 检查阻塞
SELECT
request_session_id AS spid,
blocking_session_id AS blocked,
DB_NAME(database_id) AS database_name,
OBJECT_NAME(object_id) AS table_name,
wait_type,
wait_time
FROM sys.dm_os_waiting_tasks
WHERE blocking_session_id > 0
9.3 版本兼容性问题
问题:SQL Admin与SQL Server版本不兼容
# 解决方案
# 1. 检查版本对应关系
cat /opt/sqladmin/version
# 2. 如需要,升级SQL Admin
docker pull sqladmin:latest
docker-compose down
docker-compose up -d
# 3. 或降级SQL Server客户端驱动
pip3 install pyodbc==4.0.39
# 4. 检查ODBC驱动版本
odbcinst -q -d -n "ODBC Driver 18 for SQL Server"
十、总结与建议
10.1 兼容性测试最佳实践
- 测试环境隔离:测试环境应与生产环境严格隔离,使用相同配置但独立部署
- 完整测试覆盖:每次版本升级前执行完整测试套件,包括功能、性能、安全测试
- 渐进式升级:先在测试环境验证,再在预生产环境验证,最后才升级生产环境
- 回滚计划:始终准备回滚方案,确保升级失败时能快速恢复
- 文档记录:详细记录测试结果和问题处理过程,为后续升级提供参考
10.2 版本规划建议
| 时间周期 | SQL Admin版本 | CentOS版本 | SQL Server版本 | 建议 |
|---|---|---|---|---|
| 当前稳定 | 3.2 | Stream 8/9 | 2019/2022 | 生产可用 |
| 短期规划 | 3.3+ | Stream 9 | 2022 | 关注发布说明 |
| 长期规划 | 4.0 | Stream 9 | 2022+ | 评估新功能 |
遵循以上兼容性测试指南,可以有效降低SQL Admin在CentOS环境中的部署风险,确保数据库管理系统的稳定运行。
本文基于CentOS Stream 9和SQL Admin 3.2编写,适用于CentOS环境下的SQL Admin版本兼容性测试。