[提前声明]
大数据代码案例地址: https://github.com/Mydreamandreality/sparkResearch
原文注:MySQL5.5提供新API 支持线程池插件 复用池中少量的线程来服务大量的连接
此处的并发控制指的是服务器与存储引擎两个层面的控制
场景:一张表,一条数据
同时写入
同时读:无任何影响,因为读不修改数据,但此时我在读取该数据,你在删除该数据
解决以上问题的方法:并发控制:
锁的概念:
注:在Mysql中,每时每刻都发生锁定,当某个用户在修改一部分数据时,MySQL会通过锁定防止其他用户读取同一数据,大多数时候,MySQL锁的内部管理都是透明的
提高共享资源并发性的方式就是让锁定对象更优选择性,尽量只锁定需要修改的数据,而不是所有资源,任何时候,给定的资源中,锁定的数据量越少,系统的并发程度越高
注:加锁也需要消耗资源,获得锁,检查锁状态,释放等,都会增加系统开销,如果系统花费大量的时间来管理锁,而不是存取数据,那么系统数据可能会受到影响
所谓的锁策略,就是在锁的开销和数据的安全性之间寻求平衡,这种平衡当然会影响到性能
MySQL提供多种选择,不同的存储引擎都可以实现自己的所策略和锁粒度
MySQL中两个重要的锁策略:
表锁
行级锁
注:锁只在存储引擎层实现,MySQL服务器层没有实现,并且完全不了解存储引擎中锁实现
注:这些是数据库的通用基础,如果了解,建议直接略过
事务是一组原子性的SQL查询,独立的工作单元
如果能成功的执行工作单元内的全部语句,那么就执行,否则的话,如果有任何一条语句因为崩溃或者其它问题无法执行,那么工作单元内的所有语句都不会执行
简单来说,要么全部执行成功,要么全部执行失败
事务ACID
A:atomicity 原子性
C:consistency 一致性
I:isolation 隔离性
D:durability 持久性
原子性:
一致性:
隔离性:
持久性:
在SQL的标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的,较低级别的隔离通常可以执行更高的并发,系统的开销也更低
注:每种存储引擎实现的隔离级别不一定相同
核心就是不同的锁粒度,配合锁粒度来理解
READ UNCOMMITTED (未提交读)
READ COMMITED(提交读/不可重复读)
REPEATABLE READ(可重复读)(MySQL默认级别)
SERIALIZABLE(可串行化)
死锁是指两个或者多个事务在同一资源上互相占用,请求锁定对方占用的资源,从而导致恶性循环的现象,当多个事务试图以不同的顺序锁定资源时,就可能会产生死锁
案例:
事务A:
update ... where id =1
update ... where id =2
事务B:
update ... where id =2
update ... where id =1
如果凑巧,两条事务都执行了第一条更新语句,同时锁定当前数据,接着两个事务都尝试去执行第二条语句,却发现被锁定,然后两个事务都等待对方释放锁,同时又持有对方需要的锁,陷入死循环,此时除非有外部因素介入才可能解除死锁
为了解决这种问题,数据库实现了各种死锁检测和死锁超时机制
解决方案:
当查询的时间达到锁等待超时的设定后放弃锁请求
InnDB处理死锁的方法是:将持有最少行级排它锁的事务进行回滚,就能避免死锁
注:死锁发生后,只有部分或者完全回滚其中一个事务,才能打破死锁,对于事务性的系统,这是无法避免的
事务日志可以提交事务的效率,使用事务日志,在修改表的数据时,只需要修改内存拷贝,再把修改行为记录到持久在硬盘上的事务日志中(binlog),而不用每次豆浆修改的数据本身持久到磁盘,事务日志采用的是追加的方式,因此写入日志的操作是磁盘上的一小块区域内的顺序IO,不是随机IP需要在磁盘的多个地方移动磁头,所以采用事务日志的方式相对来说要快得多,事务日志持久之后,内存中被修改的数据在后台可以慢慢的刷回到磁盘,(预写式日志),修改数据需要写两次磁盘
如果数据的修改意见记录到日志并持久化,但数据本身还没有写回磁盘,这个时候系统崩溃了,存储引擎在重启时,能够自动恢复这部分修改的数据,具体恢复方式视存储引擎而定