并行与并发根本区别在于是否会竞争共享资源,解决并发问题两个大的方向: 解决资源资源和解决并发问题 。
解决竞争资源
共享资源是引起问题的根本原因,如果将共享资源变为非共享,这样降低了并发问题产生的几率,关系数据库的分库分表,NoSql/NewSql的水平扩展都属于这个思路,MySQL多个buffer pool,JAVA的ConcurrentHashMap等都属于这种思路 。解决竞争资源可以提高效率,但不能根本上解决问题:并发问题还是存在的 。
解决并发问题
可以通过CAS,多版本,悲观锁的方式从根本上解决 。
CAS
CAS可以理解成乐观锁的一种,在数据库层面一般是采用version的方式实施 。应用在写的场景上 。
多版本
多版本的典型用法就是MVCC方式,在各种数据库中被大量采用:主要思路是保留多版本数据,在请求时根据请求时间返回数据 。只能用于读场景 。
Mysql的MVCC仅在RC/RR两种隔离级别下工作:
RC隔离级别: 会对每次请求(select)都重新生成ReadView(记录活跃的Transaction),因此多次请求返回的结果可能不同,所以存在重复读取的问题 。
RR隔离级别:
仅在Transaction第一次访问的时候生成一次ReadView,因此多次请求返回的结果相同,避免了重复读取的问题 。
锁(悲观锁)
锁是解决问题的根本方法,在多写竞争的时候只能采用锁的方式 。mysql的锁分为行锁和表锁,在获取行锁(Share或Exclude)时,会同时在表中加入相应的意向锁(IS,IX),方便在加表锁时判断是否有行级别锁 。
其他
区间锁:在RR隔离界别下,通过二级非唯一索引或区间查询的方式,添加区间锁,防止出现幻读问题 。
Select加锁: RR,RC隔离界别下,默认select不加锁,可通过for update,in share mode等语句显示加锁 。
事务:锁是同事务绑定的,非更新操作(即使是读写事务)不会生成事务id,锁仅在事务释放后才释放 。全表扫描会在所有记录上加锁,并不会在表上加锁 。
其他存储引擎:因为使用MyISAM、MEMORY、MERGE这些存储引擎的表在同一时刻只允许一个会话对表进行写操作,所以这些存储引擎实际上最好用在只读,或者大部分都是读操作,或者单用户的情景下 。
【Mysql Innodb 引擎解决并发问题】
推荐阅读
- 什么是MySQL存储引擎?
- MySQL七种JOIN类型,终于学明白了
- MySQL崩溃-修复损坏的innodb:innodb_force_recovery
- MySQL的select流程
- canal+Kafka实现mysql与redis数据同步
- PHP 开源工作流引擎 V6.0.0 正式版发布
- oracle 和 mysql 自动按照日期备份数据库脚本
- 搜索的基本原理以及搜索引擎和关键词的关系
- MySQL 使用 Mysqldump 备份导入数据导致主从异常
- Docker如何构建mysql主从?