MySQL中的隔离级别和悲观锁及乐观锁示例

MySQL中的隔离级别和悲观锁及乐观锁示例

1MySQL的事支持
MySQL
的事支持不是定在MySQL器本身,而是与存引擎相关:

 

  1. MyISAM:不支持事,用于只程序提高性能   
  2. InnoDB:支持ACID、行级锁、并   
  3. Berkeley DB:支持事  


2
隔离级别
隔离级别决定了一个session中的事可能另一个session的影响、并session数据的操作、一个session中所数据的一致性
ANSI
准定4个隔离级别MySQLInnoDB都支持:

Java

  1. READ UNCOMMITTED:最低级别的隔离,通常又称dirty read,它允一个事务读commit的数据,这样可能会提高性能,但是dirty read可能不是我想要的   
  2. READ COMMITTED:在一个事中只允commit记录,如果sessionselect查询中,另一sessioninsert一条记录新添加的数据不可   
  3. REPEATABLE READ:在一个事开始后,其他session数据的修改在本事中不可,直到本事commitrollback。在一个事中重复select果一,除非本事update数据   
  4. SERIALIZABLE:最高级别的隔离,只允串行行。了达到此目的,数据住每行已经读取的记录,其他session不能修改数据直到前一事务结束,事commit或取消  

可以使用如下MySQLsession隔离级别

1. SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

MySQL的隔离级别REPEATABLE READ,在置隔离级别为READ UNCOMMITTEDSERIALIZABLE要小心,READ UNCOMMITTED致数据完整性的问题,而SERIALIZABLE致性能问题并增加死的机率

3,隔离级别
乐观所和悲观锁策略:
观锁:在取数据时锁住那几行,其他对这几行的更新需要等到悲观锁结才能继续
乐观所:取数据,更新时检查是否数据已被更新,如果是取消当前更新
一般在悲
观锁的等待时间过长而不能接受才会选择乐观锁
观锁的例子:

CREATE PROCEDURE tfer_funds (from_account INT, to_account INT,tfer_amount NUMERIC(10,2), OUT status INT, OUT message VARCHAR(30)) BEGIN DECLARE from_account_balance NUMERIC(10,2); START TRANSACTION; SELECT balance INTO from_account_balance FROM account_balance WHERE account_id=from_account FOR UPDATE; IF from_account_balance>=tfer_amount THEN UPDATE account_balance SET balance=balance-tfer_amount WHERE account_id=from_account; UPDATE account_balance SET balance=balance+tfer_amount WHERE account_id=to_account; COMMIT; SET status=0; SET message='OK'; ELSE ROLLBACK; SET status=-1; SET message='Insufficient funds'; END IF; END;

乐观锁的例子:

CREATE PROCEDURE tfer_funds (from_account INT, to_account INT, tfer_amount NUMERIC(10,2), OUT status INT, OUT message VARCHAR(30) ) BEGIN DECLARE from_account_balance NUMERIC(8,2); DECLARE from_account_balance2 NUMERIC(8,2); DECLARE from_account_timestamp1 TIMESTAMP; DECLARE from_account_timestamp2 TIMESTAMP; SELECT account_timestamp,balance INTO from_account_timestamp1,from_account_balance FROM account_balance WHERE account_id=from_account; IF (from_account_balance>=tfer_amount) THEN -- Here we perform some long running validation that -- might take a few minutes */ CALL long_running_validation(from_account); START TRANSACTION; -- Make sure the account row has not been updated since -- our initial check SELECT account_timestamp, balance INTO from_account_timestamp2,from_account_balance2 FROM account_balance WHERE account_id=from_account FOR UPDATE; IF (from_account_timestamp1 <> from_account_timestamp2 OR from_account_balance <> from_account_balance2) THEN ROLLBACK; SET status=-1; SET message=CONCAT("Transaction cancelled due to concurrent update", " of account" ,from_account); ELSE UPDATE account_balance SET balance=balance-tfer_amount WHERE account_id=from_account; UPDATE account_balance SET balance=balance+tfer_amount WHERE account_id=to_account; COMMIT; SET status=0; SET message="OK"; END IF; ELSE ROLLBACK; SET status=-1; SET message="Insufficient funds"; END IF; END$$

你可能感兴趣的:(05_SQL,mysql,session,validation,数据库,insert,服务器)