事务隔离级别是?
事务隔离级别是数据库管理系统用来控制多个事务并发执行时对数据的可见性和一致性的机制。MySQL支持四种标准的事务隔离级别,它们定义了事务如何与其他并发事务交互。
四种事务隔离级别:
READ UNCOMMITTED(读未提交)
READ COMMITTED(读已提交)
REPEATABLE READ(可重复读)
SERIALIZABLE(可串行化)
MySQL 默认的事务隔离级别:
MySQL的默认隔离级别是 REPEATABLE READ。它确保一个事务在执行期间对数据的读取是可重复的,即使其他事务修改了数据,当前事务的查询结果也不会变化。
事务隔离级别的案例展示:
假设我们有以下的表 account,字段包括 id, name, balance:
CREATE TABLE account (
id INT PRIMARY KEY,
name VARCHAR(100),
balance DECIMAL(10, 2)
);
INSERT INTO account (id, name, balance) VALUES (1, 'Alice', 1000.00), (2, 'Bob', 500.00);
- READ UNCOMMITTED(读未提交)
在此级别,事务可以读取到其他事务尚未提交的修改。这是最弱的隔离级别,容易出现脏读。
示例:
事务A更新了数据,但还没有提交。
事务B读取到了事务A未提交的数据。
SQL代码:
-- 设置隔离级别为 READ UNCOMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- 事务A
BEGIN;
UPDATE account SET balance = balance - 100 WHERE id = 1;
-- 事务B
BEGIN;
SELECT * FROM account; -- 可能读取到事务A的未提交数据
- READ COMMITTED(读已提交)
在此级别,事务只能读取到已提交的事务修改的数据。也可以避免脏读,但仍然可能会遇到不可重复读的问题。
示例:
事务A和事务B分别对同一数据进行读取和修改,事务A读取的值可能会在事务B提交后发生变化。
SQL代码:
– 设置隔离级别为 READ COMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
– 事务A
BEGIN;
SELECT balance FROM account WHERE id = 1; -- 读取 Alice 的余额
-- 事务B
BEGIN;
UPDATE account SET balance = balance - 50 WHERE id = 1; -- 修改 Alice 的余额
COMMIT;
-- 事务A
SELECT balance FROM account WHERE id = 1; -- 可能会得到不同的余额,因为事务B已提交
- REPEATABLE READ(可重复读)
这是MySQL的默认隔离级别。它保证一个事务在执行期间对同一数据的多次读取结果是一样的,即使其他事务修改了数据。它能防止脏读和不可重复读,但可能会出现幻读。
示例:
事务A读取某个范围内的数据,事务B在此范围内插入了新数据。
事务A在后续读取时,可能会看到不同的记录(幻读)。
SQL代码:
-- 设置隔离级别为 REPEATABLE READ
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 事务A
BEGIN;
SELECT * FROM account WHERE balance > 300; -- 读取余额大于300的账户
-- 事务B
BEGIN;
INSERT INTO account (id, name, balance) VALUES (3, 'Charlie', 400.00);
COMMIT;
-- 事务A
SELECT * FROM account WHERE balance > 300; -- 可能会看到事务B插入的新记录,发生幻读
- SERIALIZABLE(可串行化)
这是最高的隔离级别。它通过强制事务之间按顺序执行,避免了脏读、不可重复读和幻读。事务的执行就像是串行执行一样。
示例:
在此级别下,事务A和事务B必须按顺序执行,事务B在事务A完成之前不能执行。
SQL代码:
-- 设置隔离级别为 SERIALIZABLE
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 事务A
BEGIN;
SELECT * FROM account WHERE balance > 300;
-- 事务B
BEGIN;
-- 事务B将被阻塞,直到事务A提交或回滚
INSERT INTO account (id, name, balance) VALUES (3, 'Charlie', 400.00);
COMMIT;
READ UNCOMMITTED:允许脏读,事务间没有隔离。 READ COMMITTED:避免脏读,但可能发生不可重复读。
REPEATABLE READ:避免脏读和不可重复读,但可能发生幻读(MySQL默认)。
SERIALIZABLE:最强的隔离级别,事务串行执行,避免所有并发问题。