1.什么是MVCC
MVCC 全称Multi-Version-Concurrenct Control,多版本并发控制.MVCC是一种并发控制的方法,一般在数据库管理系统中应用,实现对数据库的并发访问,在编程语言实现事务内存。
MVCC在mysql中InnoDb的实现主要是为了提高数据库并发性能,用更好的方式处理读写冲突,做到即使有读写冲突,也能做到不加锁,非阻塞并发读。
2.快照读和当前读(innoDB)
1.当前读
读取是当前记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的进行加锁操作
2.快照读
像不加锁的select操作就是快照读,即不加锁的非阻塞读,快照读的前提时隔离几倍不是串行级别,串行级别的快照读会退化称当前读,之所以出现快照读的情况,是基于提高并发性能的烤炉,快照读的实现是基于多版本并发控制,即mvcc可以认为mvcc是行锁的一个变种,但它在很多情况下,避免了枷锁操作,降低了开销,基于多版本,即快照读可能读到的数据不一定是数据的最新版本,可能是历史版本。
说白了mvcc就是为了实现读写冲突不加锁,而这个读是快照读而不是当前读,当前读实际上是一种枷锁的操作,是悲观锁的实现。
3.MVCC与当前读,快照读的关系
准确来说,mvcc多版本并发控制是维持一个数据的多个版本,使得读写操作没有冲突。
在mysql中实现mvcc理想概念,我们需要mysql提供具体的功能去实现它,快照读是msql为我们实现mvcc理想模型中的一个具体非阻塞读功能,而相对而言,当前读就是悲观锁的具体实现。
在mysql中 具体实现用undo日志,read view 三个隐式实现的。
4.数据库并发场景有三种
1.读-读 不存在任何问题,也不需要并发控制
2.读-写 有线程安全问题,可能造成事务隔离问题 可能遇到脏读,幻读,不可重复读
3.写-写 有线程安全问题 ,可能造成存在更新丢失问
5 MYSQL锁
1.Mysql里面的锁大致可以分为三种 全局锁、表级锁和行锁
全局锁:全局锁是对整个数据库实例加锁,mysql提供FTWRL(Flush table with read lock)来开启全局锁,当开启全局锁的时候,整个数据库只能进行读操作,数据更新语句,数据定义语句,更新类事务的语句都不能提交。
应用场景: 一般应用在数据库备份的时候,这样只有读操作可以进行
?为什么使用(set global readonly=true),来设置数据库只读,他和全局锁有什么区别 ,如果使用FTWRL在客户端链接出现错误时候,全局锁会自动释放,而set golbal readonly = true 不会释放,导致只读时间长。
为什么不使用mysqldump参数songle-transation,在导出数据之前开启事务,通过mvvc机制保证读取的时候一致性 ? 因为mysql不是所有存储引擎都支持事务,例如MYISAM。
表级锁分为两类锁,表锁和元数据锁(MDL-meta data-lock)
表锁:可以用lock tableName ...read/write进行上锁,客户端断开链接的时候自动释放,也可以通过unlock tables手动释放。
MDL: 无需显示使用,访问表的时候自动带上,主要是DDL语句和DML语句查询更新语句之间进行枷锁,保证表结构更新时,dml等语句阻塞。
应用场景
在DDL更新表的时候,因为需要便利所有表数据,我们执行的时候都比较小心,给DBA来执行当时在ddl小表的时候,如果ddl比较小但是访问量很大,那么使用不当一样会出现问题,在ddl的时候,会增加mdl锁这时,所有查询请求都会阻塞,如果客户端有重试机制,那么请求超时马上会在创建一个session,这时会很快占用满数据库的链接,这时应该给ddl语句增加一个超时时间,如果执行的时间比较长则直接超市断开,不要影响后面的请求。
行锁(Record Locks)
行锁(记录锁),为了某行记录加锁,它封锁该行的索引记录。(select * from table where id = 1 for update),id 为1的记录会被锁住,需要注意的时:id列必须为唯一索引列和主键列,则上述语句中会把行锁退化成间隙锁
间隙锁(Gap Locks)
间隙锁基于非唯一索引,它锁定一段范围内的索引记录,当更新语句更新一定范围的数据时
列入 update user set del_fag = 1 where age > 100 (删除年纪大于100岁的人),这时如果事务的隔离级别设置为可重复读时候,则会增减间隙锁,其他ddl语句无法执行,事务的隔离级别如果时读提交的话,则会成功