You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
70 KiB
HTML

12 months ago
<!doctype html>
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-split-db" data-has-hydrated="false">
<head>
<meta charset="UTF-8">
<meta name="generator" content="Docusaurus v3.0.0">
<title data-rh="true">9.29 分表分库 | Furion</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="http://furion.baiqian.ltd/docs/split-db"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="9.29 分表分库 | Furion"><meta data-rh="true" name="description" content="本章 9.28.2 至 9.28.5 小节挪用博主:雨点的名字 的 分库分表 - 理论 博客内容。特此声明。"><meta data-rh="true" property="og:description" content="本章 9.28.2 至 9.28.5 小节挪用博主:雨点的名字 的 分库分表 - 理论 博客内容。特此声明。"><link data-rh="true" rel="icon" href="/img/favicon.ico"><link data-rh="true" rel="canonical" href="http://furion.baiqian.ltd/docs/split-db"><link data-rh="true" rel="alternate" href="http://furion.baiqian.ltd/docs/split-db" hreflang="en"><link data-rh="true" rel="alternate" href="http://furion.baiqian.ltd/docs/split-db" hreflang="x-default"><link rel="alternate" type="application/rss+xml" href="/blog/rss.xml" title="Furion RSS Feed">
<link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" title="Furion Atom Feed"><link rel="stylesheet" href="/assets/css/styles.3f87a095.css">
<script src="/assets/js/runtime~main.89709a83.js" defer="defer"></script>
<script src="/assets/js/main.10e5dc01.js" defer="defer"></script>
</head>
<body class="navigation-with-keyboard">
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return localStorage.getItem("theme")}catch(t){}}();t(null!==e?e:"light")}(),function(){try{const a=new URLSearchParams(window.location.search).entries();for(var[t,e]of a)if(t.startsWith("docusaurus-data-")){var n=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(n,e)}}catch(t){}}(),document.documentElement.setAttribute("data-announcement-bar-initially-dismissed",function(){try{return"true"===localStorage.getItem("docusaurus.announcement.dismiss")}catch(t){}return!1}())</script><div id="__docusaurus"><div class="floatbar_hUWl"><div class="qrcode_sWwE"><img title="微信扫码关注 Furion 官方公众号" src="/img/weixin_qrcode.jpg" style="display:block"><div>❤️ 关注 Furion 微信公众号有惊喜哦!</div></div><div style="display:flex;flex-direction:row-reverse;align-items:flex-start"><div class="title_SD0k">🫠 遇到问题了</div><div class="extend__5i1"><a class="item_Y35a" href="/docs/subscribe"><div style="flex:1"><div class="itemTitle_If_T">⭐️ VIP 服务 ⭐️</div><div class="itemDesc_dp7r">仅需 499 元/年,尊享 365 天项目无忧</div></div><div class="jiantou_mV_o"></div></a><div class="item_Y35a"><div style="flex:1"><div class="itemTitle_If_T">问题反馈</div><div class="itemDesc_dp7r">到 Furion 开源仓库反馈</div></div><div class="jiantou_mV_o"></div></div></div></div></div><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><div class="announcementBar_mb4j" style="background-color:#4623d9;color:yellow" role="banner"><div class="content_knG7 announcementBarContent_xLdY">⭐️ 开通 VIP 服务仅需 499 元/年,尊享 365 天项目无忧 <a href="/docs/subscribe" style="background-color:rgb(199, 29, 36);color:#ffffff;padding:1px 10px;border-radius:3px;text-decoration:none;display:inline-block;margin:0 5px;font-size:12px;cursor:pointer;">立即开通</a>⭐️</div></div><nav aria-label="Main" class="navbar navbar--fixed-top navbarHideable_m1mJ"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><div class="navbar__logo"><img src="/img/furionlogo.png" alt="Furion Logo" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="/img/furionlogo.png" alt="Furion Logo" class="themedComponent_mlkZ themedComponent--dark_xIcU"></div><b class="navbar__title text--truncate">Furion</b></a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/docs/category/appendix">文档</a><a class="navbar__item navbar__link" href="/docs/global/app">静态类</a><a class="navbar__item navbar__link" href="/docs/settings/appsettings">配置</a><a class="navbar__item navbar__link" href="/blog">博客</a><div class="navbar__item dropdown dropdown--hoverable"><a href="#" aria-haspopup="true" aria-expanded="false" role="button" class="navbar__link">更新日志</a><ul class="dropdown__menu"><li><a class="dropdown__link" href="/docs/upgrade">📝 查看日志v4.9.1.7</a></li><li><a class="dropdown__link" href="/docs/target">🚀 路线图</a></li></ul></div><a href="http://furion.baiqian.ltd/api/api" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">API<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></div><div class="navbar__items navbar__it
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="9291-应用场景">9.29.1 应用场景<a href="#9291-应用场景" class="hash-link" aria-label="Direct link to 9.29.1 应用场景" title="Direct link to 9.29.1 应用场景"></a></h2>
<p>数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作增删改查的开销也会越来越大。</p>
<p>另外由于无法进行分布式部署而一台服务器的资源CPU、磁盘、内存、IO 等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。</p>
<p>这个时候就需要对数据库或数据表进行拆分。</p>
<p>数据切分可以分为:<code>垂直切分</code><code>水平切分</code></p>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="9292-垂直切分">9.29.2 垂直切分<a href="#9292-垂直切分" class="hash-link" aria-label="Direct link to 9.29.2 垂直切分" title="Direct link to 9.29.2 垂直切分"></a></h2>
<p>垂直切分又可以分为: 垂直分库和垂直分表。</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92921-垂直分库">9.29.2.1 垂直分库<a href="#92921-垂直分库" class="hash-link" aria-label="Direct link to 9.29.2.1 垂直分库" title="Direct link to 9.29.2.1 垂直分库"></a></h3>
<p>根据业务耦合性,将关联度低的不同表存储在不同的数据库。做法与大系统拆分为多个小系统类似,按业务分类进行独立划分。与&quot;微服务治理&quot;的做法相似,每个微服务使用单独的一个数据库。</p>
<img src="/img/dbsplit1.jpg">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>说明</div><div class="admonitionContent_BuS1"><p>一开始我们是单体服务,所以只有一个数据库,所有的表都在这个库里。</p><p>后来因为业务需求,单体服务变成微服务治理。所以将之前的一个商品库,拆分成多个数据库。每个微服务对于一个数据库。</p></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92922-垂直分表">9.29.2.2 垂直分表<a href="#92922-垂直分表" class="hash-link" aria-label="Direct link to 9.29.2.2 垂直分表" title="Direct link to 9.29.2.2 垂直分表"></a></h3>
<p>把一个表的多个字段分别拆成多个表,一般按字段的冷热拆分,热字段一个表,冷字段一个表。从而提升了数据库性能。</p>
<img src="/img/dbsplit2.jpg">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>说明</div><div class="admonitionContent_BuS1"><p>一开始商品表中包含商品的所有字段,但是我们发现:</p><p>1.商品详情和商品属性字段较长。2.商品列表的时候我们是不需要显示商品详情和商品属性信息,只有在点进商品商品的时候才会展示商品详情信息。</p><p>所以可以考虑把商品详情和商品属性单独切分一张表,提高查询效率。</p></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92923-优缺点">9.29.2.3 优缺点<a href="#92923-优缺点" class="hash-link" aria-label="Direct link to 9.29.2.3 优缺点" title="Direct link to 9.29.2.3 优缺点"></a></h3>
<ul>
<li>
<p>优点</p>
<ul>
<li>解决业务系统层面的耦合,业务清晰</li>
<li>与微服务的治理类似,也能对不同业务的数据进行分级管理、维护、监控、扩展等</li>
<li>高并发场景下,垂直切分一定程度的提升 IO、数据库连接数、单机硬件资源的瓶颈</li>
</ul>
</li>
<li>
<p>缺点</p>
<ul>
<li>分库后无法 Join只能通过接口聚合方式解决提升了开发的复杂度</li>
<li>分库后分布式事务处理复杂</li>
<li>依然存在单表数据量过大的问题(需要水平切分)</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="9293-水平切分">9.29.3 水平切分<a href="#9293-水平切分" class="hash-link" aria-label="Direct link to 9.29.3 水平切分" title="Direct link to 9.29.3 水平切分"></a></h2>
<p>当一个应用难以再细粒度的垂直切分或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平切分了。</p>
<p>水平切分也可以分为:水平分库和水平分表。</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92931-水平分库">9.29.3.1 水平分库<a href="#92931-水平分库" class="hash-link" aria-label="Direct link to 9.29.3.1 水平分库" title="Direct link to 9.29.3.1 水平分库"></a></h3>
<p>上面虽然已经把商品库分成 3 个库,但是随着业务的增加一个订单库也出现 QPS 过高,数据库响应速度来不及,一般 mysql 单机也就 1000 左右的 QPS如果超过 1000 就要考虑分库。</p>
<img src="/img/dbsplit3.jpg">
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92932-水平分表">9.29.3.2 水平分表<a href="#92932-水平分表" class="hash-link" aria-label="Direct link to 9.29.3.2 水平分表" title="Direct link to 9.29.3.2 水平分表"></a></h3>
<p>一般我们一张表的数据不要超过 1 千万,如果表数据超过 1 千万,并且还在不断增加数据,那就可以考虑分表。</p>
<img src="/img/dbsplit4.jpg">
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92933-优缺点">9.29.3.3 优缺点<a href="#92933-优缺点" class="hash-link" aria-label="Direct link to 9.29.3.3 优缺点" title="Direct link to 9.29.3.3 优缺点"></a></h3>
<ul>
<li>
<p>优点</p>
<ul>
<li>不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力</li>
<li>应用端改造较小,不需要拆分业务模块</li>
</ul>
</li>
<li>
<p>缺点</p>
<ul>
<li>跨分片的事务一致性难以保证</li>
<li>跨库的 Join 关联查询性能较差</li>
<li>数据多次扩展难度和维护量极大</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="9294-数据分片规则">9.29.4 数据分片规则<a href="#9294-数据分片规则" class="hash-link" aria-label="Direct link to 9.29.4 数据分片规则" title="Direct link to 9.29.4 数据分片规则"></a></h2>
<p>我们考虑去水平切分表将一张表水平切分成多张表这就涉及到数据分片的规则比较常见的有Hash 取模分表、数值 Range 分表、一致性 Hash 算法分表。</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92941-hash-取模分表">9.29.4.1 Hash 取模分表<a href="#92941-hash-取模分表" class="hash-link" aria-label="Direct link to 9.29.4.1 Hash 取模分表" title="Direct link to 9.29.4.1 Hash 取模分表"></a></h3>
<p>一般采用 Hash 取模的切分方式,例如:假设按 goods_id 分 4 张表。goods_id%4 取整确定表)</p>
<img src="/img/dbsplit5.jpg">
<p><strong>优缺点</strong></p>
<ul>
<li>
<p>优点</p>
<ul>
<li>数据分片相对比较均匀,不容易出现热点和并发访问的瓶颈。</li>
</ul>
</li>
<li>
<p>缺点</p>
<ul>
<li>后期分片集群扩容时,需要迁移旧的数据很难。</li>
<li>容易面临跨分片查询的复杂问题。比如上例中,如果频繁用到的查询条件中不带 goods_id 时,将会导致无法定位数据库,从而需要同时向 4 个库发起查询,
再在内存中合并数据,取最小集返回给应用,分库反而成为拖累。</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92942-数值-range-分表">9.29.4.2 数值 Range 分表<a href="#92942-数值-range-分表" class="hash-link" aria-label="Direct link to 9.29.4.2 数值 Range 分表" title="Direct link to 9.29.4.2 数值 Range 分表"></a></h3>
<p>按照时间区间或 ID 区间来切分。例如:将 goods_id 为 1-1000 的记录分到第一个表1000-2000 的分到第二个表,以此类推。</p>
<img src="/img/dbsplit6.jpg">
<p><strong>优缺点</strong></p>
<ul>
<li>
<p>优点</p>
<ul>
<li>单表大小可控</li>
<li>天然便于水平扩展,后期如果想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移</li>
<li>使用分片字段进行范围查找时,连续分片可快速定位分片进行快速查询,有效避免跨分片查询的问题。</li>
</ul>
</li>
<li>
<p>缺点</p>
<ul>
<li>热点数据成为性能瓶颈。
例如按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁的读写,而有些分片存储的历史数据,则很少被查询</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92943-一致性-hash-算法">9.29.4.3 一致性 Hash 算法<a href="#92943-一致性-hash-算法" class="hash-link" aria-label="Direct link to 9.29.4.3 一致性 Hash 算法" title="Direct link to 9.29.4.3 一致性 Hash 算法"></a></h3>
<p>一致性 Hash 算法能很好的解决因为 Hash 取模而产生的分片集群扩容时,需要迁移旧的数据的难题。具体原理可参考 <a href="https://www.cnblogs.com/duhuo/p/4996105.html" target="_blank" rel="noopener noreferrer">https://www.cnblogs.com/duhuo/p/4996105.html</a></p>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="9295-分库分表带来的问题">9.29.5 分库分表带来的问题<a href="#9295-分库分表带来的问题" class="hash-link" aria-label="Direct link to 9.29.5 分库分表带来的问题" title="Direct link to 9.29.5 分库分表带来的问题"></a></h2>
<p>任何事情都有两面性,分库分表也不例外,如果采用分库分表,会引入新的的问题:</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92951-分布式事务问题">9.29.5.1 分布式事务问题<a href="#92951-分布式事务问题" class="hash-link" aria-label="Direct link to 9.29.5.1 分布式事务问题" title="Direct link to 9.29.5.1 分布式事务问题"></a></h3>
<p>使用分布式事务中间件解决,具体是通过最终一致性还是强一致性分布式事务,看业务需求,这里就不多说。</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92952-跨节点关联查询-join-问题">9.29.5.2 跨节点关联查询 Join 问题<a href="#92952-跨节点关联查询-join-问题" class="hash-link" aria-label="Direct link to 9.29.5.2 跨节点关联查询 Join 问题" title="Direct link to 9.29.5.2 跨节点关联查询 Join 问题"></a></h3>
<p>切分之前,我们可以通过 Join 来完成。而切分之后,数据可能分布在不同的节点上,此时 Join 带来的问题就比较麻烦了,考虑到性能,尽量避免使用 Join 查询。</p>
<p>解决这个问题的一些方法:</p>
<ul>
<li><strong>全局表</strong></li>
</ul>
<p>全局表,也可看做是 &quot;数据字典表&quot;,就是系统中所有模块都可能依赖的一些表,为了避免跨库 Join 查询,可以将 这类表在每个数据库中都保存一份。这些数据通常很少会进行修改,所以也不担心一致性的问题。</p>
<ul>
<li><strong>字段冗余</strong></li>
</ul>
<p>利用空间换时间,为了性能而避免 join 查询。例:订单表保存 userId 时候,也将 userName 冗余保存一份,这样查询订单详情时就不需要再去查询&quot;买家 user 表&quot;了。</p>
<ul>
<li><strong>数据组装</strong></li>
</ul>
<p>在系统层面,分两次查询。第一次查询的结果集中找出关联数据 id然后根据 id 发起第二次请求得到关联数据。最后将获得到的数据进行字段拼装。</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92953-跨节点分页排序函数问题">9.29.5.3 跨节点分页、排序、函数问题<a href="#92953-跨节点分页排序函数问题" class="hash-link" aria-label="Direct link to 9.29.5.3 跨节点分页、排序、函数问题" title="Direct link to 9.29.5.3 跨节点分页、排序、函数问题"></a></h3>
<p>跨节点多库进行查询时,会出现 Limit 分页、Order by 排序等问题。分页需要按照指定字段进行排序,当排序字段就是分片字段时,通过分片规则就比较容易定位到指定的分片;</p>
<p>当排序字段非分片字段时,就变得比较复杂了。需要先在不同的分片节点中将数据进行排序并返回,然后将不同分片返回的结果集进行汇总和再次排序,最终返回给用户。</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92954-全局主键避重问题">9.29.5.4 全局主键避重问题<a href="#92954-全局主键避重问题" class="hash-link" aria-label="Direct link to 9.29.5.4 全局主键避重问题" title="Direct link to 9.29.5.4 全局主键避重问题"></a></h3>
<p>如果都用主键自增肯定不合理,如果用 UUID 那么无法做到根据主键排序,所以我们可以考虑通过<a href="https://www.cnblogs.com/qdhxhz/p/11372658.html" target="_blank" rel="noopener noreferrer">雪花 ID</a> 来作为数据库的主键,</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="92955-数据迁移问题">9.29.5.5 数据迁移问题<a href="#92955-数据迁移问题" class="hash-link" aria-label="Direct link to 9.29.5.5 数据迁移问题" title="Direct link to 9.29.5.5 数据迁移问题"></a></h3>
<p>采用双写的方式,修改代码,所有涉及到分库分表的表的增、删、改的代码,都要对新库进行增删改。同时,再有一个数据抽取服务,不断地从老库抽数据,往新库写,</p>
<p>边写边按时间比较数据是不是最新的。</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="9296-如何实现">9.29.6 如何实现<a href="#9296-如何实现" class="hash-link" aria-label="Direct link to 9.29.6 如何实现" title="Direct link to 9.29.6 如何实现"></a></h2>
<div class="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>特别说明</div><div class="admonitionContent_BuS1"><p>由于分表分库不仅仅需要内置代码的支持,同时还需要集成数据库中间件,这里推荐 <code>MyCat</code> 中间件。<a href="http://www.mycat.org.cn/" target="_blank" rel="noopener noreferrer">MyCat 官方网站</a></p></div></div>
<p><code>Furion</code> 框架中提供了轻量级的 <code>分表分库</code> 支持:</p>
<ul>
<li><strong>动态切换数据库</strong></li>
</ul>
<div class="language-cs codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cs codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm"><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 直接改变数据库</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">repository</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">ChangeDatabase</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">&quot;数据库连接字符串&quot;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain" style="display:inline-block"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// 通过数据库上下文定位器切换</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">repository</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token generic-method function" style="color:rgb(130, 170, 255)">Change</span><span class="token generic-method generic class-name punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token generic-method generic class-name" style="color:rgb(255, 203, 107)">Entity</span><span class="token generic-method generic class-name punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token generic-method generic class-name" style="color:rgb(255, 203, 107)"> MyDbContextLocator2</span><span class="token generic-method generic class-name punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>如需跨库查询,需用到数据库技术,如 <code>SqlServer</code> 链接服务器或同义词。</p>
<ul>
<li><strong>动态切换数据库表</strong></li>
</ul>
<p>第一步、配置数据库上下文特性<code>[AppDbContext( Mode=DbContextMode.Dynamic)]</code></p>
<p>第二步、需要动态修改表名的实体继承 <code>IEntityMutableTable&lt;TEntity&gt;</code> 接口,并实现 <code>GetTableName()</code> 返回表名方法</p>
<p>最后通过 <code>BuildChange&lt;TEntity&gt;</code> 切换即可。</p>
<div class="language-cs codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-cs codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm"><span class="token-line codeLine_lJS_" style="color:#bfc7d5"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token keyword" style="font-style:italic">var</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">rep</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> scoped</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> repository</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token generic-method function" style="color:rgb(130, 170, 255)">BuildChange</span><span class="token generic-method generic class-name punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token generic-method generic class-name" style="color:rgb(255, 203, 107)">Persion</span><span class="token generic-method generic class-name punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>调用 <code>BuildChange</code> 方法之后会自动调用 <code>GetTableName()</code> 方法。</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>了解更多</div><div class="admonitionContent_BuS1"><p>想了解更多 <code>DynamicModelCacheKeyFactory</code> 知识可查阅 <a href="https://docs.microsoft.com/zh-cn/ef/core/modeling/dynamic-model" target="_blank" rel="noopener noreferrer">EF Core - 多个模型之间交替</a> 章节。</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="9297-反馈与建议">9.29.7 反馈与建议<a href="#9297-反馈与建议" class="hash-link" aria-label="Direct link to 9.29.7 反馈与建议" title="Direct link to 9.29.7 反馈与建议"></a></h2>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>与我们交流</div><div class="admonitionContent_BuS1"><p>给 Furion 提 <a href="https://gitee.com/dotnetchina/Furion/issues/new?issue" target="_blank" rel="noopener noreferrer">Issue</a></p></div></div></div><footer class="theme-doc-footer docusaurus-mt-lg"><a href="http://github.crmeb.net/u/furion" target="_blank" style="display:block;margin-bottom:20px;text-decoration:none;position:relative;border-radius:5px;overflow:hidden;color:#25c2a0" title="CRMEB 专注开源电商系统研发"><img src="/img/crmeb-spec.jpg" style="display:block;pointer-events:none;max-width:100%"><span style="position:absolute;display:block;right:0;bottom:0;z-index:5;font-size:12px;background-color:rgba(0,0,0,0.8);padding:0 5px">特别赞助</span></a><div class="theme-doc-footer-edit-meta-row row"><div class="col"><a class="ass_kwc6" style="margin:0;margin-bottom:10px;height:80px;z-index:999" href="/docs/subscribe"><div class="title_MSGy">开通 VIP 服务尊享一对一技术指导</div><div class="progress_esN_"><div class="number_F0eG">344</div><div class="percent_Dln9"><div class="current_QYTp" style="width:34.4%"></div></div><div class="number_F0eG">1000</div></div></a><a href="https://gitee.com/dotnetchina/Furion/tree/v4/handbook/docs/split-db.mdx" target="_blank" rel="noopener noreferrer" class="theme-edit-this-page"><svg fill="currentColor" height="20" width="20" viewBox="0 0 40 40" class="iconEdit_Z9Sw" aria-hidden="true"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col lastUpdated_VsjB"><div class="donate_FEDP" style="margin:0;margin-bottom:10px;border:2px solid #ffb02e;margin-top:-4px" title="您的支持是我们坚持完善下去的动力!"><div style="position:relative;margin-right:9px"><img src="/img/donateme.png" style="height:100%;max-height:100%;display:block;min-width:70px" alt="赞助 Furion"><span style="position:absolute;top:25px;left:0;right:0;font-size:12px;z-index:1;text-align:center;color:white;font-weight:bold;background-color:rgba(0, 0, 0, 0.4)">查看大图</span></div><div style="display:flex;flex:1;flex-direction:column;justify-content:space-between;padding:5px 0 5px 0"><h3 style="font-weight:500;font-size:17px;margin:4px 0 0 0;text-align:left;background:linear-gradient(to right, red, blue);background-clip:text;-webkit-background-clip:text;color:transparent;white-space:nowrap;cursor:pointer">谢谢您对 Furion 的认可!</h3><div style="display:flex;justify-content:space-between;white-space:nowrap;margin-top:10px"><span style="font-size:12px;color:#ccc">微信ibaiqian</span><a href="https://gitee.com/dotnetchina/Furion" style="margin-right:6px" target="_blank"><img src="https://gitee.com/dotnetchina/Furion/badge/star.svg?theme=white" alt="star"></a></div></div></div><span class="theme-last-updated">Last updated<!-- --> on <b><time datetime="2023-04-25T02:22:00.000Z">Apr 25, 2023</time></b> by <b>MonkSoul</b></span></div></div><a style="display:flex;width:100%;box-sizing:border-box;align-items:center;justify-content:space-between;padding-left:5px" title="⭐️ 开通 VIP 服务仅需 499 元/年,尊享 365 天项目无忧2323 ⭐️" href="/docs/subscribe"><div style="flex:1;margin:5px 5px 5px 0;user-sele
</body>
</html>