gitee.com/chunanyong/dm@v1.8.12/zf.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 6 package dm 7 8 import ( 9 "context" 10 "database/sql/driver" 11 "io" 12 "reflect" 13 "time" 14 15 "gitee.com/chunanyong/dm/util" 16 ) 17 18 const SQL_GET_DSC_EP_SITE = "SELECT " + 19 "dsc.ep_seqno, " + 20 "(CASE mal.MAL_INST_HOST WHEN '' THEN mal.MAL_HOST ELSE mal.MAL_INST_HOST END) as ep_host, " + 21 "dcr.EP_PORT, " + 22 "dsc.EP_STATUS " + 23 "FROM V$DSC_EP_INFO dsc " + 24 "LEFT join V$DM_MAL_INI mal " + 25 "on dsc.EP_NAME = mal.MAL_INST_NAME " + 26 "LEFT join (SELECT grp.GROUP_TYPE GROUP_TYPE, ep.* FROM SYS.\"V$DCR_GROUP\" grp, SYS.\"V$DCR_EP\" ep where grp.GROUP_NAME = ep.GROUP_NAME) dcr " + 27 "on dsc.EP_NAME = dcr.EP_NAME and GROUP_TYPE = 'DB' order by dsc.ep_seqno asc;" 28 29 type reconnectFilter struct { 30 } 31 32 // 一定抛错 33 func (rf *reconnectFilter) autoReconnect(connection *DmConnection, err error) error { 34 if dmErr, ok := err.(*DmError); ok { 35 if dmErr.ErrCode == ECGO_COMMUNITION_ERROR.ErrCode || dmErr.ErrCode == ECGO_CONNECTION_CLOSED.ErrCode { 36 37 if connection.dmConnector.driverReconnect { 38 return rf.reconnect(connection, dmErr.getErrText()) 39 } else { 40 connection.Access.Close() 41 connection.closed.Set(true) 42 return driver.ErrBadConn 43 } 44 } 45 } 46 return err 47 } 48 49 // 一定抛错 50 func (rf *reconnectFilter) reconnect(connection *DmConnection, reason string) error { 51 // 读写分离,重连需要处理备机 52 var err error 53 if connection.dmConnector.rwSeparate { 54 err = RWUtil.reconnect(connection) 55 } else { 56 err = connection.reconnect() 57 } 58 59 if err != nil { 60 connection.closed.Set(true) 61 return ECGO_CONNECTION_SWITCH_FAILED.addDetailln(reason).throw() 62 } 63 64 // 重连成功 65 connection.closed.Set(false) 66 return ECGO_CONNECTION_SWITCHED.addDetailln(reason).throw() 67 } 68 69 func (rf *reconnectFilter) loadDscEpSites(conn *DmConnection) []*ep { 70 stmt, rs, err := conn.driverQuery(SQL_GET_DSC_EP_SITE) 71 if err != nil { 72 return nil 73 } 74 defer func() { 75 rs.close() 76 stmt.close() 77 }() 78 epList := make([]*ep, 0) 79 dest := make([]driver.Value, 4) 80 for err = rs.next(dest); err != io.EOF; err = rs.next(dest) { 81 ep := newEP(dest[1].(string), dest[2].(int32)) 82 ep.epSeqno = dest[0].(int32) 83 if util.StringUtil.EqualsIgnoreCase(dest[3].(string), "OK") { 84 ep.epStatus = EP_STATUS_OK 85 } else { 86 ep.epStatus = EP_STATUS_ERROR 87 } 88 epList = append(epList, ep) 89 } 90 return epList 91 } 92 93 func (rf *reconnectFilter) checkAndRecover(conn *DmConnection) error { 94 if conn.dmConnector.doSwitch != DO_SWITCH_WHEN_EP_RECOVER { 95 return nil 96 } 97 // check trx finish 98 if !conn.trxFinish { 99 return nil 100 } 101 var curIndex = conn.getIndexOnEPGroup() 102 if curIndex == 0 || (time.Now().UnixNano()/1000000-conn.recoverInfo.checkEpRecoverTs) < int64(conn.dmConnector.switchInterval) { 103 return nil 104 } 105 // check db recover 106 var dscEps []*ep 107 if conn.dmConnector.cluster == CLUSTER_TYPE_DSC { 108 dscEps = rf.loadDscEpSites(conn) 109 } 110 if dscEps == nil || len(dscEps) == 0 { 111 return nil 112 } 113 var recover = false 114 for _, okEp := range dscEps { 115 if okEp.epStatus != EP_STATUS_OK { 116 continue 117 } 118 for i := int32(0); i < curIndex; i++ { 119 ep := conn.dmConnector.group.epList[i] 120 if okEp.host == ep.host && okEp.port == ep.port { 121 recover = true 122 break 123 } 124 } 125 if recover { 126 break 127 } 128 } 129 130 conn.recoverInfo.checkEpRecoverTs = time.Now().UnixNano() / 1000000 131 if !recover { 132 return nil 133 } 134 135 if conn.dmConnector.driverReconnect { 136 return conn.reconnect() 137 } else { 138 conn.Access.Close() 139 conn.closed.Set(false) 140 return ECGO_CONNECTION_CLOSED.throw() 141 } 142 143 //return driver.ErrBadConn 144 // do reconnect 145 //return conn.reconnect() 146 } 147 148 // DmDriver 149 func (rf *reconnectFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error) { 150 return filterChain.DmDriverOpen(d, dsn) 151 } 152 153 func (rf *reconnectFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error) { 154 return filterChain.DmDriverOpenConnector(d, dsn) 155 } 156 157 // DmConnector 158 func (rf *reconnectFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error) { 159 return filterChain.DmConnectorConnect(c, ctx) 160 } 161 162 func (rf *reconnectFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver { 163 return filterChain.DmConnectorDriver(c) 164 } 165 166 // DmConnection 167 func (rf *reconnectFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error) { 168 dc, err := filterChain.DmConnectionBegin(c) 169 if err != nil { 170 return nil, rf.autoReconnect(c, err) 171 } 172 return dc, err 173 } 174 175 func (rf *reconnectFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) { 176 dc, err := filterChain.DmConnectionBeginTx(c, ctx, opts) 177 if err != nil { 178 return nil, rf.autoReconnect(c, err) 179 } 180 return dc, err 181 } 182 183 func (rf *reconnectFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) error { 184 if err := filterChain.DmConnectionCommit(c); err != nil { 185 return rf.autoReconnect(c, err) 186 } 187 if err := rf.checkAndRecover(c); err != nil { 188 return rf.autoReconnect(c, err) 189 } 190 return nil 191 } 192 193 func (rf *reconnectFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) error { 194 err := filterChain.DmConnectionRollback(c) 195 if err != nil { 196 err = rf.autoReconnect(c, err) 197 } 198 199 return err 200 } 201 202 func (rf *reconnectFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) error { 203 err := filterChain.DmConnectionClose(c) 204 if err != nil { 205 err = rf.autoReconnect(c, err) 206 } 207 208 return err 209 } 210 211 func (rf *reconnectFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error { 212 err := filterChain.DmConnectionPing(c, ctx) 213 if err != nil { 214 err = rf.autoReconnect(c, err) 215 } 216 217 return err 218 } 219 220 func (rf *reconnectFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error) { 221 if err := rf.checkAndRecover(c); err != nil { 222 return nil, rf.autoReconnect(c, err) 223 } 224 dr, err := filterChain.DmConnectionExec(c, query, args) 225 if err != nil { 226 return nil, rf.autoReconnect(c, err) 227 } 228 229 return dr, err 230 } 231 232 func (rf *reconnectFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) { 233 if err := rf.checkAndRecover(c); err != nil { 234 return nil, rf.autoReconnect(c, err) 235 } 236 dr, err := filterChain.DmConnectionExecContext(c, ctx, query, args) 237 if err != nil { 238 return nil, rf.autoReconnect(c, err) 239 } 240 241 return dr, err 242 } 243 244 func (rf *reconnectFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error) { 245 if err := rf.checkAndRecover(c); err != nil { 246 return nil, rf.autoReconnect(c, err) 247 } 248 dr, err := filterChain.DmConnectionQuery(c, query, args) 249 if err != nil { 250 return nil, rf.autoReconnect(c, err) 251 } 252 253 return dr, err 254 } 255 256 func (rf *reconnectFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) { 257 if err := rf.checkAndRecover(c); err != nil { 258 return nil, rf.autoReconnect(c, err) 259 } 260 dr, err := filterChain.DmConnectionQueryContext(c, ctx, query, args) 261 if err != nil { 262 return nil, rf.autoReconnect(c, err) 263 } 264 265 return dr, err 266 } 267 268 func (rf *reconnectFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error) { 269 ds, err := filterChain.DmConnectionPrepare(c, query) 270 if err != nil { 271 return nil, rf.autoReconnect(c, err) 272 } 273 274 return ds, err 275 } 276 277 func (rf *reconnectFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error) { 278 ds, err := filterChain.DmConnectionPrepareContext(c, ctx, query) 279 if err != nil { 280 return nil, rf.autoReconnect(c, err) 281 } 282 283 return ds, err 284 } 285 286 func (rf *reconnectFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error { 287 err := filterChain.DmConnectionResetSession(c, ctx) 288 if err != nil { 289 err = rf.autoReconnect(c, err) 290 } 291 292 return err 293 } 294 295 func (rf *reconnectFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error { 296 err := filterChain.DmConnectionCheckNamedValue(c, nv) 297 if err != nil { 298 err = rf.autoReconnect(c, err) 299 } 300 301 return err 302 } 303 304 // DmStatement 305 func (rf *reconnectFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) error { 306 err := filterChain.DmStatementClose(s) 307 if err != nil { 308 err = rf.autoReconnect(s.dmConn, err) 309 } 310 311 return err 312 } 313 314 func (rf *reconnectFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) int { 315 var ret int 316 defer func() { 317 err := recover() 318 if err != nil { 319 rf.autoReconnect(s.dmConn, err.(error)) 320 ret = 0 321 } 322 }() 323 ret = filterChain.DmStatementNumInput(s) 324 return ret 325 } 326 327 func (rf *reconnectFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) { 328 if err := rf.checkAndRecover(s.dmConn); err != nil { 329 return nil, rf.autoReconnect(s.dmConn, err) 330 } 331 dr, err := filterChain.DmStatementExec(s, args) 332 if err != nil { 333 return nil, rf.autoReconnect(s.dmConn, err) 334 } 335 336 return dr, err 337 } 338 339 func (rf *reconnectFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) { 340 if err := rf.checkAndRecover(s.dmConn); err != nil { 341 return nil, rf.autoReconnect(s.dmConn, err) 342 } 343 dr, err := filterChain.DmStatementExecContext(s, ctx, args) 344 if err != nil { 345 return nil, rf.autoReconnect(s.dmConn, err) 346 } 347 348 return dr, err 349 } 350 351 func (rf *reconnectFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) { 352 if err := rf.checkAndRecover(s.dmConn); err != nil { 353 return nil, rf.autoReconnect(s.dmConn, err) 354 } 355 dr, err := filterChain.DmStatementQuery(s, args) 356 if err != nil { 357 return nil, rf.autoReconnect(s.dmConn, err) 358 } 359 360 return dr, err 361 } 362 363 func (rf *reconnectFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) { 364 if err := rf.checkAndRecover(s.dmConn); err != nil { 365 return nil, rf.autoReconnect(s.dmConn, err) 366 } 367 dr, err := filterChain.DmStatementQueryContext(s, ctx, args) 368 if err != nil { 369 return nil, rf.autoReconnect(s.dmConn, err) 370 } 371 372 return dr, err 373 } 374 375 func (rf *reconnectFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error { 376 err := filterChain.DmStatementCheckNamedValue(s, nv) 377 if err != nil { 378 err = rf.autoReconnect(s.dmConn, err) 379 } 380 381 return err 382 } 383 384 // DmResult 385 func (rf *reconnectFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) { 386 i, err := filterChain.DmResultLastInsertId(r) 387 if err != nil { 388 err = rf.autoReconnect(r.dmStmt.dmConn, err) 389 return 0, err 390 } 391 392 return i, err 393 } 394 395 func (rf *reconnectFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) { 396 i, err := filterChain.DmResultRowsAffected(r) 397 if err != nil { 398 err = rf.autoReconnect(r.dmStmt.dmConn, err) 399 return 0, err 400 } 401 402 return i, err 403 } 404 405 // DmRows 406 func (rf *reconnectFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) []string { 407 var ret []string 408 defer func() { 409 err := recover() 410 if err != nil { 411 rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error)) 412 ret = nil 413 } 414 }() 415 ret = filterChain.DmRowsColumns(r) 416 return ret 417 } 418 419 func (rf *reconnectFilter) DmRowsClose(filterChain *filterChain, r *DmRows) error { 420 err := filterChain.DmRowsClose(r) 421 if err != nil { 422 err = rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err) 423 } 424 425 return err 426 } 427 428 func (rf *reconnectFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error { 429 err := filterChain.DmRowsNext(r, dest) 430 if err != nil { 431 err = rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err) 432 } 433 434 return err 435 } 436 437 func (rf *reconnectFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool { 438 var ret bool 439 defer func() { 440 err := recover() 441 if err != nil { 442 rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error)) 443 ret = false 444 } 445 }() 446 ret = filterChain.DmRowsHasNextResultSet(r) 447 return ret 448 } 449 450 func (rf *reconnectFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error { 451 err := filterChain.DmRowsNextResultSet(r) 452 if err != nil { 453 err = rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err) 454 } 455 456 return err 457 } 458 459 func (rf *reconnectFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type { 460 var ret reflect.Type 461 defer func() { 462 err := recover() 463 if err != nil { 464 rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error)) 465 ret = scanTypeUnknown 466 } 467 }() 468 ret = filterChain.DmRowsColumnTypeScanType(r, index) 469 return ret 470 } 471 472 func (rf *reconnectFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string { 473 var ret string 474 defer func() { 475 err := recover() 476 if err != nil { 477 rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error)) 478 ret = "" 479 } 480 }() 481 ret = filterChain.DmRowsColumnTypeDatabaseTypeName(r, index) 482 return ret 483 } 484 485 func (rf *reconnectFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) { 486 defer func() { 487 err := recover() 488 if err != nil { 489 rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error)) 490 length, ok = 0, false 491 } 492 }() 493 return filterChain.DmRowsColumnTypeLength(r, index) 494 } 495 496 func (rf *reconnectFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) { 497 defer func() { 498 err := recover() 499 if err != nil { 500 rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error)) 501 nullable, ok = false, false 502 } 503 }() 504 return filterChain.DmRowsColumnTypeNullable(r, index) 505 } 506 507 func (rf *reconnectFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) { 508 defer func() { 509 err := recover() 510 if err != nil { 511 rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error)) 512 precision, scale, ok = 0, 0, false 513 } 514 }() 515 return filterChain.DmRowsColumnTypePrecisionScale(r, index) 516 }