要想知道什么是数据库事务,首先要知道为什么数据库需要事务管理。
要说事务的例子,最简单的就是银行转账,A向B转账100,首先要将A记录中的金额减去100,再将B记录中的金额加上100,这才算是完成一次转账。可是,程序运行中可能出现各种不可控因素,如果在A减去100之后,银行停电或者地震之类的,各种原因导致程序停止,并没有执行对B账户的操作,A减去了100,可是B没有加上。这时候就需要事务管理。
2、事务的四个特性(ACID)是由关系数据库管理系统(RDBMS,数据库系统)来实现的。数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。
数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
二、关于脏读,不可重复读、幻读 1、脏读(DirtyReads) :所谓脏读就是对脏数据(Drity Data)的读取,而脏数据所指的就是未提交的数据。一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条数据是处于待定状态的(可能提交也可能回滚),这时,第二个事务来读取这条没有提交的数据, 并据此做进一步的处理,就会产生未提交的数据依赖关系。 2、不可重复读(Non-RepeatableReads):一个事务先后读取同一条记录,期间另一个事务修改了数据,并且已经commit,所以两次读取的数据不同,称之为不可重复读。 3、 幻读(PhantomReads):一个事务先后读取同一个表,期间其他事务插入了新的数据,并且已经commit,这种现象就称为幻读。 它和不可重复读的区别:不可重复读的重点是修改,幻读重点是新增和修改。 三、隔离级别 既然知道了事务会有脏读,不可重复读和幻读的现象,那就需要去控制他们,所以有了隔离级别。 一般隔离级别有四级: READ UNCOMMITTED:幻读,不可重复读和脏读均允许 如果数据库的隔离级别为REAE UNCOMMITTED, 则其他线程可以看到未提交的数据, 因此就出现脏读。 READ COMMITTED:允许幻读和不可重复读,但不允许脏读 如果数据库隔离级别设为READ_COMMITTED,即没提交的数据别人是看不见的,就避免了脏读.但是,正在读取的数据只获得了读取锁,读完之后就解锁,不管当前事务有没有结束,这样就容许其他事务修改本事务正在读取的数据。导致不可重复读。 REPEATABLE READ:允许幻读,但不允许不可重复读和脏读 REPEATABLE READ因为对正在操作的数据加锁,并且只有等到事务结束才放开锁, 则可以避免不可重复读。 SERIALIZABLE:幻读,不可重复读和脏读都不允许 SERIALIZABLE因为获得范围锁,且事务是一个接着一个串行执行,则保证了不会发生幻读。 隔离级别脏读可能性不可重复读可能性幻读可能性加锁读READ UNCOMMITTEDYES YES YES NOREAD COMMITTEDNOYES YES NOREPEATABLE READNONOYES NOSERIALIZABLENONONOYES 所以说, READ UNCOMMITTED级别最低, SERIALIZABLE级别最高。 级别越高肯定对于维护事务的四个特性就越好,但是它牺牲的是数据库的效率,因为 SERIALIZABLE的实现是类似于java中的线程锁。 ORACLE默认的是 READ COMMITTED,默认事务管理是开启的,使用DML语言对数据操作需要提交(commit),出错后可以回滚(rollback)。 MYSQL默认的是 REPEATABLE READ,事务默认自动提交,若想开启事务,使用set autocommit 命令。Mysql提供了两种事务型的存储引擎:InnoDB和NDB Cluster.通过执行SET TRANSACTION ISOLATION LEVEL 设置隔离级别。新的隔离界别会在下一个事务开始时生效,也可以在配置文件中设置整个数据库的隔离级别。
mysql>SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
1.InnoDB采用的是两阶段锁定协议。事务执行过程中,随时都可以锁定,在执行COMMIT或者ROLLBACK的时候才会释放。InnoDB还会根据隔离级别在需要的时候自动加锁。
2.InnoDB也支持通过特定的语句进行显示锁定。
SELECT XXX LOCK IN SHARE MODE
SELECT XXX FOR UPDATE
MYSQL也支持LOCK TABLES 和UNLOCK TABLES,这是服务器层实现的,和存储引擎无关。