mysql 事物浅析

755 查看

事物是什么?

书上说:事物作为一个不可分割的逻辑单元而被执行的一组sql语句,如果有必要,他们的执行效果可以被撤销。
我的理解:上面的这段话是《mysql技术内幕》对事物所下的定义。好高大上的样子,似乎不怎么看得懂!个人的观点是事物是一种机制,这种机制能够保证在一组的sql语句要么都成功执行、要么都不执行!

事物这么好,是否都支持?

答案是是否定的,和mysql的存储引擎有关。目前只有innodb、fclcon存储引擎支持,myisam 、memory存储引擎都不支持事物

事物的具体技术细节

1、事物而言有两种模式,自动提交模式(默认的模式)和非自动提交模式!

什么是自动提交模式?

这种模式会在每一条语句执行完之后把它作出的修改立刻提交给数据库,并使之永久化!事实上,这相当于把每一条语句当做一个事物来执行!

个人理解:由于在自动提交模式下,每执行一条sql语句都会被当做一个事物自动提交或者回滚,这样话,我们就不能保证一组sql的语句成功的提交或者回滚了。怎么办呢?这就提提现出来了start transactioin的作用了。

 start transaction的主要作用,就是挂起自动提交模式。所谓挂起自动提交模式,就是当我们明确的使用了commit语句时才将修改永久的写入数据库。

什么是非自动提交模式?

任何的语句(其中一些语句例外,如start transaction……,也就是隐式提交事物的那些语句除外)都将成为该事物中的一部分,直到你发出一条commit语句或者rollback语句来提交或者撤销它为止!

举例说明:

此时还没有进行commit,开启另外一个窗口进行查询:

直到A窗口明显是进行了commit之后,在B窗口才真正的出现了添加的 数据!

2、事物的隔离性

所谓事物的隔离性就是指:一个事物何时才能看到另外一个事物所作出的修改。
由于隔离级别的不同可能会出现各种各样的问题,常见的问题如下:
脏读:A事物在修改完一条数据,还没有进行提交,而B事物已经读取到了该条数据
幻读:A事物插入一条数据,还没有commit,而B事物已经独到了新增的这条数据

综上所述,究其原因是因为,B事物读到了其他事物还没有提交的数据。为了解决上述的一些问题,mysql的innodb引擎提供了4个事物的隔离级别?、

READ UNCOMMITED 允许某个事物看到其它事物尚未提交的数据改动!
READ COMMITED 只允许事物看到其他事物已经提交过的数据改动!
REAPEATABLE READ 顾名思义是可重复读的意思,如果事物执行了统一条select语句,其结果是相同的,即使有其他事物在同时插入或者修改该数据行看到的结果也是一样的!这个是mysql的默认隔离级别!这里我们重点说一下!

举例说明:
a、同事打开A和B两个窗口,查看事物的隔离级别,两个事物的隔离级别都是可重复读!

b、BankAccount表中的建表语句和初始数据如下:

c、A、B窗口中同时挂起自动提交!

d、在A、B窗口分别执行如下操作!

通过上面的实验我们可以知道,即使是A窗口已经commit了,那么B窗口读到的仍然是start transaction之前的数据,并没有读到commit之后那两条新增加的数据

SERIALIZABLE,这个隔离级别同REAPEATABLE READ非常的相似,但是对事物的隔离更加的彻底,某个事物证在读去的数据时不允许其他事物进行修改的,知道该事物完成时候!(个人认为和加上了写锁的效果类似)

3、哪些sql语句会隐式的提交当前事物呢?

上面的我们有所过有些语句是不能放在事物中的,它会隐式的提交当前事物,比如之前提到的事物的嵌套,start transaction 中又进行了start transaction

一般来说下面几个方面的语句是会隐式的提交当前事物的:
DDL(Data Defined Language)语句:好专业的样子,其实就是数据的定义语句,常见的有:
create databases(创建数据库)
drop databases(删除数据库)
create table (创建表)
drop table(删除表)
alter table (修改表结构)
rename table (为表重命名)
truncate table(清空表)
create index(创建索引)
drop index(删除索引)

此外关于锁定和解锁的相关操作也会提交当前事物:
lock tables(锁定表)
unlock tables(解锁表)

主要参考文献

《mysql技术内幕》

以上的观点,如有纰漏清高手不吝赐教!