(1)Buffer Pool在访问的时候需要加锁嘛?
假设MySQL同时接收到多个请求,它自然会用多个线程来处理多个请求,每个线程会负责处理每个请求,那多个线程同时访问Buffer Pool去操作里面的缓存页,同时操作一个free表,flush表,lru表,如果多个线程并发访问这个Buffer Pool,此时他们都是在访问内存里的一些共享的数据结构,比如缓存页,各种链表之类的,那此时必然要进行加锁。
多线程并发访问一个Buffer Pool,必然是要加锁的,然后让一个线程先完成一系列操作,比如说加载数据页到缓存页,更新free链表,更新lru链表,然后释放锁,下一个线程开始操作。
(2)多线程并发访问加锁,数据库性能还好吗?
应该说一个Buffer Pool,即使多个线程加锁串行排队执行,其实性能也不算太差,大部分情况下,每个线程都是查询或者更新缓存页里的数据,这个操作是发生在内存的,基本都是微秒级别,可能执行磁盘IO后面排队的线程多多等会,但是还是会很快。
(3)MySQL的生产化经验:多个Buffer Pool优化并发能力
一般来说,MySQL默认的规则是,如果你给Buffer Pool分配的内存小于1GB,那么最多只会给你1个Buffer Pool,但是如果你的机器内存很大,那么必然会给Buffer Pool分配较大的内存,比如分配8个GB内存,那么可以同时设置多个Buffer Pool。
比如服务端配置如下:
innodb_buffer_pool_size=8589934592
innodb_buffer_pool_instances=4
就是给Buffer Pool设置了8GB的总内存,然后设置了它有4个Buffer Pool,也就是每个Buffer Pool的大小是2GB,MySQL在运行的时候就会有4个Buffer Pool,每个Buffer Pool负责一部分的缓存页和描述数据块,有自己独立的free,flush,lru等链表。
一旦有了多个Buffer Pool之后,多线程并发访问的性能就会成倍的提升,多个线程可以在不同的Buffer Pool中加锁和执行自己的操作,并发的执行。
多个Buffer Pool 出现的问题:
虽然加多了 buffer pool的数量,但是buffer pool的东西实际缓存的东西却增大了4倍,如果要查一个相同的东西4次,不巧的是正好分配到4个不同的buffer pool 这个数据就要被缓存4次。 另外,假如某一个buffer pool的值更新了,还需要同步到其他buffer pool中,涉及到的pool间同步是如何实现的呢?其实可能是会维护一个 hash表的,不同的线程申请操作的buffer pool使用hash表维护,再次使用时直接根据hash表去找它在那个buffer pool里。
其实是分布式的概念,应该有个分布式id,查询唯一落入的哪一个 buffer pool。
增加buffer pool是为了提高并发性能,但是增加了buffer pool之后,从磁盘加载数据,可能会出现一样的数据被加载到多个buffer pool里面,这样就不好了,所以MySQL服务器可能使用了一致性hash算法之类的,同一个线程申请操作只会到同
一个buffer pool取数据,这样就不会同一个数据被加载到多个buffer pool里了。
如何查看Buffer Pool大小,buffer pool数量,chunk大小?
SHOW VARIABLES LIKE ‘%innodb_buffer%’;
公式是要保证 每个 buffer pool的实例都由相同数量的整数个chunk组成,
例如 512832 =20GB 每个chunk 128MB,每个buffer pool里有5个chunk实例,总共32个实例。