数据库锁
数据库锁的分类:
按锁的粒度划分:表级锁,行级锁,页级锁(BDB引擎,页级,表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。)
按锁的级别划分:共享锁、排他锁
按加锁方式分:自动锁(存储引擎自行根据需要施加的锁)、显式锁(用户手动请求的锁)
按操作划分:DML锁(对数据进行操作的锁)、DDL锁(对表结构进行变更的锁)
按使用方式划分:悲观锁(整个过程保守态度,单个线程使用数据过程中一直锁定数据,使用数据库锁机制)、乐观锁(整个过程呈乐观态度,不锁定数据,更新期间会对其他线程进行判断,不使用数据库锁机制,记录数据时间戳或版本即增加字段version)
MyISAM与InnoDB关于锁方面的区别是什么?
MyISAM默认表级锁,不支持行级锁
要模仿表级锁只能在表中放入大量数据后select时,再进行更删改,这时需要等select的读锁释放后,更删改才能完成
表级锁锁住整张表,当对两百万条数据查询时,对其余数据更新,会发现无法操作。
上了共享锁后可以再加共享锁(lock inshare mode),但是无法添加排他锁,添加排他锁后共享锁,排他锁都无法添加。
表级锁和索引无关
适合的场景:
频繁执行全表count语句
对数据进行增删改频率不高,查询非常频繁
没有事务
InnoDB默认行级锁,也支持表级锁 (在对行级上锁时,会对表级上意向锁)
二段锁:加锁解锁分成两个部分进行,会对事务中的数据先统一加锁,事务完成后统一解锁
行级锁会锁住一行,对id=3的数据加排他锁,也可以对id=4的数据加排他锁
、 除了操作id主键索引以外,涉及到的行都会被上共享锁或者排他锁
不用到索引的时候会用到表级锁,当不走索引时,会走表级锁,
共享锁和排他锁的兼容性
上了共享锁后可以再加共享锁(lock inshare mode),但是无法添加排他锁,添加排他锁后共享锁,排他锁都无法添加。
适合的场景:
数据增删改查都比较频繁
可靠性比较高,要求支持事务。
数据库事物的四大特性?
ACID
原子性(Atomic):要么全做要么全不做
一致性(Consistency):数据库数据应满足完整性约束,不论数据怎么操作,都要从一个一致性状态到另外一个一致性状态
隔离性(isolation):多个事务的执行中,一个事务执行不应该影响其他事物
持久性(Durability):一旦一个事务提交,修改永久有效,保证提交可恢复
事务隔离级别以及各级别下的并发访问问题?
事务并发访问引起的问题以及如何避免
更新丢失(更新丢失是指并发下两次更新同时进行,后一次更新覆盖了前一次更新的情况,数据没有保证一致性)-----Read Uncommitted(读未提交:可以读到未提交的内容。最低级别 )mysql所有事务隔离级别在数据库层面上都可以避免
脏读(脏读是读到了别的事务回滚前的脏数据。比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读)-----READ-COMMITTED(读已提交:一个事务只能看到其他并发的已提交事务所作的修改)事务隔离级别以上可避免
不可重复读(事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了)-------REPEATABLE-READ(可重复读:就是专门针对“不可重复读”这种情况而制定的隔离级别,自然,它就可以有效的避免“不可重复读”。而它也是MySql的默认隔离级别。)事务隔离级别以上可避免
幻读(事务A第一次查询得到一行记录row1,事务B提交修改(插入或者删除操作)后,事务A第二次查询得到两行记录row1和row2)---------SERIALIZABLE(可串行化:数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行)事务隔离级别以上可避免
InnoDB可重复读隔离级别下如何避免幻读?(大致了解)
在mysql中,提供了两种事务隔离技术,第一个是mvcc,第二个是next-key技术。这个在使用不同的语句的时候可以动态选择。不加lock inshare mode之类的就使用mvcc。否则使用next-key。mvcc的优势是不加锁,并发性高。缺点是不是实时数据。next-key的优势是获取实时数据,但是需要加锁。
表象:快照读(非阻塞读)----伪MVCC
当前读:加了锁的增删改查语句,读取的是最新版本,读取时保证其他事务无法修改当前事务,update,delete,insert
快照读:不加锁的非阻塞读,不是SERIALIZABLE隔离级别下的select
内在:next-key锁(行锁+gap锁)
gap锁:锁定一个范围不锁定本身,防止同一事物的两次当前读发生幻读 (RR以上支持)
当前读用where条件全部命中,主键索引或者唯一索引不会使用Gap锁,只有记录锁
如果where条件部分命中或者全不中,主键索引或者唯一索引会加Gap锁
gap锁会用在非唯一索引或者不走索引的当前读中
RC、RR级别下的InnoDB的非阻塞读如何实现?(大致了解)
数据行里隐层的DB_TRX_ID(标识最近一次对本行记录做修改的事务id)、DB_ROLL_PTR(回滚指针,通过undo日志完成)、DB_ROW_ID(行号,随着新行插入出现的,会出现在聚集索引中,隐藏主键)字段
undo日志:变更操作后产生,存储老版数据。将修改前的数据拷贝一份到undo日志中,然后修改当前行的DB_TRX_ID加1,DB_ROLL_PTR为undo日志中数据的地址,按照修改时间,从近到远通过DB_ROLL_PTR连接
read view来决定当前事务可看到的版本数据(可能看到的是修改后最新的或者undo日志中的)
后续可能需要看MYSQL源码。