ecodeclub / eorm

简单 ORM 框架
Apache License 2.0
191 stars 64 forks source link

分库分表: ShardingInserter 的语句生成改为 Table 维度 #205

Closed Stone-afk closed 1 year ago

Stone-afk commented 1 year ago

目前来看,在真实的执行场景下做不到按照 DB 维度来发送请求。 有两个问题:

1、尝试使用 multiStatements=true 选项的时候,依旧会出错; 2、即便可以使用 multiStatements,也难以教会用户在这里必须要指定 multiStatements,而且 db 那块代码的设计还要在原来的基础上做改动,目前也不想我们自己拼接一个

所以改成一个表一个

flycash commented 1 year ago

我仔细想了一下,的确是改成表维度更好。但是我们还是可以考虑优化的。

也就是说,如果在表维度的时候,将所有的语句放进去一个事务里面,比每个语句都单独执行性能会更加好。

for _, db := range dstDBs {
   tx := db.Begin()
    for _, tab := range tabs {
          // 执行表上面的每一个语句
         tx.Exec()
    }
    db.Commit
}

之所以会说性能好很多,主要很对的是数据库的持久化机制。比如说在 MySQL 的 innoDB 引擎下,默认配置是 redo log 每个 commit 就刷新到磁盘。所以我们这里合并为一个事务之后,那么 redo log 就可以只刷新一次,那么相比多次刷新,省去了系统调用和寻址之类的问题(虽然本身就是 WAL 也很快)。

另外一方面,这种优化可以确保,至少在某个数据库上,操作是保证 ACID 的。也就是说,虽然跨库保证不了 ACID,但是跨表但是不跨库是可以的。

Stone-afk commented 1 year ago

这里忽略了 ds 只考虑了 db 吧,还有是不是要考虑长事务带来的影响

Stone-afk commented 1 year ago

比如 造成 大量的阻塞和锁超时,主从延迟啥的

flycash commented 1 year ago

只考虑 DB,数据库是做不到跨 DB 事务的吧?暂时保持表维度吧,长事务我倒是没有想到的。不过这个要支持,需要先支持了分布式事务。

Stone-afk commented 1 year ago

“只考虑 DB,数据库是做不到跨 DB 事务的吧?” 我的意思是你的描述里忽略了 ds

Stone-afk commented 1 year ago

支持了分布式事务后,其实用户也可以自己手动开事务

flycash commented 1 year ago

我的意思是说,在支持了分布式事务之后,只要我们在操作 Insert 的时候启用那个延迟事务,就可以了。剩余的事情,事务会帮我们解决

flycash commented 1 year ago

这下子可怕了,我们要全部改成 DB 维度了。