본문 바로가기

DB/Mysql

mysql replication 문제 (update replication 실패)



며칠전에 mysql master장비에 update를 했는데 replica(slave) 장비에는 update되지 않는 현상을 발견했다. 
slave 장비의 Seconds_Behind_Master도 0이었다. 즉, update량이 많아서 늦어지는 것이 아니었다는 이야기다. 

나는 그 row들에 다시한번 update를 하다가 이상한 점을 발견했는데 실제로 update되지 않는 것을 목격한 것이다. 

즉, master에 

update MyDatabase.MyTable set myname="jigu" where id=12345;

라는 query를 쳤을 때 


mater 장비의 myname에는 "jigu"가 slave의 myname에는 "abc"라는 이전값이 그대로 있는 것이다. 

원인은 database name을 주는 방식에 있었다. 

http://gabrito.com/post/sql-statements-mysteriously-not-replicating-with-mysql-replication
저 페이지를 보면 아래 두게의 query의 의미는 같아도 replication시에는 A는 slave에 전달되고 B에는 전달되지 않는다고....

A) mysql -uxxx -pxxx -e 'update MyDatabase.MyTable set myname="jigu" where id=12345';
B) mysql -d MyDatabase -uxxx -pxxx -e 'update MyTable set myname="jigu" where id=12345';


그래서 mysql의 관련 페이지를 찾아 봤다. 
http://dev.mysql.com/doc/refman/5.0/en/replication-options-slave.html

여기서 보면 두개를 다르게 처리하는 것 (A는 replication되지 않는 것)은 default database name을 명시적으로 적어주지 않은 query에 대해서 어떤 database에 replication되어야하는지 정하기 쉽지 않기 때문이라는 것이다. 

즉, A의 예에서는 MyDatabase라는 것으로 default database name정해서 replica에게 전달해주면 된다고 생각되겠지만 여러개의 Database name을 사용하는 한개의 query에서는 사실상 default database name을 찾아내기가 불가능 하다는 것이 이유다. 

해당 부분을 copy해서 붙여 놓는다. 

--replicate-ignore-db=db_name

Command-Line Format --replicate-ignore-db=name
Option-File Format replicate-ignore-db
  Permitted Values
Type string

Tells the slave SQL thread not to replicate any statement where the default database (that is, the one selected by USE) is db_name. To specify more than one database to ignore, use this option multiple times, once for each database. You should not use this option if you are using cross-database updates and you do not want these updates to be replicated. See Section 15.2.3, “How Servers Evaluate Replication Filtering Rules”.

An example of what does not work as you might expect: If the slave is started with --replicate-ignore-db=salesand you issue the following statements on the master, the UPDATE statement is replicated:

USE prices;
UPDATE sales.january SET amount=amount+1000;
Note

In the preceding example the statement is replicated because --replicate-ignore-db only applies to the default database (set through the USE statement). Because the sales database was specified explicitly in the statement, the statement has not been filtered.

If you need cross-database updates to work, use --replicate-wild-ignore-table=db_name.% instead. SeeSection 15.2.3, “How Servers Evaluate Replication Filtering Rules”.

Beginning with MySQL 5.0.84, this option has no effect on BEGINCOMMIT, or ROLLBACK statements. (Bug #43263)



잘보면  
--replicate-wild-ignore-table=db_name.%와 같은 형식으로 지정하면 해결할 수 있기는 하다.