Mysql常见日志
(1)错误日志:记录数据库服务器启动、停止、运行时存在的问题;
(2)慢查询日志:记录查询时间超过long_query_time的sql语句,其中long_query_time可配置,且慢查询日志默认关闭;
(3)一般查询日志:记录数据库的连接信息以及所有的sql语句;
(4)二进制日志:即bin log,记录所有修改数据库状态的sql语句及这些sql语句的执行时间,修改数据库的语句包含了insert、delete、update等操作,该日志属于逻辑日志,会记录MyISAM、InnoDB引擎数据库的所有修改操作,以便进行数据恢复和主从复制,该日志仅在事务提交前提交,仅写磁盘一次。对于该日志的写入,是通过追加的方式进行的,不会覆盖已有的内容。
当数据发生丢失后,该日志可将数据库恢复到特定的时间点;主服务器上的二进制日志可以被从服务器读取,从而实现数据同步。该日志包含了二进制索引文件和二进制日志文件两部分;
(5)重做日志:即redo log,记录了每个对InnoDB表的写操作,记录的是数据页的物理变化,用来实现事务的持久性。该日志包含了重做日志缓存、重做日志文件两部分,前者在内存中,后者在磁盘中,当事务提交后会把所有修改信息存储到重做日志文件中,写入时使用循环写入和擦除的方式进行;
(6)回滚日志:即undo log,用于记录数据被修改前的信息,用于事务回滚,实现事务的原子性和持久性,也是实现MVCC多版本并发控制的关键部分,属于逻辑日志。
当delete一条记录时,undo log中会记录一条对应的insert记录,回滚时插入这一条被删除的数据,反之亦然;当update一条记录时,它记录一条对应相反的update记录,回滚时修改回去。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。
MVCC
MVCC是多版本并发控制,指维护一个数据库的多个版本,使得读写没有冲突,解决数据的并发问题。在支持MVCC的数据库中,当多个用户访问数据时,每个用户都能看到某个时间点前的数据库快照,并能够无阻塞、无干扰地执行查询和修改操作,MVCC主要通过版本链和ReadView机制实现的。
对于版本链,通过隐藏字段实现的。每一行数据都有3个隐藏字段:
(1)DB_TRX_ID:保存创建这个版本的事务ID,即最后一项修改该记录或插入该记录最新版本的事务ID;
(2)DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本,用于配合undo log;
(3)DB_ROW_ID:隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。
在undo log日志中,存在一个版本链,存储数据的旧版本,当更新一行数据时,不会覆盖原数据,而是产生一个新版本的数据,并更新DB_TRX_ID、DB_ROLL_PTR插入到版本链中,使得其指向前一个版本的数据,这样可通过版本链找到旧版本的数据,逻辑图如下:
ReadView读视图机制用于确定事务的哪些版本的行记录是可见的,解决一致性读问题。当事务创建时,会为事务创建一个ReadView记录,其中包含4个信息:
(1)creator_trx_id:创建ReadView的事务id;
(2)m_ids:活跃的事务id集合,指的是开始但未提交的事务;
(3)min_trx_id:活跃事务中最小的事务id,即m_ids中最小的事务id;
(4)max_trx_id:事务ID的最大值加1,即即将创建的事务id。
当一个事务读某条数据时,根据ReadView判断数据的某个版本是否可见:
(1)若被访问数据的DB_TRX_ID的值小于min_trx_id,则该数据对当前事务可见,因为该版本数据已被提交;
(2)若被访问数据的DB_TRX_ID的值大于max_trx_id,则该数据对当前事务不可见,创建该数据版本的事务在生成ReadView后开始执行的,尚未提交;
(3)DB_TRX_ID在min_trx_id与max_trx_id之间时,若m_ids中未包含DB_TRX_ID,则该版本数据对当前事务可见,因为该数据版本的事务在生成ReadView后已提交;若包含DB_TRX_ID,则该版本数据对当前事务不可见,因为该数据版本的事务仍处于活跃状态,或在当前事务生成 ReadView后开始。
对于可重复读和读已提交,生成ReadView有以下区别:
对于可重复读,在第一次读取数据时生成一个ReadView,ReadView一直保持到事务结束不发生变化,这样可以保证在事务中多次读取同一行数据时,读取到的数据是一致的。
对于读已提交,每次读取数据前都生成一个 ReadView,这样就能保证每次读取的数据都是最新的。
主从复制
是一种数据同步机制,将数据从一个主数据库复制到多个从数据库,广泛用于数据恢复、灾难恢复。
主从复制分为以下几步:
(1)在主数据库中,执行数据库修改操作时(Insert、Updata、Delete等),将这些操作语句写入到bin log(二进制日志),在这些操作完成后,主数据库的log dump线程将二进制日志中的内容发送给从数据库;
(2)从数据库接收到二进制日志的内容后,通过IO线程将其写到从数据库的中继日志中(relay log);
(3)从数据库中的sql线程读取中继日志,并在本地数据库中执行读取到的sql语句,从而改变从数据库中的数据,完成同步。