【问题标题】:Deadlock on MTS replicationMTS 复制死锁
【发布时间】:2017-03-07 10:40:52
【问题描述】:

情况:

我们在 Percona MySQL 5.6.32-78.1 上使用 GTID 进行主-主-复制。在服务器上,大约有 10 个数据库,我们设置了slave_parallel_workers=5。一台服务器用于前端处理,一台用于后端。每周两到三次,后端服务器上的复制因错误而死

2016-10-25 10:00:01 165238 [Warning] Slave SQL: Worker 4 failed executing transaction '0e7b97a8-a689-11e5-8b79-901b0e8b0f53:22506262' at master log mysql-bin.011888, end_log_pos 9306420; Could not execute Update_rows event on table shop.sessions; Deadlock found when trying to get lock; try restarting transaction, Error_code: 1213; handler error HA_ERR_LOCK_DEADLOCK; the event's master log mysql-bin.011888, end_log_pos 9306420, Error_code: 1213 2016-10-25 10:00:01 165238 [ERROR] Slave SQL: ... The slave coordinator and worker threads are stopped, possibly leaving data in inconsistent state. A restart should restore consistency automatically, although using non-transactional storage for data or info tables or DDL queries could lead to problems. In such cases you have to examine your data (see documentation for details). Error_code: 1756 2016-10-25 10:00:01 165238 [Note] Error reading relay log event: slave SQL thread was killed

可能是什么原因?没有跨数据库的 DML 语句,我认为通过使用 MTS,每个数据库只使用一个线程(MTS 的好处是跨多个数据库使用并行复制)?为什么回复会因死锁而中断?

编辑 2016-10-28:

表的架构看起来像

CREATE TABLE `sessions` (
  `id` int(11) NOT NULL,
  `session_id` char(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `crypt_iv` blob NOT NULL,
  `data` mediumblob NOT NULL,
  `user_id` int(11) NOT NULL,
  `last_refresh` datetime NOT NULL,
  `timeout` datetime NOT NULL,
  `closed` tinyint(4) NOT NULL,
  `inserted` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `sessions`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `session_id` (`session_id`),
  ADD KEY `user_id` (`user_id`),
  ADD KEY `timeout` (`timeout`);
ALTER TABLE `sessions` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

这个错误只发生在后端,从来没有发生在前端服务器上。目前我无法粘贴确切的语句,因为二进制日志已被清除。但是这个 GTID 事务中唯一的语句是对表的基于行的 UPDATE。

【问题讨论】:

  • 您使用的是“基于行的复制”吗?事件做什么?让我们看看有问题的表的SHOW CREATE TABLE。
  • 两台机器上都声明了事件吗?他们应该是吗? (触发器通常不应该。)

标签: mysql database-replication percona multi-master-replication gtid


【解决方案1】:

我猜所有的会话都是在前端服务器上创建的。后端服务器上是否有会话清理工作?所以你在两台机器上都有写。如果您有一个写入繁重的表作为会话,您应该只在一台机器上编写它以避免这种死锁。

实际上,您应该始终只在一台机器上执行所有写入,除了故障转移情况,当一个主服务器出现故障时。

有一些不错的设置,带有 haproxy 和运行状况检查,可以自动处理故障转移,并且对您的客户透明。

【讨论】:

  • 确实,有一个会话清理工作,但它已经在前端服务器上运行。发生死锁时(大部分时间是午夜),我们的员工在家,没有人在后台管理后台工作,因此会话表上的唯一写入来自前端服务器。
  • 是否有另一项工作在后端主机上进行写入?如果是在午夜,它可能是一个 cronjob。也许是一些与备份相关的任务。我看到死锁只有同时在多个主机上写入同一个数据库。这就是为什么 percona 还建议在一个时间点在一台机器上进行所有写入。
  • 大多数死锁发生在运行每日备份时的 mignight。但是我们使用 Perconas innobackupex 应该可以防止此类故障。但是中午也有一些死锁,这不能用运行备份来解释。
  • 哦,对不起,因为我无法相信 Percona 备份会触发这些问题,所以我再次搜索了其他任务。确实,有一个日常清理任务会丢弃旧会话。由于它会清理 7 天未使用的会话,因此很难理解为什么清理这些旧会话会导致死锁。要进入这种情况,必须在完全相同的时间(秒)重新使用 7 天前的会话,它将被丢弃!?这将是一个非常大的巧合,因为它每周发生 1-2 次,不是吗?
  • 那么你在写两个master吗?这是可能的原因之一。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
  • 1970-01-01
  • 2021-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多