那么什么时候事务需要用到多线程呢?这个问题的本质取决于下层所使用的存储,如果是内存操作,则可以动态地申请和销毁内存块;而磁盘的IOPS很低,但吞吐量很高。如果一个场景涉及多次读写操作,单线程可以很高的效率对于内存进行读写操作;但是,由于磁盘的IOPS仅为内存的几千分之一,如果依旧用操作内存的方式操作磁盘,那系统的整体性能将会很低,这意味着必须将大量的读写操作聚合成一个Batch后再提交时才能达到较好的性能。而将大量请求攒到一起的方式一是异步,也就是请求本身和线程不绑定,线程可以不Block(本质来说还是一种多线程的方式),处理完一个线程后再处理其他线程。这种做法的核心是将大量不同的请求提交到一个Buffer中,再由该Buffer统一读取或者写入磁盘,从而提高效率。在慢速设备中,多线程或异步非常常见,在设计系统时,面对磁盘、网络、SSD等慢速设备必须考虑使用多线程。 排他锁
有些场景不适合用单线程操作,可以利用排他锁的方式来快速隔离并发读写事务。数据库中有一些事务单元是共享的,如图中的事务单元1是共享的,事务单元2/3共享数据;针对事务单元2/3共享数据的所有读写Block住,事务单元1单独用一个锁来控制,用这种方式完成系统的访问控制。 读写锁
如果是一个只读的事务,例如只对数据进行查询操作,在该过程中数据一定不被修改,因此多个查询操作可以并行执行,因此一种针对读读场景的优化自然而然产生——读写锁。读写锁的核心是在多次读的操作中,同时允许多个读者来访问共享资源,提高并发性。 MVCC
在最初的数据库事务实现中是不存在MVCC的,它是Oracle在八十年代新加的功能,本质是Copy On Write,也就是每次写都是以重新开始一个新的版本的方式写入数据,atv,因此,数据库中也就包含了之前的所有版本。在数据读的过程中,先申请一个版本号,如果该版本号小于正在写入的版本号,则数据一定可以查询到,无需等到新版本完全写完即可返回查询结果。这种方式可以在读读不阻塞的前提下,实现读写/写读不阻塞,尽可能保证所有的读操作并行,而写操作串行。 事务的调优原则 事务的调优的思路是在不影响业务应用的前提下: 第一,尽可能减少锁的覆盖范围,例如Myisam表锁到Innodb的行锁就是一个减少锁覆盖范围的过程;对于原位锁(排他锁、读写锁等)可变为MVCC多版本(本质仍然是减少锁的范围)。 第二,增加锁上可并行的线程数,例如读锁和写锁的分离,允许并行读取数据。 第三,选择正确锁类型,其中悲观锁适合并发争抢比较严重的场景;乐观锁适合并发争抢不太严重的场景。 创业邦携手阿里云推出创业四重礼,包括1-3万免费云资源、35+产品6个月免费等福利>> (责任编辑:本港台直播) |