POLARDB · 最佳实践 · POLARDB不得不知道的秘密 (2)

另外,POLARDB会提前创建好下一个需要写的redolog日志(每个日志都是固定的1G,即使没有被写过),主要目的是当当前的redolog被写完后,能快速的切换到下一个,因此,也会占用额外1G空间。此外,后台定时删除任务目前是一个小时清理一次(还有优化的空间),但是不会清理到最后一个日志,会保留一个日志,主要用来做按时间点还原任务。

接下来,举个经典的例子,方便理解上述的策略:
```
mysql> show polar logs;
+-----------------+----------------+-------------+
| Log_name | Start_lsn | Log_version |
+-----------------+----------------+-------------+
| ib_logfile41008 | 19089701633024 | 100 |
| ib_logfile41009 | 19090775372800 | 100 |
+-----------------+----------------+-------------+
2 rows in set (0.00 sec)

mysql> show polar status\G
......
-----------------
Log File Info
-----------------
2 active ib_logfiles
The oldest log file number: 41008, start_lsn: 19089701633024
The newest log file number: 41009, start_lsn: 19090775372800
Log purge up to file number: 41008
8 free files for reallocation
Lastest(Doing) checkpoint at lsn 19091025469814(ib_logfile41009, offset 250099062)
......
```
`show polar logs`这条命令可以查看系统中的redolog日志,上个例子中,ib_logfile41008这文件已经被写完,但是这个日志需要被保留用来支持按照时间点还原和克隆实例任务,ib_logfile41009是最后一个redolog,表示目前正在写的redolog。

`show polar status\G`可以显示POLARDB很多内部信息,这里只截取了redolog相关的一部分,前四行就是字面的意思,不具体解释了。第五行表示缓冲池目前有8个redolog。

另外,上文提到过,POLARDB会提前创建一个redolog用以快速的切换,名字一般是最后一个文件编号加一,所以是ib_logfile41010。

结合这些信息,就可以推断出,目前系统中redolog占用量为11G = 8G(缓冲池中的)+1G(保留的ib_logfile41008)+1G(正在被写的ib_logfile41009)+1G(提前创建的ib_logfile41010)。

另外,透露一个好消息,我们内部正在调研redolog日志不收费的可行性,如果通过验证,这部分占用的空间将不会收取用户费用。

### undolog日志占用
讲完了redolog日志,接下里讲讲undolog日志。上文说过在POLARDB中undolog大部分是以独立表空间存在的,也就是说是独立的文件,而不是聚集在ibdata1文件中。目前分了8个文件,文件名为undo001-undo008,每个文件默认初始大小为10M,会随着使用增大,在某些不推荐的用法下,会导致undolog空间增长很快。这里简单举个例子,可以使undolog撑的很大:使用`START TRANSACTION WITH consistent snapshot`开启一个事务,注意要在RR隔离级别下,然后开启另外一个连接,对库中的表进行高频率的更新,可以使用sysbench辅助,很快,就会发现undolog膨胀。从数据库内核的角度来讲,就是由于一个很老的readview,导致需要把很多的历史版本都保留下来,从而导致undolog膨胀。在线上,往往是一个大查询或者一个长时间不提交的事务导致undolog膨胀。undolog膨胀后,即使所有事务都结束后,也不会自动缩小,需要使用下文的方法进行在线truncate。

目前,用户还不能直接查看undolog的占用量,后续我们会在information_schema加上,方便用户查看,但是可以通过间接的方法:如果控制台上显示日志占用量很大,但是redolog占用量很小,那么一般就是undolog了,因为其他几个都占用很小的空间,几乎可以忽略不计。

如果发现undolog占用量比较大,POLARDB也有办法清理。原理是,等undolog所对应的事务都结束后,把清理开关打开,如果发现大小超过执行大小的undo tablespace,就会在purge线程中进行undo的truncate。尽量在业务低峰期进行,并且保证没有大事务长事务。具体操作方法就两步,首先调整`innodb_max_undo_log_size`大小,这个参数表示当每个undo tablespace大于这个值时候,后续会把它缩小,重新调整为10M。接着,打开truncate开关`innodb_undo_log_truncate`,这样,后台线程就会把所有大于`innodb_max_undo_log_size`设置的undo tablespace调整为10M。注意,这里要保证没有大事务长事务,因为后台线程会等待undo tablespace中所有事务都提交后,才会下发命令,同时也要保证`innodb_undo_logs`大于等于2。另外,不建议这个功能长期开着,如果在控制台发现日志占用量减少了,建议关闭truncate功能,因为其有可能在您业务高峰期运行,导致数据库延迟

## DDL与大事务问题
如果有一个大事务或者长事务长时间未提交,由于其长期持有MDL读锁,这个会带来很多问题。在RDS MySQL上,如果后续对这张表又有DDL操作,那么这个操作会被这个大事务给堵住。在POLARDB上,这个问题更加严重,简单的说,如果只读实例上有一个大事务或者长期未提交的事务,会影响主实例上的DDL,导致其超时失败。纠其本质的原因,是因为POLARDB基于共享存储的架构,因此在对表结构变更前,必须保证所有的读操作(包括主实例上的读和只读实例上的读)结束。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzszfy.html