为帮助读者更好地学习数据库,首先讲述一些数据库的基础知识。
数据库的增删改查操作,以及数据定义等数据字典的操作都是在内存中进行的。由于内存资源有限,数据库通常是把一部分数据页保存在内存中,然后使用LRU(Least Recently Used,最近最少使用)算法进行页面置换,以此来满足数据库的并发访问需求。
内存与磁盘不同,不能持久保存数据,一旦断电或系统崩溃,内存中的数据就会丢失。为了保证数据安全,数据库实例需要将内存中发生变更的数据页(脏页)及时写入磁盘上的数据文件中。检查点就是数据库实例将数据缓冲区中的数据同步到磁盘上的数据文件的数据库事件。
检查点触发的磁盘I/O是计算机系统中非常耗费资源的操作,对系统的性能影响非常大。将检查点的发生频率控制在安全、高效的范围内,对数据库的性能提升具有重要意义。
检查点分为两类。
(1)完全检查点,将数据缓存区中的脏数据页全部刷新到磁盘上的数据文件中。
(2)增量检查点,按照检查点参数的设置,将数据缓存区中的部分脏数据页按顺序刷新到磁盘上。
完全检查点会占用大量的系统资源,通常发生在数据库实例正常关闭时。一般情况下发生的数据库检查点都是增量检查点。
达梦数据库的检查点参数。
(1)CKPT_INTERVAL:检查点发生的时间间隔,单位为秒,默认值为180。即默认值情况下,数据库至少180秒要发生一次检查点。
(2)CKPT_RLOG_SIZE:产生多少日志后触发检查点,单位为MB,默认值为128。
(3)CKPT_FLUSH_RATE:检查点刷新脏数据页的比例,默认值为5,即一次检查点刷新5%的脏数据页到磁盘上。
(4)CKPT_DIRTY_PAGES:产生多少脏数据页后产生检查点,有效值范围为0~4294967294,默认值为0(忽略)。
(5)CKPT_FLUSH_PAGES:一次检查点刷新的最小脏数据页数量。
(6)CKPT_WAIT_PAGES:一次检查点的最大写入页数,默认值为1024。
这些参数是共同发生作用的。
(1)当等待刷新的脏数据页的数量大于CKPT_DIRTY_PAGES(非0)或redo日志产生量达到CKPT_RLOG_SIZE设定的值时,即使距离上次发生检查点的时间间隔不足CKPT_INTERVAL设置的时间,检查点仍然会发生。
(2)当参数CKPT_FLUSH_RATE设定的需要刷新的脏数据页比例的数量大于参数CKPT_WAIT_PAGES设定的最大值时,则实际刷新的脏数据页数量为参数CKPT_WAIT_PAGES设定的页数。
(3)当参数CKPT_FLUSH_RATE设定的需要刷新的脏数据页比例的数量小于参数CKPT_FLUSH_PAGES设定的最小值时,则实际刷新的脏数据页数量为参数CKPT_FLUSH_PAGES设定的页数。
除了系统自动发生的检查点外,也可以手动执行检查点。Oracle数据库手动执行检查点的命令格式为:
SQL> alter system checkpoint;
达梦数据库的命令为执行检查点系统函数CHECKPOINT(FLUSH_RATE),其中参数FLUSH_RATE为刷新的脏数据页比例。例如:
SQL> checkpoint(10);
意思是将数据缓存中10%的脏数据页刷新到磁盘上。
需要注意的是,参数CKPT_WAIT_PAGES限制了刷新脏数据页的最大数量。如果CKPT_WAIT_PAGES默认值为1024,则意味着无论刷新比例多大,一次最多刷新1024个脏数据页。
检查点的信息可以从系统视图V$CKPT中查询,内容如表3-1所示。
表3-1
数据库事务的作用是将数据库从一个一致状态转移到另一个一致状态。例如,A和B两个账户的钱分别是200元、100元,从A账户转100元到B账户。在转账操作成功前,A、B账户的金额分别是200元、100元;转账操作成功后,A、B账户的金额分别是100元、200元。这两种状态的账是平的(数据一致)。具体操作分步:①A账户扣除100元;②B账户增加100元。只有这两步操作都执行成功,转账才算成功。如果出现A账户少了,而B账户没有增加,或者A账户没有减少,而B账户增加了,账目就出现了问题,数据处于不一致状态。
事务中包含的操作可以有多个,为了保证数据库的状态是一致的,只有这些操作全部成功,数据库才能转移到新的一致状态。如果有一个步骤失败了,数据库就回退到事务开始前的一致状态。
事务的特点如下。
(1)原子性(atomicity):一个事务里面所有包含的SQL语句都是一个整体,要么不做,要么都做。
(2)一致性(consistency):事务开始时,数据库中的数据是一致的,事务结束时,数据库中的数据也应该是一致的。
(3)隔离性(isolation):数据库允许多个并发事务同时对其中的数据进行读写和修改,隔离性可以防止事务在并发执行时,由于它们的操作命令交叉执行而导致的数据不一致状态。
(4)持久性(durability):事务结束后,它对数据库的影响是永久的。
提交事务的操作为commit,对执行失败或未执行完的事务进行回退的操作为rollback。
数据库表中的每一行数据都有一个唯一的地址值,称为rowid,该值在行数据插入到数据库表时即被确定且唯一。数据库对数据记录的很多操作都是通过rowid来完成的,而且使用rowid进行单行记录定位的速度是最快的。
达梦数据库的rowid分两种。
(1)逻辑rowid,对表中的每条记录生成的逻辑编号,从1开始递增,而且需要额外的存储空间来存放。
(2)物理rowid,根据数据记录所在的数据文件号、页号和页内偏移得到rowid值,无须存放。
逻辑rowid只在数据表中是唯一的。物理rowid包含数据文件、数据页的信息,因此在整个数据库中都是唯一的,定位数据记录的速度要快于逻辑rowid。
LSN(Log Sequence Number)是由系统自动维护的Bigint类型数值,具有自动递增、全局唯一特性,每个LSN值代表着数据库系统内部产生的一个物理事务。物理事务(physical transaction,ptx)是数据库内部一系列修改物理数据页操作的集合,与数据库管理系统中事务(transaction)概念相对应,具有原子性、有序性、无法撤销等特性。主要包括以下几种类型的LSN。
(1)CUR_LSN是系统已经分配的最大LSN值。物理事务提交时,系统会为其分配一个唯一的LSN值,大小等于CUR_LSN+1,然后再修改CUR_LSN=CUR_LSN+1。
(2)FLUSH_LSN是已经发起日志刷盘请求,但还没有真正写入联机redo日志文件的最大LSN值。
(3)FILE_LSN是已经写入联机redo日志文件的最大LSN值。每次将redo日志包RLOG_PKG写入联机redo日志文件后,都要修改FILE_LSN值。
(4)CKPT_LSN是检查点LSN,所有LSN <= CKPT_LSN的物理事务修改的数据页都已经从Buffer缓冲区写入磁盘,CKPT_LSN由检查点线程负责调整。
通过系统视图V$RLOG可以查询到LSN的信息。
SCN(System Change Number,系统改变号)可以看作数据库内部的时钟机制,用来维护数据库的一致性。
达梦数据库提供了时间和SCN的转换函数。
(1)TIMESTAMP_TO_SCN,将时间转换为数据库的SCN,例如:
SQL> select timestamp_to_scn('2022-09-18'); 行号 TIMESTAMP_TO_SCN('2022-09-18') 1 134715801600
(2)SCN_TO_TIMESTAMP,将SCN转换为时间,例如:
SQL> select scn_to_timestamp('134715801600'); 行号 SCN_TO_TIMESTAMP('134715801600') 1 2022-09-18 00:00:00.000000
归档是将redo日志的内容进行复制,保存到另一个路径下。归档日志和数据库备份结合可以在数据库发生介质损坏时进行数据库完全恢复,也可以用来实现按时间点恢复(将数据库恢复到归档日志范围内的指定时刻)。生产系统的数据库通常运行在归档模式下。
数据库实例遇到断电等意外故障导致重启时,会根据联机日志中的redo记录将实例恢复到故障前的状态,然后再使用undo中的信息将未提交的事务回滚。这样数据库实例就恢复到故障前的一致性状态了。