SQL事务隔离
事务分类:
1 显式事务:用begin transaction明确指定事务的开始。
2 隐性事务:打开隐性事务:set implicit_transactions on,当以隐性事务模式操作时,SQL Servler将在提交或回滚事务后自动启动新事务。无法描述事务的开始,只需要提交或回滚事务。
3 自动提交事务:SQL Server的默认模式,它将每条单独的T-SQL语句视为一个事务。如果成功执行,则自动提交,否则回滚。
并发事务成败皆归于锁——锁定
在多用户都用事务同时访问同一个数据资源的情况下,就会造成以下几种数据错误:
- 更新丢失:多个事务同时对一个数据资源进行更新,必定会产生被覆盖的数据,造成数据读写异常。
- 不可重复读:在一个事务中多次读取一条数据,而另外一个事务则同时更新了这条数据,造成第一个事务多次读取数据不一致。
- 脏读:事务已经更新数据,另一个事务此时读取同一份数据,由于一些原因,前一个事务回滚,造成后一个事务读取的数据不一致。
- 幻读:第一个事务读取一个结果集后,第二个事务,对这个结果集经行增删操作,然而第一个事务中再次对这个结果集进行查询时,数据发现丢失或新增。
然而锁定,就是为解决这些问题所生的,他的存在使得一个事务对他自己的数据块进行操作的时候,而另外一个事务则不能插足这些数据块。这就是所谓的锁定。
常见解决死锁方法:
- 不同程序并发存取多个表,约定相同顺序访问表
- 同一个事务,一次锁定所需所有资源
- 业务部分,升级锁粒度,使用表级锁定
1、锁定从类别可以分为2种:
- 共享锁(S):还可以叫他读锁。可以并发读取数据,但不能修改数据。也就是说当数据资源上存在共享锁的时候,所有的事务都不能对这个资源进行修改,直到数据读取完成,共享锁释放。共享锁可以同时加上多个。
- 排它锁(X):还可以叫他独占锁、写锁。就是如果你对数据资源进行增删改操作时,不允许其它任何事务操作这块资源,直到排它锁被释放,防止同时对同一资源进行多重操作。排它锁只能加一个,它和其他排它锁和共享锁相斥。
2、锁从粒度可以分为3种(InnoDB):
- 行级锁
- select * from tab_with_index where id = 1 for update; for update行级锁定,前提id是有索引的列,如果id没有索引,这是表索引
- InnoDB默认
- 分为共享锁和排它锁
- 出现死锁,并发度高
- 表级锁
- MyISAM,InnoDB支持
- 分为共享锁和排它锁
- 不出现死锁,并发度低
- 页级锁
- 介于表级与行级
- 出现死锁,并发度一般
3、锁算法(InnoDB):
- Record:单行记录上的锁
- Gap:间隙锁,锁定一个范围,但是不包含记录本身
- Next-key:record+gap锁定一个范围,包含记录本身
使用场景:
- 行查询使用next-key
- next-locking keying解决幻读问题
- 查询索引唯一,将next-key降为record
- gap阻止多个事务将记录插入同一个范围,防止幻读
- 除外键和唯一性,其他情况使用record
- 显示关闭gap:将事务隔离设置read committed;将InnoDB_locks_unsafe_for_binlog设置为1
事务隔离级别:
- read uncommitted(读取未提交):出现脏读,不可重复读,幻读
- read committed(读取并提交):出现不可重复读,幻读,SqlServer,Oracle默认级别
- read repeatable(可重复读):出现幻读,MySQL默认级别
- read serializable(可串行化):InnoDB在分布式事务