闲话MVCC
2015-10-14 01:28
513 查看
为什么需要事务
其实和我们需要锁是一个道理。因为我们业务上的一个逻辑操作单元Tx_A,对应的是多个计算机指令。我们需要一种机制来确保在Tx_A操作执行期间,其内部状态不可以被外界观测到。如果外界访问,要么阻塞等待直到该操作结束。要么直接返回告诉它,“Sorry ,I’m busy now”。事务就是这样一种机制。做数据库的大神说,“得了,您也别自己去实现这样一种机制了,就我实现得了。你们会用就行,免得一大堆bug”,所以事务的出现使得我们能更好focus在我们的业务上。而不用自己去实现事务等价一套APIs。
事务是一个说明性的概念,这个概念用来表述你想要达到什么样的效果。
Mysql对外暴露的事务APIs如下:
1.事务的开始START TRANSACTION
BEGIN
2.事务提交
COMMIT
3.事务回滚
ROLLBACK
ANSI/ISO isolation(隔离级别)
一言以蔽之,隔离级别是事务之间可见性的定义。1. 可序列化(Serializable)
可序列化涉及到范围锁(主要是用于解决聚集查询),所以没有幻读问题。2.可重复读(READ-REPEATABLE)
在可重复读取(REPEATABLE READS)级别下,数据库系统会在整个事务期间保持读取锁和写入锁。但相较于可序列化,范围锁不会持有,所以幻读可能会出现。Ps:MySQL的MVCC兼容此隔离级别,并且避免了幻读问题。
3.不可重复读(READ-COMMITTED)
在READ COMMITTED级别下,整个事务期间保持写入锁,但读取锁会在SELECT执行之后立即释放。所以也称为NON-REPEATABLE READ。4.读未提交(READ-UNCOMMITED)
在此隔离级别下,脏读可能会出现。Ps:此处需要注意脏读含义的理解。
事务A如果可以看见其它事务的中间状态,那么就是脏读。换句话说,一个事务能看见的数据,要么在其它事务开始之前,要么是之后。事务是将数据库状态从某个一致的状态,变成另一种一致的状态。
小结
以MySql为例,大多数应用采用的隔离级别为REPEATABLE READ,所以SELECT读到的数据可能不是目前最新的(可见性?)。其实对大多数业务来说都OK,因为大多数业务并不要求全局的happen-before关系,而只要求某几个操作之间有。
MVCC
以隔离级别「READ-REPEATABLE」为例,按照上面「读写锁」的实现,那么读写依然是冲突的,能不能达到读写也不冲突呢?毕竟人类对性能的追求是无止境的。答案是肯定的。其思想上和Java的CopyOnWriteArrayList极为类似。简单来说
就是通过”volatile+写锁”实现。这样就可以实现
读写不互斥(通过volatile);
还是以经典的Bob给Simith转账100刀为例.
事务A
start
update account set balance=balance where id=’bob’ and balance >=100
commit;
事务B
start;
select balance where id=’bob’
commit;
现在假设事务A和事务B并行执行,照例说事务B,应该会等事务A提交时候( 提交会释放锁),之后才会读到bob账户余额,事实上由于读余额时,并不会尝试获取写锁,所以无需等待。所以读写不互斥。
Ps:肯定有同学会疑惑,这样不就是读得不是最新的了嘛?的确,这样读到的数据不是最新的,但是为什么需要读到最新的呢,对大多读事务场景,并不需要读到最新值啊,如果是写事务的话,那么对业务属性是否满足更新条件,必须放在update的where子句中,而不能先select后update,当然,对大多数应用,先selelct 如果(不)满足,然后(不)更新,如果大多数条件都不用更新,那么这么写,可能会有性能优化,毕竟select 无锁,update可是必须要锁的。
显示锁
隐式锁
select 隐式获取与释放读锁写时复制(COW(Copy-On-Write))的
参考资料
關係數據庫的事務隔離、鎖定與並發控制海量数据-事务一致性2
相关文章推荐
- MySQL中的integer 数据类型
- MySQL存储过程
- mysql中int、bigint、smallint 和 tinyint的区别与长度
- mysql load data 导出、导入 csv
- source命令执行SQL脚本文件
- MySQL创建用户及权限控制
- MySQL管理数据表
- linux下mysql添加用户
- mysql procedure
- mysql触发器
- MySQL 备份和恢复策略
- mac下安装mysql(转载)
- mysql 修改编码 Linux/Mac/Unix/通用(杜绝修改后无法启动的情况!)
- MySQL数据的导出、导入(mysql内部命令:mysqldump、mysql)
- mysql数据行转列
- Linux下修改MySQL编码的方法
- MySQL Server 日志
- MySQL 安全事宜
- MySQL 备份与恢复