Press "Enter" to skip to content

Category: MySQL

不看说明的下场!

本来参加网易云课堂的MySQL课程上的还算开心,一系列课程都通过了。国庆之前提前把第五节课程赶时间做完了。我还盘算的第五节考试能顺利完成,等国庆回来的再过第六节的考试。结果,国庆一过第五节的成绩就公布了,只有62分,险过。然后大意的看看第六节的考试没出来就没管它。今天一看,才发现第六节没有考试!成绩是平时课后习题60%+课后讨论40%,压根没有考试,而且10号,也就是昨天已经截至。
功亏一篑,功亏一篑!

请简述InnoDB如何保证事务的持久化特性

在数据库运行时,为了保障整个数据库系统的正常运行,防止数据意外和不一致,数据库管理系统就要对数据库进行保护和管理。这些管理主要通过数据库的恢复、并发控制、完整性控制和安全性控制,进而引申出事务和事务的特性。

事务是构成单一逻辑工作单元的操作集合。为了保证数据库中的数据总是正确的,我们要求事务具有ACID的性质,也就是原子性、一致性、隔离性和持久性。

其中,事务的持久性就是指一个事务一旦完成全部操作之后,它对数据库的所有更新应永久地反映在数据库中,不会丢失。即使以后系统发生故障,也是如此。MySQL为了实现数据库ACID的要求,引入了支持事务的InnoDB引擎。

InnoDB一方面实现了对事务的实现,另一方通过redo log日志实现了事务的原子性和持久性。 InnoDB是事务的存储引擎,当数据操作提交commit时,必须先将该事务的所有日志写入到redo log文件进行持久化,待事务的commit操作完成才算完成。为了保证每次日志都要写入redo log,InnoDB都要调用fsync操作将日志写入磁盘。

MySQL的主从同步

MySQL从3.23版本开始提供复制的功能。复制是指将主数据库的DDL和DML操作通过二进制日志传到从数据库上,然后在从库上对这些日志redo,从而使得从库和主库的数据保持同步。


概述

  1. 主库在commit时把数据变更作为events记录在binlog中;
  2. 主库推送binlog到从库的relay_log,之后从库从relay_log执行redo,通过逻辑复制以达到主从数据一致。

MySQL通过三个线程来完成主从复制:
1. binlog dump线程在主库上运行,将数据操作推送给从库;
2. I/O线程跑在从库上,将binlog日志中的事件更新到relay_log中;
3. SQL线程跑在从库上,将relay_log中更新的数据库事件应用到从库。

架构

复制的常见架构有:
1. 一主多从复制,适用于读压力大,实现读写分离;
2. 多级复制架构,主要为了解决主库的I/O负载和网络压力,但延迟大;
3. 双主复制架构,适用于主从切换;


搭建

主库

操作系统为ubuntu,域名beijing.sujx.net,关闭ufw,开启vsftpd;

$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf 

server-id = 100
log_bin                 = /var/log/mysql/mysql-bin.log
bind-address            = 192.168.122.106

$ sudo systemctl restart mysql 
$ mysql -u root -p 
mysql> grant replication slave on *.* to replica@'%' identified by 'password'; 
mysql> flush privileges; 
mysql> flush tables with read lock; 

mysql> show master status\G
*************************** 1. row ***************************
File: **mysql-bin.000012**
Position: **1677**
Binlog_Do_DB: 
Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)
mysql> exit
mysqldump -uroot -p --all-databases --lock-all-tables --events > mysql_dump.sql
lftp sujx@shanghai.sujx.net
put mysql_dump.sql
$ mysql -u root -p 
mysql> unlock tables;

从库

操作系统为ubuntu,域名shanghai.sujx.net,关闭ufw,开启vsftpd;

$ mysql -u root -p < /tmp/mysql_dump.sql 
$ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

server-id = 101
read_only=1
report-host=beijing.sujx.net

$sudo systemctl restart mysql 
$ mysql -u root -p 
mysql> change master to
-> master_host='beijing.sujx.net',
-> master_user='replica',
-> master_password='password',
-> master_log_file='mysql-bin.000012',
-> master_log_pos=1677;
mysql> SET GLOBAL sql_slave_skip_counter = 1;
mysql> start slave;
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: beijing.sujx.net
                  Master_User: replica
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000012
          Read_Master_Log_Pos: 1677
               Relay_Log_File: shanghai-relay-bin.000020
                Relay_Log_Pos: 1202
        Relay_Master_Log_File: mysql-bin.000012
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1007
                   Last_Error: Error 'Can't create database 'sujx'; database exists' on query. Default database: 'sujx'. Query: 'create database sujx'
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 989
              Relay_Log_Space: 2147
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 1007
               Last_SQL_Error: Error 'Can't create database 'sujx'; database exists' on query. Default database: 'sujx'. Query: 'create database sujx'
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 100
                  Master_UUID: d84bbcff-a41f-11e7-a7e7-525400537531
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: 
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 170929 17:39:55
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

测试

在主库上面进行删库、建库、导入数据即可。

Tips

Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
这个问题是因为mysql目录中的auto.conf中的UUID值相同,修改之后就可以正常。

Last_IO_Errno: 1045 Last_IO_Error: error connecting to master ‘replication@
这个问题是change master语句错误

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

IO和SQL线程显示正常却无法复制数据时,需要设置SET GLOBAL sql_slave_skip_counter Syntax跳过内部出错的地方。

Ubuntu上的ibdata1文件去哪里了?

在Ubuntu桌面版上使用apt安装MySQL之后,无论使用find还是locate都找不到MySQL的重要文件ibdata1。解决问题的方法很简单,就是切换到root账号之下。

$ locate ibdata1 
$ 
$ su
# locate ibdata1
# /var/lib/mysql/ibdata1

MySQL的数据文件位置

root@TC8304:/var/lib/mysql# ls
auto.cnf         ibdata1      ibtmp1              phpmyadmin  TC8304-slow.log
debian-5.7.flag  ib_logfile0  mysql               sujx
ib_buffer_pool   ib_logfile1  performance_schema  sys