mysql事务处理学习

1.mysql从4.1就开始支持事务处理了 但是只有innodb和BDB存储引擎才支持事务。

2.事务都应该具备ACID特征。所谓ACID是Atomic(原子性),Consistent(一致性),Isolated(隔离性),Durable(持续性)四个词的首字母所写,下面以“银行转帐”为例来分别说明一下它们的含义:

原子性:组成事务处理的语句形成了一个逻辑单元,不能只执行其中的一部分。换句话说,事务是不可分割的最小单元。比如:银行转帐过程中,必须同时从一个帐户减去转帐金额,并加到另一个帐户中,只改变一个帐户是不合理的。

一致性:在事务处理执行前后,数据库是一致的。也就是说,事务应该正确的转换系统状态。比如:银行转帐过程中,要么转帐金额从一个帐户转入另一个帐户,要么两个帐户都不变,没有其他的情况。

隔离性:一个事务处理对另一个事务处理没有影响。就是说任何事务都不可能看到一个处在不完整状态下的事务。比如说,银行转帐过程中,在转帐事务没有提交之前,另一个转帐事务只能处于等待状态。

持续性:事务处理的效果能够被永久保存下来。反过来说,事务应当能够承受所有的失败,包括服务器、进程、通信以及媒体失败等等。比如:银行转帐过程中,转帐后帐户的状态要能被保存下来。

3.在事务里面的SELECT语句没有锁的行为 但是为了有锁我们可以在SQL后面加for update这样SELECT语句就加了行锁。如:
BEGIN;
SELECT book_number FROM book WHERE  book_id = 123 FOR UPDATE;
// ...
UPDATE book SET book_number = book_number - 1 WHERE  book_id = 123;
COMMIT;
-------------------------------------------------------------------------------
由于加入了FOR UPDATE,所以会在此条记录上加上一个行锁,如果此事务没有完全结束,那么其他的事务在使用SELECT ... FOR UPDATE请求的时候就会处于等待状态,直到上一个事务结束,它才能继续,从而避免了问题的发生,需要注意的是,如果你其他的事务使用的是不带FOR UPDATE的SELECT语句,将得不到这种保护。

4.
MySQL/InnoDB通过行级锁来最小化锁竞争。这样修改同一table里其他行的数据没有限制,而且读数据可以始终没有等待。
可以在SELECT语句里使用FOR UPDATE或LOCK IN SHARE MODE语句来加上行级锁

SELECT select_statement options [FOR UPDATE|LOCK IN SHARE MODE] 

FOR UPDATE会锁住该SELECT语句返回的行,其他SELECT和DML语句必须等待该SELECT语句所在的事务完成
LOCK IN SHARE MODE同FOR UPDATE,但是允许其他session的SELECT语句执行并允许获取SHARE MODE锁

5.事务设计指南
  1,保持事务短小 
  2,尽量避免事务中rollback 
  3,尽量避免savepoint 
  4,默认情况下,依赖于悲观锁 
  5,为吞吐量要求苛刻的事务考虑乐观锁 
  6,显示声明打开事务 
  7,锁的行越少越好,锁的时间越短越好 


6.
事务 ACID Atomicity(原子性)、Consistency(稳定性)、Isolation(隔离性)、Durability(可靠性) 
 
1、事务的原子性 
一组事务,要么成功;要么撤回。 
 
2、稳定性 
有非法数据(外键约束之类),事务撤回。 
 
3、隔离性 
事务独立运行。 
一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。 
事务的100%隔离,需要牺牲速度。 
 
4、可靠性 
软、硬件崩溃后,InnoDB数据表驱动会利用日志文件重构修改。 
可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit选项 决定什么时候吧事务保存到日志里。 
开启事务 
START TRANSACTION 或 BEGIN 
 
提交事务(关闭事务) 
COMMIT 
 
放弃事务(关闭事务) 
ROLLBACK 
 
折返点 
SAVEPOINT adqoo_1 
ROLLBACK TO SAVEPOINT adqoo_1 
发生在折返点 adqoo_1 之前的事务被提交,之后的被忽略 
 
事务的终止 
 
设置“自动提交”模式 
SET AUTOCOMMIT = 0 
每条SQL都是同一个事务的不同命令,之间由 COMMIT 或 ROLLBACK隔开 
掉线后,没有 COMMIT 的事务都被放弃 
 
事务锁定模式 
 
系统默认: 不需要等待某事务结束,可直接查询到结果,但不能再进行修改、删除。 
缺点:查询到的结果,可能是已经过期的。 
优点:不需要等待某事务结束,可直接查询到结果。 
 
需要用以下模式来设定锁定模式 
 
1、SELECT …… LOCK IN SHARE MODE(共享锁) 
查询到的数据,就是数据库在这一时刻的数据(其他已commit事务的结果,已经反应到这里了) 
SELECT 必须等待,某个事务结束后才能执行 
 
2、SELECT …… FOR UPDATE(排它锁) 
例如 SELECT * FROM tablename WHERE id<200 
那么id<200的数据,被查询到的数据,都将不能再进行修改、删除、SELECT …… LOCK IN SHARE MODE操作 
一直到此事务结束 
 
共享锁 和 排它锁 的区别:在于是否阻断其他客户发出的 SELECT …… LOCK IN SHARE MODE命令 
 
3、INSERT / UPDATE / DELETE 
所有关联数据都会被锁定,加上排它锁 
 
4、防插入锁 
例如 SELECT * FROM tablename WHERE id>200 
那么id>200的记录无法被插入 
 
5、死锁 
自动识别死锁 
先进来的进程被执行,后来的进程收到出错消息,并按ROLLBACK方式回滚 
innodb_lock_wait_timeout = n 来设置最长等待时间,默认是50秒 
 
事务隔离模式 
 
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL 
READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE 
1、不带SESSION、GLOBAL的SET命令 
只对下一个事务有效 
2、SET SESSION 
为当前会话设置隔离模式 
3、SET GLOBAL 
为以后新建的所有MYSQL连接设置隔离模式(当前连接不包括在内) 
 
隔离模式 
 
   READ UNCOMMITTED 
不隔离SELECT 
其他事务未完成的修改(未COMMIT),其结果也考虑在内 
 
   READ COMMITTED 
把其他事务的 COMMIT 修改考虑在内 
同一个事务中,同一 SELECT 可能返回不同结果 
 
   REPEATABLE READ(默认) 
不把其他事务的修改考虑在内,无论其他事务是否用COMMIT命令提交过 
同一个事务中,同一 SELECT 返回同一结果(前提是本事务,不修改) 
 
   SERIALIZABLE 
和REPEATABLE READ类似,给所有的SELECT都加上了 共享锁 

你可能感兴趣的:(设计模式,sql,mysql)