我有一个数据库,它是一个奴隶和一个主人。例如,它从我们的主站点复制数据,然后复制到一组从数据库。(这主要是一个测试设施,因此在工作时间之外不受监控)。
周日早上 7:55,它开始执行INSERT
查询。这是一个标准查询,每天执行数千次。它是一个查询,而不是事务的一部分。该表上没有触发器。此表(和所有其他表)是INNODB
.
但是,这一次它卡住了。当我今天进入办公室时,它已经运行了 24 小时(显然)。复制落后了一天。
但是,当我查看二进制日志时,它显示为COMMIT
ed。
#160814 7:55:25 server id 21 end_log_pos 103319397 Query thread_id=635785334 exec_time=4294967294 error_code=0
SET TIMESTAMP=1471157725/*!*/;
INSERT INTO tablename . . .
/*!*/;
# at 103319397
#160814 7:55:25 server id 21 end_log_pos 103319424 Xid = 284047583
COMMIT/*!*/;
# at 103319424
我检查了从属数据库,正如你所期望的那样,它就在那里。
我有一个监控系统,它记录(除其他外)进程列表,它表明对于该INSERT
查询,它永远停留在STATE = UPDATE
.
我还检查了slow query log
它是否在那里,它不是。
binary log
我的理解是,只有在主服务器上才能将查询写入commmited
,所以任何人都可以解释这里发生了什么吗?
有一个连锁反应,今天早上8点38分,有一次测试系统尝试连接,第一个SELECT
查询也卡住了,然后它拒绝了所有连接。所以我被迫重新启动数据库。此时它运行崩溃恢复,并继续进行,就好像什么都没发生一样。
它是 MySQL 5.5.47 并使用基于语句的复制。
好吧,它没有解释为什么数据库被锁定,但它确实回答了我的部分问题:
https://www.packtpub.com/books/content/setting-mysql-replication-high-availability
虽然,我现在刚刚阅读了以下内容:
SQL 语句不是
来自“了解 MySQL 内部”一书。
如果您从不同来源获得相互冲突的信息,请使用官方文档:
http://dev.mysql.com/doc/refman/5.5/en/binary-log.html
这意味着存在一个狭窄的窗口,其中失败可能导致未提交的事务存在于二进制日志中,但不存在于数据库中。这似乎就是你的情况。
在旁注中,重要的是要了解 innodb_support_xa 是两阶段提交模型 - 首先准备语句,然后在阶段 1 -> 在阶段 2 中将事务缓存应用于二进制日志,一旦提交 trx -> 存储引擎写入安全存储/磁盘中准备好的语句(取决于sync_binlog)。在阶段 2 之后,相关表上的锁被释放。
注意:即使在阶段 1 之后服务器崩溃,事务提交也不会失败,因为在恢复期间 - MySQL 服务器告诉 InnoDB 完成任何已成功写入二进制日志的准备好的事务,并将二进制日志截断到最后一个有效位置。这确保了二进制日志反映了 InnoDB 表的确切数据,因此从站与主站保持同步,因为它没有收到已回滚的语句。