sen*_*ett 25 mysql transaction ddl rollback
我有点惊讶地发现,DDL语句(alter table
,create index
等)隐含在MySQL提交当前事务。来自 MS SQL Server,在本地事务(然后回滚)中进行数据库更改的能力是我工作流程的重要组成部分。对于持续集成,如果迁移因任何原因而中断,则使用回滚,这样至少我们不会让数据库处于半迁移状态。
人们在使用 MySQL 进行迁移和持续集成时如何解决这两个问题?
Rol*_*DBA 11
对于许多人来说,MySQL 的致命弱点是隐式提交。
根据本书第 418 页第 3 段
以下命令可以并且将破坏交易
ALTER TABLE
BEGIN
CREATE INDEX
DROP DATABASE
DROP INDEX
DROP TABLE
RENAME TABLE
TRUNCATE TABLE
LOCK TABLES
UNLOCK TABLES
SET AUTOCOMMIT = 1
START TRANSACTION
对于 MySQL,您构建的任何 ContinuousIntegration (CI)/SelfService 作业都应始终使事务性作业和 DDL 脚本互斥。
这使您有机会创建范式
START TRANSACTION/COMMIT
块正确隔离的事务警告:如果您为此使用 MyISAM,您可以(不)友好地将 MyISAM 添加到可能破坏事务的事物列表中,可能不是隐式提交,但绝对是在数据一致性方面应该回滚需要。
LVM 快照很棒,无需执行繁重的 SQL 处理即可恢复数据库的整个实例是理想的选择。但是,当谈到 MySQL 时,您必须考虑两个存储引擎:InnoDB 和 MyISAM。
查看 InnoDB 的架构(图片由 Percona CTO Vadim Tkachenko 提供)
InnoDB 有许多活动部件
获取所有 InnoDB 数据库的 LVM 快照,其中未提交的更改漂浮在缓冲池和内存缓存中,将产生一个数据集,一旦 LUN 恢复和 mysqld 启动,该数据集将需要 InnoDB 崩溃恢复。
SET GLOBAL innodb_fast_shutdown = 0;
SET GLOBAL innodb_max_dirty_pages_pct = 0;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
service mysql stop
service mysql stop
SET GLOBAL innodb_max_dirty_pages_pct = 0;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
SET GLOBAL innodb_max_dirty_pages_pct = 75;
MyISAM 在访问时会维护一个针对它的打开文件句柄的计数。如果 MySQL 崩溃,任何打开文件句柄计数 > 0 的 MyISAM 表都将被标记为崩溃并需要修复(即使数据没有任何问题)。
当快照恢复并启动 mysqld 时,对具有正在使用的 MyISAM 表的数据库进行 LVM 快照将有一个或多个 MyISAM 表需要修复。
SET GLOBAL innodb_fast_shutdown = 0;
SET GLOBAL innodb_max_dirty_pages_pct = 0;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
service mysql stop
service mysql stop
您可以强制刷新某些 InnoDB 表
SET GLOBAL innodb_max_dirty_pages_pct = 0;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
FLUSH TABLES innodb_tbl1,... FOR EXPORT;
在关键 InnoDB 表上运行FLUSH TABLES WITH READ LOCK;
UNLOCK TABLES;
SET GLOBAL innodb_max_dirty_pages_pct = 75;
虽然您可以将一个 LVM 快照还原到两台服务器并设置 MySQL 主/从复制,但在还原快照时,这会成为清理工作的额外来源。
如果您在 Master 上运行 CI 作业并且这些作业很小,则在某些情况下复制可能会节省时间。您可以STOP SLAVE;
在 Slave 上运行START SLAVE;
,在Master 上启动 CI 作业,并在 Master 的数据得到认证后在 Slave 上运行。
如果 CI 作业提醒过多数据,您可以从头开始恢复 LVM 快照并设置复制。如果您发现自己经常这样做,您可能可以通过设置 MySQL 复制来完成。
如果您谈论持续集成,那么我认为它是一个开发环境。在这种情况下,我想说,进行结构更改的人必须对其进行测试,以确保不会破坏其他人的东西,就像更新公共库的人一样:在提交此类更改之前在自己的沙箱中进行测试。
在生产部署过程中,您通常会通过开发、质量检查甚至预生产环境来测试您的更改,就像任何代码更改一样。
请注意,这不是 MySQL 特有的:Oracle 数据库在发出“alter table”等时也会隐式执行 COMMIT。
现在,如果您想保护自己,您当然可以提前进行备份,或者创建 LVM 或文件系统快照(如果您的系统可以做到这一点)。您可能还有一个从站,您可以在敏感操作之前延迟/停止它作为安全措施。
归档时间: |
|
查看次数: |
2889 次 |
最近记录: |