达梦数据库(DM8)安装+Golang 使用
达梦数据库(DM8)安装+Golang 使用
数据库名称+版本:达梦数据库 DM8
安装方式:Docker
编程语言+版本:Golang 1.20
ORM+版本:gorm V1.25.9
随着国家对信创工程的日益重视,目前采用有自主知识产权的国产数据库将成为主流。因此公司要求使用的数据库需要由 MySQL 切换为达梦数据库。DM 数据库和 MySQL 体系结构上存在差异,SQL 语法也存在一定的差异。DM数据库针对 MySQL 做了部分兼容性。但由于有根本性的差异,兼容度不高。另外对于 Golang 语言的支持和Mac系统的支持也不够好,笔者也是详细阅读达梦的官方文档后,根据实际的操作整理出该文章。
一、简介
武汉达梦数据库股份有限公司成立于2000年,是国内领先的数据库产品开发服务商,国内数据库基础软件产业发展的关键推动者。公司为客户提供各类数据库软件及集群软件、云计算与大数据等一系列数据库产品及相关技术服务,致力于成为国际顶尖的全栈数据产品及解决方案提供商。DM8是达梦公司在总结DM系列产品研发与应用经验的基础上,坚持开放创新、简洁实用的理念,推出的新一代自研数据库。
DM8吸收借鉴当前先进新技术思想与主流数据库产品的优点,融合了分布式、弹性计算与云计算的优势,对灵活性、易用性、可靠性、高安全性等方面进行了大规模改进,多样化架构充分满足不同场景需求,支持超大规模并发事务处理和事务-分析混合型业务处理,动态分配计算资源,实现更精细化的资源利用、更低成本的投入。一个数据库,满足用户多种需求,让用户能更加专注于业务发展。
二、安装
本次安装采用 Docker 方式安装
下载 Docker 安装包
请在达梦数据库官网下载 Docker 安装包。
导入安装包
拷贝安装包到 /opt 目录下,执行以下命令导入安装包:
1 |
|
结果显示如下:
导入完成后,可以使用 docker images
查看导入的镜像。结果显示如下:
启动容器
镜像导入后,使用 docker run
启动容器,启动命令如下:
1 |
|
结果显示如下:
容器启动完成后,使用 docker ps
查看镜像的启动情况,结果显示如下:
启动完成后,可通过日志检查启动情况,命令如下:
1 |
|
结果显示如下:
启动/停止数据库
停止数据库命令如下:
1 |
|
启动数据库命令如下:
1 |
|
重启命令如下:
1 |
|
注意
1.如果使用 docker 容器里面的 disql,进入容器后,先执行 source /etc/profile 防止中文乱码。
2.新版本 Docker 镜像中数据库默认用户名/密码为 SYSDBA/SYSDBA001。
进入容器 查看
1 |
|
三、使用
使用共分为两种方式,一种是自己安装驱动包和依赖包,增加必要的文件后开始使用;第二种是直接导入go get gitlab.example.com/zhangweijie/dmgorm
包开始使用
首先介绍第一种方式:
第一种方式:自主安装使用
安装 dm 驱动包
将提供的 dm 驱动包(Go 驱动源码)下载。驱动源码为go-20230418.zip
压缩包,解压缩后会出现名为 go
的文件夹,文件夹下有三个压缩包,分别为
dm-go-driver.zip
:Go 的驱动源码,解压后会出现名为 dm
的文件夹,将文件夹放到GOPATH 的 src 目录下
注意
由于该驱动不支持Mac系统,所以需要在
/dm/security
目录下增加名为zzg_drawin.go
文件
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import "plugin"
var (
dmCipherEncryptSo *plugin.Plugin
cipherGetCountProc plugin.Symbol
cipherGetInfoProc plugin.Symbol
cipherEncryptInitProc plugin.Symbol
cipherGetCipherTextSizeProc plugin.Symbol
cipherEncryptProc plugin.Symbol
cipherCleanupProc plugin.Symbol
cipherDecryptInitProc plugin.Symbol
cipherDecryptProc plugin.Symbol
)
func initThirdPartCipher(cipherPath string) (err error) {
if dmCipherEncryptSo, err = plugin.Open(cipherPath); err != nil {
return err
}
if cipherGetCountProc, err = dmCipherEncryptSo.Lookup("cipher_get_count"); err != nil {
return err
}
if cipherGetInfoProc, err = dmCipherEncryptSo.Lookup("cipher_get_info"); err != nil {
return err
}
if cipherEncryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt_init"); err != nil {
return err
}
if cipherGetCipherTextSizeProc, err = dmCipherEncryptSo.Lookup("cipher_get_cipher_text_size"); err != nil {
return err
}
if cipherEncryptProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt"); err != nil {
return err
}
if cipherCleanupProc, err = dmCipherEncryptSo.Lookup("cipher_cleanup"); err != nil {
return err
}
if cipherDecryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt_init"); err != nil {
return err
}
if cipherDecryptProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt"); err != nil {
return err
}
return nil
}
func cipherGetCount() int {
ret := cipherGetCountProc.(func() interface{})()
return ret.(int)
}
func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
ret := cipherGetInfoProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(seqno, cipherId, cipherName, _type, blkSize, khSIze)
if ret.(int) == 0 {
panic("ThirdPartyCipher: call cipher_get_info failed")
}
}
func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
ret := cipherEncryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
if ret.(int) == 0 {
panic("ThirdPartyCipher: call cipher_encrypt_init failed")
}
}
func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
ciphertextLen := cipherGetCipherTextSizeProc.(func(uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainTextSize)
return ciphertextLen.(uintptr)
}
func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
ret := cipherEncryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
return ret.(uintptr)
}
func cipherClean(cipherId, cipherPara uintptr) {
cipherEncryptProc.(func(uintptr, uintptr))(cipherId, cipherPara)
}
func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
ret := cipherDecryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
if ret.(int) == 0 {
panic("ThirdPartyCipher: call cipher_decrypt_init failed")
}
}
func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
ret := cipherDecryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
return ret.(uintptr)
}
gorm_v1_dialect.zip
:适配 gorm v1版本,暂时不用
gorm_v2_dialect.zip
:适配 gorm v2版本,解压后也会出现名为dm
的文件夹,将文件夹放到项目能够找到的路径下即可,后续会使用
安装依赖包
1 |
|
开始使用
1 |
|
第二种:导包使用
导入现有包
1 |
|
开始使用
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!