相关文章推荐
小百科
›
开发 Java 应用使用 TiDB 的最佳实践 | PingCAP 归档文档站
sql注入
mysql update语句
连接池
tidb
斯文的春卷
3 月前
</noscript><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-TPX49SBK" height="0" width="0" style="display: none; visibility: hidden" aria-hidden="true"/></noscript><div id="___gatsby"><div style="outline:none" tabindex="-1" id="gatsby-focus-wrapper"><header class="MuiPaper-root MuiPaper-elevation MuiPaper-elevation4 MuiAppBar-root MuiAppBar-colorPrimary MuiAppBar-positionFixed doc-site-header mui-fixed css-r4hqpc"><div class="MuiToolbar-root MuiToolbar-gutters MuiToolbar-regular css-11fgfqk"><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium css-iuftj9" tabindex="0" type="button" aria-label="menu"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-vubbuv" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="MenuIcon"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg></button><div class="MuiBox-root css-13tqxrv"><a style="text-decoration:none" href="/zh"><svg width="152" height="36" viewbox="0 0 152 36" fill="none"><g clip-path="url(#clip0_789_1365)"><path d="M0 26.9605V9.04959C0 9.01208 0.0187549 8.98395 0.0468872 8.96519L15.5478 0.00973267C15.5759 -0.00902222 15.6134 -0.00902222 15.6416 0.00973267L31.1425 8.95581C31.1706 8.97457 31.1894 9.0027 31.1894 9.04021V26.9511C31.1894 26.9886 31.1706 27.0168 31.1425 27.0355L15.6416 35.991C15.6134 36.0097 15.5759 36.0097 15.5478 35.991L0.0468872 27.0355C0.0187549 27.0168 0 26.9886 0 26.9605Z" fill="#DC150B"/><path d="M10.3808 15.0336C10.3714 15.0242 10.3527 15.0149 10.3433 15.0242L5.25136 17.9688H5.2326C5.21384 17.9688 5.20447 17.9594 5.20447 17.9406V12.0047C5.20447 11.9953 5.21384 11.986 5.22322 11.9766L5.22322 11.9766L15.5572 6.01253C15.5665 6.00315 15.5759 6.00315 15.5853 6.01253L20.7241 8.9758L20.7335 8.98518C20.7429 8.99455 20.7335 9.01331 20.7241 9.02268L15.5759 11.9953C15.5665 12.0047 15.5572 12.0141 15.5572 12.0235V29.9625V29.9813C15.5478 29.9906 15.529 30 15.5197 29.9906L10.3902 27.0368C10.3902 27.0274 10.3808 27.018 10.3808 27.0086V15.0524V15.0336Z" fill="white"/><path d="M20.7992 26.9992C20.7804 26.9992 20.7616 26.9805 20.7616 26.9617V15.0336C20.7616 15.0149 20.771 15.0055 20.7804 14.9961L25.9286 12.0235L25.9286 12.0235C25.938 12.0141 25.938 12.0141 25.9474 12.0141C25.9661 12.0141 25.9849 12.0328 25.9849 12.0516V23.9797C25.9849 23.9985 25.9755 24.0078 25.9661 24.0172L20.8179 26.9899C20.8085 26.9992 20.8085 26.9992 20.7992 26.9992Z" fill="white"/></g><path d="M37.1894 12.4971H42.0242V26.9998H45.4248V12.4971H50.2596V9.37683H37.1894V12.4971Z" fill="black"/><path d="M53.6372 9C53.1197 9 52.6672 9.18709 52.2887 9.55826C51.9102 9.92943 51.7151 10.3941 51.7151 10.9373C51.7151 11.4503 51.9073 11.8999 52.2858 12.2802C52.6643 12.6574 53.1167 12.8505 53.6342 12.8505C54.1517 12.8505 54.5775 12.6574 54.9501 12.2802C55.3227 11.903 55.509 11.4503 55.509 10.9373C55.509 10.3941 55.3257 9.93245 54.9619 9.56128C54.5982 9.19011 54.1517 9.00302 53.6372 9.00302V9Z" fill="black"/><path d="M55.2895 14.3592H51.9864V27H55.2895V14.3592Z" fill="black"/><path d="M64.3322 9.37683H58.2613V26.9998H64.3322C66.9492 26.9998 69.028 26.2031 70.5124 24.6309C71.9939 23.0587 72.748 20.8921 72.748 18.1883C72.748 15.4845 71.9969 13.2967 70.5124 11.7336C69.028 10.1705 66.9492 9.37683 64.3322 9.37683ZM61.6619 12.4971H64.2109C65.9024 12.4971 67.1798 12.998 68.0137 13.9847C68.8506 14.9775 69.2734 16.3566 69.2734 18.0857C69.2734 19.8148 68.8476 21.2512 68.0108 22.3013C67.1769 23.3454 65.8994 23.8765 64.208 23.8765H61.659V12.494L61.6619 12.4971Z" fill="black"/><path d="M86.5964 19.1388C86.0346 18.4418 85.3663 17.9409 84.6152 17.6512V17.621C86.1883 16.8424 86.9838 15.566 86.9838 13.8278C86.9838 12.479 86.5461 11.3866 85.6856 10.5839C84.8251 9.78421 83.5566 9.37683 81.9154 9.37683H74.7948V26.9998H81.8681C83.6068 26.9998 84.9907 26.5652 85.9784 25.7082C86.972 24.8482 87.4747 23.6261 87.4747 22.075C87.4747 20.8468 87.179 19.8601 86.5994 19.1388H86.5964ZM78.1185 16.5256V12.1953H81.4718C82.1105 12.1953 82.628 12.3884 83.0095 12.7686C83.388 13.1489 83.5802 13.68 83.5802 14.3499C83.5802 15.0198 83.3909 15.5569 83.0184 15.9432C82.6458 16.3294 82.1105 16.5256 81.4216 16.5256H78.1156H78.1185ZM83.9972 21.8245C83.9972 22.5276 83.7872 23.101 83.3762 23.5295C82.9651 23.958 82.356 24.1753 81.5724 24.1753H78.1215V19.3471H81.5724C82.3235 19.3471 82.9237 19.5794 83.3525 20.0411C83.7813 20.5028 84.0001 21.1033 84.0001 21.8215L83.9972 21.8245Z" fill="black"/><path d="M97.3306 26.5V9.7H102.299C107.771 9.7 111.083 12.868 111.083 18.1C111.083 23.332 107.771 26.5 102.299 26.5H97.3306ZM102.299 24.364C106.331 24.364 108.659 22.06 108.659 18.1C108.659 14.14 106.331 11.836 102.299 11.836H99.7066V24.364H102.299ZM118.968 26.764C115.464 26.764 112.824 24.052 112.824 20.5C112.824 16.948 115.464 14.236 118.968 14.236C122.472 14.236 125.112 16.948 125.112 20.5C125.112 24.052 122.472 26.764 118.968 26.764ZM118.968 24.628C121.152 24.628 122.736 22.876 122.736 20.5C122.736 18.124 121.152 16.372 118.968 16.372C116.784 16.372 115.2 18.124 115.2 20.5C115.2 22.876 116.784 24.628 118.968 24.628ZM132.772 26.764C129.22 26.764 126.7 24.124 126.7 20.5C126.7 16.876 129.22 14.236 132.772 14.236C135.652 14.236 137.884 15.964 138.244 18.532H135.844C135.532 17.236 134.332 16.372 132.772 16.372C130.588 16.372 129.076 18.076 129.076 20.5C129.076 22.9 130.588 24.628 132.772 24.628C134.332 24.628 135.532 23.764 135.844 22.468H138.244C137.884 25.036 135.652 26.764 132.772 26.764ZM144.557 26.764C141.677 26.764 139.781 25.108 139.709 22.732H142.085C142.229 23.956 142.973 24.724 144.581 24.724C145.733 24.724 146.765 24.34 146.765 23.332C146.765 22.588 146.333 22.06 145.157 21.7L143.333 21.172C141.173 20.548 140.093 19.3 140.093 17.716C140.093 15.604 141.965 14.236 144.413 14.236C146.885 14.236 148.685 15.7 148.829 17.74H146.453C146.285 16.828 145.445 16.204 144.341 16.204C143.261 16.204 142.469 16.804 142.469 17.716C142.469 18.412 142.925 18.868 144.245 19.228L146.069 19.732C148.109 20.308 149.141 21.556 149.141 23.188C149.141 25.396 147.197 26.764 144.557 26.764Z" fill="black"/><defs><clippath id="clip0_789_1365"><rect width="31.1894" height="36" fill="white"/></clippath></defs></svg></a></div><div class="css-2iqpys"><div class="MuiBox-root css-irbys9"><a style="text-decoration:none" hreflang="zh" href="/zh/tidb/v2.1"><div class="MuiTypography-root MuiTypography-body1 css-jhf72c">TiDB</div></a></div><div class="MuiBox-root css-kiou0g"><a class="MuiTypography-root MuiTypography-body1 css-z7v9yr" target="_blank" href="https://asktug.com/" style="text-decoration:none"><div class="MuiTypography-root MuiTypography-body1 css-jhf72c">社区</div></a></div><div class="MuiBox-root css-kiou0g"><a class="MuiTypography-root MuiTypography-body1 css-z7v9yr" target="_blank" href="https://cn.pingcap.com/contact/" style="text-decoration:none"><div class="MuiTypography-root MuiTypography-body1 css-jhf72c">联系我们</div></a></div><div class="MuiBox-root css-kiou0g"><a class="MuiTypography-root MuiTypography-body1 css-z7v9yr" target="_blank" href="https://cn.pingcap.com/product/#SelectProduct" style="text-decoration:none"><div class="MuiTypography-root MuiTypography-body1 css-jhf72c"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="DownloadIcon"><path d="M5 20h14v-2H5v2zM19 9h-4V3H9v6H5l7 7 7-7z"/></svg></div></a></div></div><div class="MuiBox-root css-1vn3uc0"><button class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-textInherit MuiButton-sizeMedium MuiButton-textSizeMedium MuiButton-colorInherit MuiButton-disableElevation css-tjg32r" tabindex="0" type="button" id="header-nav-items" aria-haspopup="true"><span class="MuiButton-startIcon MuiButton-iconSizeMedium css-1l6c7y9"><svg width="152" height="36" viewbox="0 0 152 36" fill="none"><g clip-path="url(#clip0_789_1365)"><path d="M0 26.9605V9.04959C0 9.01208 0.0187549 8.98395 0.0468872 8.96519L15.5478 0.00973267C15.5759 -0.00902222 15.6134 -0.00902222 15.6416 0.00973267L31.1425 8.95581C31.1706 8.97457 31.1894 9.0027 31.1894 9.04021V26.9511C31.1894 26.9886 31.1706 27.0168 31.1425 27.0355L15.6416 35.991C15.6134 36.0097 15.5759 36.0097 15.5478 35.991L0.0468872 27.0355C0.0187549 27.0168 0 26.9886 0 26.9605Z" fill="#DC150B"/><path d="M10.3808 15.0336C10.3714 15.0242 10.3527 15.0149 10.3433 15.0242L5.25136 17.9688H5.2326C5.21384 17.9688 5.20447 17.9594 5.20447 17.9406V12.0047C5.20447 11.9953 5.21384 11.986 5.22322 11.9766L5.22322 11.9766L15.5572 6.01253C15.5665 6.00315 15.5759 6.00315 15.5853 6.01253L20.7241 8.9758L20.7335 8.98518C20.7429 8.99455 20.7335 9.01331 20.7241 9.02268L15.5759 11.9953C15.5665 12.0047 15.5572 12.0141 15.5572 12.0235V29.9625V29.9813C15.5478 29.9906 15.529 30 15.5197 29.9906L10.3902 27.0368C10.3902 27.0274 10.3808 27.018 10.3808 27.0086V15.0524V15.0336Z" fill="white"/><path d="M20.7992 26.9992C20.7804 26.9992 20.7616 26.9805 20.7616 26.9617V15.0336C20.7616 15.0149 20.771 15.0055 20.7804 14.9961L25.9286 12.0235L25.9286 12.0235C25.938 12.0141 25.938 12.0141 25.9474 12.0141C25.9661 12.0141 25.9849 12.0328 25.9849 12.0516V23.9797C25.9849 23.9985 25.9755 24.0078 25.9661 24.0172L20.8179 26.9899C20.8085 26.9992 20.8085 26.9992 20.7992 26.9992Z" fill="white"/></g><path d="M37.1894 12.4971H42.0242V26.9998H45.4248V12.4971H50.2596V9.37683H37.1894V12.4971Z" fill="black"/><path d="M53.6372 9C53.1197 9 52.6672 9.18709 52.2887 9.55826C51.9102 9.92943 51.7151 10.3941 51.7151 10.9373C51.7151 11.4503 51.9073 11.8999 52.2858 12.2802C52.6643 12.6574 53.1167 12.8505 53.6342 12.8505C54.1517 12.8505 54.5775 12.6574 54.9501 12.2802C55.3227 11.903 55.509 11.4503 55.509 10.9373C55.509 10.3941 55.3257 9.93245 54.9619 9.56128C54.5982 9.19011 54.1517 9.00302 53.6372 9.00302V9Z" fill="black"/><path d="M55.2895 14.3592H51.9864V27H55.2895V14.3592Z" fill="black"/><path d="M64.3322 9.37683H58.2613V26.9998H64.3322C66.9492 26.9998 69.028 26.2031 70.5124 24.6309C71.9939 23.0587 72.748 20.8921 72.748 18.1883C72.748 15.4845 71.9969 13.2967 70.5124 11.7336C69.028 10.1705 66.9492 9.37683 64.3322 9.37683ZM61.6619 12.4971H64.2109C65.9024 12.4971 67.1798 12.998 68.0137 13.9847C68.8506 14.9775 69.2734 16.3566 69.2734 18.0857C69.2734 19.8148 68.8476 21.2512 68.0108 22.3013C67.1769 23.3454 65.8994 23.8765 64.208 23.8765H61.659V12.494L61.6619 12.4971Z" fill="black"/><path d="M86.5964 19.1388C86.0346 18.4418 85.3663 17.9409 84.6152 17.6512V17.621C86.1883 16.8424 86.9838 15.566 86.9838 13.8278C86.9838 12.479 86.5461 11.3866 85.6856 10.5839C84.8251 9.78421 83.5566 9.37683 81.9154 9.37683H74.7948V26.9998H81.8681C83.6068 26.9998 84.9907 26.5652 85.9784 25.7082C86.972 24.8482 87.4747 23.6261 87.4747 22.075C87.4747 20.8468 87.179 19.8601 86.5994 19.1388H86.5964ZM78.1185 16.5256V12.1953H81.4718C82.1105 12.1953 82.628 12.3884 83.0095 12.7686C83.388 13.1489 83.5802 13.68 83.5802 14.3499C83.5802 15.0198 83.3909 15.5569 83.0184 15.9432C82.6458 16.3294 82.1105 16.5256 81.4216 16.5256H78.1156H78.1185ZM83.9972 21.8245C83.9972 22.5276 83.7872 23.101 83.3762 23.5295C82.9651 23.958 82.356 24.1753 81.5724 24.1753H78.1215V19.3471H81.5724C82.3235 19.3471 82.9237 19.5794 83.3525 20.0411C83.7813 20.5028 84.0001 21.1033 84.0001 21.8215L83.9972 21.8245Z" fill="black"/><path d="M97.3306 26.5V9.7H102.299C107.771 9.7 111.083 12.868 111.083 18.1C111.083 23.332 107.771 26.5 102.299 26.5H97.3306ZM102.299 24.364C106.331 24.364 108.659 22.06 108.659 18.1C108.659 14.14 106.331 11.836 102.299 11.836H99.7066V24.364H102.299ZM118.968 26.764C115.464 26.764 112.824 24.052 112.824 20.5C112.824 16.948 115.464 14.236 118.968 14.236C122.472 14.236 125.112 16.948 125.112 20.5C125.112 24.052 122.472 26.764 118.968 26.764ZM118.968 24.628C121.152 24.628 122.736 22.876 122.736 20.5C122.736 18.124 121.152 16.372 118.968 16.372C116.784 16.372 115.2 18.124 115.2 20.5C115.2 22.876 116.784 24.628 118.968 24.628ZM132.772 26.764C129.22 26.764 126.7 24.124 126.7 20.5C126.7 16.876 129.22 14.236 132.772 14.236C135.652 14.236 137.884 15.964 138.244 18.532H135.844C135.532 17.236 134.332 16.372 132.772 16.372C130.588 16.372 129.076 18.076 129.076 20.5C129.076 22.9 130.588 24.628 132.772 24.628C134.332 24.628 135.532 23.764 135.844 22.468H138.244C137.884 25.036 135.652 26.764 132.772 26.764ZM144.557 26.764C141.677 26.764 139.781 25.108 139.709 22.732H142.085C142.229 23.956 142.973 24.724 144.581 24.724C145.733 24.724 146.765 24.34 146.765 23.332C146.765 22.588 146.333 22.06 145.157 21.7L143.333 21.172C141.173 20.548 140.093 19.3 140.093 17.716C140.093 15.604 141.965 14.236 144.413 14.236C146.885 14.236 148.685 15.7 148.829 17.74H146.453C146.285 16.828 145.445 16.204 144.341 16.204C143.261 16.204 142.469 16.804 142.469 17.716C142.469 18.412 142.925 18.868 144.245 19.228L146.069 19.732C148.109 20.308 149.141 21.556 149.141 23.188C149.141 25.396 147.197 26.764 144.557 26.764Z" fill="black"/><defs><clippath id="clip0_789_1365"><rect width="31.1894" height="36" fill="white"/></clippath></defs></svg></span><span class="MuiButton-endIcon MuiButton-iconSizeMedium css-pt151d"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-vubbuv" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="KeyboardArrowDownIcon"><path d="M7.41 8.59 12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/></svg></span></button></div><div class="css-1w2hxsf"><div class="MuiBox-root css-19itmc6"><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium css-jwr93t" tabindex="0" type="button"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-vubbuv" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="TranslateIcon"><path d="m12.87 15.07-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7 1.62-4.33L19.12 17h-3.24z"/></svg></button><button class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-textInherit MuiButton-sizeMedium MuiButton-textSizeMedium MuiButton-colorInherit MuiButton-disableElevation css-1r5wmim" tabindex="0" type="button" id="header-lang-switch" aria-haspopup="true"><span class="MuiButton-startIcon MuiButton-iconSizeMedium css-1l6c7y9"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1msahp5" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="TranslateIcon"><path d="m12.87 15.07-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7 1.62-4.33L19.12 17h-3.24z"/></svg></span><span class="MuiButton-endIcon MuiButton-iconSizeMedium css-pt151d"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1msahp5" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="KeyboardArrowDownIcon"><path d="M7.41 8.59 12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/></svg></span></button></div></div></div></header><div class="PingCAP-Doc MuiBox-root css-s1brf2"><div class="MuiBox-root css-hboir5"><aside class="MuiBox-root css-2tzg8"><div class="MuiBox-root css-ysaqso"><button class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeMedium MuiButton-textSizeMedium MuiButton-disableElevation css-1q0sqyi" tabindex="0" type="button" id="version-select-button" aria-haspopup="true"><div class="MuiTypography-root MuiTypography-body1 css-hg1lfe">v7.6 (DMR)</div><span class="MuiButton-endIcon MuiButton-iconSizeMedium css-pt151d"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1rrdqpg" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg></span></button><ul role="tree" id="left-nav-treeview" aria-multiselectable="false" class="MuiTreeView-root css-12mehxg" tabindex="0" aria-label="left navigation"><a class="MuiTypography-root MuiTypography-body1 css-z7v9yr" target="_blank" href="https://docs.pingcap.com/zh" style="text-decoration:none;width:100%;color:inherit"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-0" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">文档中心</div></div></div></div></div></li></a><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-1" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">关于 TiDB</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-2" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">快速上手</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-3" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">应用开发</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-4" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">部署标准集群</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-5" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">数据迁移</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-6" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">数据集成</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-7" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">运维操作</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-8" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">监控与告警</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-9" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">故障诊断</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-10" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">性能调优</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="true" id="left-nav-treeview-0-11" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content Mui-expanded" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-13dmm4z" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">教程</div></div></div></div></div><ul class="MuiCollapse-root MuiCollapse-vertical MuiTreeItem-group MuiCollapse-entered css-1xxsnna" style="min-height:0px" role="group"><div class="MuiCollapse-wrapper MuiCollapse-vertical css-hboir5"><div class="MuiCollapse-wrapperInner MuiCollapse-vertical css-8atqhb"><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/multi-data-centers-in-one-city-deployment"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-0" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-2jyri7"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">单区域多 AZ 部署</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/three-data-centers-in-two-cities-deployment"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-1" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-2jyri7"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">双区域多 AZ 部署</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/two-data-centers-in-one-city-deployment"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-2" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-2jyri7"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">单区域双 AZ 部署</div></div></div></div></div></li></a><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-11-3" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-2jyri7"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">读取历史数据</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="true" id="left-nav-treeview-0-11-4" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content Mui-expanded" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-2jyri7"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-13dmm4z" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">最佳实践</div></div></div></div></div><ul class="MuiCollapse-root MuiCollapse-vertical MuiTreeItem-group MuiCollapse-entered css-1xxsnna" style="min-height:0px" role="group"><div class="MuiCollapse-wrapper MuiCollapse-vertical css-hboir5"><div class="MuiCollapse-wrapperInner MuiCollapse-vertical css-8atqhb"><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/tidb-best-practices"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-0" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">TiDB 最佳实践</div></div></div></div></div></li></a><a aria-current="page" style="text-decoration:none;width:100%;color:inherit" class="" href="/zh/tidb/v7.6/java-app-best-practices"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-selected="true" id="left-nav-treeview-0-11-4-1" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content Mui-expanded Mui-selected" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">Java 应用开发最佳实践</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/haproxy-best-practices"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-2" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">HAProxy 最佳实践</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/high-concurrency-best-practices"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-3" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">高并发写入场景最佳实践</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/grafana-monitor-best-practices"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-4" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">Grafana 监控最佳实践</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/pd-scheduling-best-practices"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-5" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">PD 调度策略最佳实践</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/massive-regions-best-practices"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-6" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">海量 Region 集群调优</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/three-nodes-hybrid-deployment"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-7" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">三节点混合部署最佳实践</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/three-dc-local-read"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-8" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">在三数据中心下就近读取数据</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/uuid"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-9" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">使用 UUID</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/readonly-nodes"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-4-10" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-xeut16"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">只读存储节点最佳实践</div></div></div></div></div></li></a></div></div></ul></li><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/configure-placement-rules"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-5" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-2jyri7"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">Placement Rules 使用文档</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/configure-load-base-split"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-6" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-2jyri7"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">Load Base Split 使用文档</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/configure-store-limit"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-7" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-2jyri7"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">Store Limit 使用文档</div></div></div></div></div></li></a><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/ddl-introduction"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-11-8" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-2jyri7"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">DDL 执行原理及最佳实践</div></div></div></div></div></li></a></div></div></ul></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-12" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">TiDB 工具</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-13" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">参考指南</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-14" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">常见问题解答 (FAQ)</div></div></div></div></div></li><li class="MuiTreeItem-root css-14t19hb" role="treeitem" aria-expanded="false" id="left-nav-treeview-0-15" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiTreeItem-ChevronRightIcon css-hkir54" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ChevronRightIcon"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">版本发布历史</div></div></div></div></div></li><a style="text-decoration:none;width:100%;color:inherit" href="/zh/tidb/v7.6/glossary"><li class="MuiTreeItem-root css-14t19hb" role="treeitem" id="left-nav-treeview-0-16" tabindex="-1" style="margin-top:0.1875rem;margin-bottom:0.1875rem"><div class="css-zfdk9c MuiTreeItem-content" style="width:inherit"><div class="MuiTreeItem-iconContainer"/><div class="MuiTreeItem-label"><div class="css-w8t2sr"><div class="MuiBox-root css-3o0h5k"/><div class="MuiBox-root css-8atqhb"><div class="MuiTypography-root MuiTypography-body1 css-1rc6ywa">术语表</div></div></div></div></div></li></a></ul></div></aside><main class="MuiBox-root css-sb2sd0"><div class="MuiBox-root css-w0vdto"><div class="css-1q5cbag"><div class="MuiBox-root css-was4pq"><div class="MuiContainer-root MuiContainer-maxWidthLg MuiContainer-disableGutters doc-content css-5csqms"><div class="markdown-body MuiBox-root css-0"><div class="MuiBox-root css-1weqspv"><div class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation0 MuiAlert-root MuiAlert-standardError MuiAlert-standard css-kdwypz" role="alert"><div class="MuiAlert-icon css-1l54tgj"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ErrorOutlineIcon"><path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></svg></div><div class="MuiAlert-message css-1xsto0d"><div class="MuiTypography-root MuiTypography-body1 MuiTypography-gutterBottom MuiAlertTitle-root css-o4nulc">重要</div>你正在查看 TiDB 数据库的归档文档,归档文档不再提供任何更新。如无特殊需求,建议使用 TiDB 数据库的<a class="MuiTypography-root MuiTypography-body1 css-10lxhgt" target="_blank" href="https://docs.pingcap.com/zh/tidb/stable/java-app-best-practices" style="text-decoration:none">最新 LTS 版本</a>。</div></div></div><h1 id="开发-java-应用使用-tidb-的最佳实践" style="position:relative">开发 Java 应用使用 TiDB 的最佳实践<a href="#%E5%BC%80%E5%8F%91-java-%E5%BA%94%E7%94%A8%E4%BD%BF%E7%94%A8-tidb-%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5" aria-label="开发 java 应用使用 tidb 的最佳实践 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h1><p>本文主要介绍如何开发 Java 应用程序以更好地使用 TiDB,包括开发中的常见问题与最佳实践。</p><h2 id="java-应用中的数据库相关组件" style="position:relative">Java 应用中的数据库相关组件<a href="#java-%E5%BA%94%E7%94%A8%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9B%B8%E5%85%B3%E7%BB%84%E4%BB%B6" aria-label="java 应用中的数据库相关组件 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h2><p>通常 Java 应用中和数据库相关的常用组件有:</p><ul><li>网络协议:客户端通过标准 <a href="https://dev.mysql.com/doc/dev/mysql-server/latest/PAGE_PROTOCOL.html" target="_blank" referrerpolicy="no-referrer-when-downgrade">MySQL 协议</a>和 TiDB 进行网络交互。</li><li>JDBC API 及实现:Java 应用通常使用 <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/" target="_blank" referrerpolicy="no-referrer-when-downgrade">JDBC (Java Database Connectivity)</a> 来访问数据库。JDBC 定义了访问数据库 API,而 JDBC 实现完成标准 API 到 MySQL 协议的转换,常见的 JDBC 实现是 <a href="https://github.com/mysql/mysql-connector-j" target="_blank" referrerpolicy="no-referrer-when-downgrade">MySQL Connector/J</a>,此外有些用户可能使用 <a href="https://mariadb.com/kb/en/library/about-mariadb-connector-j/#about-mariadb-connectorj" target="_blank" referrerpolicy="no-referrer-when-downgrade">MariaDB Connector/J</a>。</li><li>数据库连接池:为了避免每次创建连接,通常应用会选择使用数据库连接池来复用连接,JDBC <a href="https://docs.oracle.com/javase/8/docs/api/javax/sql/DataSource.html" target="_blank" referrerpolicy="no-referrer-when-downgrade">DataSource</a> 定义了连接池 API,开发者可根据实际需求选择使用某种开源连接池实现。</li><li>数据访问框架:应用通常选择通过数据访问框架 (<a href="https://mybatis.org/mybatis-3/zh_CN/index.html" target="_blank" referrerpolicy="no-referrer-when-downgrade">MyBatis</a>, <a href="https://hibernate.org/" target="_blank" referrerpolicy="no-referrer-when-downgrade">Hibernate</a>) 的封装来进一步简化和管理数据库访问操作。</li><li>业务实现:业务逻辑控制着何时发送和发送什么指令到数据库,其中有些业务会使用 <a href="https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html" target="_blank" referrerpolicy="no-referrer-when-downgrade">Spring Transaction</a> 切面来控制管理事务的开始和提交逻辑。</li></ul><p><img src="https://download.pingcap.com/images/docs-cn/best-practices/java-practice-1.png" alt="Java Component"/></p><p>如上图所示,应用可能使用 Spring Transaction 来管理控制事务非手工启停,通过类似 MyBatis 的数据访问框架管理生成和执行 SQL,通过连接池获取已池化的长连接,最后通过 JDBC 接口调用实现通过 MySQL 协议和 TiDB 完成交互。</p><p>接下来将分别介绍使用各个组件时可能需要关注的问题。</p><h2 id="jdbc" style="position:relative">JDBC<a href="#jdbc" aria-label="jdbc permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h2><p>Java 应用尽管可以选择在不同的框架中封装,但在最底层一般会通过调用 JDBC 来与数据库服务器进行交互。对于 JDBC,需要关注的主要有:API 的使用选择和 API Implementer 的参数配置。</p><h3 id="jdbc-api" style="position:relative">JDBC API<a href="#jdbc-api" aria-label="jdbc api permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h3><p>对于基本的 JDBC API 使用可以参考 <a href="https://docs.oracle.com/javase/tutorial/jdbc/" target="_blank" referrerpolicy="no-referrer-when-downgrade">JDBC 官方教程</a>,本文主要强调几个比较重要的 API 选择。</p><h4 id="使用-prepare-api" style="position:relative">使用 Prepare API<a href="#%E4%BD%BF%E7%94%A8-prepare-api" aria-label="使用 prepare api permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><p>对于 OLTP 场景,程序发送给数据库的 SQL 语句在去除参数变化后都是可穷举的某几类,因此建议使用<a href="https://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html" target="_blank" referrerpolicy="no-referrer-when-downgrade">预处理语句 (Prepared Statements)</a> 代替普通的<a href="https://docs.oracle.com/javase/tutorial/jdbc/basics/processingsqlstatements.html#executing_queries" target="_blank" referrerpolicy="no-referrer-when-downgrade">文本执行</a>,并复用预处理语句来直接执行,从而避免 TiDB 重复解析和生成 SQL 执行计划的开销。</p><p>目前多数上层框架都会调用 Prepare API 进行 SQL 执行,如果直接使用 JDBC API 进行开发,注意选择使用 Prepare API。</p><p>另外需要注意 MySQL Connector/J 实现中默认只会做客户端的语句预处理,会将 <code>?</code> 在客户端替换后以文本形式发送到服务端,所以除了要使用 Prepare API,还需要在 JDBC 连接参数中配置 <code>useServerPrepStmts = true</code>,才能在 TiDB 服务器端进行语句预处理(下面参数配置章节有详细介绍)。</p><h4 id="使用-batch-批量插入更新" style="position:relative">使用 Batch 批量插入更新<a href="#%E4%BD%BF%E7%94%A8-batch-%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E6%9B%B4%E6%96%B0" aria-label="使用 batch 批量插入更新 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><p>对于批量插入更新,如果插入记录较多,可以选择使用 <a href="https://www.tutorialspoint.com/jdbc/jdbc-batch-processing" target="_blank" referrerpolicy="no-referrer-when-downgrade">addBatch/executeBatch API</a>。通过 addBatch 的方式将多条 SQL 的插入更新记录先缓存在客户端,然后在 executeBatch 时一起发送到数据库服务器。</p><div class="MuiBox-root css-1weqspv"><div class="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation0 MuiAlert-root MuiAlert-standardInfo MuiAlert-standard css-1bzshic" role="alert"><div class="MuiAlert-icon css-1l54tgj"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="InfoOutlinedIcon"><path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20, 12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10, 10 0 0,0 12,2M11,17H13V11H11V17Z"/></svg></div><div class="MuiAlert-message css-1xsto0d"><div class="MuiTypography-root MuiTypography-body1 MuiTypography-gutterBottom MuiAlertTitle-root css-o4nulc">注意</div><p>对于 MySQL Connector/J 实现,默认 Batch 只是将多次 addBatch 的 SQL 发送时机延迟到调用 executeBatch 的时候,但实际网络发送还是会一条条的发送,通常不会降低与数据库服务器的网络交互次数。</p><p>如果希望 Batch 网络发送,需要在 JDBC 连接参数中配置 <code>rewriteBatchedStatements = true</code>(下面参数配置章节有详细介绍)。</p></div></div></div><h4 id="使用-streamingresult-流式获取执行结果" style="position:relative">使用 StreamingResult 流式获取执行结果<a href="#%E4%BD%BF%E7%94%A8-streamingresult-%E6%B5%81%E5%BC%8F%E8%8E%B7%E5%8F%96%E6%89%A7%E8%A1%8C%E7%BB%93%E6%9E%9C" aria-label="使用 streamingresult 流式获取执行结果 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><p>一般情况下,为提升执行效率,JDBC 会默认提前获取查询结果并将其保存在客户端内存中。但在查询返回超大结果集的场景中,客户端会希望数据库服务器减少向客户端一次返回的记录数,等客户端在有限内存处理完一部分后再去向服务器要下一批。</p><p>在 JDBC 中通常有以下两种处理方式:</p><ul><li><p>设置 <a href="https://dev.mysql.com/doc/connector-j/en/connector-j-reference-implementation-notes.html#ResultSet" target="_blank" referrerpolicy="no-referrer-when-downgrade"><code>FetchSize</code> 为 <code>Integer.MIN_VALUE</code></a> 让客户端不缓存,客户端通过 StreamingResult 的方式从网络连接上流式读取执行结果。</p><p> 使用流式读取数据时,需要将 <code>resultset</code> 读取完成或 close 后,才能继续使用该语句进行下次查询,否则会报错 <code>No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.</code>。</p><p> 如果需要在 <code>resultset</code> 读取完成或 close 前进行查询避免上述报错,可在 URL 中添加配置参数 <code>clobberStreamingResults=true</code>,这样会自动 close <code>resultset</code>,但之前流式查询未被读取的结果集会丢失。</p></li><li><p>使用 Cursor Fetch,首先需<a href="http://makejavafaster.blogspot.com/2015/06/jdbc-fetch-size-performance.html" target="_blank" referrerpolicy="no-referrer-when-downgrade">设置 <code>FetchSize</code></a> 为正整数,且在 JDBC URL 中配置 <code>useCursorFetch = true</code>。</p></li></ul><p>TiDB 中同时支持两种方式,但更推荐使用第一种将 <code>FetchSize</code> 设置为 <code>Integer.MIN_VALUE</code> 的方式,比第二种功能实现更简单且执行效率更高。</p><h3 id="mysql-jdbc-参数" style="position:relative">MySQL JDBC 参数<a href="#mysql-jdbc-%E5%8F%82%E6%95%B0" aria-label="mysql jdbc 参数 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h3><p>JDBC 实现通常通过 JDBC URL 参数的形式来提供实现相关的配置。这里以 MySQL 官方的 Connector/J 来介绍<a href="https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html" target="_blank" referrerpolicy="no-referrer-when-downgrade">参数配置</a>(如果使用的是 MariaDB,可以参考 <a href="https://mariadb.com/kb/en/library/about-mariadb-connector-j/#optional-url-parameters" target="_blank" referrerpolicy="no-referrer-when-downgrade">MariaDB 的类似配置</a>)。因为配置项较多,这里主要关注几个可能影响到性能的参数。</p><h4 id="prepare-相关参数" style="position:relative">Prepare 相关参数<a href="#prepare-%E7%9B%B8%E5%85%B3%E5%8F%82%E6%95%B0" aria-label="prepare 相关参数 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><h5 id="useserverprepstmts" style="position:relative"><code>useServerPrepStmts</code><a href="#useserverprepstmts" aria-label="useserverprepstmts permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h5><p>默认情况下,<code>useServerPrepStmts</code> 的值为 <code>false</code>,即尽管使用了 Prepare API,也只会在客户端做 “prepare”。因此为了避免服务器重复解析的开销,如果同一条 SQL 语句需要多次使用 Prepare API,则建议设置该选项为 <code>true</code>。</p><p>在 TiDB 监控中可以通过 <strong>Query Summary</strong> > <strong>CPS By Instance</strong> 查看请求命令类型,如果请求中 <code>COM_QUERY</code> 被 <code>COM_STMT_EXECUTE</code> 或 <code>COM_STMT_PREPARE</code> 代替即生效。</p><h5 id="cacheprepstmts" style="position:relative"><code>cachePrepStmts</code><a href="#cacheprepstmts" aria-label="cacheprepstmts permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h5><p>虽然 <code>useServerPrepStmts = true</code> 能让服务端执行预处理语句,但默认情况下客户端每次执行完后会 close 预处理语句,并不会复用,这样预处理的效率甚至不如文本执行。所以建议开启 <code>useServerPrepStmts = true</code> 后同时配置 <code>cachePrepStmts = true</code>,这会让客户端缓存预处理语句。</p><p>在 TiDB 监控中可以通过 <strong>Query Summary</strong> > <strong>CPS By Instance</strong> 查看请求命令类型,如果请求中 <code>COM_STMT_EXECUTE</code> 数目远远多于 <code>COM_STMT_PREPARE</code> 即生效。</p><p>另外,通过 <code>useConfigs = maxPerformance</code> 配置会同时配置多个参数,其中也包括 <code>cachePrepStmts = true</code>。</p><h5 id="prepstmtcachesqllimit" style="position:relative"><code>prepStmtCacheSqlLimit</code><a href="#prepstmtcachesqllimit" aria-label="prepstmtcachesqllimit permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h5><p>在配置 <code>cachePrepStmts</code> 后还需要注意 <code>prepStmtCacheSqlLimit</code> 配置(默认为 <code>256</code>),该配置控制客户端缓存预处理语句的最大长度,超过该长度将不会被缓存。</p><p>在一些场景 SQL 的长度可能超过该配置,导致预处理 SQL 不能复用,建议根据应用 SQL 长度情况决定是否需要调大该值。</p><p>在 TiDB 监控中通过 <strong>Query Summary</strong> > <strong>CPS By Instance</strong> 查看请求命令类型,如果已经配置了 <code>cachePrepStmts = true</code>,但 <code>COM_STMT_PREPARE</code> 还是和 <code>COM_STMT_EXECUTE</code> 基本相等且有 <code>COM_STMT_CLOSE</code>,需要检查这个配置项是否设置得太小。</p><h5 id="prepstmtcachesize" style="position:relative"><code>prepStmtCacheSize</code><a href="#prepstmtcachesize" aria-label="prepstmtcachesize permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h5><p><code>prepStmtCacheSize</code> 控制缓存的预处理语句数目(默认为 <code>25</code>),如果应用需要预处理的 SQL 种类很多且希望复用预处理语句,可以调大该值。</p><p>和上一条类似,在监控中通过 <strong>Query Summary</strong> > <strong>CPS By Instance</strong> 查看请求中 <code>COM_STMT_EXECUTE</code> 数目是否远远多于 <code>COM_STMT_PREPARE</code> 来确认是否正常。</p><h4 id="batch-相关参数" style="position:relative">Batch 相关参数<a href="#batch-%E7%9B%B8%E5%85%B3%E5%8F%82%E6%95%B0" aria-label="batch 相关参数 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><p>在进行 batch 写入处理时推荐配置 <code>rewriteBatchedStatements = true</code>,在已经使用 <code>addBatch</code> 或 <code>executeBatch</code> 后默认 JDBC 还是会一条条 SQL 发送,例如:</p><pre><code class="hljs language-java"><div class="MuiBox-root css-1qhimia">pstmt = prepare(“insert into <span class="hljs-title function_">t</span> <span class="hljs-params">(a)</span> values(?)”); pstmt.setInt(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>); pstmt.addBatch(); pstmt.setInt(<span class="hljs-number">1</span>, <span class="hljs-number">11</span>); pstmt.addBatch(); pstmt.setInt(<span class="hljs-number">1</span>, <span class="hljs-number">12</span>); pstmt.executeBatch(); </div><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1rmx1rm" tabindex="0" type="button" aria-label="Toggle code wrap"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="WrapTextIcon"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></svg></button><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-fxo539" tabindex="0" type="button" aria-label="copy"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ContentCopyIcon"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></code></pre><p>虽然使用了 batch 但发送到 TiDB 语句还是单独的多条 insert:</p><pre><code class="hljs language-sql"><div class="MuiBox-root css-1qhimia"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t(a) <span class="hljs-keyword">values</span>(<span class="hljs-number">10</span>); <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t(a) <span class="hljs-keyword">values</span>(<span class="hljs-number">11</span>); <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t(a) <span class="hljs-keyword">values</span>(<span class="hljs-number">12</span>); </div><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1rmx1rm" tabindex="0" type="button" aria-label="Toggle code wrap"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="WrapTextIcon"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></svg></button><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-fxo539" tabindex="0" type="button" aria-label="copy"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ContentCopyIcon"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></code></pre><p>如果设置 <code>rewriteBatchedStatements = true</code>,发送到 TiDB 的 SQL 将是:</p><pre><code class="hljs language-sql"><div class="MuiBox-root css-1qhimia"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t(a) <span class="hljs-keyword">values</span>(<span class="hljs-number">10</span>),(<span class="hljs-number">11</span>),(<span class="hljs-number">12</span>); </div><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1rmx1rm" tabindex="0" type="button" aria-label="Toggle code wrap"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="WrapTextIcon"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></svg></button><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-fxo539" tabindex="0" type="button" aria-label="copy"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ContentCopyIcon"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></code></pre><p>需要注意的是,insert 语句的改写,只能将多个 values 后的值拼接成一整条 SQL,insert 语句如果有其他差异将无法被改写。例如:</p><pre><code class="hljs language-sql"><div class="MuiBox-root css-1qhimia"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t (a) <span class="hljs-keyword">values</span> (<span class="hljs-number">10</span>) <span class="hljs-keyword">on</span> duplicate key <span class="hljs-keyword">update</span> a <span class="hljs-operator">=</span> <span class="hljs-number">10</span>; <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t (a) <span class="hljs-keyword">values</span> (<span class="hljs-number">11</span>) <span class="hljs-keyword">on</span> duplicate key <span class="hljs-keyword">update</span> a <span class="hljs-operator">=</span> <span class="hljs-number">11</span>; <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t (a) <span class="hljs-keyword">values</span> (<span class="hljs-number">12</span>) <span class="hljs-keyword">on</span> duplicate key <span class="hljs-keyword">update</span> a <span class="hljs-operator">=</span> <span class="hljs-number">12</span>; </div><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1rmx1rm" tabindex="0" type="button" aria-label="Toggle code wrap"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="WrapTextIcon"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></svg></button><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-fxo539" tabindex="0" type="button" aria-label="copy"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ContentCopyIcon"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></code></pre><p>上述 insert 语句将无法被改写成一条语句。该例子中,如果将 SQL 改写成如下形式:</p><pre><code class="hljs language-sql"><div class="MuiBox-root css-1qhimia"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t (a) <span class="hljs-keyword">values</span> (<span class="hljs-number">10</span>) <span class="hljs-keyword">on</span> duplicate key <span class="hljs-keyword">update</span> a <span class="hljs-operator">=</span> <span class="hljs-keyword">values</span>(a); <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t (a) <span class="hljs-keyword">values</span> (<span class="hljs-number">11</span>) <span class="hljs-keyword">on</span> duplicate key <span class="hljs-keyword">update</span> a <span class="hljs-operator">=</span> <span class="hljs-keyword">values</span>(a); <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t (a) <span class="hljs-keyword">values</span> (<span class="hljs-number">12</span>) <span class="hljs-keyword">on</span> duplicate key <span class="hljs-keyword">update</span> a <span class="hljs-operator">=</span> <span class="hljs-keyword">values</span>(a); </div><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1rmx1rm" tabindex="0" type="button" aria-label="Toggle code wrap"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="WrapTextIcon"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></svg></button><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-fxo539" tabindex="0" type="button" aria-label="copy"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ContentCopyIcon"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></code></pre><p>即可满足改写条件,最终被改写成:</p><pre><code class="hljs language-sql"><div class="MuiBox-root css-1qhimia"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t (a) <span class="hljs-keyword">values</span> (<span class="hljs-number">10</span>), (<span class="hljs-number">11</span>), (<span class="hljs-number">12</span>) <span class="hljs-keyword">on</span> duplicate key <span class="hljs-keyword">update</span> a <span class="hljs-operator">=</span> <span class="hljs-keyword">values</span>(a); </div><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1rmx1rm" tabindex="0" type="button" aria-label="Toggle code wrap"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="WrapTextIcon"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></svg></button><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-fxo539" tabindex="0" type="button" aria-label="copy"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ContentCopyIcon"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></code></pre><p>批量更新时如果有 3 处或 3 处以上更新,则 SQL 语句会改写为 multiple-queries 的形式并发送,这样可以有效减少客户端到服务器的请求开销,但副作用是会产生较大的 SQL 语句,例如这样:</p><pre><code class="hljs language-sql"><div class="MuiBox-root css-1qhimia"><span class="hljs-keyword">update</span> t <span class="hljs-keyword">set</span> a <span class="hljs-operator">=</span> <span class="hljs-number">10</span> <span class="hljs-keyword">where</span> id <span class="hljs-operator">=</span> <span class="hljs-number">1</span>; <span class="hljs-keyword">update</span> t <span class="hljs-keyword">set</span> a <span class="hljs-operator">=</span> <span class="hljs-number">11</span> <span class="hljs-keyword">where</span> id <span class="hljs-operator">=</span> <span class="hljs-number">2</span>; <span class="hljs-keyword">update</span> t <span class="hljs-keyword">set</span> a <span class="hljs-operator">=</span> <span class="hljs-number">12</span> <span class="hljs-keyword">where</span> id <span class="hljs-operator">=</span> <span class="hljs-number">3</span>; </div><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1rmx1rm" tabindex="0" type="button" aria-label="Toggle code wrap"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="WrapTextIcon"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></svg></button><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-fxo539" tabindex="0" type="button" aria-label="copy"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ContentCopyIcon"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></code></pre><p>另外,因为一个<a href="https://bugs.mysql.com/bug.php?id=96623" target="_blank" referrerpolicy="no-referrer-when-downgrade">客户端 bug</a>,批量更新时如果要配置 <code>rewriteBatchedStatements = true</code> 和 <code>useServerPrepStmts = true</code>,推荐同时配置 <code>allowMultiQueries = true</code> 参数来避免这个 bug。</p><h4 id="集成参数" style="position:relative">集成参数<a href="#%E9%9B%86%E6%88%90%E5%8F%82%E6%95%B0" aria-label="集成参数 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><p>通过监控可能会发现,虽然业务只向集群进行 insert 操作,却看到有很多多余的 select 语句。通常这是因为 JDBC 发送了一些查询设置类的 SQL 语句(例如 <code>select @@session.transaction_read_only</code>)。这些 SQL 对 TiDB 无用,推荐配置 <code>useConfigs = maxPerformance</code> 来避免额外开销。</p><p><code>useConfigs = maxPerformance</code> 会包含一组配置,可查看 MySQL Connector/J <a href="https://github.com/mysql/mysql-connector-j/blob/release/8.0/src/main/resources/com/mysql/cj/configurations/maxPerformance.properties" target="_blank" referrerpolicy="no-referrer-when-downgrade">8.0 版本</a> 或 <a href="https://github.com/mysql/mysql-connector-j/blob/release/5.1/src/com/mysql/jdbc/configs/maxPerformance.properties" target="_blank" referrerpolicy="no-referrer-when-downgrade">5.1 版本</a> 来确认当前 MySQL Connector/J 中 <code>maxPerformance</code> 包含的具体配置。</p><p>配置后查看监控,可以看到多余语句减少。</p><h4 id="超时参数" style="position:relative">超时参数<a href="#%E8%B6%85%E6%97%B6%E5%8F%82%E6%95%B0" aria-label="超时参数 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><p>TiDB 提供两个与 MySQL 兼容的超时控制参数,<code>wait_timeout</code> 和 <code>max_execution_time</code>。这两个参数分别控制与 Java 应用连接的空闲超时时间和连接中 SQL 执行的超时时间,即控制 TiDB 与 Java 应用的连接最长闲多久和最长忙多久。这两个参数的默认值都是 <code>0</code>,即默认允许连接无限闲置以及无限忙碌(一个 SQL 语句执行无限的长的时间)。</p><p>但在实际生产环境中,空闲连接和一直无限执行的 SQL 对数据库和应用都有不好的影响。你可以通过在应用的连接字符串中配置这两个参数来避免空闲连接和执行时间过长的 SQL 语句。例如,设置 <code>sessionVariables=wait_timeout=3600</code>(1 小时)和 <code>sessionVariables=max_execution_time=300000</code>(5 分钟)。</p><h2 id="连接池" style="position:relative">连接池<a href="#%E8%BF%9E%E6%8E%A5%E6%B1%A0" aria-label="连接池 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h2><p>TiDB (MySQL) 连接建立是比较昂贵的操作(至少对于 OLTP),除了建立 TCP 连接外还需要进行连接鉴权操作,所以客户端通常会把 TiDB (MySQL) 连接保存到连接池中进行复用。</p><p>Java 的连接池实现很多 (<a href="https://github.com/brettwooldridge/HikariCP" target="_blank" referrerpolicy="no-referrer-when-downgrade">HikariCP</a>, <a href="https://tomcat.apache.org/tomcat-10.1-doc/jdbc-pool.html" target="_blank" referrerpolicy="no-referrer-when-downgrade">tomcat-jdbc</a>, <a href="https://github.com/alibaba/druid" target="_blank" referrerpolicy="no-referrer-when-downgrade">druid</a>, <a href="https://www.mchange.com/projects/c3p0/" target="_blank" referrerpolicy="no-referrer-when-downgrade">c3p0</a>, <a href="https://commons.apache.org/proper/commons-dbcp/" target="_blank" referrerpolicy="no-referrer-when-downgrade">dbcp</a>),TiDB 不会限定使用的连接池,应用可以根据业务特点自行选择连接池实现。</p><h3 id="连接数配置" style="position:relative">连接数配置<a href="#%E8%BF%9E%E6%8E%A5%E6%95%B0%E9%85%8D%E7%BD%AE" aria-label="连接数配置 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h3><p>比较常见的是应用需要根据自身情况配置合适的连接池大小,以 HikariCP 为例:</p><ul><li><code>maximumPoolSize</code>:连接池最大连接数,配置过大会导致 TiDB 消耗资源维护无用连接,配置过小则会导致应用获取连接变慢,所以需根据应用自身特点配置合适的值,可参考<a href="https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing" target="_blank" referrerpolicy="no-referrer-when-downgrade">这篇文章</a>。</li><li><code>minimumIdle</code>:连接池最小空闲连接数,主要用于在应用空闲时存留一些连接以应对突发请求,同样是需要根据业务情况进行配置。</li></ul><p>应用在使用连接池时,需要注意连接使用完成后归还连接,推荐应用使用对应的连接池相关监控(如 <code>metricRegistry</code>),通过监控能及时定位连接池问题。</p><h3 id="探活配置" style="position:relative">探活配置<a href="#%E6%8E%A2%E6%B4%BB%E9%85%8D%E7%BD%AE" aria-label="探活配置 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h3><p>连接池维护客户端到 TiDB 的长连接的方式如下:</p><ul><li>v5.4 版本前,TiDB 默认不会主动关闭客户端连接,除非出现报错情况。</li><li>从 v5.4 起,TiDB 默认会在连接空闲超过 <code>28800</code> 秒(即 8 小时)后,自动关闭客户端连接。你可以使用 TiDB 与 MySQL 兼容的 <code>wait_timeout</code> 变量控制此超时时间,详见 <a href="/zh/tidb/v7.6/dev-guide-timeouts-in-tidb#jdbc-查询超时">JDBC 查询超时</a>文档。</li></ul><p>此外,客户端到 TiDB 之间通常还会有 <a href="https://en.wikipedia.org/wiki/Linux_Virtual_Server" target="_blank" referrerpolicy="no-referrer-when-downgrade">LVS</a> 或 <a href="https://en.wikipedia.org/wiki/HAProxy" target="_blank" referrerpolicy="no-referrer-when-downgrade">HAProxy</a> 之类的网络代理。这些代理通常会在连接空闲超过特定时间(由代理的 idle 配置决定)后主动清理连接。除了关注代理的 idle 配置外,连接池还需要进行保活或探测连接。</p><p>如果常在 Java 应用中看到以下错误:</p><pre><code class="hljs language-plaintext"><div class="MuiBox-root css-1qhimia">The last packet sent successfully to the server was 3600000 milliseconds ago. The driver has not received any packets from the server. com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure </div><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1rmx1rm" tabindex="0" type="button" aria-label="Toggle code wrap"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="WrapTextIcon"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></svg></button><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-fxo539" tabindex="0" type="button" aria-label="copy"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ContentCopyIcon"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></code></pre><p>如果 <code>n milliseconds ago</code> 中的 <code>n</code> 如果是 0 或很小的值,则通常是执行的 SQL 导致 TiDB 异常退出引起的报错,推荐查看 TiDB stderr 日志;如果 n 是一个非常大的值(比如这里的 3600000),很可能是因为这个连接空闲太久然后被中间 proxy 关闭了,通常解决方式除了调大 proxy 的 idle 配置,还可以让连接池执行以下操作:</p><ul><li>每次使用连接前检查连接是否可用。</li><li>使用单独线程定期检查连接是否可用。</li><li>定期发送 test query 保活连接。</li></ul><p>不同的连接池实现可能会支持其中一种或多种方式,可以查看所使用的连接池文档来寻找对应配置。</p><h2 id="数据访问框架" style="position:relative">数据访问框架<a href="#%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AE%E6%A1%86%E6%9E%B6" aria-label="数据访问框架 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h2><p>业务应用通常会使用某种数据访问框架来简化数据库的访问。</p><h3 id="mybatis" style="position:relative">MyBatis<a href="#mybatis" aria-label="mybatis permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h3><p><a href="http://www.mybatis.org/mybatis-3/" target="_blank" referrerpolicy="no-referrer-when-downgrade">MyBatis</a> 是目前比较流行的 Java 数据访问框架,主要用于管理 SQL 并完成结果集和 Java 对象的来回映射工作。MyBatis 和 TiDB 兼容性很好,从历史 issue 可以看出 MyBatis 很少出现问题。这里主要关注如下几个配置。</p><h4 id="mapper-参数" style="position:relative">Mapper 参数<a href="#mapper-%E5%8F%82%E6%95%B0" aria-label="mapper 参数 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><p>MyBatis 的 Mapper 中支持两种参数:</p><ul><li><code>select 1 from t where id = #{param1}</code> 会作为预处理语句,被转换为 <code>select 1 from t where id = ?</code> 进行预处理,并使用实际参数来复用执行,通过配合前面的 Prepare 连接参数能获得最佳性能。</li><li><code>select 1 from t where id = ${param2}</code> 会做文本替换为 <code>select 1 from t where id = 1</code> 执行,如果这条语句被预处理为不同参数,可能会导致 TiDB 缓存大量的预处理语句,并且以这种方式执行 SQL 有注入安全风险。</li></ul><h4 id="动态-sql-batch" style="position:relative">动态 SQL Batch<a href="#%E5%8A%A8%E6%80%81-sql-batch" aria-label="动态 sql batch permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><p><a href="http://www.mybatis.org/mybatis-3/dynamic-sql.html#foreach" target="_blank" referrerpolicy="no-referrer-when-downgrade">动态 SQL - foreach</a></p><p>要支持将多条 insert 语句自动重写为 <code>insert ... values(...), (...), ...</code> 的形式,除了前面所说的在 JDBC 配置 <code>rewriteBatchedStatements = true</code> 外,MyBatis 还可以使用动态 SQL 来半自动生成 batch insert。比如下面的 mapper:</p><pre><code class="hljs language-xml"><div class="MuiBox-root css-1qhimia"><span class="hljs-tag"><<span class="hljs-name">insert</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"insertTestBatch"</span> <span class="hljs-attr">parameterType</span>=<span class="hljs-string">"java.util.List"</span> <span class="hljs-attr">fetchSize</span>=<span class="hljs-string">"1"</span>></span> insert into test (id, v1, v2) values <span class="hljs-tag"><<span class="hljs-name">foreach</span> <span class="hljs-attr">item</span>=<span class="hljs-string">"item"</span> <span class="hljs-attr">index</span>=<span class="hljs-string">"index"</span> <span class="hljs-attr">collection</span>=<span class="hljs-string">"list"</span> <span class="hljs-attr">separator</span>=<span class="hljs-string">","</span>></span> #{item.id}, #{item.v1}, #{item.v2} <span class="hljs-tag"></<span class="hljs-name">foreach</span>></span> on duplicate key update v2 = v1 + values(v1) <span class="hljs-tag"></<span class="hljs-name">insert</span>></span> </div><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1rmx1rm" tabindex="0" type="button" aria-label="Toggle code wrap"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="WrapTextIcon"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></svg></button><button class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-fxo539" tabindex="0" type="button" aria-label="copy"><svg class="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1cw4hi4" focusable="false" aria-hidden="true" viewbox="0 0 24 24" data-testid="ContentCopyIcon"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg></button></code></pre><p>会生成一个 <code>insert on duplicate key update</code> 语句,values 后面的 <code>(?, ?, ?)</code> 数目是根据传入的 list 个数决定,最终效果和使用 <code>rewriteBatchStatements = true</code> 类似,可以有效减少客户端和 TiDB 的网络交互次数,同样需要注意预处理后超过 <code>prepStmtCacheSqlLimit</code> 限制导致不缓存预处理语句的问题。</p><h4 id="streaming-结果" style="position:relative">Streaming 结果<a href="#streaming-%E7%BB%93%E6%9E%9C" aria-label="streaming 结果 permalink" class="anchor after"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"/></svg></a></h4><p>前面介绍了在 JDBC 中如何使用流式读取结果,除了 JDBC 相应的配置外,在 MyBatis 中如果希望读取超大结果集合也需要注意:</p><ul><li>可以通过在 mapper 配置中对单独一条 SQL 设置 <code>fetchSize</code>(见上一段代码段),效果等同于调用 JDBC <code>setFetchSize</code></li><li>可以使用带 <code>ResultHandler</code> 的查询接口来避免一次获取整个结果集</li><li>可以使用 <code>Cursor</code> 类来进行流式读取</li></ul><p>对于使用 xml 配置映射,可以通过在映射 <code><select></code> 部分配置 <code>fetchSize="-2147483648"</code>(<code>Integer.MIN_VALUE</code>) 来流式读取结果。</p><pre><code class="hljs language-xml"><div class="MuiBox-root css-1qhimia"><span class="hljs-tag"><<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"getAll"</span> <span class="hljs-attr">resultMap</span>=<span class="hljs-string">"postResultMap"</span> <span class="hljs-attr">fetchSize</span>=<span class="hljs-string">"-2147483648"</span>></span>
推荐文章