mysql中如何实现事务隔离级别
事务是一组一起成功或一起失败的 SQL 语句。事务还应该具有原子性、一致性、隔离性和持久性。
1.事务的基本要素(ACID)
1.原子性:事务启动后,所有操作要么成功,要么失败,这是不可能的。在中间状态下,交易是一个不可分割的整体,就像一个原子。
2.一致性:事务开始和结束前后,不违反数据库的完整性约束。 A转账给B,A扣了钱,B却没有收到。
3.隔离性:同时事务(concurrent transactions)不应该导致数据库处于不一致的状态。每笔交易独立执行,不影响交易结果是否存在其他交易。
4.持久性:事务对数据库所做的更改将保存在磁盘上并且不会丢失。
2.事务并发问题
1.脏读:事务A读取了事务B未提交的写入数据,读到的数据称为脏数据
2。不可重复读:事务A多次读取相同的数据,但在读取过程中,事务B修改了数据并提交。结果,相同的数据被多次读取,结果不同。
3.幻读:事务A修改了表中的所有数据行,比如设置status = 1,但同时事务B向表中插入了一行status = 0的新数据。对于操作事务 对于用户A来说,表中还有一条记录没有被修改,就像幻觉一样。
3.四级事务隔离
Transact离子隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交读未提交 | √ | √ | √ | < /tr>
× | √ | < h2>√ h2> | |
可重复读取 | × | ×< /h2> | √ |
可序列化 | ×td> | × | × |
4.获取和设置数据库隔离级别
SHOW VARIABLES LIKE '%isolation%';SHOW GLOBAL VARIABLES LIKE '%isolation%';
使用系统变量查询
SELECT @@GLOBAL.tx_isolation;SELECT @@SESSION.tx_isolation;SELECT @@tx_isolation;
对于mysql8,使用以下变量进行查询
SELECT @@GLOBAL.transaction_isolation;SELECT @@SESSION.transaction_isolation;SELECT @@transaction_isolation;
设置隔离级别
SET GLOBAL tx_isolation = '隔离级别';SET SESSION tx_isolation = '隔离级别';SET @@tx_isolation = '隔离级别';
对于mysql8,使用如下语句设置
SET GLOBAL transaction_isolation = '隔离级别';SET SESSION transaction_isolation = '隔离级别';SET @@transaction_isolation = '隔离级别';
5.通过例子解释各个隔离级别
首先准备一个表和一些数据。
创建表 `account` ( `id` int(11) unsigned NOT NULL AUTO_INCRMENT COMMENT 'ID', `name` varchar(32) DEFAULT '' COMMENT 'name ', `money` 小数(11,2) DEFAULT '0.00' COMMENT 'Money', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;INSERT INTO `account` (`name`, `money`) VALUES ('A', '500.00');INSERT INTO `account` (`name`, `money`) VALUES ('B', '100.00');
1.读取未提交
set transaction_isolation = 'READ-UNCOMMITTED';set autocommit = 0;
事务B修改了表中的数据,但未提交,事务A确认修改的数据被读取。如果事务B由于某种原因回滚,那么事务A读到的数据就是脏数据。
2.读提交
set transaction_isolation = 'READ-COMMITTED';set autocommit = 0;
事务B修改数据但不提交,那么事务A仍然获取到原始数据,解决了脏读问题。
但是事务B提交,事务A执行上一次查询,结果与上一次查询不一致,导致不可重复读问题。
3.可重复读取
set transaction_isolation = 'REPEATABLE-READ';set autocommit = 0;
事务B修改了数据并提交了。事务A的两次查询结果是一致的,这说明解决了不可重复读取的问题。
此时,交易A修改了名为A的钱数据。
名为A的钱变成了350,而不是400,可以重复读取,保证数据一致性。
我们将交易A中所有账户的资金重新修改为200,同时在交易B中插入一条新的数据。
事务A仍然获取两条数据,解决了新增数据时事务A的幻读问题。
4.序列化
set transaction_isolation = 'SERIALIZABLE';set autocommit = 0;< p>事务A查询表,如果如果没有提交,事务B的insert语句就会在那里等待,直到超时或者事务A提交。
反之,事务B插入表但未提交后,事务A对该表的查询也会等到事务B提交。
此时,表wi读写表时会被锁定。当然,对并发性能的影响也会比较大。
隔离级别越高,可以保证数据越完整和一致。
6. MySQL锁
锁分为两种类型:
内部锁:内部锁由MySQL服务器内部执行,用于管理多个会话中表内容的争用。
外部锁:MySQL为客户端会话提供显式获取表锁的功能,以防止其他会话访问该表。
内部锁有两种类型:
1。行级锁:行级锁是细粒度的。只有被访问的行才会被锁定,这允许多个会话同时进行写访问。
2.表级锁:MySQL 对 myisam、内存和合并表使用表级锁,一次只允许一个会话更新表,这使得这些存储引擎更适合基于读的操作操作。
外部锁:可以使用LOCK TABLE和UNLOCK TABLE来控制锁定。
READ(共享锁):多个会话可以从表中读取数据,而无需获取锁。此外,多个会话可以获取同一个表上的锁。当 READ 锁定时,没有会话可以向表写入数据。任何写操作都将等待 READ 锁被释放。
WRITE(独占锁):当表被WRITE锁定时,除了持有该锁的会话之外,任何其他会话都不能读取或写入数据,除非释放WRITE锁。
锁定表的语句:
LOCK TABLES table_name [READ | WRITE];
解锁表的语句:
p>UNLOCK TABLES;
锁定数据库中的所有表:
使用读锁刷新表;
我在这里分享一下如何在mysql中实现事务隔离级别。希望以上内容能够对大家有所帮助大家都可以学到更多的知识。如果您觉得文章不错,可以分享出去,让更多的人看到。
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > mysql中如何实现事务隔离级别