一 MySQL默认采用自动提交(autocommit)
注意,MySQL的innodb引擎支持事务,MyISAM不支持。对于innodb而言,每一条“sql+分号”+回车后,就相当于封装了一个事务,即以下的第一种方式实质上就是第二种方式:
第一种:
第二种:
一言以蔽之 —— Innodb的每一条sql都默认是自动提交的事务。
则就有了这样的推论:采用Innodb引擎的默认情况下(autocommit为真),客户端向服务器的请求都被封装成了事务的形式,而这也引出了很有趣的一个问题:
我们对表的增删改查sql真的都持久化到硬盘中了吗?
答案:并没有。
看下个点。
二 事务日志
这段文字涉及到“内存拷贝”这个知识点,这里简单介绍。
数据库中的数据(包括索引)都是在硬盘中的,对表的修改是通过磁盘 —— 内存的I/O来实现的,最小单位为固定的16K,即计算机每次将磁盘中需要的数据库数据调入内存(一页16K),如上例sql查询:
其实是从磁盘中调入内存之后显示的(更具体的是,将student表从硬盘调入内存???),那么如果现在进行更新操作,如:
首先,这里的update会被封装成事务,然后尝试对原来的 id为1,name为Tom的记录进行修改,但这里的修改不是直接去硬盘中修改(或者说将内存中的拷贝修改完了立马持久化到硬盘中),从上面的说明中可以看到,Innodb采用这样的策略:
①.修改内存中的拷贝数据
②.将update事务的行为(相当于DML和DCL日志)记录到事务日志中
③.慢慢地(分摊到系统较为空闲的时间段内)将内存中的拷贝数据刷回硬盘
这其中涉及到两个注意的地方(图中用星号表示):
两次写硬盘:一次持久化事务日志,一次将内存拷贝刷回硬盘。
如果第二次写硬盘过程中发生掉电,则没有关系,下次开机从利用事务日志的记录重新持久化即可。
这里顺便补充一下:
如果第一次持久化(写硬盘中的事务日志)过程中发生掉电怎么办?
封装成事务的前提是:只有事务持久化完成了才会返回成功,换言之,如果事务持久化过程中发生掉电,则:
这条语句将会返回失败,回头再看掉电之前的数据变化:其实就仅仅次改了内存拷贝而已,硬盘中数据没有任何变化(事务日志都没搞完),这和外部结果——sql执行失败是一致的,符合逻辑。
同理,如果在修改内存拷贝过程中掉电,则更不用说,外部sql执行失败(这个事务的第一步都没完成),内部硬盘中的数据也没有发生任何改变。OK。