什么是达梦数据库?

达梦数据库(DM Database)是由武汉达梦数据库股份有限公司研发的具有完全自主知识产权的高性能数据库管理系统。作为国产数据库的领军者,达梦数据库在政府、金融、能源、电信等关键领域得到广泛应用,是信创产业的核心基础软件之一。

发展历程

  • 2000年:达梦数据库DM4发布
  • 2004年:DM5发布,支持64位系统
  • 2008年:DM6发布,支持大规模并行处理
  • 2012年:DM7发布,支持云计算
  • 2019年:DM8发布,支持分布式和AI
  • 2023年:DM8.6发布,支持云原生和HTAP

核心特性

1. 完全自主可控

  • 100%自主知识产权:无国外技术依赖
  • 源代码可控:安全审计透明
  • 符合信创标准:通过国家各项安全认证

2. 高性能

  • 并行处理:支持大规模并行计算
  • 内存优化:高效的内存管理
  • 存储优化:智能存储引擎
  • 查询优化:基于成本的优化器

3. 高可用性

  • 双机热备:主备自动切换
  • 读写分离:负载均衡
  • 集群部署:支持RAC集群
  • 容灾备份:异地容灾方案

4. 兼容性

  • SQL标准:完全兼容SQL92/99/2003
  • Oracle兼容:高度兼容Oracle语法
  • MySQL兼容:支持MySQL常用语法
  • PostgreSQL兼容:支持PG特性

体系架构

1. 逻辑架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
达梦数据库实例
├── 内存结构
│ ├── 数据缓冲区
│ ├── 日志缓冲区
│ ├── 字典缓冲区
│ └── SQL缓冲区
├── 后台进程
│ ├── 日志写进程
│ ├── 数据写进程
│ ├── 检查点进程
│ └── 归档进程
└── 存储结构
├── 表空间
├── 数据文件
├── 控制文件
└── 重做日志

2. 存储结构

  • 表空间:逻辑存储单元
  • 数据文件:物理存储文件
  • :表、索引的存储空间
  • :数据存储的基本单位
  • :最小的I/O单元(默认8KB)

安装与配置

1. 系统要求

1
2
3
4
5
6
7
8
9
# 操作系统支持
- Linux:CentOS 7.x/8.x, RedHat 7.x/8.x, Ubuntu 18.04/20.04
- Windows:Windows Server 2012/2016/2019/2022
- 国产OS:银河麒麟、中标麒麟、统信UOS

# 硬件要求
- CPU:x86_64或ARM64架构
- 内存:最少4GB,推荐8GB以上
- 磁盘:最少10GB可用空间

2. 安装步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Linux安装
# 1. 创建用户和组
groupadd dinstall
useradd -g dinstall -m -d /home/dmdba -s /bin/bash dmdba

# 2. 设置环境变量
export DM_HOME=/opt/dmdbms
export PATH=$DM_HOME/bin:$PATH
export LD_LIBRARY_PATH=$DM_HOME/bin:$LD_LIBRARY_PATH

# 3. 安装数据库
./DMInstall.bin -i

# 4. 初始化实例
dminit path=/opt/dmdbms/data db_name=DAMENG instance_name=DMSERVER

3. 服务管理

1
2
3
4
5
6
7
8
9
10
11
# 启动服务
systemctl start DmServiceDMSERVER

# 停止服务
systemctl stop DmServiceDMSERVER

# 查看状态
systemctl status DmServiceDMSERVER

# 连接数据库
disql SYSDBA/SYSDBA@localhost:5236

基本操作

1. 数据库操作

1
2
3
4
5
6
7
8
9
10
-- 创建数据库
CREATE DATABASE testdb
DATAFILE '/opt/dmdbms/data/testdb.dbf' SIZE 100M
LOGFILE '/opt/dmdbms/data/testdb.log' SIZE 50M;

-- 修改数据库
ALTER DATABASE testdb ADD DATAFILE '/opt/dmdbms/data/testdb02.dbf' SIZE 50M;

-- 删除数据库
DROP DATABASE testdb;

2. 表空间管理

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 创建表空间
CREATE TABLESPACE test_ts
DATAFILE '/opt/dmdbms/data/test_ts.dbf' SIZE 100M
AUTOEXTEND ON NEXT 10M MAXSIZE 2G;

-- 修改表空间
ALTER TABLESPACE test_ts ADD DATAFILE '/opt/dmdbms/data/test_ts02.dbf' SIZE 50M;

-- 设置默认表空间
ALTER DATABASE DEFAULT TABLESPACE test_ts;

-- 删除表空间
DROP TABLESPACE test_ts INCLUDING CONTENTS AND DATAFILES;

3. 用户管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 创建用户
CREATE USER test_user IDENTIFIED BY "password123"
DEFAULT TABLESPACE test_ts
TEMPORARY TABLESPACE temp
QUOTA UNLIMITED ON test_ts;

-- 授权
GRANT CONNECT TO test_user;
GRANT RESOURCE TO test_user;
GRANT CREATE TABLE TO test_user;
GRANT CREATE VIEW TO test_user;

-- 修改用户
ALTER USER test_user IDENTIFIED BY "newpassword";

-- 删除用户
DROP USER test_user CASCADE;

表和索引操作

1. 创建表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
-- 创建基本表
CREATE TABLE employees (
employee_id INT PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
hire_date DATE DEFAULT SYSDATE,
salary DECIMAL(10,2) CHECK (salary > 0),
department_id INT,
CONSTRAINT fk_department
FOREIGN KEY (department_id)
REFERENCES departments(department_id)
);

-- 创建分区表
CREATE TABLE sales (
sale_id INT,
sale_date DATE,
amount DECIMAL(10,2),
region VARCHAR(50)
)
PARTITION BY RANGE (sale_date) (
PARTITION p2024_q1 VALUES LESS THAN ('2024-04-01'),
PARTITION p2024_q2 VALUES LESS THAN ('2024-07-01'),
PARTITION p2024_q3 VALUES LESS THAN ('2024-10-01'),
PARTITION p2024_q4 VALUES LESS THAN ('2025-01-01')
);

-- 创建临时表
CREATE GLOBAL TEMPORARY TABLE temp_employees (
employee_id INT,
first_name VARCHAR(50),
last_name VARCHAR(50)
) ON COMMIT DELETE ROWS;

2. 索引操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 创建B树索引
CREATE INDEX idx_employees_last_name ON employees(last_name);

-- 创建唯一索引
CREATE UNIQUE INDEX idx_employees_email ON employees(email);

-- 创建位图索引
CREATE BITMAP INDEX idx_employees_dept ON employees(department_id);

-- 创建函数索引
CREATE INDEX idx_employees_upper_name ON employees(UPPER(first_name));

-- 创建分区索引
CREATE INDEX idx_sales_date ON sales(sale_date) LOCAL;

-- 查看索引信息
SELECT * FROM USER_INDEXES WHERE TABLE_NAME = 'EMPLOYEES';

DMSQL编程

1. 存储过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-- 创建存储过程
CREATE OR REPLACE PROCEDURE update_salary(
p_emp_id IN INT,
p_increase_pct IN DECIMAL
) AS
v_current_salary DECIMAL(10,2);
BEGIN
SELECT salary INTO v_current_salary
FROM employees
WHERE employee_id = p_emp_id;

UPDATE employees
SET salary = salary * (1 + p_increase_pct/100)
WHERE employee_id = p_emp_id;

COMMIT;

PRINT 'Salary updated successfully';
EXCEPTION
WHEN NO_DATA_FOUND THEN
PRINT 'Employee not found';
WHEN OTHERS THEN
PRINT 'Error: ' || SQLERRM;
ROLLBACK;
END;
/

-- 调用存储过程
CALL update_salary(1001, 10);

2. 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 创建函数
CREATE OR REPLACE FUNCTION get_employee_name(
p_emp_id IN INT
) RETURN VARCHAR AS
v_full_name VARCHAR(100);
BEGIN
SELECT first_name || ' ' || last_name
INTO v_full_name
FROM employees
WHERE employee_id = p_emp_id;

RETURN v_full_name;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 'Employee not found';
END;
/

-- 使用函数
SELECT get_employee_name(1001);

3. 触发器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 创建触发器
CREATE OR REPLACE TRIGGER trg_employees_audit
AFTER INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW
DECLARE
v_action VARCHAR(10);
BEGIN
IF INSERTING THEN
v_action := 'INSERT';
ELSIF UPDATING THEN
v_action := 'UPDATE';
ELSIF DELETING THEN
v_action := 'DELETE';
END IF;

INSERT INTO employees_audit (
employee_id, action, action_date, old_salary, new_salary
) VALUES (
:OLD.employee_id, v_action, SYSDATE, :OLD.salary, :NEW.salary
);
END;
/

高级查询

1. 分析函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 排名函数
SELECT employee_id, first_name, salary,
RANK() OVER (ORDER BY salary DESC) as salary_rank,
DENSE_RANK() OVER (ORDER BY salary DESC) as dense_rank,
ROW_NUMBER() OVER (ORDER BY salary DESC) as row_num
FROM employees;

-- 分区分析
SELECT department_id, employee_id, first_name, salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) as dept_rank,
SUM(salary) OVER (PARTITION BY department_id) as dept_total_salary
FROM employees;

-- 移动平均
SELECT employee_id, hire_date, salary,
AVG(salary) OVER (ORDER BY hire_date ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) as moving_avg
FROM employees;

2. 子查询和集合操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-- 相关子查询
SELECT e.employee_id, e.first_name, e.salary
FROM employees e
WHERE e.salary > (
SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id
);

-- 集合操作
SELECT employee_id FROM employees
UNION
SELECT manager_id FROM departments;

SELECT employee_id FROM employees
INTERSECT
SELECT manager_id FROM departments;

SELECT employee_id FROM employees
EXCEPT
SELECT manager_id FROM departments;

性能优化

1. 执行计划分析

1
2
3
4
5
6
7
8
9
10
11
12
-- 查看执行计划
EXPLAIN SELECT * FROM employees e, departments d
WHERE e.department_id = d.department_id
AND e.salary > 5000;

-- 使用HINT优化
SELECT /*+ USE_HASH(e d) */ *
FROM employees e, departments d
WHERE e.department_id = d.department_id;

-- 收集统计信息
SP_INDEX_STAT_INIT('SYSDBA', 'IDX_EMPLOYEES_LAST_NAME');

2. 索引优化

1
2
3
4
5
6
7
8
9
10
11
-- 创建复合索引
CREATE INDEX idx_emp_dept_salary ON employees(department_id, salary);

-- 部分索引
CREATE INDEX idx_active_employees ON employees(department_id) WHERE status = 'ACTIVE';

-- 函数索引
CREATE INDEX idx_upper_name ON employees(UPPER(first_name));

-- 查看索引使用情况
SELECT * FROM V$OBJECT_USAGE WHERE INDEX_NAME = 'IDX_EMPLOYEES_LAST_NAME';

3. 内存优化

1
2
3
4
5
6
-- 查看内存配置
SELECT * FROM V$DM_INI WHERE PARA_NAME LIKE '%MEMORY%';

-- 修改内存参数
SP_SET_PARA_VALUE(2, 'MEMORY_TARGET', 8589934592);
SP_SET_PARA_VALUE(2, 'MEMORY_POOL', 200);

高可用性

1. 主备集群

1
2
3
4
5
6
7
8
9
10
11
12
13
# 配置主库
# 修改dm.ini
ARCH_INI = 1
RLOG_SEND_APPLY_MON = 64

# 配置备库
# 修改dm.ini
ARCH_INI = 1
RLOG_APPLY_THRESHOLD = 0

# 启动守护进程
dmserver /opt/dmdbms/data/DAMENG/dm.ini mount
dmserver /opt/dmdbms/data/DAMENG/dm.ini standby

2. 读写分离集群

1
2
3
4
5
6
-- 配置读写分离
-- 在dm_svc.conf中配置
[DAMENG]
LOGIN_MODE = (1)
SWITCH_TIMES = (60)
SWITCH_INTERVAL = (1000)

3. 分布式集群

1
2
3
4
5
6
7
8
9
10
11
12
-- 创建分布式表
CREATE TABLESPACE dpc_ts DATAFILE '/opt/dmdbms/data/dpc_ts.dbf' SIZE 100M;

-- 创建分布式表
CREATE TABLE orders (
order_id INT,
customer_id INT,
order_date DATE,
amount DECIMAL(10,2)
)
DISTRIBUTED BY HASH (order_id)
STORE IN (dpc_ts);

数据迁移

1. 从Oracle迁移

1
2
3
4
5
6
# 使用DTS工具
dts.exe -s oracle -h localhost -p 1521 -d orcl -u system -w oracle
-t dameng -H localhost -P 5236 -D DAMENG -U SYSDBA -W SYSDBA

# 使用命令行迁移
dimp userid=SYSDBA/SYSDBA file=oracle_dump.dmp log=import.log

2. 从MySQL迁移

1
2
3
# 使用DTS工具
dts.exe -s mysql -h localhost -P 3306 -d testdb -u root -w password
-t dameng -H localhost -P 5236 -D DAMENG -U SYSDBA -W SYSDBA

3. 从PostgreSQL迁移

1
2
3
# 使用DTS工具
dts.exe -s postgresql -h localhost -P 5432 -d postgres -u postgres -w password
-t dameng -H localhost -P 5236 -D DAMENG -U SYSDBA -W SYSDBA

安全管理

1. 权限管理

1
2
3
4
5
6
7
8
9
10
-- 创建角色
CREATE ROLE hr_manager;
GRANT SELECT, INSERT, UPDATE, DELETE ON employees TO hr_manager;
GRANT SELECT ON departments TO hr_manager;

-- 授予角色给用户
GRANT hr_manager TO test_user;

-- 回收权限
REVOKE DELETE ON employees FROM hr_manager;

2. 数据加密

1
2
3
4
5
6
7
8
9
10
11
12
-- 透明数据加密
ALTER TABLE employees MODIFY (salary ENCRYPT);

-- 列级加密
CREATE TABLE sensitive_data (
id INT PRIMARY KEY,
credit_card VARCHAR(20) ENCRYPT,
ssn VARCHAR(11) ENCRYPT
);

-- 查看加密信息
SELECT * FROM V$ENCRYPT_TABLES;

3. 审计功能

1
2
3
4
5
6
7
8
9
-- 开启审计
SP_SET_ENABLE_AUDIT(1);

-- 设置审计策略
CREATE AUDIT POLICY emp_policy
ACTIONS SELECT, INSERT, UPDATE, DELETE ON employees;

-- 应用审计策略
AUDIT POLICY emp_policy BY test_user;

备份与恢复

1. 物理备份

1
2
3
4
5
6
7
8
# 全库备份
dmrman CTLSTMT="BACKUP DATABASE '/opt/dmdbms/data/DAMENG/dm.ini' FULL TO BACKUP_01 BACKUPSET '/opt/dmdbms/backup/BACKUP_01'"

# 增量备份
dmrman CTLSTMT="BACKUP DATABASE '/opt/dmdbms/data/DAMENG/dm.ini' INCREMENT TO INCRE_01 BACKUPSET '/opt/dmdbms/backup/INCRE_01'"

# 表空间备份
dmrman CTLSTMT="BACKUP TABLESPACE MAIN '/opt/dmdbms/data/DAMENG/dm.ini' TO TS_BACKUP BACKUPSET '/opt/dmdbms/backup/TS_BACKUP'"

2. 逻辑备份

1
2
3
4
5
6
7
8
# 使用dexp导出
dexp userid=SYSDBA/SYSDBA file=full_backup.dmp log=full_export.log full=y

# 使用dimp导入
dimp userid=SYSDBA/SYSDBA file=full_backup.dmp log=full_import.log full=y

# 导出特定模式
dexp userid=SYSDBA/SYSDBA file=hr_backup.dmp log=hr_export.log owner=hr

3. 恢复操作

1
2
3
4
5
# 全库恢复
dmrman CTLSTMT="RESTORE DATABASE '/opt/dmdbms/data/DAMENG/dm.ini' FROM BACKUPSET '/opt/dmdbms/backup/BACKUP_01'"

# 表空间恢复
dmrman CTLSTMT="RESTORE TABLESPACE MAIN FROM BACKUPSET '/opt/dmdbms/backup/TS_BACKUP'"

与Java集成

1. JDBC连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.sql.*;

public class DMConnection {
public static void main(String[] args) {
String url = "jdbc:dm://localhost:5236/DAMENG";
String user = "SYSDBA";
String password = "SYSDBA";

try (Connection conn = DriverManager.getConnection(url, user, password)) {
String sql = "SELECT employee_id, first_name, salary FROM employees";

try (PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {

while (rs.next()) {
System.out.println("ID: " + rs.getInt("employee_id") +
", Name: " + rs.getString("first_name") +
", Salary: " + rs.getBigDecimal("salary"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

2. 连接池配置

1
2
3
4
5
6
7
8
9
10
11
<!-- context.xml -->
<Resource name="jdbc/dameng"
auth="Container"
type="javax.sql.DataSource"
driverClassName="dm.jdbc.driver.DmDriver"
url="jdbc:dm://localhost:5236/DAMENG"
username="SYSDBA"
password="SYSDBA"
maxActive="20"
maxIdle="10"
maxWait="-1"/>

与Spring Boot集成

1. 配置依赖

1
2
3
4
5
6
<!-- pom.xml -->
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
<version>8.1.1.49</version>
</dependency>

2. 配置文件

1
2
3
4
5
6
7
# application.yml
spring:
datasource:
driver-class-name: dm.jdbc.driver.DmDriver
url: jdbc:dm://localhost:5236/DAMENG
username: SYSDBA
password: SYSDBA

3. 实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Entity
@Table(name = "employees")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer employeeId;

@Column(name = "first_name")
private String firstName;

@Column(name = "last_name")
private String lastName;

@Column(name = "email")
private String email;

@Column(name = "salary")
private BigDecimal salary;

// getters and setters
}

常见应用场景

  1. 政府系统:电子政务、人口管理、税务系统
  2. 金融行业:银行核心系统、保险业务系统
  3. 能源行业:电力调度、石油石化管理
  4. 电信行业:计费系统、客户关系管理
  5. 教育行业:教务管理系统、数字校园
  6. 医疗行业:医院信息系统、电子病历

国产化替代方案

1. Oracle替代

  • 语法兼容:95%以上Oracle语法兼容
  • 存储过程:PL/SQL到DMSQL的自动转换
  • 数据类型:完整的数据类型映射
  • 工具支持:DTS数据迁移工具

2. MySQL替代

  • 语法兼容:90%以上MySQL语法兼容
  • 存储引擎:类似InnoDB的存储机制
  • 字符集:完整支持UTF-8、GBK等
  • 迁移工具:一键迁移工具

3. PostgreSQL替代

  • 高级特性:支持JSON、GIS等高级功能
  • 扩展机制:支持自定义数据类型
  • 并行查询:支持并行处理
  • 兼容性:90%以上PG语法兼容

优缺点分析

优点

  • 完全自主可控:无国外技术依赖
  • 高度兼容:兼容主流数据库语法
  • 性能优秀:针对国产硬件优化
  • 安全可靠:通过国家各项安全认证
  • 服务支持:本地化技术支持

缺点

  • 生态相对较小:第三方工具支持有限
  • 学习成本:需要适应国产数据库特性
  • 社区资源:开源社区相对较小
  • 国际化:国际影响力有限

学习资源推荐

  • 官方文档https://eco.dameng.com/docs
  • 认证考试:达梦DCA、DCP认证
  • 书籍:《达梦数据库实用教程》、《达梦数据库管理与维护》
  • 实践项目:政府OA系统、国产化ERP系统
  • 在线课程:达梦大学在线培训平台

总结

达梦数据库作为国产数据库的领军者,凭借其完全自主可控、高度兼容、性能优秀等特点,在信创产业中发挥着重要作用。随着国产化替代的深入推进,达梦数据库在政府、金融、能源等关键领域的应用将越来越广泛。对于需要满足国产化要求的项目,达梦数据库是最佳选择之一。掌握达梦数据库对于国产化系统开发者和数据库管理员来说是必备技能。