一、前言
本人是MySQL出身,从业MySQL DBA七年时间,最近开始学习达梦数据库。学习达梦数据库已经有一个多月了,刚刚将DCA认证通过,对达梦数据库已经有了一个初步的了解,对比MySQL确实有很多不同之处,还有很多东西没有学到,下面我就来聊聊这俩个数据库之间的异同之处,不涉及代码只谈理论上的东西,后面再学习到新的知识点再来补充,毕竟刚入坑不久,有些东西认识的还是很浅显,如有不对之处还请客官海涵。
二、体系结构
2.1 逻辑存储结构
不同的点就是,MySQL的页默认都是用16k大小,64个连续的页组成一个区,一个区大小是1M。
那么DM这边是簇=区,页的大小默认是8k,可以设置成4k、8k、16k、32k,一般在生产环境中会设置成32k,簇跟MySQL一样都是连续的数据页组成,DM这边默认是16,可以设置成16个页、32个页、64个页,一般在生产环境中会设置成32个页,也就是32*32,一个簇也是1M。
注:设置1M的大小可以更好地管理数据块,减少碎片化,提高数据的连续性和访问速度,可以确保磁盘的寻址时间明显小于磁盘的传输时间,从而提高整体的数据处理效率
2.2 内存结构
MySQL在服务器占的内存,主要分为两大块,全局的共享缓存和所有线程缓存之和,全局共享缓存包括innodb_buffer_pool_size + Sharing buffer部分大小。线程级的独立缓存=max_threads(当前活跃连接数) * (会话级内存分配总和)。
- 全局共享缓存主要用于缓存数据页、索引页、数据字典等常用数据,这部分为常驻内存,只有数据库重启才会释放。
- 线程级独立缓存针对每个数据库连接会话会独立分配缓存,thread buffer与连接数成正比,连接数越高则总的thread buffers占用越高。这些缓存通常会随着连接的释放而关闭。
首先达梦的内存占用主要分为两大块:主内存+缓冲区。内存池有一个共享内存池,很多缓冲区不够用了就会来共享内存池来申请内存,用完了再还回去。缓冲区占用内存最多就是数据缓冲区。
- 内存池:一次向操作系统申请一片较大内存,即为内存池。参数MEMORY_POOL控制(以兆为单位),当需要申请内存时,可在共享内存池内进行申请,当用完该内存时,再释放掉。内存池不够用了就去操作系统申请,每次申请MEMORY_EXTENT_SIZE(以兆为单位),最大能扩充到MEMORY_TARGET(以兆为单位)。
- 缓冲区:分为数据缓冲区、日志缓冲区、字典缓冲区、SQL缓冲区。
- 数据缓冲区,参数BUFFER控制(以M为单位),存储的是数据页,使用三条链表来进行管理,就是经典的LRU链表、FREE链表、flush链表,这里就不多做赘述了,不懂小伙伴可以去搜搜LRU。数据缓冲区是固定大小的,数据缓冲区满了,就会淘汰LRU链表上很少被使用到的数据页(这里的算法是什么还没学到)。
- 日志缓冲区,缓存的重做日志的信息,参数RLOG_BUF_SIZE控制(以日志页个数为单位),取值只能为2的次幂值,最小值为1,最大值为20480。默认为1024,当页为16M的时候,日志缓冲区就能占到16G。当重做日志缓冲区不够用时,会向共享内存池申请内存。
- 字典缓冲区,缓存的是数据字典的信息,参数DICT_BUF_SIZE控制(以M为单位),有效值范围(1~2048),默认50M。字典缓冲区不够用时,会向共享内存池申请内存。
- SQL缓冲区,缓冲的是SQL、执行计划、结果集信息。参数CACHE_POOL_SIZE控制(以M为单位),默认200M,SQL缓冲区不够用时,会向共享内存池申请内存。
- 存储数据页在MySQL中是buffer pool,DM是在数据缓冲区。
- 达梦的缓冲区不够用了,就去共享内存池去申请;MySQL不够用了比如临时表就会取用磁盘临时表效率就大大降低了,再比如sort_buffer不够用了就会直接报错。
2.3 对象关系
- MySQL和DM都是单进程多线程的,一个进程就是一个实例。
- DM的模式 = MySQL的数据库
- DM创建一个用户就会有相同的名字的模式,而MySQL的数据库是需要手动创建的然后赋权给用户。
- 表空间上,DM需要手动创建表空间赋予给用户,其模式下创建的表就都会存储在同一个表空间中。而MySQL一个表就是一个表空间。
- DM的归档日志相当于redo的复制品,而MySQL的归档日志,可以看做是binlog在做,只不过binlog还有做主从复制的功能。
- MySQL默认是自动提交,而DM默认不自动提交,这需要注意。
三、主备复制
从上图可以看出,两种数据库的复制是完全不同的,下面我仅以常用的复制模式(半同步复制 & 实时归档)来做一下对比:
MySQL:无损半同步复制是MySQL5.7才提出的目的是解决半同步复制存在的潜在问题,在主库等待从库ACK信号的时机做出了改变:
- 普通半同步:客户端提交事务—>SQL解析—>redo prepare—>写binlog—>commit—>等待从库反馈—>返回客户端
- 无损半同步:客户端提交事务—>SQL解析—>redo prepare—>写binlog—>等待从库反馈—>commit—>返回客户端
废话不多说,先上复制原理:MySQL复制过程会产生三个线程,主库的二进制转储线程dump,主要负责生成二进制日志并响应从库的I/O线程请求。从库生成2个线程,IO线程负责与主库生成一个客户端连接并请求二进制日志,并将接收到的日志写入中继日志。当I/O线程成功接收到日志后,会发送ACK信号给主库确认;另一个是SQL线程负责执行中继日志中的操作,更新数据以保持与主库一致。
整个流程大概就是主库事务提交一个事务,写入binlog,唤醒dump读取二进制日志中的事件给到IO线程,IO线程将接受到的事件记录到中继日志中,写入到中继日志中后,IO线程返回给主库一个ACK信号,主库将事务commit,返回客户端,SQL线程读取事件在从库上执行,实现从库的数据更新。
达梦:实时归档分为两种,一种是高性能模式、一种是事务一致性模式,一般会采用高性能模式,在读写分离的场景下采用事务一致性模式,下面我来简单讲讲两种模式的原理
高性能模式:dmarch.ini中配置项ARCH_WAIT_APPLY=0,主库提交一个事务,写入redo log,产生一个RLOG_PKG的日志包,然后通过MAL系统(MAL是达梦内部高速通信系统,基于 TCP/IP 协议实现。内部包含一系列线程,有 MAL 监听线程、MAL 发送工作线程、MAL 接收工作线程等)传送到备库,备库将最新收到的RLOG_PKG保存在内存中,备库会给主库一个响应成功的信号,主库收到信号后对redo联机日志进行刷盘,同时归档日志刷盘,备库这边将接受到的日志包并不会立即重演,它先将原来的KEEP_PKG替换掉,原KEEP_PKG加入到APPLY线程队列中进行重演。
达梦引入KEEP_PKG,是为了解决在主库写入联机日志前宕机,备库的数据会比主库的数据还要多,造成的数据不一致的问题。
因为备库不对外提供服务,所以5s的等待重演时间也无所谓,但是读写分离就不能用这个模式。
事务一致性模式:dmarch.ini中配置项ARCH_WAIT_APPLY=1,事务一致性模式就没有KEEP_PKG的概念了,备库接受到日志包后会直接加入到APPLY线程队列中进行重演,重演后才会给主库响应。
为了避免日志堆积,达梦这边引入了参数REDOS_PARALLEL_NUM可以并行对日志进行重演,有效值1~64。
- MySQL这边会产生一个TCP/IP往返的一个时间延迟。达梦这边是MAL系统高速通道产生的延迟。
- redo记录的是在某个页做了什么修改,binlog记录的是逻辑SQL语句,所以在备库重现上,达梦是要更快的。
- 一主多备的场景下,MySQL这边是等一台主机ACK消息就会返回客户端,达梦是需要所有备机均需给出响应才会返回客户端,从性能上来看MySQL更优,但是从数据保护角度看,达梦做得更好。
四、语句操作
元数据信息
在MySQL中查询一些系统参数信息,数据库信息,表信息都是show的,比如:
- show variables like'XXX'; -- 查看系统参数
- select user,host from mysql.user; -- 查看用户信息
- show databases; -- 查看都有哪些数据库.
- show tables; -- 列出某数据中都有哪些表
- show create tables XXX; -- 列出表结构
还有在MySQL中有一些重要的内置系统表,比如information_schema,保存维护其他所有数据库的元信息。还有performance_schema存放的是数据库的一些性能指标。
- select * from v$dm_ini;-- 查看系统参数。
- select * from DBA_USERS; -- 查看用户信息
- select * from all_users; 查看都有哪些模式,其实也是看用户
- select * from dba_tables where owner='xxx';就会列出XXX模式下都有哪些表
- select * from DBA_TABLESPACES; -- 列出表空间信息
- SELECT * FROM DBA_TAB_COLUMNS WHERE OWNER='TANG'; -- 查看表的列信息,对应MySQL的information_schema.columns
数据类型
1.longtext:MySQL支持的,达梦不支持,使用用clob代替2.mediumint:3字节的整型,MySQL支持,达梦没有。
3.varchar(10):这个10,在MySQL中代表的字符数,在达梦代表的事字节数,如果做迁移的话要注意避免too long。
4.timestamp:MySQL取值范围只能到'2038-01-19 03:14:07' ,达梦取值范围到'9999-12-31'。
语句
1.注释:创建表时,达梦不支持直接列后面comment注释,需要使用 comment on is代替。2.全外连接:达梦支持,MySQL不支持可以通过left join 和right join,然后union all合并起来实现。
3.插入语句:达梦只有insert,MySQL还支持replace和ignore。
函数
1.不支持 date_sub 函数,使用 dateadd(datepart,n,date) 代替2.不支持 date_format 函数,使用 date_part 代替,或者使用 extract 代替。
3.不支持 substring_index 函数, 使用 substr / substring 代替。
4.不支持 group_concat 函数,使用 wm_concat 代替。
5.不支持 from_unixtime 函数,使用 round 代替。
6.不支持 on duplicate key update,使用 merge into 代替。
7.不支持 ignore,使用 insert ignore into代替。
8.不支持 auto_increment, 使用 identity 代替,从1开始,每次增1。
五、常用工具
DM只要安装了数据库就会有一些管理端工具,在tool目录下很是方便。MySQL一般依赖第三方工具进行管理。




