前置小知识:数据库的并发控制
前置小知识:数据库的并发控制
所谓并发 *** 作,是指多用户共享的系统中,许多用户可能同时对同一数据进行 *** 作。并发 *** 作带来的问题是数据的不一致性,主要有:
丢失修改不可重复读读脏数据幻读丢失修改: 如图所示,T1事务对数据库的修改被T2事务覆盖而丢失了,破坏了事务的隔离性。
不可重复读: 事务对同一数据进行两次读取的结果不同,原因是两次读取间隙数据被另一事务修改了。
读脏数据: 某事务读取的数据是其他事务修改后的值,但该修改后来又被撤销(ROLLBACK)了。
幻读: 事务A查询得到N条数据,然后事务B又插入了M条数据,或者改变了这N条数据之外的M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据,就产生了幻读。
不可重复读和幻读的区别:
不可重复读:两次数据读取的值
不同。幻读:两次查询得出的数据条数
不同。
SQL的事务四种隔离级别 (TRANSACTION ISOLATION LEVEL)
隔离级别从上到下依次增高,随着隔离级别增高,并发性能随之降低!
READ UNCOMMITTED(读未提交)
最低级别,任何情况都无法保证。
READ COMMITTED(读已提交)
可避免读脏数据;
但仍可能产生不可重复读,幻读。
REPEATABLE READ(可重复读)
可避免读脏数据,不可重复读;
但仍可能产生幻读。
SERIALIZABLE(串行化)
最高级别,可避免读脏数据,不可重复读和幻读。
值得注意的是,SERIALIZABLE(串行化) 是牺牲了并发性能带来的隔离级别,该隔离级别的效率很低。
MySQL的默认隔离级别
我们最熟悉的关系型数据库MySQL默认的隔离级别是:
REPEATABLE READ(可重复读)
我们可以通过SELECT @@tx_isolation
命令来查看
那么问题来了,怎么在SQL中定义隔离级别呢?
这里我举一个小栗子🌰:
CREATE PROCEDURE buy(IN:CommNo VARCHAR(20),IN :AmountBuy INT)
BEGIN
if (:AmountBuy<1) return -1;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
// 定义隔离级别为READ UNCOMMITTED(读未提交)
BEGIN TRANSACTION; // 插入销售记录
INSERT INTO Sale
VALUES(getGUID(),:CommNo,:AmountBuy,getDATETIME());
// 函数getGUID():获取唯一值
// 函数getDATETIME():获取当前系统日期时间
if error
BEGIN
ROLLBACK; return -2;
END
UPDATE Commodity
SET qty=qty-:AmountBuy
WHERE Ccode= :CommNo;
if error
BEGIN
ROLLBACK; return -3;
END
COMMIT; return 0;
END TRANSACTION;
END;
这样,buy这个存储过程中的事务的隔离级别就被定义为
READ UNCOMMITTED(读未提交)了~
(SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;)
各位节日快乐~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)