不知道大家有没有想过下面这件事?
这还用问吗?当然是被删除了啊 ![]()
那么这里又有个新的问题了,如果在 InnoDB 下,多事务并发的情况下,如果事务A删除了 没错,这就需要了解一下 MySQL 的多版本并发的原理相关的东西,感兴趣的可以去看我之前写的这篇文章。
所以,实际情况中,调用了
![]()
在 MySQL 中, 那么问题又来了,那这些删除的数据如果一直这么堆下去,那不早晚把硬盘撑爆? ![]() 如果都玩儿成这样了,那 MySQL 还能像现在这样被大规模的用于生产环境中吗?那 MySQL 到底是怎么玩的? 这就需要提到 Purge 操作了。 Purge操作是啥? Purge 操作才是真正将数据(已被标记为已删除)物理删除的操作。 ![]() Purge 操作针对的数据对象,不仅仅是某一行,还有其对应的索引数据和 Undo Log。 好的那么问题又来了。 ![]() 问题是,Purge 操作什么时候会执行呢?实际上,你可以将执行 Purge 操作的线程(简称 Purge 线程)理解成一个后台周期性执行的线程。
Purge 线程可以有一个,也可以有多个,具体的线程数量可以由 MySQL 的配置项 ![]() InnoDB 会根据 MySQL 中表的数量和 Purge 线程的数量进行分配。 ![]() 但正是因为有这种特性,Purge 线程的数量才需要根据业务的实际情况来做调整。举个例子,假设 DML 操作都集中在某张表,比如表1上... 你先等等,我打断一下...... ![]() 什么叫 DML 操作?总喜欢搞些复杂的名词...DML(Data Manipulation Language)数据操作语句,实际上就是CRUD增删改查...
与之类似的概念还有DDL(Data Definition Language)数据定义语句,也就是
以及DCL(Data Control Language)数据控制语句,也就是
继续说回来,虽然 Purge 线程的数量是可配置的,但是也不是你想配多少就配多少的。不然你给它干个
![]() 你看着上面这个图问问自己,这「河里」吗?这样不仅浪费了系统的资源,同时还使得不同的 Purge 线程之间发生了数据竞争。不仅如此,Purge 线程还可能跟用户线程产生竞争。 但是当系统中真的有 32 张表的时候,情况又不一样了,一个 Purge 线程对应一张表,线程与线程之间就不会存在数据竞争,并且没有浪费系统资源,还能够提升执行 Purge 操作的性能。 这就是为啥 InnoDB 会根据实际情况来调整 MySQL 中 Purge 线程的数量,所以我们在配置的时候也要按照实际情况来设置。
举个例子,如果你的数据库中,增删改 的操作只集中在某几张表上,则可以考虑将 了解完 Purge 线程本身之后,我们就可以来了解 Purge 线程所针对的对象了。Purge 线程主要清理的对象是 Undo Logs,其次是行记录。 ![]() 因为 Undo Log 可以分为:
所以更准确的说法是,Purge 线程清理的对象是 Update Undo Log 和 行记录,因为 Insert Undo Log 会在事务提交之后就会被删除。 我们都知道 InnoDB 的 MVCC 的数据来源是一个一个 Undo Log 形成的单链表,而 Purge 线程就是用于定期清理 Undo Log 的,并且在清理完 删除数据所生成的 Undo Log 的时候,就会把对应的行记录给移除了。 那么问题又来了,Purge 线程每次会读取多少条件 Undo Log 记录呢?
很明显,它不是看当时的心情来决定取多少条的。它是通过配置项 |