Skip to content

Commit 67bd89b

Browse files
committed
give up pseudo GTID, only support GTID
1 parent b089cc3 commit 67bd89b

File tree

4 files changed

+161
-159
lines changed

4 files changed

+161
-159
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ mysql -h127.0.0.1 -P4000 -uroot -p
127127

128128
Failover supports to promote a new master and let other slaves replicate from it automatically when the old master was down.
129129

130+
Failover only support MySQL >= 5.6.9 with GTID mode, if you use lower version, e.g, MySQL 5.0 - 5.5, please use [MHA](http://code.google.com/p/mysql-master-ha/) or [orchestrator](https://github.com/outbrain/orchestrator).
131+
132+
Failover may try to support MariaDB with GTID mode later.
133+
134+
Why only GTID? Supporting failover with no GTID mode is very hard, because slave can not find the proper binlog filename and position with the new master.
135+
Although there are many companies use MySQL 5.0 - 5.5, I think upgrade MySQL to 5.6 or higher is easy.
130136

131137
## Feedback
132138

failover/doc.go

-6
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,4 @@
44
// Failover does not support monitoring whether a master is alive or not,
55
// and will think the master is down.
66
//
7-
// Failover will support file-position-based replication and GTID replication.
8-
// Using GTID is easy for refactoring the replication topologies when the master is down,
9-
// but file-position-based is not.
10-
// There are some ways to solve it, like MHA using comparing and syncing relay log at first, but
11-
// I think using a Pseudo GTID like [orchestrator](https://github.com/outbrain/orchestrator) may be
12-
// more easy, only with little limitation (must open log-slave-update in slave).
137
package failover

failover/failover.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func Failover(slaves []*Server) ([]*Server, error) {
2626
if gtidMode == GTIDModeOn {
2727
h = new(GTIDHandler)
2828
} else {
29-
h = new(PseudoGTIDHandler)
29+
return nil, fmt.Errorf("failover only supports GTID mode")
3030
}
3131

3232
// Stop all slave IO_THREAD and wait the relay log done

failover/pseudo_gtid_handler.go

+154-152
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,158 @@
11
package failover
22

3-
import (
4-
"fmt"
5-
. "github.com/siddontang/go-mysql/mysql"
6-
)
3+
// Only support GTID mode
74

8-
type PseudoGTIDHandler struct {
9-
Handler
10-
}
5+
// import (
6+
// "fmt"
7+
// . "github.com/siddontang/go-mysql/mysql"
8+
// )
119

12-
// Promote to master, you must not use this slave after Promote
13-
func (h *PseudoGTIDHandler) Promote(s *Server) error {
14-
if err := h.WaitRelayLogDone(s); err != nil {
15-
return err
16-
}
17-
18-
if err := s.StopSlave(); err != nil {
19-
return err
20-
}
21-
22-
// todo.....
23-
24-
return nil
25-
}
26-
27-
const changeMasterToWithPos = `CHANGE MASTER TO
28-
MASTER_HOST="%s", MASTER_PORT=%s,
29-
MASTER_USER="%s", MASTER_PASSWORD="%s",
30-
MASTER_LOG_FILE="%s", MASTER_LOG_POS=%d`
31-
32-
func (h *PseudoGTIDHandler) ChangeMasterTo(s *Server, m *Server) error {
33-
// Wait all relay logs done with last master
34-
if err := h.WaitRelayLogDone(s); err != nil {
35-
return err
36-
}
37-
38-
// Stop slave
39-
if err := s.StopSlave(); err != nil {
40-
return err
41-
}
42-
43-
// Reset slave
44-
if err := s.ResetSlave(); err != nil {
45-
return err
46-
}
47-
48-
// Change master to with position
49-
50-
// Start slave
51-
if err := s.StartSlave(); err != nil {
52-
return err
53-
}
54-
55-
return nil
56-
}
57-
58-
func (h *PseudoGTIDHandler) WaitRelayLogDone(s *Server) error {
59-
if err := s.StopSlaveIOThread(); err != nil {
60-
return err
61-
}
62-
63-
pos, err := h.fetchReadPos(s)
64-
if err != nil {
65-
return err
66-
}
67-
68-
if err = h.waitUntilPosition(s, pos); err != nil {
69-
return err
70-
}
71-
72-
return nil
73-
}
74-
75-
func (h *PseudoGTIDHandler) Compare(s1 *Server, s2 *Server) (int, error) {
76-
// todo, check same master
77-
78-
p1, err := h.fetchReadPos(s1)
79-
if err != nil {
80-
return 0, err
81-
}
82-
83-
p2, err := h.fetchReadPos(s2)
84-
if err != nil {
85-
return 0, err
86-
}
87-
88-
return p1.Compare(p2), nil
89-
}
90-
91-
func (h *PseudoGTIDHandler) FindBestSlaves(slaves []*Server) ([]*Server, error) {
92-
// todo, check same master
93-
94-
bestSlaves := []*Server{}
95-
96-
ps := make([]Position, len(slaves))
97-
98-
lastIndex := -1
99-
100-
for i, slave := range slaves {
101-
pos, err := h.fetchReadPos(slave)
102-
if err != nil {
103-
return nil, err
104-
}
105-
106-
ps[i] = pos
107-
108-
if lastIndex == -1 {
109-
lastIndex = i
110-
bestSlaves = []*Server{slave}
111-
} else {
112-
switch ps[lastIndex].Compare(pos) {
113-
case 1:
114-
//do nothing
115-
case -1:
116-
lastIndex = i
117-
bestSlaves = []*Server{slave}
118-
case 0:
119-
// these two slaves have same data,
120-
bestSlaves = append(bestSlaves, slave)
121-
}
122-
}
123-
}
124-
125-
return bestSlaves, nil
126-
}
127-
128-
func (h *PseudoGTIDHandler) WaitCatchMaster(s *Server, m *Server) error {
129-
r, err := m.MasterStatus()
130-
if err != nil {
131-
return err
132-
}
133-
134-
fname, _ := r.GetStringByName(0, "File")
135-
pos, _ := r.GetIntByName(0, "Position")
136-
137-
return h.waitUntilPosition(s, Position{fname, uint32(pos)})
138-
}
139-
140-
// Get current binlog filename and position read from master
141-
func (h *PseudoGTIDHandler) fetchReadPos(s *Server) (Position, error) {
142-
r, err := s.SlaveStatus()
143-
if err != nil {
144-
return Position{}, err
145-
}
146-
147-
fname, _ := r.GetStringByName(0, "Master_Log_File")
148-
pos, _ := r.GetIntByName(0, "Read_Master_Log_Pos")
149-
150-
return Position{fname, uint32(pos)}, nil
151-
}
152-
153-
func (h *PseudoGTIDHandler) waitUntilPosition(s *Server, pos Position) error {
154-
_, err := s.Execute(fmt.Sprintf("SELECT MASTER_POS_WAIT('%s', %s)", pos.Name, pos.Pos))
155-
return err
156-
}
10+
// type PseudoGTIDHandler struct {
11+
// Handler
12+
// }
13+
14+
// // Promote to master, you must not use this slave after Promote
15+
// func (h *PseudoGTIDHandler) Promote(s *Server) error {
16+
// if err := h.WaitRelayLogDone(s); err != nil {
17+
// return err
18+
// }
19+
20+
// if err := s.StopSlave(); err != nil {
21+
// return err
22+
// }
23+
24+
// // todo.....
25+
26+
// return nil
27+
// }
28+
29+
// const changeMasterToWithPos = `CHANGE MASTER TO
30+
// MASTER_HOST="%s", MASTER_PORT=%s,
31+
// MASTER_USER="%s", MASTER_PASSWORD="%s",
32+
// MASTER_LOG_FILE="%s", MASTER_LOG_POS=%d`
33+
34+
// func (h *PseudoGTIDHandler) ChangeMasterTo(s *Server, m *Server) error {
35+
// // Wait all relay logs done with last master
36+
// if err := h.WaitRelayLogDone(s); err != nil {
37+
// return err
38+
// }
39+
40+
// // Stop slave
41+
// if err := s.StopSlave(); err != nil {
42+
// return err
43+
// }
44+
45+
// // Reset slave
46+
// if err := s.ResetSlave(); err != nil {
47+
// return err
48+
// }
49+
50+
// // Change master to with position
51+
52+
// // Start slave
53+
// if err := s.StartSlave(); err != nil {
54+
// return err
55+
// }
56+
57+
// return nil
58+
// }
59+
60+
// func (h *PseudoGTIDHandler) WaitRelayLogDone(s *Server) error {
61+
// if err := s.StopSlaveIOThread(); err != nil {
62+
// return err
63+
// }
64+
65+
// pos, err := h.fetchReadPos(s)
66+
// if err != nil {
67+
// return err
68+
// }
69+
70+
// if err = h.waitUntilPosition(s, pos); err != nil {
71+
// return err
72+
// }
73+
74+
// return nil
75+
// }
76+
77+
// func (h *PseudoGTIDHandler) Compare(s1 *Server, s2 *Server) (int, error) {
78+
// // todo, check same master
79+
80+
// p1, err := h.fetchReadPos(s1)
81+
// if err != nil {
82+
// return 0, err
83+
// }
84+
85+
// p2, err := h.fetchReadPos(s2)
86+
// if err != nil {
87+
// return 0, err
88+
// }
89+
90+
// return p1.Compare(p2), nil
91+
// }
92+
93+
// func (h *PseudoGTIDHandler) FindBestSlaves(slaves []*Server) ([]*Server, error) {
94+
// // todo, check same master
95+
96+
// bestSlaves := []*Server{}
97+
98+
// ps := make([]Position, len(slaves))
99+
100+
// lastIndex := -1
101+
102+
// for i, slave := range slaves {
103+
// pos, err := h.fetchReadPos(slave)
104+
// if err != nil {
105+
// return nil, err
106+
// }
107+
108+
// ps[i] = pos
109+
110+
// if lastIndex == -1 {
111+
// lastIndex = i
112+
// bestSlaves = []*Server{slave}
113+
// } else {
114+
// switch ps[lastIndex].Compare(pos) {
115+
// case 1:
116+
// //do nothing
117+
// case -1:
118+
// lastIndex = i
119+
// bestSlaves = []*Server{slave}
120+
// case 0:
121+
// // these two slaves have same data,
122+
// bestSlaves = append(bestSlaves, slave)
123+
// }
124+
// }
125+
// }
126+
127+
// return bestSlaves, nil
128+
// }
129+
130+
// func (h *PseudoGTIDHandler) WaitCatchMaster(s *Server, m *Server) error {
131+
// r, err := m.MasterStatus()
132+
// if err != nil {
133+
// return err
134+
// }
135+
136+
// fname, _ := r.GetStringByName(0, "File")
137+
// pos, _ := r.GetIntByName(0, "Position")
138+
139+
// return h.waitUntilPosition(s, Position{fname, uint32(pos)})
140+
// }
141+
142+
// // Get current binlog filename and position read from master
143+
// func (h *PseudoGTIDHandler) fetchReadPos(s *Server) (Position, error) {
144+
// r, err := s.SlaveStatus()
145+
// if err != nil {
146+
// return Position{}, err
147+
// }
148+
149+
// fname, _ := r.GetStringByName(0, "Master_Log_File")
150+
// pos, _ := r.GetIntByName(0, "Read_Master_Log_Pos")
151+
152+
// return Position{fname, uint32(pos)}, nil
153+
// }
154+
155+
// func (h *PseudoGTIDHandler) waitUntilPosition(s *Server, pos Position) error {
156+
// _, err := s.Execute(fmt.Sprintf("SELECT MASTER_POS_WAIT('%s', %s)", pos.Name, pos.Pos))
157+
// return err
158+
// }

0 commit comments

Comments
 (0)