日志

事务的实现原理
  • mysql在读写操作的时候锁定,commit或rollback时候解锁

    • 行(记录)锁:解决并发写的问题(可重复读级别)。若要操作的行是有索引的,则会直接在索引字段找到并加行锁;无索引加行锁的方式是:先锁整张表,然后过滤非操作行,留下的就是行锁,故而性能较差,大表建议加索引。

      行锁特点:锁粒度小,并发性能高,开销大,加锁慢,会出现死锁,mysql的Innodb支持(myisam不支持),分为共享锁和排它锁,锁冲突概率低。

    • 表锁:锁粒度大,并发性能低,简单,开销小,加锁快,不会出现死锁,很多数据库引擎都支持,分为共享锁和排它锁,锁冲突概率高。lock/unlock table 语句可以显示开启

    • 页级锁:介于行锁和表锁之间,各种指标中规中矩。

    • next-key(临键)锁:行锁+间隙锁(解决并发写和幻读),假如age两条字段10、30都加了索引,底层维护一套B+树分割区间,现在操作age=10,则10加行锁,(-∞,10]加间隙锁,(10,30]加间隙锁, 30和(30,+∞)不受影响。

      mysql利用next-key锁解决了在可重复读下的幻读问题。

      间隙锁的危害:有些间隙范围被无辜上锁,影响性能。所以一般是逻辑上的删除(一个标致字段),避免产生间隙锁。

    • 读锁(共享、S)锁:可并发读,不可并发写。可以用select xx lock in share mode 语句可以显示开启

    • 写(排它、独占、X)锁:只有一个获取到这个锁的事务能够读和写,其他没锁的就阻塞。select xx for update 语句可以显示开启

    • 意向锁:Intention Share(Exclusive) Lock,即IS、IX锁,加行级的读、写锁之前在表级进行标记,避免其他事务想加锁还需要一行行遍历看是否加过锁了。Innodb自动加,无需用户干预。

    • 死锁:比如事务A、B,A持有某个行锁或间隙锁,B持有某个行锁或间隙锁,A、B继续操作都需要等待另外一个事务给他资源,互相等待形成死锁。形成了死锁闭环后,innodb会等待锁释放超时:innodb_lock_wait_timeout=50s,超时后会让其中一个事务让出资源,另外的事务执行成功。死锁排查show engine innodb status

  • 基于日志

    • bin log:主从复制用的日志,记录着主库当前已完成的修改操作信息,从库也执行这些操作,就得到和主库一样的数据。

    • redo log:记录修改后的值,出于性能考虑,mysql不会每次都把修改实时同步到磁盘,而是先存到buffer pool(缓存池)中,后台有专门线程慢慢将缓存池数据持久化到磁盘,为了避免宕机缓存数据丢失来不及同步问题,还需要加一层保障,那就是redo log,在每次提交操作之后就立马将信息持久化到磁盘的redo log日志中,即是宕机了,下次系统还会从redo log恢复已提交的操作。 故redo log保证持久性

      buffer pool(缓存池)的存在大大提升了数据库的性能,但因为是缓存,也有宕机丢失的风险。

      redo log 一般分为4组,每组1G,记录位置分为write poscheckpoint

      write pos :是当前记录的位置,一边写一边后移,写到第3号文件末尾后就回到0号文件开头。

      check point:是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

      ​ 若write pos 追上了checkpoint,此时就阻塞,先擦除一些数据,checkpoint往前面跑,然后write pos再跟上来。

      事务执行过程中发生宕机怎么处理(redo log二阶段提交?)

      innodb容灾能力叫crash-safe,由redo log和bin log的逻辑同步保证,即redolog二阶段提交保证,分为两个阶段:

      1 prepare阶段(写入redo log) --> 2 写binlog --> 3 commit。

      当在2之前崩溃时,重启恢复后发现没有commit,回滚。备份恢复:没有binlog 。一致

      当在3之前崩溃时,重启恢复发现虽没有commit,但满足prepare和binlog完整,所以重启后会自动commit。备份:有binlog. 一致

    • 日志恢复和checkpoint:崩溃前最后的提交信息还没有标记成已检查点END_CKPT,恢复后从最后的已检查点开始恢复redo log,将崩溃时未写入的已提交信息写入磁盘。

    • undo log:记录修改前的值,回滚日志,记录和写操作相反的操作,当事务回滚,就执行这些反操作,将数据恢复成修改前的模样。保证的是原子性

      分为2种,insert undo log和 update undo log

    • MVCC (MultiVersion Concurrency Control):通过数据的多版本来实现读写分离,从而实现不加锁且读写并行。依赖undo log与read view(用于判断当前版本数据可见性)。

      每个事务都有自己的事务id、创建时间、过期时间,记录在undo log中,相当于对数据进行一个版本控制,每个事务根据版本信息就只能查到自己操作的那个数据版本,其他版本是查不到的,比如事务2只能查到创建时间小于等于它的创建时间、以及过期时间要大于等于它的创建时间的 所有操作,这样就保证了事务的隔离性

mysql通过 保证持久性(redo log)、原子性(undo log)、隔离性(读写锁+MVCC) 来最终实现 一致性!!!

上一篇:mysql-innodb的事务日志


下一篇:【DB笔试面试750】在Oracle中,请简单描述DG的架构。