2021-11-29 来源:华纳网 责任编辑:韩玉玲 人气:
核心提示:大家好,欢迎来到谷雨课堂在以前的课程里我们讲过连接MySQL数据库,以及实现一个MySQL协议的数据库,今天谷雨老师和大家一起,实现一个完整的兼容MySQL5.7协议的数据库。

知识点:

超强大的TiDB

本课内容:

大家好,欢迎来到谷雨课堂

 

在以前的课程里我们讲过连接MySQL数据库,

以及实现一个MySQL协议的数据库,

 

今天谷雨老师和大家一起,

实现一个完整的兼容MySQL5.7协议的数据库,

 

今天的主角是TiDB!

TiDB是一个功能强大的开源数据库,

而且他是一个高并发、分布式的数据库,

 

更重要的是,

TiDB的大部分模块是用Go来开发的,

所以我们用Go可以很方便的集成TiDB的大部分功能,

 

以下代码就完整的实现了一台数据库服务器,

启动后可以使用PhpMyadmin或Navicat进行正常连接使用,

 

同时也可以在代码中进行任何的SQL操作,

以下是全部代码:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
package main
import ("context""database/sql""fmt""log""os""os/signal""syscall"
"github.com/pingcap/errors""github.com/pingcap/tidb/session""github.com/pingcap/tidb/sessionctx""github.com/pingcap/tidb/types""github.com/pingcap/tidb/util/chunk""github.com/pingcap/tidb/util/sqlexec")
var tidbServer1 *TiDBServervar ses session.Session
// GetRows4Test gets all the rows from a RecordSet, only used for test.func GetRows4Test(ctx context.Context, sctx sessionctx.Context, rs sqlexec.RecordSet) ([]chunk.Row, error) {if rs == nil {return nil, nil  }var rows []chunk.Row  req := rs.NewChunk()// Must reuse `req` for imitating server.(*clientConn).writeChunksfor {    err := rs.Next(ctx, req)if err != nil {return nil, err    }if req.NumRows() == 0 {break    }
    iter := chunk.NewIterator4Chunk(req.CopyConstruct())for row := iter.Begin(); row != iter.End(); row = iter.Next() {      rows = append(rows, row)    }  }return rows, nil}
func ResultSetToStringSlice(ctx context.Context, s session.Session, rs sqlexec.RecordSet) ([][]string, error) {  rows, err := GetRows4Test(ctx, s, rs)if err != nil {return nil, err  }  err = rs.Close()if err != nil {return nil, err  }  sRows := make([][]string, len(rows))for i := range rows {    row := rows[i]    iRow := make([]string, row.Len())for j := 0; j < row.Len(); j++ {if row.IsNull(j) {        iRow[j] = ""      } else {        d := row.GetDatum(j, &rs.Fields()[j].Column.FieldType)        iRow[j], err = d.ToString()if err != nil {return nil, err        }      }    }    sRows[i] = iRow  }return sRows, nil}
func Exec(sql string, args ...interface{}) (sqlexec.RecordSet, error) {var err errorif ses == nil {    ses, err = tidbServer1.GetSession()if err != nil {return nil, err    }  }
  ctx := context.Background()if len(args) == 0 {    sc := ses.GetSessionVars().StmtCtx    prevWarns := sc.GetWarnings()    rss, err := ses.Execute(ctx, sql)if err != nil {return nil, errors.Trace(err)    }    warns := sc.GetWarnings()    parserWarns := warns[len(prevWarns):]var rs0 sqlexec.RecordSetfor i, rs := range rss {if i == 0 {        rs0 = rs      }if err != nil {        ses.GetSessionVars().StmtCtx.AppendError(err)return nil, errors.Trace(err)      }    }if len(parserWarns) > 0 {      fmt.Println(parserWarns)    }return rs0, nil  }  stmtID, _, _, err := ses.PrepareStmt(sql)if err != nil {return nil, errors.Trace(err)  }  params := make([]types.Datum, len(args))for i := 0; i < len(params); i++ {    params[i] = types.NewDatum(args[i])  }  rs, err := ses.ExecutePreparedStmt(ctx, stmtID, params)if err != nil {return nil, errors.Trace(err)  }  err = ses.DropPreparedStmt(stmtID)if err != nil {return nil, errors.Trace(err)  }return rs, nil}
func main() {  str, _ := os.Getwd()  fmt.Println(str)
  tidbServer1, _ = NewTiDBServer("d:/ysdb2", 4002)defer tidbServer1.Close()
  fmt.Println(Exec("use guyu"))
  a, e := Exec("select * from tbl_guyu where k=? ", "111")
  fmt.Println(a, e)if e == nil {    cntFields := len(a.Fields())    fmt.Println("字段数:", cntFields)for idx, colInfo := range a.Fields() {      fmt.Println(idx,        colInfo.Column.FieldType.Tp,        colInfo.Column.Name.String())    }    r, e := ResultSetToStringSlice(context.TODO(), ses, a)if e == nil {      fmt.Println("结果:", r)    }  }
  dbConn, _ := tidbServer1.CreateConn()
  result, _ := dbConn.Query("SELECT now()")defer result.Close()
var version sql.NullStringfor result.Next() {    result.Scan(&version)break  }  fmt.Println("-->", version)
  signalCh := make(chan os.Signal, 1)  signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)  sigQuit := <-signalCh  log.Println(sigQuit)  log.Println("Server Quit")
  tidbServer1.Close()
}

 

扩展阅读:

TiDB 是 PingCAP 公司自主设计、研发的

开源分布式关系型数据库,

是一款同时支持在线事务处理与在线分析处理

(Hybrid Transactional and Analytical Processing, HTAP) 的

融合型分布式数据库产品,

具备水平扩容或者缩容、

金融级高可用、实时 HTAP、

云原生的分布式数据库、

兼容 MySQL 5.7 协议和 MySQL 生态等重要特性。

目标是为用户提供一站式 OLTP (Online Transactional Processing)、

OLAP (Online Analytical Processing)、

HTAP 解决方案。

TiDB 适合高可用、

强一致要求较高、

数据规模较大等各种应用场景。

 

 

完整的源代码可以登录【华纳网】下载。

https://www.worldwarner.com/




 





免责声明:本文仅代表作者个人观点,与华纳网无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。