Post on 13-Apr-2017
Устройство Mysql репликации Master -> Slave
• MASTER запиcывает изменения в “binary-log”
• SLAVE подключается к MASTER как клиент
• SLAVE скачивает “binary-log” в “replication-log”
• SLAVE последовательно выполняет изменения из “replication-log”
binlog_format
• STATEMENT
• ROW
• MIXEDPrior to MySQL 5.7.7, statement-based logging format was the default. In MySQL 5.7.7 and later, row-based logging format is the default.
Настройка Репликации
CHANGE MASTER TO MASTER_HOST='localhost', MASTER_USER='root', MASTER_PASSWORD='q12345'
MASTER my.cnfserver_id = 1
SLAVE my.cnfserver_id = 2
log_bin = /var/log/mysql/mysql-bin.log
Проблемы• Два лога транзакций на мастере • Остановка репликации
• проблема в логе • проблема в отличии структур или данных
Особенности
• Настройка баз/таблиц для записи в binary_log
• Настройка баз/таблиц для чтения из replication_log
• Ключи/формат/тип могут не совпадать
Пример настройки репликации CREATE TRIGGER `table_insert` AFTER INSERT ON table FOR EACH ROW BEGIN if (‘active’=NEW.status) THEN INSERT INTO table Set id = NEW.id, …. END IF; END;
CREATE TRIGGER `table_delete` AFTER DELETE ON table FOR EACH ROW BEGIN DELETE FROM table where id=OLD.id; END;
CREATE TRIGGER `table_update` AFTER UPDATE ON table FOR EACH ROW BEGIN if (‘active’=NEW.status) THEN UPDATE table SET status=NEW.status, … WHERE id = NEW.id; ELSE DELETE FROM table where id=NEW.id; END IF; END;
Поиск ошибки
В базе появилась ошибка Необходимо выяснить как была создана запись в таблице payments с id=92346
bin-log файлы находятся в /log
Source
class Promo < ActiveRecord::Base belongs_to :payment def self.redeem(code) transaction do promo = where(code: code, is_used: false).first if promo promo.payment = Payment.create(amount: promo.amount) promo.is_used = true promo.save! end end endend
class Promo < ActiveRecord::Base belongs_to :payment def self.redeem(code) transaction do promo = where(code: code, is_used: false).first if promo promo.payment = Payment.create(amount: promo.amount) promo.is_used = true promo.save! end end endend
INSERT INTO `payments` (`amount`, `created_at`, `updated_at`) VALUES (12, '2016-02-11 21:12:56', '2016-02-11 21:12:56’) UPDATE `promos` SET `payment_id` = 92346, `is_used` = 1, `updated_at` = '2016-02-11 21:12:56' WHERE `promos`.`id` = 16460 INSERT INTO `payments` (`amount`, `created_at`, `updated_at`) VALUES (12, '2016-02-11 21:12:56', '2016-02-11 21:12:56’) UPDATE `promos` SET `payment_id` = 92347, `is_used` = 1, `updated_at` = '2016-02-11 21:12:56' WHERE `promos`.`id` = 16460
Решение
• Optimistic Locking • field lock_version
• Pessimistic Locking promo = where(code: code, is_used: false).lock(true).first
promo.lock!if promo && !promo.is_used