zoukankan      html  css  js  c++  java
  • 错误查询二进制日志mysqlbinlog1

    事务的日志

    1. redo log,重做日志,是事务日志的一种
    
    作用
    在事务ACID过程中,实现的是'D'持久化的作用。(#保存在磁盘)
    REDO:记录的是,内存数据页的'变化过程'
    特性:WAL(Write Ahead Log)日志优先写
    

    U5gLqJ.md.jpg

    文字描述

    #修改,创建,删除
    1)首先将表中 id=1的行所在'数据页'加载到内存中data buffer page('数据缓冲区')
    2)MySQL实例在内存中将 id=1的数据页'改'成 id=2
    3)id=1变成 id=2的'变化过程会记录到',redo内存区域,也就是redo buffer page中('重做缓冲区')
    4)当敲下'commit'命令的瞬间,MySQL会将redo buffer page'写入磁盘'区域redo log,返回ok
    #过程
    ibdata1 --> data buffer page --> redobuffer page -->redo log
    #数据库重启或者隔一段时间,redo log中的日志会写入到ibdata1(.ibd)中
    
    #查询
    1.首先将表中id=1的行所在数据页加载到内存中data buffer page
    2.将redo log中id=1变成id=2的变化过程取加载到redo buffer page
    3.通过data buffer page和redo buffer page得到一个结果
    #过程
    ibdata1 --> data buffer page '???' redo buffer page <-- redo log
    

    2.undo log,回滚日志,也是事务日志的一种
    
    作用
    在事务ACID过程中,实现的是'A'原子性的作用。当然CI的特性也和undo有关
    
    #redo log 和undo log 都是事务的日志,不是数据库命令的日志
    

    U5gXZ9.md.jpg

    断电的三种情况(如何恢复内存中的数据)

    1.执行了commit,启动数据库,数据恢复,id=2(CSR)
    2.没有执行commit,但是数据保存到了redo log(过了一段时间),id=2,但是因为undo buffer page中没有记录commit,所以 id=1
    3.没有执行commit,数据没有保存到redo log, id=1
    
    #源数据+变化过程=修改后的内容
    

    redo和undo的存储位置

    #redo位置
    [root@db02 ~]# ll /usr/local/mysql/data/
    -rw-rw---- 1 mysql mysql 50331648 Aug 15 06:34 ib_logfile0
    -rw-rw---- 1 mysql mysql 50331648 Mar  6  2017 ib_logfile1
    
    #undo位置
    [root@db02 ~]# ll /usr/local/mysql/data/
    -rw-rw---- 1 mysql mysql 79691776 Aug 15 06:34 ibdata1		#共享表空间
    -rw-rw---- 1 mysql mysql 79691776 Aug 15 06:34 ibdata2
    

    事务中的锁

    作用
    在事务ACID特性过程中,'锁'和'隔离'级别一起来实现'I'隔离性的作用。
    
    #查看mysql存储引擎
    mysql> show create table cs;
    | cs    | CREATE TABLE `cs` (
      `id` int(11) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
    
    #mysql innodb存储引擎支持锁,pyisam不支持锁
    
    #创建指定innodb存储引擎的表
    mysql> create table suo(id int) engine=innodb;
    
    #锁
    db03 tty1
    mysql> create table suo1(id int);
    mysql> insert suo1 values(1);
    mysql> select * from suo1;
    +------+
    | id   |
    +------+
    |    1 |
    +------+
    mysql> update suo1 set id=2 where id=1;
    mysql> select * from suo1;
    +------+
    | id   |
    +------+
    |    2 |
    +------+
    
    db03 tty2
    mysql> update suo1 set id=3 where id=1;
    mysql> select * from suo1;
    +------+
    | id   |
    +------+
    |    2 |
    +------+
    
    
    #mysql里面谁先提交谁为准,Redis里面谁后提交谁为准
    

    innoDB中锁的类别

    排他锁:在我'修改时',别人不能修改(#行级锁)
    共享锁:保证在多事务工作期间,'数据查询时'不会被阻塞。
    
    乐观锁:多事务操作时,数据可以同时修改,谁先提交,以谁为准(#购票)
    悲观锁:多事务操作时,数据只有一个人可以修改(#购物车+购票)
    

    多版本并发控制(多锁一起用)

    1.只阻塞修改类操作(排他锁),不阻塞查询类操作(共享锁)
    2.乐观锁的机制(谁先提交谁为准)
    

    锁的粒度

    1.myisam		表级锁
    2.innoDB		行级锁,效率更高
    

    隔离

    事务中的隔离级别

    1.RU级别:READ UNCOMMITTED(独立提交):'未提交读',允许事务查看其他事务所进行的未提交更改,
    问题1.不安全,2.会出现脏读
    
    2.RC级别:READ COMMITTED:允许事务查看其他事务所进行的已提交更改,查看'不需要重新进入数据库'
    3.RR级别:REPEATABLE READ:允许事务查看其他事务所进行的已提交更改,查看数据需要'有时重新进入数据库'('InnoDB 的默认级别')
    
    4.串行化:SERIALIZABLE:将一个事务的结果与其他事务'完全隔离'(最大程度的隔离)
    
    #查看隔离级别
    mysql> show variables like '%iso%';
    +---------------+-----------------+
    | Variable_name | Value           |
    +---------------+-----------------+
    | tx_isolation  | REPEATABLE-READ |  #RR级别,系统默认
    +---------------+-----------------+
    
    #设置隔离级别(RU RC #RR)
    [root@db03 ~]# vim /etc/my.cnf
    #log_bin=mysql-bin
    transaction_isolation=read-uncommit
    transaction_isolation=read-commit
    [root@db03 ~]# /etc/init.d/mysqld restart
    mysql> show variables like '%iso%';
    +---------------+------------------+
    | Variable_name | Value            |
    +---------------+------------------+
    | tx_isolation  | READ-UNCOMMITTED |  #RU级别
    +---------------+------------------+
    mysql> update suo1 set id=1 where id=100;
    mysql> select * from suo1;
    +------+
    | id   |
    +------+
    |    1 |
    +------+
    mysql> rollback;
    mysql> select * from suo1;
    +------+
    | id   |
    +------+
    |  100 |	#如果id=1已经被使用,那么这种现象即为脏读	
    +------+
    
    名词:
    1.RU级别会出现'脏读':RU级别,执行事务修改数据,被读取,但是数据最终回滚了,查询到的数据就是脏
    2.幻读:删除所有表数据,删除的同时有人插入数据,查看数据时'以为是'没删干净
    3.不可重复读:修改数据后被读取,被读取之后再次修改数据,两次数据不一致(#访问次数)
    

    查看隔离级别

    #查看隔离级别
    mysql> show variables like '%iso%';
    

    设置隔离级别

    #设置RU级别
    [root@db03 ~]# vim /etc/my.cnf
    transaction_isolation=read-uncommit
    
    #设置RC级别
    [root@db03 ~]# vim /etc/my.cnf
    transaction_isolation=read-commit
    

    mysql日志

    mysql 错误日志

    1.错误日志'默认是关闭的'
    2.错误日志文件默认路径是 $datadir/主机名.err
    
    查看错误日志路径
    0)初始化之后
    rm -rf /usr/local/mysql/data/ibdata*
    ./mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data/
    /etc/init.d/mysqld start
    1)命令行
    [root@db02 ~]# mysql -e "show variables like '%log_err%'"
    +---------------------+---------------------------------+
    | Variable_name       | Value                           |
    +---------------------+---------------------------------+
    | log_error           | 							 |
    +---------------------+---------------------------------+
    2)SQL语句
    mysql> show variables like 'log_err';
    
    #配置错误日志
        [root@db02 ~]# vim /etc/my.cnf
        [mysqld]
        server_id=1
        basedir=/usr/local/mysql
        datadir=/usr/local/mysql/data
        port=3306
        socket=/tmp/mysql.sock
        skip-name-resolve
        log_err=/usr/local/mysql/data/mysql.err  (#相对路径的话,放到data目录)
    
        [mysql]
        socket=/tmp/mysql.sock
    
    #查看错误日志
    less /usr/local/mysql/data/mysql.err
    
    #作用
    mysql数据库启动不了的时候,查看报错
    
    #购买了阿里云主机,安装mysql后,第一时间修改mysql错误日志,来指定mysql错误日志的格式
    

    mysql查询日志

    1.查询日志默认是'关闭的'
    2.查询日志'文件默路径'是 $datadir/主机名.log
    
    查看查询日志路径
        mysql> show variables like '%general%';
        +------------------+--------------------------------+
        | Variable_name    | Value                          |
        +------------------+--------------------------------+
        | general_log      | OFF                            |	#
        | general_log_file | /usr/local/mysql/data/db02.log |
        +------------------+--------------------------------+
    
    配置查询日志
        [root@db02 ~]# vim /etc/my.cnf
        [mysqld]
        log_err=/usr/local/mysql/data/mysql.err
        general_log=on/1
        general_log_file=/usr/local/mysql/data/db02.log
    
        [mysql]
        socket=/tmp/mysql.sock
        
    #查看查询日志
    less /usr/local/mysql/data/db02.log
    
    #作用
    记录sql语句执行过的命令(#一般不用 Ctrl+R)
    

    二进制日志

    1.二进制文件'默认是关闭的'
    2.二进制配置'路径和名字'由配置文件决定,一般保存在 $datadir/mysql-bin 命名(默认)
    
    

    1.二进制日志管理操作

    1)开启二进制日志

    配置bin_log
    3.配置binlog
        [root@db02 ~]# vim /etc/my.cnf
        [mysqld]
        server_id
        log_bin=/usr/local/mysql/data/mysql-bin
    	#log-bin=/usr/local/mysql/data/mysql-bin
    
    #mysql5.7(log_bin)只支持下划线_ ,5.6支持 - _
    #mysql5.7必须指定server_id
    #binlog生成默认大小是120(刷新后是143),也是binlog当前的位置点
    #数据库重启会生成新的mysql-bin.00000x
    #企业全备和增备一起用
    

    2)查看二进制日志

    #物理查看
    [root@db02 ~]# ll /usr/local/mysql/data/
    -rw-rw---- 1 mysql mysql      120 Jul 21 19:24 mysql-bin.000001
    -rw-rw---- 1 mysql mysql       39 Jul 21 19:24 mysql-bin.index
    [root@db03 ~]# mysql -uroot -p123 -e'show variables like "%log_bin%"'
    
    #数据库查看
    mysql> show variables like '%bin%'		#查看like命令和默认
    | log_bin                                 | OFF                  |
    show variables like 'log_bin'
    +---------------------------------+-------+
    | Variable_name                   | Value |
    +---------------------------------+-------+
    | log_bin                         | OFF   |		#默认关闭
    | log_bin_basename                |       |
    | log_bin_index                   |       |
    | log_bin_trust_function_creators | OFF   |
    | log_bin_use_v1_row_events       | OFF   |
    | sql_log_bin                     | ON    |
    +---------------------------------+-------+
    

    3)事件

    1.什么是事件
    	1)在binlog中最小的记录单元为event('一个SQL命令')
    	2)一个'事务'会被拆分成多个事件(event)
    
    2.事件(event)特性
        1)每个event都有一个'开始位置'(start position)和'结束位置'(stop position)。
        2)所谓的位置就是event对整个二进制的文件的'相对位置'。(相对于120)
        3)对于一个二进制日志中,'前120个'position是'文件格式信息预留空间'。
        4)MySQL第一个记录的事件,都是从120开始的。
    
    #查看bin_log
    
    物理查看
    [root@db03 ~]# ll /service/mysql/data/
    -rw-rw---- 1 mysql mysql      120 Jul 20 21:40 mysql-bin.000001
    -rw-rw---- 1 mysql mysql      143 Jul 20 21:52 mysql-bin.000002	#最新(143)
    
    SQL语句查看
    [root@db03 ~]# vim /etc/my.cnf
    log_bin=mysql-bin
    server_id=2
    mysql> show master status;
    +------------------+----------+
    | File             | Position |
    +------------------+----------+
    | mysql-bin.000010 |      120 |
    
    #重启数据库(修改模式)会生成新的bin_log,默认的bin_log大小变成143,写入了一点系统记录
    

    4)刷新binlog

    1)flush logs;		#会产生新的log-bin.00000x  #可以和全备一起用
    2)重启数据库时会刷新
    3)二进制日志上限,默认1G(可以使用 max_binlog_size=xx修改)
    

    5)删除binlog

    1.根据存在时间删除日志
    #临时生效
    mysql> set global expire_logs_days=7;
    #永久生效
    [root@db01 data]# vim /etc/my.cnf
    [mysqld]
    expire_logs_days = 7
    
    2.使用purge命令删除(删除从现在起 3天前)
    mysql> purge binary logs before now() -interval 3 day;
    
    3.根据文件名删除(只保留10)
    PURGE BINARY LOGS TO 'mysql-bin.000010';
    
    4.使用reset master(重置binlog,删除所有的binlog)(会导致主从复制卡住)
    mysql> reset master; 
    
    #不能使用rm删除binlog,因为索引里仍有该索引的记录
    [root@db03 data]# cat mysql-bin.index 
    ./mysql-bin.000001
    ./mysql-bin.000002
    ./mysql-bin.000003
    
    #没有备份的情况下,删除binlog的话无法找回
    

    2.二进制日志作用

    1.记录已提交的DML事务语句,并拆分为多个事件('event执行单元')来进行记录
    2.记录所有DDL、DCL等语句,总之,二进制日志会'记录'所有对数据库发生修改的操作
    
    3.如果我拥有数据库搭建开始,'有所有的二进制日志',那么我可以'把数据恢复到任意时刻'
    但是一般使用'全备和增备'恢复数据库数据
    4.利用bin_log进行数据的备份与恢复
    5.数据的主从复制
    
    #查看帮助
    [root@db03 ~]# mysqldump --help
    
    #使用mysqldump命令需要指定 -S /tmp/mysql.sock
    

    1)数据库的备份与恢复

    1>添加数据
    mysql> create database binlog;
    mysql> use binlog
    mysql> create table binlog(id int);
    mysql> insert binlog values(1),(2),(3);
    mysql> insert binlog values(4);
    mysql> insert binlog values(5);
    
    mysql> select * from binlog;
    +------+
    | id   |
    +------+
    |    1 |
    |    2 |
    |    3 |
    |    4 |
    |    5 |
    +------+
    
    2>删除数据
    #误删除两条数据
    mysql> delete from binlog where id=5;
    mysql> delete from binlog where id=4;
    mysql> delete from bl where id=5 or id=4;
    
    3>通过binlog恢复数据
    #查看二进制日志找到位置点
    [root@db02 data]# mysqlbinlog mysql-bin.000002
    ...
    ...
    # at 4
    ...
    ...
    # at 120 (位置点)
    create database bl
    /*!*/;
    # at 208
    use `bl`/*!*/;
    SET TIMESTAMP=1595361536/*!*/;
    create table bbl(id int)
    /*!*/;
    
    #将位置点之间的数据取出
    [root@db02 data]# mysqlbinlog --start-position=631 --stop-position=978 mysql-bin.000002 > /tmp/hf.sql
    
    #将数据导入回去
    [root@db02 data]# mysql < /tmp/45.sql
    
    #查看
    select * from binlog
    
    #一个事务可以包含多个位置点
    #企业数据库不会随便重启,所以binlog可能会很大
    #通过binlog恢复数据是不现实的,因为企业中的binlog很大(不好操作)
    #企业中不会超过一个月的binlog,但是binlog数据量依然很大
    

    2)使用binlog配合数据库升级(企业数据库的切换)

    1.准备一台新的数据库,版本为5.6.38
    2.旧数据库备份数据(同时导出多个库)(要想使用--master-data=2,数据库必须配置bin_log)
    	[root@db03 ~]# mysqldump -uroot -p123 --triggers -R --master-data=2 -B ku linux9 myisam qiudao qiudaodsb tmp world xiangqing >/tmp/full.sql
    3.将备份的数据库传到新数据库
    	[root@db03 ~]# scp /tmp/full.sql 172.16.1.52:/tmp/
    4.修改sql中的存储引擎
    	[root@db02 data]# sed -i 's#MyISAM#InnoDB#g' /tmp/full.sql
    5.将修改后的sql文件导入新数据
    	[root@db02 data]# mysql < /tmp/full.sql
    	
    	
    6.将代码中的数据库地址修改为新的数据库地址
    7.通过binlog将数据迁移过程中新生成的数据取出
    	[root@db03 data]# mysqlbinlog -uroot -p123 --start-position=120 --stop-position=465 mysql-bin.000014 > /tmp/bu.sql
    	[root@db03 data]# scp /tmp/bu.sql 172.16.1.52:/tmp/
    8.将新数据导入新库
    	[root@db02 data]# mysql < /tmp/bu.sql
    	select * from xx
    
    #解决新数据写入的方法
    1.先导入'旧数据',将web中代码的地址修改为新库,再通过binlog将'新数据'导出再导入新库就可以了
    2.先做旧库和新库做'主从复制',再根据位置点导入'旧数据',再'切库',再断开主从(切库会导致数据少量丢失)
    

    报错

    mysql> insert bbl values(1);
    ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
    
    
  • 相关阅读:
    Google Web 字体 API 访谈
    关于如何跨越抄袭程序阶段的一些断想
    DirectX开发中找不到dxtrans.h的问题的解决
    Google Web 字体 API 访谈
    NetBeans 6.9 发布后选版 1 已经可用
    Thrift java服务器与客户端示例
    Wing IDE Pro v. 4.1.91 Python Wingware Python IDE
    tkang's blog
    Thrift的简单使用
    maven加载自己的包
  • 原文地址:https://www.cnblogs.com/syy1757528181/p/13357581.html
Copyright © 2011-2022 走看看