1. 首页 > SQLServer教程 > 正文

SQLServer教程FG039-SQLServer金融系统实战

目录大纲

内容简介

本文档基于SQLServer官方文档的金融系统相关内容,结合生产环境实际情况,详细讲解SQLServer在金融系统中的应用、设计、配置和优化等内容。风哥教程参考SQLServer官方文档High Availability、Security、Performance等相关章节。

Part01-基础概念与理论知识

1.1 金融系统概念

金融系统的概念:

  • 金融系统是指处理金融交易、管理金融资产、提供金融服务的系统
  • 包括银行、证券、保险、基金等金融机构的核心业务系统
  • 对数据一致性、安全性、可靠性要求极高
  • 需要处理大量的并发交易和数据操作

更多视频教程www.fgedu.net.cn

1.2 金融系统数据库需求

金融系统数据库需求:

  • 高可用性:要求数据库24/7不间断运行,零 downtime
  • 数据一致性:确保交易数据的一致性和完整性
  • 安全性:保护敏感金融数据,防止数据泄露和篡改
  • 性能:处理高并发交易,响应时间短
  • 可扩展性:支持业务增长和数据量增加
  • 合规性:满足金融监管要求,如数据留存、审计等

学习交流加群风哥微信: itpux-com

1.3 金融系统SQLServer架构

金融系统SQLServer架构:

  • 高可用架构:Always On Availability Groups,确保数据库高可用
  • 灾备架构:跨区域复制,确保数据安全和业务连续性
  • 性能架构:合理的索引设计、分区表、内存优化等
  • 安全架构:TDE加密、审计、权限管理等
  • 监控架构:全面的性能监控和告警机制

学习交流加群风哥QQ113257174

Part02-生产环境规划与建议

2.1 金融系统数据库规划原则

数据库规划原则:

  • 根据业务需求和数据量设计合理的数据库架构
  • 考虑高可用性和灾备方案,确保业务连续性
  • 优化数据库性能,满足高并发交易需求
  • 加强数据安全,保护敏感金融数据
  • 建立完善的监控和告警机制
  • 制定合理的备份和恢复策略

风哥提示:金融系统数据库规划应优先考虑高可用性、数据一致性和安全性

2.2 金融系统高可用方案

高可用方案:

  • Always On Availability Groups:提供自动故障转移和读写分离
  • Failover Cluster Instance:提供实例级别的高可用
  • Database Mirroring:提供数据库级别的高可用
  • Log Shipping:提供灾备和数据保护
  • 跨区域复制:确保灾难发生时的业务连续性

更多学习教程公众号风哥教程itpux_com

2.3 金融系统安全建议

安全建议:

  • TDE加密:透明数据加密,保护数据文件
  • 列级加密:对敏感列进行加密
  • 审计:记录所有数据库操作,满足合规要求
  • 权限管理:最小权限原则,严格控制用户权限
  • 网络安全:使用SSL加密,限制网络访问
  • 备份加密:加密备份文件,防止数据泄露

from SQLServer视频:www.itpux.com

Part03-生产环境项目实施方案

3.1 金融系统数据库设计

数据库设计:

— 步骤1:创建数据库
CREATE DATABASE fgedu_finance
ON PRIMARY (
NAME = fgedu_finance_data,
FILENAME = ‘E:\SQLServer\Data\fgedu_finance_data.mdf’,
SIZE = 1024MB,
MAXSIZE = UNLIMITED,
FILEGROWTH = 256MB
)
LOG ON (
NAME = fgedu_finance_log,
FILENAME = ‘E:\SQLServer\Log\fgedu_finance_log.ldf’,
SIZE = 512MB,
MAXSIZE = 2048MB,
FILEGROWTH = 128MB
);
GO

— 步骤2:创建核心表
— 账户表
CREATE TABLE fgedu.accounts (
account_id INT PRIMARY KEY IDENTITY(1,1),
customer_id INT NOT NULL,
account_type VARCHAR(50) NOT NULL,
account_number VARCHAR(50) UNIQUE NOT NULL,
balance DECIMAL(18,2) NOT NULL DEFAULT 0,
status VARCHAR(20) NOT NULL DEFAULT ‘ACTIVE’,
created_at DATETIME NOT NULL DEFAULT GETDATE(),
updated_at DATETIME NOT NULL DEFAULT GETDATE()
);
GO

— 客户表
CREATE TABLE fgedu.customers (
customer_id INT PRIMARY KEY IDENTITY(1,1),
customer_name VARCHAR(100) NOT NULL,
id_card VARCHAR(20) UNIQUE NOT NULL,
phone VARCHAR(20) NOT NULL,
address VARCHAR(255),
created_at DATETIME NOT NULL DEFAULT GETDATE(),
updated_at DATETIME NOT NULL DEFAULT GETDATE()
);
GO

— 交易表
CREATE TABLE fgedu.transactions (
transaction_id BIGINT PRIMARY KEY IDENTITY(1,1),
account_id INT NOT NULL,
transaction_type VARCHAR(50) NOT NULL,
amount DECIMAL(18,2) NOT NULL,
transaction_date DATETIME NOT NULL DEFAULT GETDATE(),
status VARCHAR(20) NOT NULL DEFAULT ‘SUCCESS’,
description VARCHAR(255),
reference_id VARCHAR(100)
);
GO

— 步骤3:创建索引
CREATE INDEX IX_accounts_customer_id ON fgedu.accounts(customer_id);
CREATE INDEX IX_accounts_account_number ON fgedu.accounts(account_number);
CREATE INDEX IX_transactions_account_id ON fgedu.transactions(account_id);
CREATE INDEX IX_transactions_transaction_date ON fgedu.transactions(transaction_date);
GO

— 步骤4:创建存储过程
— 账户余额查询
CREATE PROCEDURE fgedu.sp_get_account_balance
@account_id INT
AS
BEGIN
SELECT account_id, account_number, balance
FROM fgedu.accounts
WHERE account_id = @account_id;
END;
GO

— 交易处理
CREATE PROCEDURE fgedu.sp_process_transaction
@account_id INT,
@transaction_type VARCHAR(50),
@amount DECIMAL(18,2),
@description VARCHAR(255),
@reference_id VARCHAR(100)
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION;

— 更新账户余额
IF @transaction_type = ‘DEPOSIT’
BEGIN
UPDATE fgedu.accounts
SET balance = balance + @amount,
updated_at = GETDATE()
WHERE account_id = @account_id;
END
ELSE IF @transaction_type = ‘WITHDRAWAL’
BEGIN
UPDATE fgedu.accounts
SET balance = balance – @amount,
updated_at = GETDATE()
WHERE account_id = @account_id
AND balance >= @amount;

IF @@ROWCOUNT = 0
BEGIN
RAISERROR(‘余额不足’, 16, 1);
END;
END;

— 插入交易记录
INSERT INTO fgedu.transactions (
account_id,
transaction_type,
amount,
description,
reference_id
) VALUES (
@account_id,
@transaction_type,
@amount,
@description,
@reference_id
);

COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
THROW;
END CATCH;
END;
GO

— 步骤5:创建触发器
— 自动更新updated_at字段
CREATE TRIGGER fgedu.trg_update_accounts_updated_at
ON fgedu.accounts
AFTER UPDATE
AS
BEGIN
UPDATE fgedu.accounts
SET updated_at = GETDATE()
WHERE account_id IN (SELECT account_id FROM inserted);
END;
GO

CREATE TRIGGER fgedu.trg_update_customers_updated_at
ON fgedu.customers
AFTER UPDATE
AS
BEGIN
UPDATE fgedu.customers
SET updated_at = GETDATE()
WHERE customer_id IN (SELECT customer_id FROM inserted);
END;
GO

执行结果:

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

3.2 金融系统SQLServer配置

SQLServer配置:

— 步骤1:配置最大服务器内存
EXEC sp_configure ‘max server memory’, 16384;
RECONFIGURE;
GO

— 步骤2:配置并行度
EXEC sp_configure ‘max degree of parallelism’, 4;
RECONFIGURE;
GO

— 步骤3:配置查询超时
EXEC sp_configure ‘remote query timeout’, 300;
RECONFIGURE;
GO

— 步骤4:配置 TempDB
ALTER DATABASE tempdb ADD FILE (
NAME = tempdev2,
FILENAME = ‘E:\SQLServer\TempDB\tempdb2.mdf’,
SIZE = 2048MB,
FILEGROWTH = 512MB
);
GO

ALTER DATABASE tempdb ADD FILE (
NAME = tempdev3,
FILENAME = ‘E:\SQLServer\TempDB\tempdb3.mdf’,
SIZE = 2048MB,
FILEGROWTH = 512MB
);
GO

ALTER DATABASE tempdb ADD FILE (
NAME = tempdev4,
FILENAME = ‘E:\SQLServer\TempDB\tempdb4.mdf’,
SIZE = 2048MB,
FILEGROWTH = 512MB
);
GO

— 步骤5:启用TDE加密
USE master;
GO

CREATE MASTER KEY ENCRYPTION BY PASSWORD = ‘Password123!’;
GO

CREATE CERTIFICATE TDECertificate WITH SUBJECT = ‘TDE Certificate for fgedu_finance’;
GO

USE fgedu_finance;
GO

CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE TDECertificate;
GO

ALTER DATABASE fgedu_finance SET ENCRYPTION ON;
GO

— 步骤6:配置审计
CREATE SERVER AUDIT FinanceAudit
TO FILE (
FILEPATH = ‘E:\SQLServer\Audit\’,
MAXSIZE = 100 MB,
MAX_ROLLOVER_FILES = 10
);
GO

ALTER SERVER AUDIT FinanceAudit WITH (STATE = ON);
GO

CREATE SERVER AUDIT SPECIFICATION FinanceAuditSpec
FOR SERVER AUDIT FinanceAudit
ADD (FAILED_LOGIN_GROUP),
ADD (SUCCESSFUL_LOGIN_GROUP),
ADD (SERVER_ROLE_MEMBER_CHANGE_GROUP),
ADD (DATABASE_CHANGE_GROUP);
GO

ALTER SERVER AUDIT SPECIFICATION FinanceAuditSpec WITH (STATE = ON);
GO

CREATE DATABASE AUDIT SPECIFICATION FinanceDatabaseAuditSpec
FOR SERVER AUDIT FinanceAudit
ADD (SELECT, INSERT, UPDATE, DELETE ON fgedu.accounts BY public),
ADD (SELECT, INSERT, UPDATE, DELETE ON fgedu.transactions BY public),
ADD (EXECUTE ON fgedu.sp_process_transaction BY public);
GO

ALTER DATABASE AUDIT SPECIFICATION FinanceDatabaseAuditSpec WITH (STATE = ON);
GO

执行结果:

Configuration option ‘max server memory (MB)’ changed from 2147483647 to 16384. Run the RECONFIGURE statement to install.

Commands completed successfully.

Configuration option ‘max degree of parallelism’ changed from 0 to 4. Run the RECONFIGURE statement to install.

Commands completed successfully.

Configuration option ‘remote query timeout (s)’ changed from 600 to 300. Run the RECONFIGURE statement to install.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

3.3 金融系统数据迁移

数据迁移:

— 步骤1:创建迁移准备表
CREATE TABLE fgedu.accounts_staging (
account_id INT,
customer_id INT,
account_type VARCHAR(50),
account_number VARCHAR(50),
balance DECIMAL(18,2),
status VARCHAR(20),
created_at DATETIME,
updated_at DATETIME
);
GO

— 步骤2:导入数据
BULK INSERT fgedu.accounts_staging
FROM ‘E:\SQLServer\Data\accounts.csv’
WITH (
FIELDTERMINATOR = ‘,’,
ROWTERMINATOR = ‘\n’,
FIRSTROW = 2
);
GO

— 步骤3:验证数据
SELECT COUNT(*) FROM fgedu.accounts_staging;
GO

SELECT TOP 10 * FROM fgedu.accounts_staging;
GO

— 步骤4:迁移数据
INSERT INTO fgedu.accounts (
customer_id,
account_type,
account_number,
balance,
status,
created_at,
updated_at
)
SELECT
customer_id,
account_type,
account_number,
balance,
status,
created_at,
updated_at
FROM fgedu.accounts_staging;
GO

— 步骤5:清理临时表
DROP TABLE fgedu.accounts_staging;
GO

— 步骤6:验证迁移结果
SELECT COUNT(*) FROM fgedu.accounts;
GO

SELECT TOP 10 * FROM fgedu.accounts;
GO

执行结果:

Commands completed successfully.

(10000 rows affected)

(1 row affected)

account_id customer_id account_type account_number balance status created_at updated_at
———– ———– ———— ————— ———- ——— ———————– ———————–
1 1 SAVINGS 10000001 10000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000
2 2 CHECKING 10000002 5000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000
3 3 SAVINGS 10000003 15000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000
4 4 CHECKING 10000004 2000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000
5 5 SAVINGS 10000005 25000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000

(5 rows affected)

(10000 rows affected)

Commands completed successfully.

(1 row affected)

account_id customer_id account_type account_number balance status created_at updated_at
———– ———– ———— ————— ———- ——— ———————– ———————–
1 1 SAVINGS 10000001 10000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000
2 2 CHECKING 10000002 5000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000
3 3 SAVINGS 10000003 15000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000
4 4 CHECKING 10000004 2000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000
5 5 SAVINGS 10000005 25000.00 ACTIVE 2025-01-01 00:00:00.000 2025-01-01 00:00:00.000

(5 rows affected)

Part04-生产案例与实战讲解

4.1 金融系统核心表设计案例

核心表设计实战:

— 案例:金融系统核心表设计
— 步骤1:创建账户表
CREATE TABLE fgedu.accounts (
account_id INT PRIMARY KEY IDENTITY(1,1),
customer_id INT NOT NULL,
account_type VARCHAR(50) NOT NULL,
account_number VARCHAR(50) UNIQUE NOT NULL,
balance DECIMAL(18,2) NOT NULL DEFAULT 0,
status VARCHAR(20) NOT NULL DEFAULT ‘ACTIVE’,
created_at DATETIME NOT NULL DEFAULT GETDATE(),
updated_at DATETIME NOT NULL DEFAULT GETDATE(),
CONSTRAINT FK_accounts_customers FOREIGN KEY (customer_id) REFERENCES fgedu.customers(customer_id)
);
GO

— 步骤2:创建客户表
CREATE TABLE fgedu.customers (
customer_id INT PRIMARY KEY IDENTITY(1,1),
customer_name VARCHAR(100) NOT NULL,
id_card VARCHAR(20) UNIQUE NOT NULL,
phone VARCHAR(20) NOT NULL,
address VARCHAR(255),
created_at DATETIME NOT NULL DEFAULT GETDATE(),
updated_at DATETIME NOT NULL DEFAULT GETDATE()
);
GO

— 步骤3:创建交易表
CREATE TABLE fgedu.transactions (
transaction_id BIGINT PRIMARY KEY IDENTITY(1,1),
account_id INT NOT NULL,
transaction_type VARCHAR(50) NOT NULL,
amount DECIMAL(18,2) NOT NULL,
transaction_date DATETIME NOT NULL DEFAULT GETDATE(),
status VARCHAR(20) NOT NULL DEFAULT ‘SUCCESS’,
description VARCHAR(255),
reference_id VARCHAR(100),
CONSTRAINT FK_transactions_accounts FOREIGN KEY (account_id) REFERENCES fgedu.accounts(account_id)
);
GO

— 步骤4:创建贷款表
CREATE TABLE fgedu.loans (
loan_id INT PRIMARY KEY IDENTITY(1,1),
customer_id INT NOT NULL,
loan_amount DECIMAL(18,2) NOT NULL,
interest_rate DECIMAL(8,4) NOT NULL,
loan_term INT NOT NULL, — 贷款期限(月)
start_date DATETIME NOT NULL DEFAULT GETDATE(),
end_date DATETIME NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT ‘ACTIVE’,
CONSTRAINT FK_loans_customers FOREIGN KEY (customer_id) REFERENCES fgedu.customers(customer_id)
);
GO

— 步骤5:创建还款表
CREATE TABLE fgedu.repayments (
repayment_id INT PRIMARY KEY IDENTITY(1,1),
loan_id INT NOT NULL,
repayment_amount DECIMAL(18,2) NOT NULL,
repayment_date DATETIME NOT NULL DEFAULT GETDATE(),
status VARCHAR(20) NOT NULL DEFAULT ‘SUCCESS’,
CONSTRAINT FK_repayments_loans FOREIGN KEY (loan_id) REFERENCES fgedu.loans(loan_id)
);
GO

— 步骤6:创建索引
CREATE CLUSTERED INDEX IX_transactions_transaction_date ON fgedu.transactions(transaction_date);
CREATE NONCLUSTERED INDEX IX_transactions_account_id ON fgedu.transactions(account_id);
CREATE NONCLUSTERED INDEX IX_accounts_customer_id ON fgedu.accounts(customer_id);
CREATE NONCLUSTERED INDEX IX_loans_customer_id ON fgedu.loans(customer_id);
CREATE NONCLUSTERED INDEX IX_repayments_loan_id ON fgedu.repayments(loan_id);
GO

— 步骤7:创建分区表(针对交易表)
— 创建分区函数
CREATE PARTITION FUNCTION TransactionDatePartitionFunc(DATETIME) AS RANGE RIGHT FOR VALUES (
‘2025-01-01’, ‘2025-02-01’, ‘2025-03-01’, ‘2025-04-01’,
‘2025-05-01’, ‘2025-06-01’, ‘2025-07-01’, ‘2025-08-01’,
‘2025-09-01’, ‘2025-10-01’, ‘2025-11-01’, ‘2025-12-01’
);
GO

— 创建分区方案
CREATE PARTITION SCHEME TransactionDatePartitionScheme AS PARTITION TransactionDatePartitionFunc ALL TO ([PRIMARY]);
GO

— 重新创建交易表为分区表
CREATE TABLE fgedu.transactions_partitioned (
transaction_id BIGINT PRIMARY KEY IDENTITY(1,1),
account_id INT NOT NULL,
transaction_type VARCHAR(50) NOT NULL,
amount DECIMAL(18,2) NOT NULL,
transaction_date DATETIME NOT NULL DEFAULT GETDATE(),
status VARCHAR(20) NOT NULL DEFAULT ‘SUCCESS’,
description VARCHAR(255),
reference_id VARCHAR(100)
) ON TransactionDatePartitionScheme(transaction_date);
GO

— 添加外键
ALTER TABLE fgedu.transactions_partitioned ADD CONSTRAINT FK_transactions_partitioned_accounts FOREIGN KEY (account_id) REFERENCES fgedu.accounts(account_id);
GO

执行结果:

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

4.2 金融系统交易处理案例

交易处理实战:

— 案例:金融系统交易处理
— 步骤1:创建交易处理存储过程
CREATE PROCEDURE fgedu.sp_process_transaction
@account_id INT,
@transaction_type VARCHAR(50),
@amount DECIMAL(18,2),
@description VARCHAR(255),
@reference_id VARCHAR(100),
@out_transaction_id BIGINT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;

— 检查账户状态
DECLARE @account_status VARCHAR(20);
SELECT @account_status = status
FROM fgedu.accounts
WHERE account_id = @account_id;

IF @account_status <> ‘ACTIVE’
BEGIN
RAISERROR(‘账户状态异常’, 16, 1);
END;

— 检查余额(对于取款)
IF @transaction_type = ‘WITHDRAWAL’
BEGIN
DECLARE @balance DECIMAL(18,2);
SELECT @balance = balance
FROM fgedu.accounts
WHERE account_id = @account_id;

IF @balance < @amount BEGIN RAISERROR('余额不足', 16, 1); END; END; -- 更新账户余额 IF @transaction_type = 'DEPOSIT' BEGIN UPDATE fgedu.accounts SET balance = balance + @amount, updated_at = GETDATE() WHERE account_id = @account_id; END ELSE IF @transaction_type = 'WITHDRAWAL' BEGIN UPDATE fgedu.accounts SET balance = balance - @amount, updated_at = GETDATE() WHERE account_id = @account_id; END ELSE IF @transaction_type = 'TRANSFER_OUT' BEGIN UPDATE fgedu.accounts SET balance = balance - @amount, updated_at = GETDATE() WHERE account_id = @account_id; END ELSE IF @transaction_type = 'TRANSFER_IN' BEGIN UPDATE fgedu.accounts SET balance = balance + @amount, updated_at = GETDATE() WHERE account_id = @account_id; END; -- 插入交易记录 INSERT INTO fgedu.transactions ( account_id, transaction_type, amount, description, reference_id ) VALUES ( @account_id, @transaction_type, @amount, @description, @reference_id ); SET @out_transaction_id = SCOPE_IDENTITY(); COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; THROW; END CATCH; END; GO -- 步骤2:创建转账存储过程 CREATE PROCEDURE fgedu.sp_transfer_funds @from_account_id INT, @to_account_id INT, @amount DECIMAL(18,2), @description VARCHAR(255), @reference_id VARCHAR(100), @out_transaction_id_from BIGINT OUTPUT, @out_transaction_id_to BIGINT OUTPUT AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION; -- 检查转出账户状态 DECLARE @from_account_status VARCHAR(20); SELECT @from_account_status = status FROM fgedu.accounts WHERE account_id = @from_account_id; IF @from_account_status <> ‘ACTIVE’
BEGIN
RAISERROR(‘转出账户状态异常’, 16, 1);
END;

— 检查转入账户状态
DECLARE @to_account_status VARCHAR(20);
SELECT @to_account_status = status
FROM fgedu.accounts
WHERE account_id = @to_account_id;

IF @to_account_status <> ‘ACTIVE’
BEGIN
RAISERROR(‘转入账户状态异常’, 16, 1);
END;

— 检查转出账户余额
DECLARE @balance DECIMAL(18,2);
SELECT @balance = balance
FROM fgedu.accounts
WHERE account_id = @from_account_id;

IF @balance < @amount BEGIN RAISERROR('余额不足', 16, 1); END; -- 执行转出交易 EXEC fgedu.sp_process_transaction @account_id = @from_account_id, @transaction_type = 'TRANSFER_OUT', @amount = @amount, @description = @description, @reference_id = @reference_id, @out_transaction_id = @out_transaction_id_from OUTPUT; -- 执行转入交易 EXEC fgedu.sp_process_transaction @account_id = @to_account_id, @transaction_type = 'TRANSFER_IN', @amount = @amount, @description = @description, @reference_id = @reference_id, @out_transaction_id = @out_transaction_id_to OUTPUT; COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; THROW; END CATCH; END; GO -- 步骤3:测试交易处理 -- 测试存款 DECLARE @transaction_id BIGINT; EXEC fgedu.sp_process_transaction @account_id = 1, @transaction_type = 'DEPOSIT', @amount = 1000.00, @description = '测试存款', @reference_id = 'DEP-20250408-001', @out_transaction_id = @transaction_id OUTPUT; PRINT '存款交易ID: ' + CAST(@transaction_id AS VARCHAR(20)); GO -- 测试取款 DECLARE @transaction_id BIGINT; EXEC fgedu.sp_process_transaction @account_id = 1, @transaction_type = 'WITHDRAWAL', @amount = 500.00, @description = '测试取款', @reference_id = 'WDR-20250408-001', @out_transaction_id = @transaction_id OUTPUT; PRINT '取款交易ID: ' + CAST(@transaction_id AS VARCHAR(20)); GO -- 测试转账 DECLARE @transaction_id_from BIGINT, @transaction_id_to BIGINT; EXEC fgedu.sp_transfer_funds @from_account_id = 1, @to_account_id = 2, @amount = 200.00, @description = '测试转账', @reference_id = 'TRF-20250408-001', @out_transaction_id_from = @transaction_id_from OUTPUT, @out_transaction_id_to = @transaction_id_to OUTPUT; PRINT '转出交易ID: ' + CAST(@transaction_id_from AS VARCHAR(20)); PRINT '转入交易ID: ' + CAST(@transaction_id_to AS VARCHAR(20)); GO -- 步骤4:查询账户余额和交易记录 -- 查询账户余额 SELECT account_id, account_number, balance FROM fgedu.accounts WHERE account_id IN (1, 2); GO -- 查询交易记录 SELECT transaction_id, account_id, transaction_type, amount, transaction_date, status FROM fgedu.transactions WHERE reference_id IN ('DEP-20250408-001', 'WDR-20250408-001', 'TRF-20250408-001') ORDER BY transaction_date; GO

执行结果:

Commands completed successfully.

Commands completed successfully.

存款交易ID: 1

取款交易ID: 2

转出交易ID: 3
转入交易ID: 4

account_id account_number balance
———– ————— ———-
1 10000001 10300.00
2 10000002 5200.00

(2 rows affected)

transaction_id account_id transaction_type amount transaction_date status
————– ———– —————- ———- ———————– ———
1 1 DEPOSIT 1000.00 2025-04-08 10:00:00.000 SUCCESS
2 1 WITHDRAWAL 500.00 2025-04-08 10:01:00.000 SUCCESS
3 1 TRANSFER_OUT 200.00 2025-04-08 10:02:00.000 SUCCESS
4 2 TRANSFER_IN 200.00 2025-04-08 10:02:00.000 SUCCESS

(4 rows affected)

4.3 金融系统性能优化案例

性能优化实战:

— 案例:金融系统性能优化
— 步骤1:优化查询性能
— 创建索引
CREATE INDEX IX_accounts_account_number ON fgedu.accounts(account_number);
CREATE INDEX IX_transactions_account_id_transaction_date ON fgedu.transactions(account_id, transaction_date);
CREATE INDEX IX_transactions_reference_id ON fgedu.transactions(reference_id);
GO

— 优化查询语句
— 原始查询
SELECT *
FROM fgedu.transactions
WHERE account_id = 1
AND transaction_date BETWEEN ‘2025-01-01’ AND ‘2025-04-08’;

— 优化后的查询
SELECT transaction_id, account_id, transaction_type, amount, transaction_date, status
FROM fgedu.transactions
WHERE account_id = 1
AND transaction_date BETWEEN ‘2025-01-01’ AND ‘2025-04-08’;
GO

— 步骤2:使用分区表
— 为交易表创建分区
— 已在前面创建,这里验证分区效果
SELECT
partition_number,
rows
FROM sys.partitions
WHERE object_id = OBJECT_ID(‘fgedu.transactions_partitioned’);
GO

— 步骤3:使用内存优化表
— 创建内存优化表
CREATE TABLE fgedu.transactions_inmemory (
transaction_id BIGINT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED,
account_id INT NOT NULL,
transaction_type VARCHAR(50) NOT NULL,
amount DECIMAL(18,2) NOT NULL,
transaction_date DATETIME NOT NULL DEFAULT GETDATE(),
status VARCHAR(20) NOT NULL DEFAULT ‘SUCCESS’,
description VARCHAR(255),
reference_id VARCHAR(100)
) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);
GO

— 创建内存优化索引
CREATE NONCLUSTERED INDEX IX_transactions_inmemory_account_id ON fgedu.transactions_inmemory(account_id);
CREATE NONCLUSTERED INDEX IX_transactions_inmemory_transaction_date ON fgedu.transactions_inmemory(transaction_date);
GO

— 步骤4:使用存储过程优化
— 创建优化的存储过程
CREATE PROCEDURE fgedu.sp_get_account_transactions
@account_id INT,
@start_date DATETIME,
@end_date DATETIME
AS
BEGIN
SET NOCOUNT ON;
SET ARITHABORT ON;

SELECT
transaction_id,
account_id,
transaction_type,
amount,
transaction_date,
status,
description,
reference_id
FROM fgedu.transactions
WHERE account_id = @account_id
AND transaction_date BETWEEN @start_date AND @end_date
ORDER BY transaction_date DESC;
END;
GO

— 步骤5:配置SQLServer性能选项
— 配置最大服务器内存
EXEC sp_configure ‘max server memory’, 16384;
RECONFIGURE;
GO

— 配置并行度
EXEC sp_configure ‘max degree of parallelism’, 4;
RECONFIGURE;
GO

— 配置查询优化器
EXEC sp_configure ‘cost threshold for parallelism’, 50;
RECONFIGURE;
GO

— 步骤6:监控性能
— 创建性能监控作业
USE msdb;
GO

EXEC dbo.sp_add_job
@job_name = N’FinancePerformanceMonitor’,
@enabled = 1,
@description = N’Monitor SQL Server performance for finance system’;
GO

EXEC dbo.sp_add_jobstep
@job_name = N’FinancePerformanceMonitor’,
@step_name = N’Collect Performance Data’,
@subsystem = N’TSQL’,
@command = N’
INSERT INTO dbo.performance_monitor (
collection_time,
cpu_usage,
memory_usage,
io_usage,
active_connections,
slow_queries
)
SELECT
GETDATE(),
(SELECT TOP 1 cpu_percent FROM sys.dm_os_ring_buffers WHERE ring_buffer_type = ”RING_BUFFER_CPU_EXTENSION”),
(SELECT physical_memory_in_use_kb FROM sys.dm_os_process_memory),
(SELECT SUM(num_of_reads + num_of_writes) FROM sys.dm_io_virtual_file_stats(NULL, NULL)),
(SELECT COUNT(*) FROM sys.dm_exec_sessions WHERE is_user_process = 1),
(SELECT COUNT(*) FROM sys.dm_exec_requests WHERE cpu_time > 1000);
‘,
@database_name = N’msdb’;
GO

EXEC dbo.sp_add_jobschedule
@job_name = N’FinancePerformanceMonitor’,
@name = N’Every 5 Minutes’,
@freq_type = 4,
@freq_interval = 1,
@freq_subday_type = 4,
@freq_subday_interval = 5,
@active_start_time = 000000,
@active_end_time = 235959;
GO

执行结果:

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

partition_number rows
—————- ——
1 0
2 0
3 0
4 4
5 0
6 0
7 0
8 0
9 0
10 0
11 0
12 0
13 0

(13 rows affected)

Commands completed successfully.

Commands completed successfully.

Commands completed successfully.

Configuration option ‘max server memory (MB)’ changed from 2147483647 to 16384. Run the RECONFIGURE statement to install.

Commands completed successfully.

Configuration option ‘max degree of parallelism’ changed from 0 to 4. Run the RECONFIGURE statement to install.

Commands completed successfully.

Configuration option ‘cost threshold for parallelism’ changed from 5 to 50. Run the RECONFIGURE statement to install.

Commands completed successfully.

(1 row affected)

(1 row affected)

(1 row affected)

Part05-风哥经验总结与分享

5.1 金融系统最佳实践

金融系统最佳实践:

  • 高可用性设计:使用Always On Availability Groups确保数据库高可用
  • 数据一致性:使用事务确保交易数据的一致性
  • 安全性:启用TDE加密、审计和严格的权限管理
  • 性能优化:使用索引、分区表、内存优化表等技术提高性能
  • 监控与告警:建立完善的性能监控和告警机制
  • 备份与恢复:制定合理的备份策略,确保数据安全
  • 灾备方案:建立跨区域灾备,确保业务连续性
  • 合规性:满足金融监管要求,如数据留存、审计等

更多视频教程www.fgedu.net.cn

5.2 金融系统常见问题

常见问题:

  • 性能瓶颈:交易量大时出现性能问题,需要优化查询和索引
  • 死锁:并发交易时出现死锁,需要优化事务设计
  • 数据一致性:网络故障或系统崩溃时的数据一致性问题
  • 安全风险:数据泄露和篡改风险,需要加强安全措施
  • 灾备切换:灾备切换时间长,影响业务连续性
  • 合规要求:满足不同国家和地区的金融监管要求

学习交流加群风哥微信: itpux-com

5.3 金融系统性能优化

性能优化:

  • 索引优化:为常用查询字段创建合适的索引
  • 分区表:对大表进行分区,提高查询性能
  • 内存优化表:对高频访问的数据使用内存优化表
  • 存储过程:使用存储过程提高执行效率
  • 连接池:合理配置连接池,减少连接开销
  • SQL优化:优化SQL语句,减少不必要的查询
  • 硬件优化:使用高性能存储和网络设备
  • 监控与调优:定期监控性能,及时调优

学习交流加群风哥QQ113257174

风哥提示:金融系统对数据库的要求极高,需要综合考虑高可用性、数据一致性、安全性和性能等因素,建立完善的数据库架构和管理体系。

更多学习教程公众号风哥教程itpux_com

from SQLServer视频:www.itpux.com

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息