吸血鬼日记第二季21,群众工作,陈嘉庚的资料
最近买了《高性能MySQL》这本书回来看,从中收益颇多!我来一吐为快!
我们都知道事务,那么在什么情况下我们需要使用事务呢?
银行应用是解释事务的一个经典例子。假设一个银行的数据库有两张表:支票(checking)和储蓄(savings)表。现在johnson要从支票账户中转移200块大洋到储蓄表中,那么至少需要三个步骤:
试想一下,如果上面步骤执行到第二步,突然因为什么原因而终止了,顾客支票账户中莫名其妙的减少了200块大洋。如果顾客恰好是一位情绪激动的大妈,那你就等着大妈带着平底锅和四级头去银行找你吧!
所以为了避免这种情况,就必须用到事务,上述三个步骤中有任何一个执行失败,就必须回滚所有的步骤,以免有大妈找上门。事务SQL如下所示:
事务之所以可靠,当然离不开ACID特性:
细心的人可能会注意到。在讨论隔离性的时候,我用了“通常来说”,下面就让我们讨论下事务的隔离级别。
隔离级别 | 脏读可能性 | 不可重复读可能性 | 幻读可能性 | 加锁读 |
READ UNCOMMITTED | YES | YES | YES | NO |
READ COMMITTED | NO | YES | YES | NO |
REPEATABLE READ | NO | NO | YES | NO |
SERIALIZABLE | NO | NO | NO | YES |
到这里,如果还不是太懂,你需要细细消化下前面的内容,这时可以打开mysql,将隔离级别设置为READ COMMITTED。然后试试它是不是解决了脏读,会不会出现不可重复读?再将隔离级别设置为REPETABLE READ。看看REPETABLE READ是不是解决了不可重复读,会不会出现幻读?
SET session transaction isolation level read committed;
如果你真的实验了,会发现mysql的REPETABLE READ隔离级别并不会出现幻读的现象。那你有没有想过mysql的事务是怎么实现的呢?
你肯定听说mysql的表锁和行锁,那你可能以为事务是基于行锁实现的。其实并没有那么简单,为了提高并发性能,mysql的大多是事务引擎都同时实现了多版本并发控制(MVCC)。它在很多情况下避免了加锁操作,所以开销更低。MVCC大都实现了非阻塞的读操作,写操作也只锁定必要的行。
那么InnoDB中的MVCC是如何工作的呢?其实是通过在每行数据后面增加两个列,一个是创建版本号,一个是删除版本号。里面存储的是系统版本号,你开启一个事务系统版本号就会递增。事务开始时刻的系统版本号就作为事务版本号,用来和查询的每行记录的版本号做比较。下面看下REPETABLE READ隔离界别下,MVCC具体是如何操作的。
保存这两个额外的系统版本号,可以使大多数读操作都不用加锁,这样性能就会更好。但需要额外的存储空间和一些额外的检查工作,这也相当于用空间换时间。
在某些情况下我们还是需要用的锁。InnoDB采用两段锁协议。在事务执行过程中随时都可以加锁,事务提交或回滚时同时释放所有锁。这些锁一般都是隐式锁定,InnoDB会根据需要自动加锁。当然,你也可以通过SQL语句自己加锁:
SELECT ..... LOCK IN SHARE MODE; 乐观锁 SELECT ..... FOR UPDATE; 悲观锁
个人建议,除非你明确知道自己在干什么,否则轻易不要显式加锁,只会事倍功半!!!
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
小白安装登录mysql-8.0.19-winx64的教程图解(新手必看)
Navicat连接MySQL时报10060、1045错误及my.ini位置问题
网友评论