java学习(九)
1、MySQL的日志模块binlog和redo log有了解吗?
在MySQL的使用中,更新操作也是很频繁的,如果每一次更新操作都根据条件找到对应的记录,然后将记录更新,再写回磁盘,那么IO成本以及查找记录的成本都很高。所以,出现了日志模块,即我们的update更新操作是先写日志,在合适的时间才会去写磁盘,日志更新完毕就将执行结果返回给了客户端。
MySQL中的日志模块主要有redo log(重做日志)和binlog(归档日志)。
redo log:
redo log是InnoDB引擎特有的日志模块,redo log是物理日志,记录了某个数据页上做了哪些修改。InnoDB的redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,那么redo log总共就可以记录 4GB的操作。从头开始写,写到末尾就又回到开头循环写。
InnoDB的redo log保证了数据库发生异常重启之后,之前提交的记录不会丢失,这个能力称为crash-safe。
binlog:
binlog是Server层自带的日志模块,binlog是逻辑日志,记录本次修改的原始逻辑,说白了就是SQL语句。binlog是追加写的形式,可以写多个文件,不会覆盖之前的日志。通过mysqlbinlog可以解析查看binlog日志。binlog日志文件的格式:statement,row,mixed。
- statement格式的binlog记录的是完整的SQL语句,优点是日志文件小,性能较好,缺点也很明显,那就是准确性差,遇到SQL语句中有now()等函数会导致不准确
- row格式的binlog中记录的是数据行的实际数据的变更,优点就是数据记录准确,缺点就是日志文件较大。
- mixed格式的binlog是前面两者的混合模式
业界目前推荐使用的是 row 模式,因为很多情况下对准确性的要求是排在第一位的。
2、为什么MySQL会突然变慢一下?
当内存数据页和磁盘数据页内容不一致的时候,这个内存页就是“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,这个时候的内存页就是”干净页“。
前面我们介绍了更新数据库的时候是先写日志,当合适的机会(空闲)出现的时候才会更新磁盘。但是当redo log 写满了,要 flush 脏页,也就是把内存里的数据写入磁盘,会导致MySQL执行速度突然变慢一瞬间。
3、MySQL事务有哪些特性?
事务是单个逻辑工作单元执行的一系列操作,是一个不可分割的工作单位。满足如下的四大特性:
- 原子性(Atomicity):事务作为一个整体被执行 ,要么全部执行,要么全部不执行;
- 一致性(Consistency):保证数据库状态从一个一致状态转变为另一个一致状态;
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行;
- 持久性(Durability):一个事务一旦提交,对数据库的修改应该永久保存
4、如果不做控制,多个事务并发操作数据库会产生哪些问题吗?
- 丢失更新:
两个不同事务同时获得相同数据,然后在各自事务中同时修改了该数据,那么先提交的事务更新会被后提交事务的更新给覆盖掉,这种情况先提交的事务所做的更新就被覆盖,导致数据更新丢失。
- 脏读:
事务A读取了事务B未提交的数据,由于事务B回滚,导致了事务A的数据不一致,结果事务A出现了脏读;
- 不可重复读:
一个事务在自己没有更新数据库数据的情况,同一个查询操作执行两次或多次得到的结果数值不同,因为别的事务更新了该数据,并且提交了事务。
- 幻读:
事务A读的时候读出了N条记录,事务B在事务A执行的过程中增加 了1条,事务A再读的时候就变成了N+1条,这种情况就叫做幻读。
5、MySQL中的锁机制?
ySQL数据库的锁分为表级锁和行级锁。从数据库的角度看,行级锁又可以分为独占锁和共享锁。
独占锁(排他锁),也称X锁(Exclusive Lock):
独占锁锁定的资源只允许进行锁定操作的程序使用,其它任何对它的操作均不会被接受。执行数据更新命令,即INSERT、UPDATE 或DELETE 命令时,MySQL会自动使用独占锁。但当对象上有其它锁存在时,无法对其加独占锁。独占锁一直到事务结束才能被释放。
在select命令中使用独占锁的SQL语句为:select … for update;
共享锁,也叫S锁(Shared Lock):
共享锁顾名思义,那就是其锁定的资源可以被其它用户读取,但其它用户不能修改。如果在select查询语句中要手动加入共享锁,那么对应的SQL语句为:select ... lock in share mode
6、MySQL的死锁该如何解决?
我们可以在业务上和数据库设置上来解决MySQL死锁。分别介绍如下:
业务逻辑上的死锁解决方案:
- 指定锁的获取顺序
- 大事务拆分成各个小事务
- 在同一个事务中,一次锁定尽量多的资源,减少死锁概率
- 给表建立合适的索引以及降低事务的隔离级别等
数据库的设置来解决死锁:
- 通过参数 innodb_lock_wait_timeout 根据实际业务场景来设置超时时间,InnoDB引擎默认值是50s。
- 发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑(默认是开启状态)。
7、悲观锁与乐观锁
悲观锁:利用数据库的锁机制实现,在整个数据处理过程中都加入了锁,以保持排他性。
乐观锁:乐观锁可以利用CAS实现,在操作数据的时候进行一个比较,按照当前事务中的数据和数据库表中的该数据是否一致来决定是否要执行本次操作。
8、乐观锁的ABA问题有了解吗?如何解决?
ABA问题是指在当前事务读取该行数据时是A,经过别的事务修改成B,但是在当前事务要更新数据的时候,该行数据又被别的事务修改为A,事实上数据行是发生过改变的,存在并发问题。
ABA问题可以通过基于数据版本(Version)记录机制来解决。也就是为数据增加一个版本标识。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。根据当前事务的数据版本号和数据库中数据的版本号对比来决定是否更新数据。
与给当前数据增加一个数据版本类似,我们也可以增加基于时间戳机制来解决ABA问题,通过时间戳来记录当前数据行变化。
根据相关面试及学习进行归纳总结