事务是指将一个业务流程中对数据库的多次操作绑定在一起,使其成为一个最小的执行颗粒,当这些操作中某一个失败了,整个流程也会失败,这样做能防止数据库数据不一致等问题.
事务有以下几个特征(ACID):
原子性(A: atomicity)
一个事务是一个最小的执行颗粒,不可再分,整个事务要么都成功,要么都失败.一致性(C:consistency)
<没理解,感觉更像是原子性的一个补充>隔离性(I:isolaton)
一个事务在未提交前对其它事务都是不可见的,其它事务不能访问未提交事务修改的数据.持久性(D:durability)
一旦事务提交,其所作的修改都会持久保存下来.
在数据库中,实现了ACID的数据库比未实现了要消耗更多的CPU 和硬盘资源.
在mysql中,可以通过对autocommit
参数的修改来开启或者关闭自动提交,当其为0时表示关闭自动提交,这时候在执行sql语句时需要手动在末尾执行commit
或rollback
来提交或者回滚事务.修改autocommit
参数的方式为set autocommit=0;
另外,还可以在执行语句前加上start tranaction;
来开启一个事务,其优先级大于autocommit
,即使autocommit
为1,也会开启事务.
1.3.1 事务的隔离级别
在数据库中有如下四种隔离级别:
read uncommitted(未提交度)
是指读取其它事务未提交的数据,这样会造成造成脏读,因为可能会读取到其它事务最终回滚掉的垃圾数据或者未处理完成的数据.read commit(提交读)
每次读取到的都是其它事务提交的数据,这样有个问题是会造成在同一个事务中多次对同一个数据读取,由于在读取期间其它事务对同一条数据进行了修改提交,这样会造成同一个数据库中的多次读取数据不一样,即不可重复读.repeatable read(可重复读)
此级别保证了在同一个事务中的多次读取到的数据都是相同的,但这样会出现幻读,它是当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
可重复读是mysql默认的事务隔离级别,其使用了MVCC解决了幻读的问题.serializable (可串行化)
此界别是将事务的执行全部串行化,既禁止对同一个数据的并发读取,主要是使用锁来实现.此级别是最高隔离界别,会出现大量的锁的争用和超时问题,只有在确保数据一致性和可以接受没有并发的情况下才考虑用户此级别.
隔离级别 | 脏读可能性 | 不可重复读可能性 | 幻读可能性 | 加锁读 |
---|---|---|---|---|
read uncommitted | yes | yes | yes | no |
read commit | no | yes | yes | no |
repeatable read | no | no | yes | no |
serializable | no | no | no | yes |
1.3.2 死锁
死锁是指当多个事务在同一个资源上相互占用,并请求锁定对方占用的资源,从而导致的恶性循环现象.例如:
- 事务 1
start stranaction;
update user set user_name ='A' where user_id=1;
update user set user_name ='B' where user_id=2;
commit;
- 事务 2
start stranaction;
update user set user_name ='C' where user_id=2;
update user set user_name ='D' where user_id=1;
commit;
在上面的两个事务中,若两个事务都执行了第一个update
语句,这时候这两行数据都被锁定,这时候再执行第二个update
语句,就会出现死锁现象.
在mysql的innodb中处理死锁的方式是当检测到死锁发生时,将持有最少行级排它锁的事务进行回滚.对于事务性数据库,死锁是无法避免的.
1.3.3 事务日志
事务日志是在事务数据库中,一次事务的操作修改的是数据表的内存拷贝部分,然后在提交数据后,数据库再将这部分数据拷贝写到数据库中,既对数据表的一次修改操作设计的是硬盘的两次读写.当数据拷贝时突然发生断电,下次再启动时,数据库会再从缓存中将数据拷贝到数据表中,目前mysql采用的是这样的方式.
1.3.4 mysql中的事务
msyql中提供了两种事务型数据库引擎: Innodb 和 NDB Cluster.
- 自动提交
在mysql中autocommit
是默认开着的,即默认自动提交,可以使用下面命令查看
show variables like 'autocommit
可使用set autocommit=1
来修改其状态.
mysql 可以通过以下命令修改隔离级别
set session tranaction isoltion level <read committed>