(1)InnoDB的重要内存结构:缓冲池
存储引擎有一个非常重要的放在内存里的组件,就是缓冲池(Buffer Pool),这里会缓存很多的数据,以便于以后在查询的时候,内存缓冲池里有数据,就可以不用去查磁盘了;
比如执行更新 update users set name=”xxx” where id=10,比如id=10,先将id=10这一行数据看看是否在缓冲池里,如果不在的话,那么会直接从磁盘里加载到缓冲池里,而且会对 这行记录加独占锁,因为我们在更新id=10这一行数据时,肯定是不允许别人同时更新的,所以必须对这行记录加锁。
(2)undo日志文件,如何让你更新的数据进行回滚?
假设 id=10 这行数据的name原来是“zhangsan”,现在我们更新为“xxx”,那么我们需要把原来的值“zhangsan”和 “id=10”信息写入到undo日志文件里去,如果我们执行更新一条语句,加了事务的话,在事务提交之前是可以进行事务回滚的,也就是把你更新为“xxx”的值回滚到之前的“zhangsan”,所以考虑可能会回滚数据的需要,这是会把你的更新前的值写入undo日志文件。
(3)更新buffer pool中的缓存数据
当我们把要更新的那行记录从磁盘文件加载到缓冲池,同时对他加锁之后,还要把更新前的旧值写入undo日志文件之后,我们就可以正式更新这行记录了,更新的时候,先是会更新缓冲池中的记录,此时这个数据是脏数据,因为磁盘上“id=10”这行数据的name字段还是“zhangsan”,但是内存里这行数据已经被修改了,所以就会叫他脏数据。(缓冲池已经更新的但是磁盘没更新的叫脏数据)
(4)Redo Log Buffer:万一系统宕机,如何避免数据丢失
现在已经把内存里的数据进行了修改,但是磁盘上的数据还没修改,万一此时MySQL所在的机器宕机了,必然会导致内存里修改过的数据丢失,那么该怎么解决呢? 这个时候就需要对内存所作的修改写入到一个 Redo Log Buffer里去,这也是内存里的一个缓冲区,用来存放redo日志的,redo日志就是记录你在缓冲池做了什么操作,比如 你对“id=10”这行记录修改了name字段的值为“xxx”,这就是一个日志。这个日志的作用就是用来在MySQL突然宕机的时候,用来恢复你更新过的数据的。
(5)如果还没提交事务,MySQL宕机了怎么办?
到目前为止还没有提交事务,那么此时如果MySQL崩溃,必然会导致内存里Buffer Pool中的修改过的数据都丢失,同时你写入Redo Log Buffer的redo日志也会丢失,此时数据丢失数据紧要嘛?其实是不要紧的,因为更新一条数据没提交事务,就代表它没执行成功,此时MySQL宕机虽然内存里的数据都丢失了,但是磁盘上的数据还是修改之前的值。所以此时宕机问题不大。(没提交事务MySQL崩溃,此时丢失数据不要紧)
(6)提交事务的时候将redo日志写入磁盘:
此时我们更新了数据后想要提交数据,就会根据一定的策略把redo日志从redo log buffer里刷入到磁盘文件里去,
这个策略通过 innodb_flush_log_at_trx_commit来配置的:
innodb_flush_log_at_trx_commit=0,当你提交事务的时候,不会把redo log buffer里的数据刷入到磁盘文件,此时可能你提交了事务,结果MySQL服务器宕机,导致内存中的数据和redo日志都丢失了。该模式下在事务提交时不会主动触发写入磁盘的操作。
innodb_flush_log_at_trx_commit=1,当你提交事务的时候,就必须把redo log buffer的日志从内存刷入到磁盘文件里去,只要事务提交成功,那么redo log就必然在磁盘里,哪怕此时buffer pool中更新过的数据还没刷新到磁盘里,此时磁盘还是“name=zhangsan”,然后MySQL服务器突然宕机,此时数据会丢失嘛?不会,他会根据redo日志去恢复之前做过的修改。
innodb_flush_log_at_trx_commit=2,当你提交事务的时候,把redo日志写入到磁盘文件对应的(os cache)系统缓存里去,而不是直接写入磁盘文件,可能1秒后才会把os cache里的数据写入磁盘,这种模式下,redo log可能仅仅停留在os cache缓存里,没实际进入磁盘文件,万一此时机器宕机,那么丢失的就是os cache里的redo log的1秒日志。
对于上述的刷盘策略,通常是设置成1;
3种策略:
根据业务需求如果必须保证数据不能丢失同时容忍TPS不是很高这种情况,可以使用策略1,如果业务上允许丢一部分数据而去追求极高的性能,选择使用策略0,当然还有一种策略是两者之间的一个情况,MySQL如果宕机可能会丢一小部分数据,但是性能影响不大,选择使用这种。当然我们使用关系型数据库的原因就是保证数据完全不能丢失。