问题现象
采用 OceanBase 数据库 V4.2.1 BP7 版本,基于网络的主备租户,在使用 OCP V4.2.2 版本,进行日常 SWITCHOVER 切换操作时报错:(conn=3405099) wait tenant sync to lastest failed(original error code:-4179),switch to primary not allowed,OCP V4.2.2 版本异常信息如下所示。
错误码:OBE10002
错误信息:操作 OceanBase 失败,错误信息:(conn=3405099) wait tenant sync to latest failed(original error code:-4179),switch to primary not allowed
错误原因:连接 standby_mysql_test 执行 ALTER SYSTEM SWITCHOVER TO PRIMARY; args: 失败,错误信息:(conn=3405099) wait tenant sync to latest failed(original error code:-4179),switch to primary not allowed
主租户信息:
在主租户上通过 dba_ob_tenants 视图,展示本租户的信息。
MySQL [oceanbase]> select tenant_id,tenant_name,tenant_type,status,tenant_role,switchover_status,log_mode from dba_ob_tenants;输出结果如下:
+-----------+---------------+-------------+--------+-------------+-------------------+--------------+ | tenant_id | tenant_name | tenant_type | status | tenant_role | switchover_status | log_mode | +-----------+---------------+-------------+--------+-------------+-------------------+--------------+ | 1002 | tnt_mysql_test| USER | NORMAL | PRIMARY | NORMAL | ARCHIVELOG | +-----------+---------------+-------------+--------+-------------+-------------------+--------------+ 1 rows in set (0.057 sec)在主租户上通过 dba_ob_access_point 视图,展示租户入口的 Server 列表。
MySQL [oceanbase]> select * from dba_ob_access_point;输出结果如下:
+-----------+----------------+----------------+----------+ | TENANT_ID | TENANT_NAME | SVR_IP | SQL_PORT | +-----------+----------------+----------------+----------+ | 1002 | tnt_mysql_test | xx.xxx.xxx.xxx | 2881 | +-----------+----------------+----------------+----------+ | 1002 | tnt_mysql_test | xx.xxx.xxx.xxx | 2881 | +-----------+----------------+----------------+----------+ | 1002 | tnt_mysql_test | xx.xxx.xxx.xxx | 2881 | +-----------+----------------+----------------+----------+在主租户上通过 gv$ob_server_schema 动态视图,展示所有 OBServer 节点上的 Schema 信息。
MySQL [oceanbase]> select * from gv$ob_server_schema_info;输出结果如下:
+----------------+----------+-----------+--------------------------+-------------------------+--------------+-------------+----------------------------+ | SVR_IP | SVR_PORT | TENANT_ID | REFRESHED_SCHEMA_VERSION | RECEIVED_SCHEMA_VERSION | SCHEMA_COUNT | SCHEMA_SIZE | MIN_SSTABLE_SCHEMA_VERSION | +----------------+----------+-----------+--------------------------+-------------------------+--------------+-------------+----------------------------+ | xx.xx.xxx.xx | 2882 | 1002 | 1718774101199160 | 1718774101199160 | 1565 | 1831783 | -1 | | xx.xx.xxx.xx | 2882 | 1002 | 1718774101199160 | 1718774101199160 | 1565 | 1831783 | -1 | | xx.xx.xxx.xx | 2882 | 1002 | 1718774101199160 | 1718774101199160 | 1565 | 1831783 | -1 | +----------------+----------+-----------+--------------------------+-------------------------+--------------+-------------+----------------------------+ 3 rows in set (0.055 sec)
备租户信息:
在备租户上通过 dba_ob_tenants 视图,展示本租户的信息。
MySQL [oceanbase]> select tenant_id,tenant_name,tenant_type,status,tenant_role,switchover_status,log_mode from dba_ob_tenants;输出结果如下:
+-----------+--------------------+-------------+--------+-------------+-------------------+--------------+ | tenant_id | tenant_name | tenant_type | status | tenant_role | switchover_status | log_mode | +-----------+--------------------+-------------+--------+-------------+-------------------+--------------+ | 1002 | standby_mysql_test | USER | NORMAL | STANDBY | NORMAL | NOARCHIVELOG | +-----------+--------------------+-------------+--------+-------------+-------------------+--------------+ 1 rows in set (0.057 sec)在备租户上通过 gv$ob_server_schema 动态视图,展示所有 OBServer 节点上的 Schema 信息。
MySQL [oceanbase]> select * from gv$ob_server_schema_info;输出结果如下:
+----------------+----------+-----------+--------------------------+-------------------------+--------------+-------------+----------------------------+ | SVR_IP | SVR_PORT | TENANT_ID | REFRESHED_SCHEMA_VERSION | RECEIVED_SCHEMA_VERSION | SCHEMA_COUNT | SCHEMA_SIZE | MIN_SSTABLE_SCHEMA_VERSION | +----------------+----------+-----------+--------------------------+-------------------------+--------------+-------------+----------------------------+ | xx.xx.xxx.xx | 2882 | 1002 | 1718774101199160 | 1718774101199160 | 1565 | 1831783 | -1 | | xx.xx.xxx.xxx | 2882 | 1002 | 1718774101199160 | 1718774101199160 | 1565 | 1831783 | -1 | | xx.xx.xxx.xx | 2882 | 1002 | 1718774101199160 | 1718774101199160 | 1565 | 1831783 | -1 | +----------------+----------+-----------+--------------------------+-------------------------+--------------+-------------+----------------------------+ 3 rows in set (0.055 sec)在备租户上通过 dba_ob_log_restore_source 视图,展示物理恢复租户、备租户的日志恢复源信息。
MySQL [oceanbase]> select * from dba_ob_log_restore_source\G;输出结果如下:
*************************** 1. row *************************** TENANT_ID: 1002 ID: 1 TYPE: SERVICE VALUE: IP_LIST=xx.xx.xxx.xx:xxxx;xx.xx.xxx.xx:xxxx;xx.xx.xxx.xx:xxxx,USER=STANDBYRO@tnt_mysql_test,PASSWORD=xxxxxxxx,TENANT_ID=1002,CLUSTER_ID=xxxxxxxxxx,COMPATIBILITY_MODE=MYSQL,IS_ENCRYPTED=true RECOVERY_UNTIL_SCN:xxxxxxxxxxxxxxxx 1 row in set (0.041 sec)
问题分析
基于 OCP 报错任务查看错误相关信息。登录备租户,查看
dba_ob_rootservice_event_history,查看 SWITCHOVER 切换过程。登录备租户,通过
dba_ob_rootservice_event_history查看 SWITCHOVER 切换过程。
在
wait tenant sync from latest报 -4016 错误。备租户在切换成主租户时,备需要同步完日志恢复源的所有日志,防止备切为主之后丢失数据,因此在switchover to primary过程中,wait sync to latest就是在检查备租户是否已经同步完原主租户的日志。根据上一步报错的信息,
RS_SVR_IP和RS_SVR_PORT表示了 SWITCHOVER 命令执行的 OBServer,登陆到该 OBServer 节点,根据 trace_id 查看 SWITCHOVER 的执行日志。WDIAG [RPC] wait (ob_async_rpc_pr.h:422)[195120][T1002_L0_G0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=19] [errcode=0] execute rpc failed(re-4016,server="xx.xx.xx.xx",timeout=xxxxxxx,packet code-l856, arge{tenant id:1002, is_id:(id:(id:l), check_sync_to_latest:erue}) WDIAG [STANDBY] get_checkpoints_by_rpc (ob_tenant_role_transition_service.cpp:1368) [1951201][T1002_L0_G0][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=20][errcode=-4016] get checkpoints: send rpc failed(ret=-4016,ret="OB_ERR_UNEXPECTED",tmp_ret=-4016,tmp_ret="OB_ERR_UNEXPECTED",i=0) WDIAG [STANDBY] get_sys_ls_sync_scn_ (ob_tenant_role_transition_service.cpp:1434) [1951201][T1002_L0_G0][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=10] [errcode=-4016] fail to get_checkpoints_by_rpc(ret=-4016,ret="OB_ERR_UNEXPECTED",tenant_id=1002,sys_ls_status_array=[{tenant_id=1002,ls_id:{id:1},ls_group_id:0,status:"NORMAL",unit_group_id:0,primary_zone:"zone1",flag:{flag:0 is_duplicate:false,is_block_tablet_in:false}}]) WDIAG [STANDBY] check_sync_to_latest_ (ob_tenant_role_transition_service.cpp:1270) [1951201][T1002_L0_G0][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=12][errcode=-4016] failed to get_sys_ls_sync_scn_(ret=-4016,ret="OB_ERR_UNEXPECTED",switchover_checkpoints=[]) INFO [STANDBY] check_sync_to_latest_ (ob_tenant_role_transition_server.cpp:1299) [1951201][T1002_L0_G0][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=7] check sync to latest(ret=-4016,ret="OB_ERR_UNEXPECTED")-4016 为备租户跟原主租户进行 RPC 通信失败:
send rpc failed(ret=-4016,ret="OB_ERR_UNEXPECTED"。根据 RPC 失败的日志,通过 trace_id 搜索相应的 server=10.xx.xx.107 的 OBServer 日志。
INFO [SHARE] per_run (ob_tenant_base.cpp:314) [3060484][][xxxxx-xxxxx-xxxxx-xxxxx] [lt=13] tenant thread pre_run(MTL_ID()=1002,ret=0,thread_count_=305) INFO run1 (ob_timer.cpp:360) [3060484][][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=7] timer thread started(this=0x7c301ebfec0,tid=3060484,lbt()=0x1324a35c 0x5658c7c 0x1350bcf1 0x13507e93 0x7fc3f160f1b 0x7fc3f15e81c0) WDIAG [LIB.MYSQLC] connect (ob_mysql_connection.cpp:240)[2820974][T1002_L0_G18][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=11][errcode=-1045] fail to connect to mysql server(get_sessid()=0,host=xx.xx.xx.xx,user=STANDBY@tnt_mysql_test,db=oceanbase,port=2881,info="Acess denied for user 'STANDBYRO'@'xxx.xxx.xxx'using password: YES"), ret=-1045) WDIAG [LIB.MYSQLC] try_connect (ob_mysql_connection_pool.cpp:533) [2820974][T1002_L0_G18][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=21][errocode=-1045] fail to connect to server(connection->get_server()="xxx.xxx.xxx.xxx:xxxx",ret=-1045)发现是 STANDBYRO 用户连接原主租户 server(10.xx.xx.80/91/69)时失败,信息如下。
[errcode=-1045] fail to connect to mysql server,info="Access denied for user 'STANDBYRO'@'xxx.xxx.xxx.xxx' (using password: YES)", ret=-1045)从报错信息看应该是 STANDBYRO 用户密码不正确导致。
通过了解整个操作过程,在做 SWITCHOVER 之前,在 OCP 白屏修改了主租户的同步用户 STANDBYRO 的密码,判断本次报错是因为手动修改 STANDBYRO 密码导致的。
修改完 STANDBYRO 用户密码后,主备同步也是正常的,原因是修改账号密码,只会导致底层日志传输服务的 SQL 连接失效,但是本地还缓存着 Server 列表,RPC 能正常通信,因此可以获取到对应的日志,因此备库是可以继续同步的。
说明
关于
STANDBYRO用户的详细信息,参见:创建空备租户。
问题原因
人为修改同步专用用户 STANDBYRO 密码后,在 SWITCHOVER 切换时,备需要同步原主租户最新的日志信息,导致旧密码连接 RPC 失败,因此 SWITCHOVER 切换报错:-4179,switch to primary not allowed 。
问题的风险及影响
同步卡住(如:主备升级后同步卡住)或运维 SWITCHOVER 切换失败等。
影响的租户
影响 OceanBase 数据库中的 SYS 租户和 Oracle 租户以及 MySQL 租户。
关于 STANDBYRO 用户
在 OceanBase 数据库 V4.2.0 及之后版本,开始支持基于网络的主备租户,而 STANDBYRO 用户是基于网络主备同步时使用的一个只读用户。
当使用 OCP 部署基于网络的主备库时,在为主租户创建首个备租户时,OCP 会自动为主租户创建一个 STANDBYRO 只读用户,并授予相应的某些系统视图查询权限,密码为符合等保三规定的随机密码,保存到密码箱。
基于网络的主备租户,为了支持在主租户节点故障、日志回收等场景下保障备租户的高可用性,备租户需要主租户某些系统视图的查询权限,因此主租户需要提供一个 STANDBYRO 只读用户,同步给备租户。
关于 STANDBYRO 用户权限,参见:创建空备租户 。
影响的版本
OceanBase 数据库 V4.2.0 及之后版本,基于网络的主备租户场景。
解决方法及规避方式
解决方法:
此时由于原主租户已经
switchover to standby了,此时两个租户都是备租户,原备租户需要同步完原主租户的日志,由于 STANDBYRO 密码被修改了,此时需要重新修改原备租户的日志同步源,让其重新连接原主租户同步完日志,最后在 OCP 界面上重试失败任务即可。登录原备租户,使用新的 STANDBYRO 用户密码,重新设置日志恢复源。
alter system set log_restore_source="SERVICE=$ip_list:port USER=STANDBYRO@$tenant_name PASSWORD=$new_password";在 OCP 中重试该失败步骤的任务,继续进行后续的 SWITCHOVER 切换。
规避方式:
后续运维侧需要注意,禁止人为修改主备同步用户的密码,防止引起不必要的主备同步卡住或其它问题。