Mysql事务以及特性

事务(transaction),是一个操作序列。这些操作要么都做,要么都不做。

事务有四个特性,即ACID。

Atomicity(原子性),指一个事务是一个不可分割的工作单位,其中的操作要么都成功,要么都失败,不能存在部分成功或者部分失败的情况。如果事务中一个SQL语句执行失败,则已执行的语句也必须回滚,数据库退回到事务前的状态。

InnoDB保证原子性是通过redo log以及undo log来进行的。在InnoDB中,redo log是以512字节进行存储的,正好是磁盘页大小,因此写入是原子性的,不需要额外的机制进行保证。

redo log文件内容是以顺序循环的方式写入文件,写满时则回溯到第一个文件,进行覆盖写。

控制 redo log 的写入策略,InnoDB 提供了 innodb_flush_log_at_trx_commit 参数,它有三种可能取值:

0:表示每次事务commit时,把redo log写入redo log buffer中,后台线程以每秒一次把buffer中的数据刷到磁盘,速度最快,但存在1秒丢失数据的可能性。
1:表示每次事务commit时,直接把redo log持久化写入磁盘,速度最慢,但最安全。
2:表示每次事务commit时,把redo log写入page cache中,后台Master线程以每秒一次刷入磁盘。

redo log负责重做,undo log负责回滚。redo log记录了事务完成后的数据状态,undo log记录了事务开始前的数据状态。


Consistency(一致性),事务必须使数据库从一个一致性状态变换到另外一个一致性状态,事务按照预期生效,数据的状态是预期的状态。数据库的”一致性“从底层来说,是一组约束。这组约束可以是约束条件、可以是触发器等,也可以是它们的组合。从更高的层面来说,“一致性”是一种目的,即保持数据库与真实世界之间的正确映射。此时,需要靠各种锁来达成“一致性”。

例如A有五百元,B有一百元,此时A向B转账一百元,则正确结果是A有四百元,B有两百元,这就是一致性。如果不是这个结果,说明一致性被破坏。

再比如,一个学生从学校退学了,那么所有记录到该学生的表都要进行删除操作,如果不进行或者只进行了部分操作,则说明一致性被破坏。

undo log可以保证事务的一致性


Isolation(隔离性),事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

MySQL中有四种隔离级别,分别是未提交读(read uncommitted)、已提交读(read committed)、可重复读(repeatable read)、序列化读(serializable)。其中序列化读是最安全的,它保证各个事务串行执行,前一个事务未完成,后面的事务进行等待。

未提交读,事务对当前被读取的数据不加锁,只在更新的瞬间,加上行级共享锁,直到事务结束。此时,当事务未commit时,别的事务也可以看到数据的修改。
提交读,事务读取到数据时,加上行级共享锁,一旦读完该行就立即释放;当事务更新数据时,加上行级排他锁,事务结束释放。由于更新时使用的是排他锁,因此别的事务读取的数据都是已经提交过的数据。
可重复读,事务读取诗句时,必须先加上行级共享锁,直到事务结束释放(和提交读不同);当事务更新数据时,必须加上行级排他锁,直到事务结束释放。
序列化读,事务读取数据,加上表级共享锁,事务结束释放;事务更新数据,加上表级排他锁,事务结束释放。

以上是只使用锁来实现隔离级别,但是这样会导致频繁的加锁解锁,影响性能,因此引入了MVCC机制(多版本并发控制)。

不同的隔离级别,会引发各种各样的问题:脏读、不可重复读、幻读。

脏读,一个事务读取了另一个事务已修改但未提交的事务。未提交读会引发。
不可重复读,一个事务多次读取数据,不保证一致性。未提交读、提交读引发。
幻读,一个事务多次查询的结果集不同。未提交读、提交读、可重复读引发

MySQL默认是可重复读。


Durability(持久性),持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

你可能感兴趣的:(游戏服务器,数据库,java,database)