什么时块裂呢?
这就涉及到OS(操作系统)的原子写的大小,一般情况下OS原子写是4K,硬盘一个扇区是512字节,4K需要写8个扇区。
假如写了4个扇区发生了断电,或者其他的意外,那么不就是丢失了另外4个扇区的数据吗?是另外2K字节没有写入!
这是OS和磁盘之间的故事,属于硬件工程师或者叫存储工程师操心的事,不过一般采用UPS或者是RAID卡上的电池来保证。
RAID卡10模式采用写两份来保证,RAID5 采用奇偶校验方式。
那么DATABASE(数据库) 与OS 这两者咋办呢?DATABASE MYSQL是16K一个数据页,ORACLE是8K一个块。远比OS4K原子写要大得多。
如何保证断电的时候数据页只写入了一半?
要么靠硬件来保证,要么靠软件机制来保证!
MYSQL 双写机制
当修改页的事务提交后,通过MEMCPY把该脏页复制到DOUBLE WRITE BUFFER中,DWB不是内存而是硬盘一个区域
它在共享表空间IBDATA分配的连续空间。大小2MB,分两个部分每个部分1MB,根据16K可以分128个页。
DWB 写满后或者刷脏行为,则把DWB写入数据文件中。
当断电时候,MYSQL会检查数据文件的页的CHECKSUM有问题,则从DWB拷贝完整的页来覆盖,然后再根据REDO恢复。
感觉它有点像ORACLE的REDO BUFFER机制,先写在内存的REDO BUFFER,满1/3,1MB,COMMIT行为就写入REDO FILE中。
O是为了提高REDO写入性能。
MYSQL 8.0 DOUBLE优化来提高写性能
INNODB_DOUBLEWRITE_FILES
INNODB_DOUBLEWRITE_PAGES
INNODB_DOUBLEWRITE_BATCH_SIZE
参数 skip_innodb_doublewrite可以禁止使用 doublewrite功能
若需要统计数据库在生产环境中写人的量,最安全的方法
还是根据 Innodb_dblwr_pages_written来进行统计
很显然这个是INNODB引擎专用参数,至于其它引擎是否有双写来保证块裂,就不得而知了.不过可以通过全备份+BINLOG来恢复.
MYSQL 必须双写是因为BINGLOG是逻辑的,只能恢复数据无法恢复物理块,而且REDOLOG不归档。
Oracle 这部分怎么处理的呢?
ORACLE 在块的头和尾都记录下SCN,如果读取来的时候对比下是否相同?不同就表示发生了块裂
早期由DBA处理,如果块有问题由DBA对块所在的文件做一个完全介质恢复。
9I 从RMAN块恢复功能,11G 从DG读取错误的块到主库
RMAN RECOVER DATAFILE 6 BLOCK 3
坏块视图:V$DATABASE_BLOCK_CORRUPTION, V$DIAG_INFO;
检验坏块:
ANALYZE TABLE ANALYZE ;INDEX DBVERIFY;BACKUP...VALIDATE;LIST FAILURE;VALIDATE
PG 这部分怎么处理的呢?
用FULL PAGE WRITE 实现无DBA参与块列恢复.
要恢复一个块,先有块的完整备份和备份后来的修改日志
FULL PAGE WRITE 是块的完整备份。
FULL PAGE WRITE 是在CHECKPOINT后第一次修改时把页写入XLOG中。
虽然PG FULL PAGE WRITE会造成XLOG日志肥大,人家也可以开启压缩日志开关。而PG XLOG是物理的,还有归档。
高斯这部分怎么处理的呢?
华为高斯把XLOG里面的FULL PAGE WRITE改成MYSQL的DOUBLE WRITE 有些画龙点睛的味道。
OS的改进
硬件支持原子写大于4K有 NVME的SSD固态硬盘.一个扇区是4K,有的是16KB
OS支持原子写是ZFS系统 EXT4和XFS支持不够完美。