MySQL Replication - Triggers do not replicate multiple databases - mysql

I have the following MySQL 5.5.16 setup, properly running:
Server A w/ db.a and db.b
Server B configured as slave for db.a (not db.b), by means of --replicate-wild-do-table
Tables on Srv.A-db.b have triggers on insert that insert/update db.a
db.a is properly replicated in Server.B, ie, if an update via an SQL client on db.a on server.A happens, is properly replicated to db.a on Server.B
Now comes the problem: triggers on Server.A/db.b that update/insert db.a are not replicated... have lost many hours exhausting all my knowledge on this...
On Srv.A/db.b I finally created a federated table pointing to Srv.A/db.a and the triggers working through the federated table are properly replicating but is VERY slow and some things cannot be used (ON DUPLICATE UPDATE for example)... so is really a stop-goat solution.
If I try to replicate both db.a and db.b the triggers work ok, but db.b is HUGE and not supposed to be replicated the server.B.
Any suggestions on how to make triggers work on db.b-->db.a when only db.a is replicated ??
Thanks for the suggestion.

See MySQL Trigger FAQ B.5.12: http://dev.mysql.com/doc/refman/5.0/en/faqs-triggers.html#qandaitem-B-5-1-12
'Triggers and replication in MySQL 5.0 work in the same way as in most other database systems: Actions carried out through triggers on a master are not replicated to a slave server.'
Maybe you can change all events that cause the trigger to run to instead call a stored procedure which will do the same work the trigger does now.

Related

MySQL: Strategy to move data to another server

So my situation is as follows:
There is a single Master-Slave Replication on a MySQL 5.5 basis.
The master use a small SSD as data partition.
Therefore I want to clean a certain Inno Table (lets call this table MasterA) and move old (datediff < -2) rows to another database on the slave (SlaveA) with more space on the SATA-HDD.
The problem gets interesting as in some cases I need to access data from SlaveA.
So I think it would be the best if an event triggers a transaction like this:
INSERT INTO SlaveA SELECT * FROM MasterA WHERE datediff(created, now()) < -2;
DELETE FROM MasterA WHERE datediff(created, now()) < -2;
But how could I access SlaveA from the master? I already tried the federated engine, but it gets stuck with the read_only option activated on the slave and the super privilege for the user accessing the federated table.
Maybe the event should only call the copy query on the slave, but how to delete the rows on the master afterwards?
There should be other options than installing MySQL 5.6 and use another partition for the SlaveA table on the master.
Thanks in advance!
An external daemon process (with handles to both databases) could accomplish what you are looking for but it is not a very clean solution.
If you did have a single handle with access to both databases a trigger would be a viable solution. I would change your code to use a MySQL user defined variable setting it in the first statement and use it in the second statement.
On the other hand I would question why you think you need the write master on a SSD. Insert queries are normally a lot cheaper than delete queries. If you make sure all the reads are against the slaves the master should have very minimal latency. I would recommend putting it on SATA HDD and not running delete quires against it. Then you don't have to create a custom trigger; MySQL's built in replication should work just fine.

MySQL replication without delete statments

I have been looking for a way to prevent MySQL delete statements from getting processed by the slave, I'm working on data warehousing project, and I would like to delete data from production server after having data replicated to slave.
what is the best way to get this done?
Thank you
There are several ways to do this.
Run SET SQL_LOG_BIN=0; for the relevant session on the master before executing your delete. That way it is not written to the binary log
Implement a BEFORE DELETE trigger on the slave to ignore the deletes.
I tend to use approach #1 for statements that I don't want to replicate. It requires SUPER privilege.
I have not tried #2, but it should be possible.
You'll only be able to achieve this with a hack, and it will likely cause problems. MySQL replication isn't designed for this.
Imagine you insert a record in your master, it replicates to the slave. You then delete from the master, but it doesn't delete from the slave. If someone adds a record with the same unique key, there will be a conflict on the slave.
Some alternatives:
If you are looking to make a backup, I would do this by another means. You could do a periodic backup with a cronjob that runs mysqldump, but this assumes you don't want to save EVERY record, only create periodic restore points.
Triggers to update a second, mirror database. This can't cross servers though, you'd have to recreate each table with a different name. Also, the computational cost would be high and restoring from this backup would be difficult.
Don't actually delete anything, simply create a Status field which is Active or Disabled, then hide Disabled from the users. This has issues as well, for example, ON DELETE CASCADE couldn't be used, it would have to be all manually done in code.
Perhaps if you provide the reason you want this mirror database without deletes, I could give you a more targeted solution.

Only replicate DDL in MySQL

I wonder if there is any easy way to keep the scheme consistent in two different MySQL clusters. Apart from classic replication, I would like to have a special "replication" which would reproduce all DDL queries (CREATE, ALTER, DROP, ...) on another cluster (namely the master of that cluster).
I don't need the actual data to be replicated.
Has anyone ever done or tried anything like this?
You can filter replication in MySQL based upon the database in which a query was executed. That doesn't prevent you making changes in other databases, however! So you can do;
USE ddl_repl_db;
ALTER TABLE other_db.foo ADD COLUMN <etc>
This relies on you configuring your servers correctly. I haven't set up MySQL replication for a while, but IIRC you can both filter what you send out from the master for replication and what you accept on the slave.
Old but still high in search.
So, on you DDL replica set all tables engine to BLACKHOLE

MySQL triggers + replication with multiple databases

I am running a couple of databases on MySQL 5.0.45 and am trying to get my legacy database to sync with a revised schema, so I can run both side by side. I am doing this by adding triggers to the new database but I am running into problems with replication. My set up is as follows.
Server "master"
Database "legacydb", replicates to server "slave".
Database "newdb", has triggers which update "legacydb" and no replication.
Server "slave"
Database "legacydb"
My updates to "newdb" run fine, and set off my triggers. They update "legacydb" on "master" server. However, the changes are not replicated down to the slaves. The MySQL docs say that for simplicity replication looks at the current database context (e.g. "SELECT DATABASE();" ) when deciding which queries to replicate rather than looking at the product of the query. My trigger is run from the context of database "newdb", so replication ignores the updates.
I have tried moving the update statement to a stored procedure in "legacydb". This works fine (i.e. data replicates to slave) when I connect to "master" and manually run "USE newdb; CALL legacydb.do_update('Foobar', 1, 2, 3, 4);". However, when this procedure is called from a trigger it does not replicate.
So far my thinking on how to fix this has been one of the following.
Force the trigger to set a new current database. This would be easiest, but I don't think this is possible. This is what I hoped to achieve with the stored procedure.
Replicate both databases, and have triggers in both master and slave. This would be possible, but a pain to set up.
Force the replication to pick up all changes to "legacydb", regardless of the current database context.
If replication runs at too high a level, it will never even see any updates run by my trigger, in which case no amount of hacking is going to achieve what I want.
Any help on how to achieve this would be greatly appreciated.
This may have something to do with it:
A stored function acquires table locks before executing, to avoid inconsistency in the binary log due to mismatch of the order in which statements execute and when they appear in the log. Statements that invoke a function are recorded rather than the statements executed within the function. Consequently, stored functions that update the same underlying tables do not execute in parallel.
In contrast, stored procedures do not acquire table-level locks. All statements executed within stored procedures are written to the binary log.
Additionally, there are a whole list of issues with Triggers:
http://dev.mysql.com/doc/refman/5.0/en/routine-restrictions.html

MySQL Trigger & Stored Procedure Replication

Ok,I'm running a setup with a single master and a number of slaves. All writes go through the master and are replicated down to the slaves which are used strictly for reads.
Now I have a stored procedure (not function) which is called by a trigger on an insert. According to the MySQL docs, for replication triggers log the call to the trigger while stored procedures actually log the result of the stored procedure.
So my question is, when my trigger gets fired, will it replicate both the trigger and the results of the procedure that the trigger calls (resulting in the procedure effectively being run twice)? Or will it simply replicate the trigger have the slaves re-run the stored procedure on their own?
Thanks
In MySQL 5.0 (and MySQL 5.1 with statement based binary logging), only the calling query is logged, so in your case, the INSERT would be logged.
On the slave, the INSERT will be executed and then the trigger will be re-run on the slave. So the trigger needs to exist on the slave, and assuming it does, then it will be executed in exactly the same way as the master.
In MySQL 5.1, there is row-based binary logging, which will log only the rows being changed, so the trigger would not be re-fired on the slave, but all rows that changed would still be propagated.
In addition to Harrison's excellent answer:
Assuming the databases are in sync (schema, data, same version) to start with, it should just work
If it doesn't, then it may be that you're using something non deterministic in your queries or trigger. Fix that.
Regardless of how you use replication, you need to have monitoring to check that the slaves are always in sync. Without any monitoring, they will become out of sync (subtly) and you won't notice. MySQL has no automatic built-in feature for checking this or fixing it.