1.mysql innodb:
InnoDB下的当前读和快照读:
当前读: select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时 还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。 快照读:不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本。 MVCC就是为了实现读-写冲突不加锁,而这个读指的就是快照读, 而非当前读,当前读实际上是一种加锁的操作,是悲观锁的实现。MVCC模型在MySQL中的具体实现则是由 3个隐式字段,undo日志 ,Read View 等去完成的,具体可以看下面的MVCC实现原理。Mysql的多版本并发控制时,Mysql会自动在表中每一行记录的后面增加两个隐藏列,记录创建版本号和删除版本号;
MVCC就是因为大牛们,不满意只让数据库采用悲观锁这样性能不佳的形式去解决读-写冲突问题,而提出的解决方案,所以在数据库中,因为有了MVCC,所以我们可以形成两个组合:
- MVCC + 悲观锁
MVCC解决读写冲突,悲观锁解决写写冲突 - MVCC + 乐观锁
MVCC解决读写冲突,乐观锁解决写写冲突
这种组合的方式就可以最大程度的提高数据库并发性能,并解决读写冲突,和写写冲突导致的问题
刷盘:落盘可以从3个方向分析
(1)数据:bufferpool中的有个change buffer,也就是”插入缓存“,缓存了二级索引的变更信息,通过合并写入二级索引减少离散IO以提高性能。
刷脏页一般发生在commit之后,redo和binlog提交之后。innodb可以根据脏页在bufferpool中的水位强制刷脏页。Adaptive Flushing根据数据库负载情况调整刷每秒应该刷多少脏页。 (2)binlog日志:
在实际应用中, binlog
的主要使用场景有两个,分别是 主从复制 和 数据恢复 。用于记录数据库执行的写入性操作(不包括查询)信息。
-
主从复制 :在
Master
端开启binlog
,然后将binlog
发送到各个Slave
端,Slave
端重放binlog
从而达到主从数据一致。 -
数据恢复 :通过使用
mysqlbinlog
工具来恢复数据。
binlog日志刷盘可以通过sync_binlog
参数控制 biglog
的刷盘时机。当设置为1时每次commit都需要刷盘,但是会影响数据库性能。
(3)redo log用于数据库的持久化,为了提高数据的写入和更新性能,不是每次insert和update都写盘,这样随机io会降低数据库性能。
为了保证数据不丢失,会刷盘前会先写redo_log,redo_log顺序写性能比较高。同理,redo_log也不是每次commit都直接刷盘,也会先写用户缓冲区,在写入到内核缓冲区后调用fsync()来写盘。控制参数innodb_flush_log_at_trx_commit可以控制是否每次commit都将用户空间的redo_log_buffer中的数据写入到内核缓冲区。
mysql日志双写最重要的参数有2个
1.innodb_flush_log_at_trx_commit刷log buffer的redo_log到log file中。0——每秒刷盘,1——每次commit都刷盘
2.sync_binlog刷binlog cache的事务到binlog文件中。0——不写binlog。1——每次提交都写binlog
2个参数的默认值都是1,表示提交既写log(redolog和binlog都写),也就是mysql日志双写。
undo_log:
原子性 底层就是通过 undo log
实现的。undo log
主要记录了数据的逻辑变化,比如一条 INSERT
语句,对应一条DELETE
的 undo log
,对于每个 UPDATE
语句,对应一条相反的 UPDATE
的 undo log
,这样在发生错误时,就能回滚到事务之前的数据状态。
同时, undo log
也是 MVCC
(多版本并发控制)实现的关键。
每条数据修改(insert、update或delete)操作都伴随一条undo log的生成,并且回滚日志必须先于数据持久化到磁盘上