Mysql 学习笔记

  1. mysql 的请求流程为客户端发起请求,进入链接层,这里会进行 mysql 用户密码及权限认证,然后去查询缓存,缓存没有的话通过解析器,优化器查询数据并返回,这里做不做缓存?

  2. 锁机制,从锁粒度来分有表锁,行锁,页锁,从使用方式来分有共享锁和排它锁,其实就是读锁和写锁,从思想上分有乐观锁和悲观锁。

  3. 表锁的话就是锁定整张表,一个用户要写入数据时,需要先获取写锁,这个时候其他用户不能读或者写数据,只有没有锁的时候才能获取读锁。

  4. 行级锁是在存储引擎中实现的,最常用的有 innodb,它不在服务器层实现。

  5. 事务就是一组原子性的 sql 查询,或者说是第一独立的工作单元,说到原子性就不得不说一下 acid,即原子性,一致性,隔离性,持久性。原子性简单来说就是要不全部成功,要不全部失败然后回滚,一致性呢就是从一个一致性的状态转换到另外一个一致性的状态,隔离性的意思是该事务在提交前对其他事务是不可见的,持久性就是当事务提交后,事务所做的修改就被持久储存了下来,就算系统崩溃,被修改的数据也被存储了下来;

  6. 隔离级别在 sql 标准中定义了四个,通常来说,越低的隔离级别代表可以支持更高的并发及更低的系统开销。说到四个隔离级别,分别是未提交读,已提交读,可重复读,可串行化。mysql 的默认隔离级别是可重复读。未提交读的含义就是说我事务还没提交的数据其他事务也是可见的,就像是我打算跳槽,还没跳,其他同事就知道了,这样会遭成脏读,可以理解成我最终没跳,但其他同事以为我跳了,情况不一致;已提交读是大多数数据库的隔离级别,但不是 mysql 的。这个级别的含义就是,一个事务开始时,只能看见已经提交的事务所做的修改,可以理解成别的同事要了解我的在职状态只有我确定离职了才知道,这个级别也叫做不可重复读,因为有时候两次同样的查询,结果是不一样的;可重复读可以解决脏读的问题,但它又有可能造成一个新的问题,幻读,啥意思呢,就是说一个事务在读取某个范围的数据的时候,另外一个事务在这个范围内插入了新的数据,当之前的事务再次读这个范围的数据的时候会产生幻行。innodb 通过 mvcc 解决了幻读的问题,那么什么是 mvcc?可串行化是最高的隔离级别,它解决了上面说的幻读的问题,当然也不会出现脏读,因为它会在每一行读取的数据上加锁,鱼和熊掌不可兼得,当然它的锁开销就很大,容易造成大量超时和锁争用的问题,实际也很少用这个隔离级别。那么总结下就是未提交读容易造成脏读,不可重复读,幻读,不加锁,可串行化这三个读都不造成,但加锁,mysql 默认的隔离级别容易造成幻读,但是通过 mvcc 处理了,已提交读容易造成不可重复读和幻读。

  7. 说到锁,就不得不说一下死锁。死锁是指两个或多个事务在同一资源上互相占用,并请求锁定对方占用资源,从而导致恶性循环的现象。针对这一情况,数据库系统实现了各种死锁检测和死锁超时机制。通常解决方法有两种,一种就是 innodb 这类通过检测死锁的循环依赖,返回一个错误,另外一种就是当查询等待超时的时候,放弃锁请求,这种方法不太推荐。目前 innodb 的死锁处理方式是,将持有最少行级排他锁的事务进行回滚,这是相对简单的死锁回滚算法。

  8. 再来说锁,锁的行为和顺序是和存储引擎相关的,相同的顺序执行语句,不同的引擎,有的会产生死锁,有的不会(这里没再往深研究);死锁的产生原因有两种,一种是真的数据冲突,另外一种是因为存储引擎的实现方式导致的,一般情况下,产生死锁后,回滚部分事务,然后重新执行被回滚的事务即可;

  9. 事务日志可以帮助提高事务的效率,每次修改数据的时候,只需要修改内存拷贝,再把这一行为记录在事务日志中,然后在后台会慢慢写进硬盘中,而不用每次都在硬盘中修改。事务日志是追加的方式,所以在内存中是顺序 io,而不是随机 io,从而要快的多。

  10. 事务的自动提交,mysql 默认是自动提交的模式,可以通过 autocommit 设置是否关闭,1 | on 是启用,0 | off 是禁用。如果不是显式地开始一个事务,则每个查询都会当作一个事务执行提交操作。(建议再看看显式和隐式锁定这部分)

  11. 在一个事务中尽量不要混合使用存储引擎。首先我们知道一点,事务是下层的存储引擎决定的,和 mysql 的服务器层没关系,如果我们混合使用的事务中有一个事务型表和一个非事务型表,正常情况是没问题的,但回滚的时候,事务型表回滚来,非事务型表不会回滚,而且这种情况很难修复,事务的最终结果无法确定。

  12. 接下来说说之前提到的 mvcc,mvcc 可以看作行级锁的一个变种,它减少了很多情况下的加锁操作,从而减少锁开销,它实现了非阻塞的读操作,写操作也只是锁定必要的行。它是通过保存数据在某个时间点的快照实现的。简单讲 innodb 的 mvcc 就是每行记录后面保存了两个列,一个是创建时间,一个是过期/删除时间,当然也不是真的时间,是系统版本号,没新开一个事务,版本号就会递增,用事务开始时候的版本号和查询到的版本号做比较。(简单说了下)

  13. 新概念:间隙锁,它的作用是防止幻读的产生。它不仅锁定了查询所涉及到的行,还对索引中的间隙进行了锁定,以防止幻影行的插入。

89283d98-59ee-e3db-8114-fe0113a06246

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 (CC BY-NC-ND 4.0) 进行许可。