mysql锁,脏读、幻读

来源:互联网 发布:域名买卖赚钱吗 编辑:程序博客网 时间:2024/06/02 15:36

脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

例子:

事务1:更新一条数据
               ------------->事务2:读取事务1更新的记录
 事务1:调用commit进行提交


不可重复读(Non-repeatable read):事务T1读取一行记录,紧接着事务T2修改 了T1刚才读取的那一行记录。然后T1又再次读取这行记录,发现与刚才读取的结果不同。这就称为“不可重复”读,因为T1原来读取的那行记录已经发生了变化。

例子:

事务1:查询一条记录
            -------------->事务2:更新事务1查询的记录
            -------------->事务2:调用commit进行提交
事务1:再次查询上次的记录


幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。


隔离级别:


事务隔离五种级别:
        TRANSACTION_NONE  不使用事务。
        TRANSACTION_READ_UNCOMMITTED  允许脏读。
        TRANSACTION_READ_COMMITTED  防止脏读,最常用的隔离级别,并且是大多数数据库的默认隔离级别
        TRANSACTION_REPEATABLE_READ  可以防止脏读和不可重复读,
        TRANSACTION_SERIALIZABLE  可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的效率
  以上的五个事务隔离级别都是在Connection接口中定义的静态常量,

  使用setTransactionIsolation(int level) 方法可以设置事务隔离级别。
        如:con.setTransactionIsolation(Connection.REPEATABLE_READ);


Innodb锁控制

加锁方法:

对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁。
  共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。
  排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。

用SELECT ... IN SHARE MODE获得共享锁,主要用在需要数据依存关系时来确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT... FOR UPDATE方式获得排他锁。


InnoDB行锁实现方式:

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!


Mysql锁设置

用户可以用SET TRANSACTION语句改变单个会话或者所有新进连接的隔离级别。它的语法如下:

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
你可以用下列语句查询全局和会话事务隔离级别:

SELECT @@global.tx_isolation; SELECT @@session.tx_isolation; SELECT @@tx_isolation;set tx_isolation='read-committed';




关于幻象读 

innodb默认事务隔离级别是不会出现的。不会出现:“不可重复读”。


关于锁

写锁和读锁的区别在于,当表被写锁定之后,除非解锁,后面的会话进程(SESSION),什么事情也做不了,只能够等待解锁.

0 0
原创粉丝点击