8

TiDB如何实现版本升级

 3 years ago
source link: https://www.zenlife.tk/tidb-upgrade-safety.md
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

TiDB如何实现版本升级

2017-04-01

如何不考虑兼容性,都好办。但是考虑已经有上线用户,就比较麻烦。必须考虑兼容性,能够平滑升级,不影响到业务。

除了数据编码外,还有一些其它可能有兼容性的地方。比如某个全局session variable,以前默认值是1,现在新版本里面要变成2。比如某张表以前没有,现在新版本想添加。比如以前有某张表,现在想修改schema添加一列...

现在的做法,TiDB里面存了一个字段表示当前的TiDB的bootstrap版本,在bootstrap的时候如果发现程序的版本大于当前bootstrap的版本,则执行upgrade操作。

由于TiDB是分布式的,升级版本会引入一些风险性:

  • 多台机器同时执行bootstrap的一致性保证

假设整个集群同时重启,会有多个机器同时执行bootstrap操作。需要保证只有一个做bootstrap的TiDB能够成功,其它都会失败。执行失败的TiDB也能正确启动,不会起不来。

涉及到DDL操作不会因为同时执行而被重复执行多次。失败的重试不会用旧版本数据覆盖新的。更新的操作和版本号不会交叉,即更新操作成功,修改版本号却失败了,或者更新失败而版本号修改了。

  • 升级过程中断了是否可恢复

如果升级过程中,被用户手动杀进程了,整个数据应该处于可恢复的状态。不能出现,那bootstrap处于一个升级版本做了一半的状态。 然后再执行一直失败,永远处于一个再也无法启动的状态,整个集群就废了。

  • DDL的花费的时间问题

实现上的限制,做DDL添加列每次只能添加1列。每个DDL最快要经过两个lease。如果lease时间设置的10秒,如果更新涉及30个DDL操作,那升级操作会花费10分钟。

  • slave集群的存在对升级的影响

如果有slave集群存在,会有binlog同步的过程。binlog同步在遇到DDL会阻塞。slave会被阻塞这也是一个风险。

主要说说多机同时bootstrap的一致性问题。这里想到三种方案

第一种,最简单直观的应该是分布式锁。假设有分布式锁的机制,就可以保证只有一个机器拿到锁,只有拿到锁的那台机器能做bootstrap,其它都拿无法执行bootstrap。

分布式锁的,这里有一篇同事的demo教程

第二种,利用事务实现。

TiDB本身已经有事务了。如果把更新要做的操作,和更新版本号,扔到一个事务里面,就可以保证两者都成功,或者两者都失败。

begin
updateOperation
updateVersion
commit

但是这种遇到updateOperation里面有DDL的时候会出现问题,因为DDL会自动提交前面的操作,就不能保证整个是在一个事务了。

第三种,把整个过程拆小,并保证每一小步操作都是可重入的,记录checkpoint。我觉得这种理解上面最复杂,展开说一下。

关键点在于可重入。如果是加表需要是create table if not exist,执行多次也没问题。如果插入数据,则需要把插数据和改版本放事务里,不能让插数据执行多次。

然后保证:checkpoint之前的,都是一定成功了的。也就是操作成功才记录checkpoint,而如果操作失败,即使有脏数据,由于是可重入的,从上个checkpoint开始重新执行一遍,也没问题。

以上就是TiDB在版本升级时的一些实现细节。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK