Beispiel #1
0
func (m *MysqlProxy) DeleteTable(table *schema.MysqlTable) {
	curTables := []*schema.MysqlTable{}
	curTableIds := []string{}

	for _, one := range m.Tables {
		if one.Name != table.Name {
			curTables = append(curTables, one)
		}
	}

	for _, one := range m.TableIds {
		if one != table.Id {
			curTableIds = append(curTableIds, one)
		}
	}

	// delete the relations.
	m.TableIds = curTableIds
	m.Tables = curTables

	err := redis.UpdateDB("main", redis.EncodeData(m), "MysqlProxy")

	if err != nil {
		fmt.Printf("Delete table error when write redis: %s\n", err)
		return
	}

	schema.Tables = curTables

	// delete selfs.
	table.Destroy()
}
Beispiel #2
0
// build a new shard DB after more the limit
// or no any one shard DB.
func buildNewShardDB(grp *host.Group) (*MysqlShardDB, error) {
	mut.Lock()
	defer mut.Unlock()

	shardDBName := "shard" + strconv.Itoa(ShardDBCnt+1)

	// to check this new shard db has been exists.
	isExists := IsExistsShardDB(shardDBName)
	if isExists != nil {
		return isExists, nil
	}

	newShardDBId := redis.BuildPrimaryKey(shardDBName, true)

	shardDB := &MysqlShardDB{
		Id:          newShardDBId,
		Name:        shardDBName,
		TableTotal:  uint64(0),
		SizeTotal:   uint64(0),
		HostGroupId: grp.Id,
		Created:     time.Now().Unix(),
		HostGroup:   grp,
	}

	// create the database to host.
	//
	master := host.GetBetterHost(grp.Master, "master")
	db, err := (&master).ConnToDB("mysql")
	if err != nil {
		return nil, err
	}

	stmt, err := db.Prepare(fmt.Sprintf("CREATE DATABASE `%s` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci", shardDBName))
	if err != nil {
		return nil, err
	}

	_, err = stmt.Exec()
	if err != nil {
		return nil, err
	}
	stmt.Close()
	db.Close()

	// to write the new shard db to redis
	//
	err = redis.WriteDB(newShardDBId, redis.EncodeData(shardDB), "MysqlShardDB")
	if err != nil {
		return nil, err
	}

	// notice Mysql Project object to add a new shard db memery.
	NewShardDBCh <- shardDB

	return shardDB, nil
}
Beispiel #3
0
// get the table status.
func (m *MysqlProxy) GetStatus() (map[string]interface{}, error) {
	result := map[string]interface{}{}

	result["main"] = redis.EncodeData(m)
	tables := []string{}
	shardDB := []string{}

	for _, table := range m.Tables {
		tables = append(tables, redis.EncodeData(table))
	}

	for _, db := range m.ShardDBs {
		shardDB = append(shardDB, redis.EncodeData(db))
	}

	result["tables"] = tables
	result["sharddbs"] = shardDB

	return result, nil
}
Beispiel #4
0
func (tbl *MysqlTable) GetGId() string {
	curId := tbl.CurGId
	tbl.CurGId++

	err := redis.UpdateDB(tbl.Id, redis.EncodeData(tbl), "MysqlTable")
	if err != nil {
		log.Printf("get gid error: %s", err)
	}

	return strconv.FormatUint(curId, 10)
}
Beispiel #5
0
// To init the necessary data.
func (m *MysqlProxy) Init() {
	m.InitMain()
	m.InitMysqlDB()
	m.InitMysqlTable()
	m.InitConnPooling()

	if isUpdated {
		// save mysql proxy.
		err := redis.UpdateDB("main", redis.EncodeData(m), "MysqlProxy")
		CheckError(err)
	}

	// panic(fmt.Sprintf("OK: %#v", m))
}
Beispiel #6
0
func (m *MysqlProxy) BuildNewShardDB(group *host.Group, name string) (*schema.MysqlShardDB, error) {
	if name == "" {
		return nil, errors.New("Sorry, can not build the no name databases")
	}

	// init the shard db to host.
	master := group.Master[0]
	db, err := (&master).ConnToDB("mysql")
	if err != nil {
		return nil, err
	}

	stmt, err := db.Prepare(fmt.Sprintf("CREATE DATABASE `%s` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci", name))
	if err != nil {
		return nil, err
	}

	_, err = stmt.Exec()
	if err != nil {
		return nil, err
	}
	stmt.Close()

	shardDbId := redis.BuildPrimaryKey(name, true)
	shardDb := &schema.MysqlShardDB{
		Id:          shardDbId,
		Name:        name,
		TableTotal:  0,
		SizeTotal:   0,
		HostGroupId: group.Id,
		Created:     redis.GetCurTime(),
		HostGroup:   group,
	}

	// save this new shard database to tracker.
	err = redis.WriteDB(shardDbId, redis.EncodeData(shardDb), "MysqlShardDB")
	if err != nil {
		return nil, err
	}

	(&master).CloseDB()

	schema.ShardDBCnt++

	return shardDb, nil
}
Beispiel #7
0
func (sdb *MysqlShardDB) InitShardTable(tName string) (*MysqlShardTable, error) {
	shardTabId := redis.BuildPrimaryKey(tName, true)
	newSTable := &MysqlShardTable{
		Id:        shardTabId,
		Name:      tName + "_shard1",
		RowTotal:  0,
		ShardDBId: sdb.Id,
		Created:   time.Now().Unix(),
		ShardDB:   sdb,
	}

	err := redis.WriteDB(shardTabId, redis.EncodeData(newSTable), "MysqlShardTable")
	if err != nil {
		return nil, err
	}

	return newSTable, nil
}
Beispiel #8
0
func (sdb *MysqlShardDB) InitTable(tName string, sql string) (*MysqlTable, error) {
	// 为了避免高并发时,整体tabletotal延迟执行导致的total数据不准确,
	// 所有在后面如果出现错误时, 需要将此添加回退.
	sdb.TableTotal += 1

	tableId := redis.BuildPrimaryKey(tName, true)
	newTable := &MysqlTable{
		Id:       tableId,
		Name:     tName,
		CurGId:   1,
		RowTotal: 0,
		Created:  time.Now().Unix(),
		// Columns: make([]TableColumn, 0, 16),
		Indexes: make([]*Index, 0, 8),
	}

	newShardTable, err := sdb.InitShardTable(tName)
	if err != nil {
		sdb.TableTotal -= 1
		return nil, err
	}

	newTable.ShardIds = []string{newShardTable.Id}
	newTable.Shards = []*MysqlShardTable{newShardTable}

	// add column data to memery.
	newTable.RestoreColumnsByDB()

	err = redis.WriteDB(tableId, redis.EncodeData(newTable), "MysqlTable")
	if err != nil {
		sdb.TableTotal -= 1
		return nil, err
	}

	sdb.UpdateToRedisDB()

	return newTable, nil
}
Beispiel #9
0
func (m *MysqlProxy) UpdateToRedisDB() error {
	return redis.UpdateDB("main", redis.EncodeData(m), "MysqlProxy")
}
Beispiel #10
0
// get the current db cluster data infomations
func (m *MysqlProxy) InitMysqlDB() {
	// panic(fmt.Sprintf("%#v, %#v", m.ShardDBIds, len(m.ShardDBIds)))
	if len(m.ShardDBIds) == 0 {
		// init the shard DB
		shardDBs := []*schema.MysqlShardDB{}
		shardDBIds := []string{}
		m.ShardDBCnt = 0

		for _, group := range host.Groups {
			m.ShardDBCnt++
			shardDb, err := m.BuildNewShardDB(&group, "shard"+strconv.Itoa(m.ShardDBCnt))

			CheckError(err)

			shardDBs = append(shardDBs, shardDb)
			shardDBIds = append(shardDBIds, shardDb.Id)
		}

		m.ShardDBs = shardDBs
		m.ShardDBIds = shardDBIds

		// to prepare save new data.
		isUpdated = true

		// add shard dbs map.
		schema.Sdbs = shardDBs

	} else {
		// 分析数据,并恢复至MysqlProxy结构体中.
		shardDBs := []*schema.MysqlShardDB{}
		for _, sid := range m.ShardDBIds {
			dbs, err := redis.ReadDB("MysqlShardDB", sid)
			CheckError(err)
			if len(dbs) != 1 {
				panic("no found relation shard db for id:" + sid)
			}

			sdb := dbs[0][sid].(map[string]interface{})
			groupId := sdb["HostGroupId"].(string)
			curGroup, err := host.GetHostGroupById(groupId)
			CheckError(err)

			shardDB := &schema.MysqlShardDB{
				Id:          sdb["Id"].(string),
				Name:        sdb["Name"].(string),
				TableTotal:  uint64(sdb["TableTotal"].(float64)),
				SizeTotal:   uint64(sdb["SizeTotal"].(float64)),
				HostGroupId: groupId,
				Created:     int64(sdb["Created"].(float64)),
				HostGroup:   curGroup,
			}

			shardDBs = append(shardDBs, shardDB)
		}

		m.ShardDBs = shardDBs

		// add shard dbs map.
		schema.Sdbs = shardDBs
	}

	// listen the sharddb change status.
	locker := &sync.Mutex{}

	go func() {
		for {
			newShardDB := <-schema.NewShardDBCh

			locker.Lock()
			defer locker.Unlock()
			m.ShardDBIds = append(m.ShardDBIds, newShardDB.Id)
			m.ShardDBs = append(m.ShardDBs, newShardDB)
			schema.Sdbs = m.ShardDBs

			err := redis.UpdateDB("main", redis.EncodeData(m), "MysqlProxy")
			if err != nil {
				log.Printf("new shard db listener error:%s", err)
			}

			m.ShardDBCnt++
			schema.ShardDBCnt = m.ShardDBCnt
			fmt.Printf("current shard total: %d\n", schema.ShardDBCnt)

		}
	}()

	// listen the table drop action.
	go func() {
		for {
			dropedTable := <-schema.DropedTableCh
			m.DeleteTable(dropedTable)
		}
	}()

	// panic(fmt.Sprintf("in init shard db: %#v, %#v", m))
}
Beispiel #11
0
func (stb *MysqlShardTable) UpdateToRedisDB() error {
	return redis.UpdateDB(stb.Id, redis.EncodeData(stb), "MysqlShardTable")
}
Beispiel #12
0
func (sdb *MysqlShardDB) UpdateToRedisDB() error {
	return redis.UpdateDB(sdb.Id, redis.EncodeData(sdb), "MysqlShardDB")
}
Beispiel #13
0
func (tbl *MysqlTable) UpdateToRedisDB() error {
	return redis.UpdateDB(tbl.Id, redis.EncodeData(tbl), "MysqlTable")
}
Beispiel #14
0
// restore the schema ddl.
func (tbl *MysqlTable) BuildNewShardTable() (*MysqlShardTable, error) {
	curSharded := len(tbl.Shards)
	tTableName := tbl.Name + "_shard" + strconv.Itoa(curSharded+1)

	newTabId := redis.BuildPrimaryKey(tTableName, true)

	shardTable := &MysqlShardTable{
		Id:        newTabId,
		Name:      tTableName,
		RowTotal:  uint64(0),
		ShardDBId: "",
		Created:   time.Now().Unix(),
		ShardDB:   nil,
	}

	// get bettet group.
	group := host.GetBetterMasterGroup()

	shardDB, err := tbl.GetMasterShardDBByGroup(group)
	if err != nil {
		return nil, err
	}

	shardTable.ShardDBId = shardDB.Id
	shardTable.ShardDB = shardDB

	betterHost := host.GetBetterHost(group.Master, "master")

	ddlSql, err := tbl.GetSchemaDDLByDb()
	if err != nil {
		return nil, err
	}

	ddlSql = strings.Replace(ddlSql, tbl.Shards[0].Name, tTableName, -1)
	db, err := betterHost.ConnToDB(shardDB.Name)
	if err != nil {
		return nil, err
	}

	stmt, err := db.Prepare(ddlSql)
	if err != nil {
		return nil, err
	}

	_, err = stmt.Exec()
	if err != nil {
		return nil, err
	}

	stmt.Close()

	// write the new shard table to redis
	err = redis.WriteDB(newTabId, redis.EncodeData(shardTable), "MysqlShardTable")
	if err != nil {
		return nil, err
	}

	tbl.Shards = append(tbl.Shards, shardTable)
	tbl.ShardIds = append(tbl.ShardIds, newTabId)

	err = redis.UpdateDB(tbl.Id, redis.EncodeData(tbl), "MysqlTable")
	if err != nil {
		return nil, err
	}

	return shardTable, nil
}