MySQL Master - Master (Select, Insert, Update, Delete for both) - mysql

I'm looking for a way to have 2 databases running; 1 at the office and 1 at a data center. When at the office, employees would connect locally but when outside the office they would connect remotely to the data center. Both databases would be fully synchronized. That means that an employee could log in and update a record on the data center and that change would replicate instantly to the office server (or vice-versa). So, either user could edit the same record.
So, the typical scenario of auto_increment_offset etc. won't work because, in this case, each server has to be able to update the same record.
Am I missing something obvious? I can't think of a viable way to handle this. 2 users on 1 db can modify the same records so there HAS to be a way to do the same in this type of setup. I just can't think of one.

You can not do this reliably with asynchronous replication. Consider this simple example:
site A: update foo set bar = 1
site B: update foo set bar = 2
Some time later (milliseconds or hours depending) the transactions are replicated to each site:
site A: update foo set bar = 2
site B: update foo set bar = 1
foo.bar will now be 2 on site A and 1 on site B. There is nothing in MySQL that will detect this or prevent it from happening.
Either partition the problem so the masters "own" different parts of the data or elect a primary master for all updates. Or implement some global locking mechanism.
With one database things are completely different since there is synchronous locking going on internally.

Here's how we did it:
In master-master configuration there are 2 masters and 2 slaves. Both are masters and slaves at the same time:
master1 => slave1[master2]
[slave1]master1 <= slave2
enable binlogging on master server - my.cnf file under [mysqld] section:
log-bin=mysql-bin.log
relay_log=relay-bin.log
server-id = 1
log-slave-updates
auto_increment_increment = 10
auto_increment_offset = 1
You may need to add:
skip-slave-start option too, to prevent from start slave at database startup.
Note:
Each server should use different server-id
auto_increment_offset should differs
Auto increment options:
auto_increment_increment controls the increment between successive AUTO_INCREMENT values.
auto_increment_offset determines the starting point for AUTO_INCREMENT column values.
With auto_increment_increment = 10 and auto_increment_offset=5, auto_inc values would be 5, 15, 25..
Dedicated user:
GRANT REPLICATION SLAVE ON . TO 'replication'#'%' IDENTIFIED BY 'some_password';
Create consistent, binary backup of MySQL database (needed to setup a replication) using LVM but the same steps will apply to ZFS/UFS snapshot and other popular techniques:
connect to MySQL database on master (server1) and run "FLUSH TABLES WITH READ LOCK". It might take few second to complete flush operation and it will lock all tables! It is imporant to keep it in mind, because such operation may impact in production load in some cases. It's better to schedule replication setup to peak-off hours.
Create LVM snapshot (server1): lvcreate -L10G -s -n mysqlbackup /dev/vg/lvm_mysql_partition
Get information about master position. Using previously created connection to database run : SHOW MASTER STATUS; to get all information about current binlog, position and so on.
Copy-paste output somewhere - for future usage.
Uunlock all tables: UNLOCK TABLES;
Mount previously created filesystem: mount /dev/vg/mysqlbackup (this will allow you to access shapshot of data created).
Now you can just copy this data to the second server directly to data dir. Before you start up your database add previously mentioned parameters to my.cnf file, changing value of server-id.
Now, with master information copied somewhere and database files propagated to slave you can remove snapshot: lvremove -f /dev/vg/mysqlbackup on master (server1).
Now, you can log into server2 to check for permissions (depends on which user was used to copy files you'll need to correct it) and after that, startup MySQL instance. Database should start, perform InnoDB recovery (if you're signed it) and after a bit, you will be able to log into using command line client. Because of skip-slave-start your slave will not start by default.
Now, on both servers you need to configure replication thread by setting up master hostname, master port, password, user and info about position:
CHANGE MASTER TO master_host='IP_addr_of_server1', master_port=3306, master_user='replication', master_password='some_password', master_log_file='info_from_MASTER_STATUS', master_log_pos='info_from_MASTER_STATUS';
Now you can start replication: START SLAVE;
Check to make sure: SHOW SLAVE STATUS\G (on new machine)
Seconds_Behind_Master might not be equal to 0 because of changes done to database after you release all tables but with replication working slave should catch master pretty fast.
After your slave server catches up with master, start master-master (server1-server2) setup. Lock all tables on server2 ( FLUSH TABLES WITH READ LOCK;) and run SHOW MASTER STATUS;. On server1 set-up replication by CHANGE MASTER TO..
of course you need to change master_host to valid IP address, master_log_file and master_log_pos values. After that, UNLOCK TABLES on server2 and START SLAVE on server1.
Now you should have master-master-slave configuration with master-master replication between server1 and server2.

Related

Mysql Master Master Replication errors master/slave

i tried master-master replication; as a part of it first I tried master- slave replication. The replication connection is successful but when I made changes on master, the slave is throwing a lot of duplicate errors.
Last_SQL_Error: Error 'Duplicate entry '1576' for key 'PRIMARY'' on query. Default database: 'nagiosxi'. Query: 'INSERT INTO xi_auditlog (log_time,source,user,type,message,ip_address,details) VALUES ('2018-05-15 16:34:19','Nagios XI','NULL',32,'cmdsubsys: User [nagiosadmin] applied a new configuration to Nagios Core','localhost','')' Replicate_Ignore_Server_Ids:
As per my understandings the master cannot overwrite the values in the slave.
the databases which am replicating are application databases, both master and slave databases throwing a lot of errors, as the values cannot be overridden.
Can someone please help me in master master replication.
Do I need to script for this purpose?
To make master-master or Galera safe to use AUTO_INCREMENT one should use the system variables auto_increment_increment and auto_increment_offset to generate unique values for each server.
https://mariadb.com/kb/en/library/auto_increment/
Set auto_increment_increment to 2 on both masters. Set auto_increment_offset to 2 on one server and to 1 (default) on the other.
This causes one server to only create even-numbered values, and the other to create only odd-numbered values. They will still tend to be sequential, because if one server creates 1, 3, 5, 7, and 9, and the next insert occurs on the other server after all of these have replicated, the next id will be 10. The gaps are inevitable, but as any experienced DBA will tell you, do not obsess about the gaps.
You should set your binlog_format to ROW or MIXED -- not STATEMENT -- on both servers. If you are backing up your binlogs as you should be, then log_slave_updates should also be enabled. If you have subtended replicas, the master to which they are connected must have this option enabled.
Also, you're going to need to destroy and rebuild one of the servers at this point, because their data will never be consistent.
The recommended practice for master/master is to only write to one server at a time. Your application can switch at will, but it is most stable if only one is treated as writable.

MySQL 2 masters N-slaves replication

I'm trying to set up a two masters, N-slaves replication in MySQL
I have setup two masters that works perfectly fine with each other.
It breaks when I add a slave for master#1.
Creating
master#1 : Create database test.
master#2 : test database gets created from master#1's query.
creates a test database in slave#1
Deleting
master#2 : Delete database test.
master#1 : test database gets deleted from master#2's query.
test doesn't get removed in slave#1
What I did was to create a user in **master#
create user 'root'#'slave.one.ip' identified by 'slaveonepass';
Give it replication privileges:
grant replication slave on dbname.* to 'root'#'slave.one.ip';
Get the info of master#1:
show master status;
Add the info from above to slave#1
mysql> change master to\
master_host='first.master.ip',\
master_user='root',\
master_password='slaveonepass',\
master_log_file='mysql-bin.123456',\
master_log_pos=123456;`
Reference:
How To Set Up MySQL Master-Master Replication
This would be the expected behavior if you have not set LOG_SLAVE_UPDATES=ON on both masters. Set this in the configuration files, and restart the masters.
Normally, a slave does not write to its own binary log any updates that are received from a master server. This option causes the slave to write the updates performed by its SQL thread to its own binary log
https://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#sysvar_log_slave_updates
This option is mandatory for all cascading replication configurations, where an instance needs to propagate incoming replication events out to additional replicas.
You should also enable this in any slave that will have downstream slaves connected.

mariaDB(mysql) replication after slave is up after down

I have remote host (centos6) with mariadb (10.0.17-MariaDB-log - MariaDB Server) as master:
server-id = 1
log-bin=mysql-bin
binlog_do_db = mydatabase
and local (win8.1) with mariadb (10.0.16-MariaDB-log - mariadb.org binary distribution) as a slave:
server-id = 2
As initial procedure I've dumped database on remote host, imported it on local host, then executed SHOW MASTER STATUS, get filename and offset and run:
CHANGE MASTER TO MASTER_HOST='$host', MASTER_USER='$user', MASTER_PORT = $port, MASTER_PASSWORD='$pass', MASTER_LOG_FILE='$fname', MASTER_LOG_POS=$pos
STOP SLAVE
START SLAVE
Replication starts. Everything I do with table on master is reflected to slave.
But if slave goes down, after it is up no changes (made on master) while slave was offline reflected to slave! So it looks like my slave should always be online, but it's a laptop!
However after slave is up realtime replication still works - it doesn't remember all changes from offline, but if I change database on master when slave is online and started all changes are perfectly reflected to slave. Of course I know that replication is statement based, so I get not data diff but instructions. But I thought master remembers what it sent and what did not. So on next operation it just sends all non-delivered changes. Am I wrong?
My replication scenario: master server interacts with clients (mobile devices) and they change the database. From time to time I launch my laptop, start replication, get updated database and do some heavy analysis (it's too hard for my 2-core cheap server).
Maybe there is a better method? Is there a way to get "offline changes" like in ICQ messenger? :)
For now I can see only one solution - full db dump, but it is inconvenient, takes too much time and loads master heavily.
While the Slave is not connected to the Master, the Master is writing to its binlog(s). The Slave has remembered where it left off in reading from those binlogs. When the Slave reconnects, it picks up "where it left off", copies the changes from the Master's binlog(s) to the Slaves relay-log(s) and performs them. This "catchup" process will take a little time, how long depends on a lot of factors.
Do SHOW SLAVE STATUS; on the Slave to verify that it is connected and running ("Yes").
Normally, the version of the Slave should be no older than that of the Master. (I doubt if there is any issue between 10.0.17 vs 16. Nothing in the changelog for 10.0.17 jumps out at me.)
Are you using "parallel replication"? See bug fixed in 10.0.18.

MySQL Master-Slave Replication When Master is Down

I'm running MySQL as the database on Ubuntu instances. I'm using MySQL Master-Slave replication where master's changes will be written to slave and slave's changes will not be reflected on the master. That's fine. I'm using a HAProxy load balancer to front the MySQL instances where all the requests will be sent to master MySQL instance. If the master MySQL instance is down slave MySQL instance will act as master and HAProxy will send all the requests to salve. Active-Passive scenario.
HAProxy - 192.168.A.ABC
MySQL Master - 192.168.A.ABD
MySQL Slave - 192.168.A.ABE
Let's assume that the MySQL master(192.168.A.ABD) is down. Now all the requests will be sent to MySQL slave(192.168.A.ABE) by HAProxy where now he acts as the master MySQL server for the time being.
My problems are
What happens when original master MySQL instance(192.168.A.ABD) is up?
Will changes written to new MySQL master (192.168.A.ABE) be replicated to original master(192.168.A.ABD) again?
How should I address this scenario?
First of all I should say that I have never used HA Proxy so con't comment on that directly.
However, in your current setup the Master (ABD) will be out of sync, and wont catch up. You will have to rebuild that using mysqlDump or similar tool.
What you would need is a Master < > Master setup (as opposed to Master > Slave), which enables you to write to either database and have it reflected in the other. This isn't quite as straight forward as it sounds though.
Assuming you already have your master > slave setup, and they are in sync
On the Master (ABD) you want to add:
auto_increment_increment=2
auto_increment_offset=1
log-slave-updates
On the Slave (ABE) add:
auto_increment_increment=2
auto_increment_offset=2
log-slave-updates
to your my.cnf files. Restart the Database. This will help to prevent Duplicate Key Errors. (n.b. that log-slave-updates isn't strictly required but makes it easier to add another slave in future)
Next you want to tell the Master (ABD) to replicate from the Slave (ABE).
Depending on what version of MySQL and if you are using GTID etc. the exact process differs slightly. But basically you are going to issue a CHANGE MASTER statement on the Master so it replicates from the slave.
And away you go. You probably want to avoid writing to both at the same time as that opens up a whole other kettle of fish. But if the Master goes down, you can switch your writes to the slave, and when the master comes back up, it will simply start replicating the missing data.
I am considering you scenario
Master - 192.168.A.ABD
Slave - 192.168.A.ABE
You cannot directly add the master in system. To Add master in system you need to perform below steps:
1) When master is up you can add this as a slave. So now this happens
Master - 192.168.A.ABE
Slave - 192.168.A.ABD
2) Then Now U can put master Down. Means You can put 192.168.A.ABD Down
3) Then Again Add this as slave. So After this You will get below scenarion
Master - 192.168.A.ABD
Slave - 192.168.A.ABE
You can refer this link
https://dev.mysql.com/doc/refman/5.5/en/replication-solutions-switch.html

Altering MySQL InnoDB table with minimal downtime

I've got a huge InnoDB table(>500 millions rows) which I'd like to partition by hash in order to decrease the index size. I'd like to achieve this with a minimal downtime(e.g 10 minutes is acceptable), what are the possible options?
I was thinking about something as follows:
create the new partitioned table
insert into this new table all the data from the old one using "insert ... select ..."
make server unavailable for clients
somehow sync changes which happened to the old table during step 2 with the new table
replace the old table with the new one
make server available for clients
The main question is what tool can be used in the step 4. The problem is that during step 2 there can be lots of changes to the original table: new inserts, updates, deletes - the sync tool should take all of this into account...
Another possible way, I believe, is:
setup a replicating slave server
sync this slave server with master
switch master/slave roles and re-configure all clients to connect to the new master
alter table on the previous master
wait for master/slave synchronization
switch master/slave roles again, re-configure all clients
Which one would you recommend?
I would go with master/slave replication. If the master and slave can be on the same subnet, I would also add a new IP to the master, change the clients to point to the new IP. Then when you are about to switch to the slave, just:
stop mysql on the master
ifconfig down the extra IP on the master
ifconfig up the extra IP on the new master
Clients will just connect to the new master without any client reconfig. Then you do the same thing when you switch back to the original master (if you switch back).
I recommend that a slave always be equivalent hardware to its master so that when it takes over for the master you don't find out it's so much slower that it can't keep up and your whole system fails. If you do that, then you need only switch once (from the current master to the new master).