zoukankan      html  css  js  c++  java
  • MySQL 二进制文件 (STATEMENT)浅谈

    看完<高可用性 MySQL>的第三章,对二进制日志有加深了一些认识,现在总结下知识点。

    知识点:
    1:二进制日志是公共资源,所有的线程都向它写入语句,避免两个线程同时更新二进制日志。在写二进制日志前,需要获得一个互斥锁,在事件完成后释放。由于服务器的所有线程都向二进制日志写语句,所以这个锁会常常阻塞某些会话线程。

    2:默认情况下,二进制日志不是在每次写的时候直接同步到磁盘的,需要先写到二进制日志缓存里(binlog_cache_size)。当宕机时,会丢失该部分的事务,需要用sync_binlog=1来确保写1次缓存就同步到磁盘来保证,特殊情况下还需要用innodb_support_xa (确保二进制日志和存储引擎的分布提交)开启来保证。二进制日志在事务提交前写磁盘。

         使用支持事务的存储引擎,所有未提交的二进制日志先放到缓存里面,等到事务提交,再把缓冲中的二进制日志写到磁盘。

    3:二进制日志的结构:
    Log_name:这个event所在的binlog名称。
    Pos:这个event在当前binlog中的位置
    Event_type:这个event的类型,类型是有很多。每个二进制日志文件的开头都是Format_desc类型。
    Server_id:这个event是在哪个server上发生的。注意在replication中这个server id记录的是master端的server id。不是replication则记录自己的server id。
    End_log_pos:下一个event的位置,因此当前这个event的长度是End_log_pos-Pos
    Info:本条event的信息。

    关于Event_type这里简单说明下:event 类型是有很多:Format_desc、Query、User var、Xid、Rand、Intvar、Stop、Rotate 等等。下面解释:
    User var:自定义变量。
    Rand : 随机数种子。
    Intvar :Auto_increment信息。
    Format_desc:每一个binlog文件的头,格式信息。
    Rotate:每个binlog文件的结束event时候,如Flush logs、大小上线时产生的类型。
    Stop :每个binlog文件的结束event时候,如MySQL 重启时产生的类型。
    注意,要是数据库被Kill掉的话,这个时候不会有任何event写入。
    Query :一般执行的查询。
    Xid : 事务提交的信息。
    其他还有很多event类型,最常见的可能就是Query了,update、delete等操作都是Query类型.通常一个update操作在binlog文件中会产生好几个event,因为为了保证主从一致,需要确保很多外部因素的一致。
    在这里我们引入一个分组的概念:除了format_desc和rotate,其他的event我们往往可以对其进行分组,对于事务型数据库来说,往往认为一个事务就是一个分组,对于非事务型数据库和类似create、alter这类语句来说,一条语句本身就是一个分组.

    View Code
    *************************** 1. row ***************************
       Log_name: mysql-bin.000005
            Pos: 4
     Event_type: Format_desc
      Server_id: 1
    End_log_pos: 106
           Info: Server ver: 5.1.66-0ubuntu0.11.10.2-log, Binlog ver: 4
    *************************** 2. row ***************************
       Log_name: mysql-bin.000005
            Pos: 106
     Event_type: Query
      Server_id: 1
    End_log_pos: 174
           Info: BEGIN
    *************************** 3. row ***************************
       Log_name: mysql-bin.000005
            Pos: 174
     Event_type: Query
      Server_id: 1
    End_log_pos: 260
           Info: use `test`; truncate table employee
    *************************** 4. row ***************************
       Log_name: mysql-bin.000005
            Pos: 260
     Event_type: Xid
      Server_id: 1
    End_log_pos: 287
           Info: COMMIT /* xid=48640 */
    *************************** 5. row ***************************
       Log_name: mysql-bin.000005
            Pos: 287
     Event_type: Query
      Server_id: 1
    End_log_pos: 355
           Info: BEGIN
    *************************** 6. row ***************************
       Log_name: mysql-bin.000005
            Pos: 355
     Event_type: User var
      Server_id: 1
    End_log_pos: 433
           Info: @`pass`=_latin1 0x2A36424234383337454237343332393130354545343536384444413744433637454432434132414439 COLLATE latin1_swedish_ci
    *************************** 7. row ***************************
       Log_name: mysql-bin.000005
            Pos: 433
     Event_type: Query
      Server_id: 1
    End_log_pos: 577
           Info: use `test`; insert into employee(name,email,password) values('mats','mats@example.com',@pass)
    *************************** 8. row ***************************
       Log_name: mysql-bin.000005
            Pos: 577
     Event_type: Xid
      Server_id: 1
    End_log_pos: 604
           Info: COMMIT /* xid=48641 */
    *************************** 9. row ***************************
       Log_name: mysql-bin.000005
            Pos: 604
     Event_type: Rotate
      Server_id: 1
    End_log_pos: 647
           Info: mysql-bin.000006;pos=4

    这里有一个疑问:因为主上binlog中的每个event都会把信息通过IO线程传给从,在上面说的binlog格式中End_log_pos表示下一个事件的开始位置, 当主宕机的时候,再开起来,会新起一个binlog,而前一个binlogEnd_log_pos表示下一个事件的位置已经无效了,并且Event_type没有任何提示说轮循了。同理所以它在replication中会遇到从找不到pos,因为没有提示从,主已经另起来一个binlog文件了。解决办法是重新change 到 最新的binlog最新的pos。<等待验证>

    3:触发器(trigger)、事件(Event)、存储函数(Procedure、Function)的记录:
    请见这篇文章
    触发器主从都需要有,事件和存储函数只需要做主上有就可以了。
    注意:在Row Format格式下,触发器不需要从上也存在。

    4:一张A表上有Before 触发器的时候,需要注意,即使在A表有错误的执行(比如重复键),也会导致该触发器执行,使触发的内容写到和触发器相关的表中(B<Myisam>)。在STATEMENT 下,触发的sql不会记录。导致主从不一致。

    5:ROW 和 STATEMENT 模式下的记录方式不同。

    ~~~~~~~~~~~~~~~ 万物之中,希望至美 ~~~~~~~~~~~~~~~
  • 相关阅读:
    MySQL优化---主从复制
    MySQL性能优化---优化方案
    MySQL性能优化---索引
    MySQL性能优化---定位慢查询
    Linux开机启动过程详解
    naginx
    Git搭建
    脚本中特殊字符
    Shell脚本
    简单Shell脚本(实例)
  • 原文地址:https://www.cnblogs.com/zhoujinyi/p/2773650.html
Copyright © 2011-2022 走看看