知识卡片
基于语句和基于行复制:核心权衡是灵活性对确定性
内容
MySQL复制把主库上发生的变更传给备库重放,具体”传什么、怎么重放”有 两种模式,权衡完全不同。基于语句的复制传的是实际执行过的SQL语句, 备库照着这条语句原样再执行一遍——这样做的好处是日志内容就是可读的 SQL,出问题时容易定位;而且因为重放的是”做什么”而不是”具体改了哪些 行”,主备表结构/存储引擎允许有一定差异(比如列顺序不同、数据类型兼容 但不完全相同),这给”先在备库改schema、再把备库提升为主库”这类降低 停机时间的操作留了空间。但它的致命弱点是”确定性”:只要某条语句在主库 和备库上可能跑出不同结果(不确定函数、依赖执行顺序的操作、某些触发器/ 存储过程场景),主备就会悄悄产生数据分歧,而且历史上这类语句复制的 边界情况长期存在大量bug。基于行的复制换了个角度:不管语句长什么样, 只记录这行数据从什么变成了什么,备库直接按记录的”变化”应用,天然对 几乎所有SQL结构、触发器、存储过程都能正确复制,因为它根本不关心”怎么 算出来的”,只关心”结果是什么”;副作用是丢失了语句本身的可读性和上下文 ——如果一个操作用低效的方式定位并更新了行,从行日志里完全看不出来, 排查这类隐藏的低效执行路径会更难;而且无法再支持”备库表结构不同”这类 灵活操作。这本质上是”记录意图(怎么做)”和”记录结果(做成了什么)”两种 日志策略的权衡:前者更紧凑、更灵活、但正确性依赖”意图能被无歧义重放” 这个未必总成立的假设;后者天然正确、但牺牲了紧凑性和对执行路径的 可观察性。
参考来源
- 位置:《高性能MySQL:第3版》第10章"复制"10.3.3节"基于行或基于语句:
哪种更优"(源文件:_epub-src/OEBPS/Text/part0017.xhtml)
- 结论依据:原文明确"很多情况下通过基于语句的模式无法正确复制……
如果正在使用触发器或者存储过程,就不要使用基于语句的复制模式……
几乎没有基于行的复制模式无法处理的场景……由于语句并没有在日志里
记录,因此无法判断执行了哪些SQL……执行基于行的变化的过程就像一个
黑盒子",逐条对比两种模式在正确性、可读性、兼容性上的优劣。
- 原始内容:基于语句的复制方式一般允许更灵活的操作……几乎没有基于
行的复制模式无法处理的场景……执行基于行的变化的过程就像一个黑盒子,
你无法知道服务器正在做什么。