数据库事务原子性、一致性是怎样实现的?
atomicity/consistency
数据库的一致性依赖于其他三种特性:原子性,隔离性,持久性
原子性用于保证事务中的语句要么全部执行要么全部不执行
隔离性用于保证多事务并发处理下事务处理顺序与结果的保证
隔离性的处理分为四个级别
- read uncommit ted
- read committed
- repeatable read
- serializable
原子性如何保证
atomicity
innodb使用undo log
回滚日志,记录事务操作以便回滚
- insert->delete
- delete->insert
- update->update 更新的回滚就先记录更改前的数据然后回滚就跟新为之前的状态
使用undo log撤回之前的操作
持久性如何保证
durability
redo log
Mysql是先把磁盘上的数据加载到内存中,在内存中对数据进行修改,再刷回磁盘上。如果此时突然宕机,内存中的数据就会丢失。
怎么解决?
事务提交前直接把数据写入磁盘
太浪费IO资源
使用redo log来解决持久性和读写IO消耗严重问题
当做数据修改的时候,不仅在内存中操作,还会在redo log中记录这次操作。当事务提交的时候,会将redo log日志进行刷盘(redo log一部分在内存一部分在磁盘)。当数据库宕机重启会将redolog中的内容恢复到数据库再根据undo log和binlog内容决定回滚数据还是提交数据
隔离性如何保证?
isolation
使用锁机制,保证每个事务能够看到的数据总是一致的,就好像其他事务不存在一样,多个事务并发执行后的状态和它们串行执行后的状态是等价的
两种锁
-
悲观锁
当前事务设计操作的对象加锁,操作完成后释放给其它对象使用。
提高性能->{各种粒度:数据库/表/行/各种性质:共享/排他/共享意向/排他意向/共享排他意向}
解决死锁->{两阶段协议/死锁检测}
-
乐观锁
不同事物可同时可能到同一对象的不同历史版本。使用MVCC(多版本并发控制,Multi-Version Concurrency Control),可在事务提交前查看修改事务的版本,如果与读取版本不一致可放弃提交
如果有两个事务同时修改了同一数据行,那么在较晚的事务提交时进行冲突检测。实现:通过undo log来获取历史版本,另一种简单地在内存中保存同一数据行的多个历史版本,通过时间戳来区分。