{"id":371257,"date":"2024-05-21T04:44:26","date_gmt":"2024-05-21T04:44:26","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=371257"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-05-21T04:44:26","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=371257","title":{"rendered":"<span>\u041a\u0430\u043a \u043c\u044b \u043f\u0435\u0440\u0435\u0435\u0445\u0430\u043b\u0438 \u0441 Oracle \u043d\u0430 PostgreSQL \u0432 \u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u0431\u0435\u0437 \u0434\u0430\u0443\u043d\u0442\u0430\u0439\u043c\u0430<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3fc\/ef1\/4cd\/3fcef14cd499224f06a824eab4ced815.png\" alt=\"\u0413\u0440\u0430\u0444\u0438\u043a 99-\u0433\u043e \u043f\u0435\u0440\u0446\u0435\u043d\u0442\u0438\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e user-facing-\u0441\u0435\u0440\u0432\u0438\u0441\u0430: \u0436\u0438\u0437\u043d\u044c \u0434\u043e, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0435\u0437\u0434\u0430. \u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u043b\u043e \u043b\u0443\u0447\u0448\u0435!\" title=\"\u0413\u0440\u0430\u0444\u0438\u043a 99-\u0433\u043e \u043f\u0435\u0440\u0446\u0435\u043d\u0442\u0438\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e user-facing-\u0441\u0435\u0440\u0432\u0438\u0441\u0430: \u0436\u0438\u0437\u043d\u044c \u0434\u043e, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0435\u0437\u0434\u0430. \u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u043b\u043e \u043b\u0443\u0447\u0448\u0435!\" width=\"1600\" height=\"629\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3fc\/ef1\/4cd\/3fcef14cd499224f06a824eab4ced815.png\"\/><\/p>\n<div><figcaption>\u0413\u0440\u0430\u0444\u0438\u043a 99-\u0433\u043e \u043f\u0435\u0440\u0446\u0435\u043d\u0442\u0438\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e user-facing-\u0441\u0435\u0440\u0432\u0438\u0441\u0430: \u0436\u0438\u0437\u043d\u044c \u0434\u043e, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0435\u0437\u0434\u0430. \u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u043b\u043e \u043b\u0443\u0447\u0448\u0435!<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u042f \u0421\u0435\u0440\u0433\u0435\u0439, \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 B2B-\u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u042f\u043d\u0434\u0435\u043a\u0441 \u041c\u0430\u0440\u043a\u0435\u0442\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 3,5\u00a0\u0433\u043e\u0434\u0430. \u041a\u0430\u043a \u0443\u0436\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430, \u0441\u0435\u0439\u0447\u0430\u0441 \u044f \u0432\u0430\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e yet-another-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u0431\u0430\u0437\u044b \u043d\u0430 \u0431\u0430\u0437\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u0447\u0430\u043b\u0430\u0441\u044c \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 2021 \u0433\u043e\u0434\u0430 \u0438 \u0437\u0430\u043d\u044f\u043b\u0430 \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0434. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u043c\u0435\u043c\u0443\u0430\u0440\u044b.<\/p>\n<p>\u0412\u0430\u0441 \u0436\u0434\u0451\u0442 \u0440\u0430\u0441\u0441\u043a\u0430\u0437 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u044b:<\/p>\n<ul>\n<li>\n<p>\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432 \u0447\u0438\u043d\u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \u0438 \u0434\u0435\u043b\u0430\u043b\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440;<\/p>\n<\/li>\n<li>\n<p>\u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0440\u0430\u0437 \u043f\u0435\u0440\u0435\u043b\u0438\u0432\u0430\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435;<\/p>\n<\/li>\n<li>\n<p>\u0447\u0438\u043d\u0438\u043b\u0438 \u0431\u0430\u0433\u0438 \u043d\u0435\u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0437\u0430\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 PostgreSQL \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043d\u0430 Oracle.<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h2>\u0427\u0442\u043e \u0431\u044b\u043b\u043e \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435<\/h2>\n<p>\u0415\u0441\u0442\u044c \u0432 \u042f\u043d\u0434\u0435\u043a\u0441 \u041c\u0430\u0440\u043a\u0435\u0442\u0435 \u043e\u0434\u0438\u043d \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043f\u0430\u0440\u0442\u043d\u0451\u0440\u0430\u043c\u0438 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u0440\u043e\u0434\u0430\u0432\u0446\u0430\u043c\u0438 \u0438\u043b\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430\u043c\u0438. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f, \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0430\u0441\u0441\u043e\u0440\u0442\u0438\u043c\u0435\u043d\u0442\u043e\u043c, \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u043a\u0430\u0437\u043e\u0432 \u2014 \u0432 \u043e\u0431\u0449\u0435\u043c, \u0432 \u043d\u0451\u043c \u0441\u043e\u0431\u0440\u0430\u043d\u043e \u0432\u0441\u0451, \u0441 \u0447\u0435\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0430\u0440\u0442\u043d\u0451\u0440\u0430\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c.\u00a0<\/p>\n<p>\u041f\u043e \u0441\u0443\u0442\u0438 \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u0445 API (\u0431\u044d\u043a \u0434\u043b\u044f \u043f\u0430\u0440\u0442\u043d\u0451\u0440\u0441\u043a\u043e\u0433\u043e UI, API \u0434\u043b\u044f \u043f\u0430\u0440\u0442\u043d\u0451\u0440\u043e\u0432, API \u0434\u043b\u044f \u0441\u043c\u0435\u0436\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c), \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0434\u043b\u044f \u0444\u043e\u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 (\u0432\u0441\u044f\u043a\u0438\u0435 \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u0435 \u0440\u0430\u0441\u0447\u0451\u0442\u044b, \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u0447\u0451\u0442\u043e\u0432, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441\u043e \u0441\u043c\u0435\u0436\u043d\u044b\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438) \u0438 \u0430\u0434\u043c\u0438\u043d\u043a\u0430. \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u044d\u0442\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0436\u0438\u0432\u0451\u0442 \u043d\u0430 \u043e\u0431\u0449\u0435\u0439 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0441\u0432\u043e\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0422\u0430\u043a \u0438\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043b\u043e\u0436\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0431\u044b\u043b Oracle. \u041f\u043e\u0447\u0435\u043c\u0443? \u041f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u0437\u0430\u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043e\u043d \u0443\u0436\u0435 \u0431\u044b\u043b \u043a\u0443\u043f\u043b\u0435\u043d, \u0430 \u043c\u044b \u0432\u0437\u044f\u043b\u0438 \u0442\u043e, \u0447\u0442\u043e \u0431\u044b\u043b\u043e. \u0421\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 Oracle \u2014 \u044d\u0442\u043e \u043c\u043e\u0449\u043d\u0430\u044f \u0431\u0430\u0437\u0430. \u0412 \u044d\u0442\u043e\u043c \u043f\u043b\u0430\u043d\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u043d\u0435\u0439 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0436\u0438\u0442\u044c \u043d\u0430 \u043d\u0435\u0439 \u0438 \u0434\u0430\u043b\u044c\u0448\u0435, \u0435\u0441\u043b\u0438 \u0431\u044b \u043d\u0435 \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u2014 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438.<\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, Oracle \u0436\u0438\u043b \u043d\u0430 \u0434\u043e\u0440\u043e\u0433\u0438\u0445 \u0436\u0435\u043b\u0435\u0437\u043d\u044b\u0445 \u0442\u0430\u0447\u043a\u0430\u0445, \u0431\u0435\u0437 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, Oracle DBA \u2014 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0440\u043e\u0433\u0438\u0435 \u0440\u0435\u0431\u044f\u0442\u0430 \u0438 \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043d\u0430 \u0432\u0441\u044e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044e \u0438\u0445 \u0441\u0442\u0430\u043b\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0442\u044c. \u041d\u0443 \u0438 \u0432-\u0442\u0440\u0435\u0442\u044c\u0438\u0445, \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u043b\u0430\u0442\u043d\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 Oracle, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0451\u043d\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438, \u0441\u043e\u00a0\u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0441\u0442\u0430\u043b\u0430 \u043e\u0433\u0440\u043e\u043c\u043d\u0430.<\/p>\n<p>\u0412\u043e\u043f\u0440\u043e\u0441 \u043f\u0435\u0440\u0435\u0435\u0437\u0434\u0430 \u0441 Oracle \u0432\u0441\u0442\u0430\u043b \u0440\u0435\u0431\u0440\u043e\u043c.<\/p>\n<p>\u0410 \u0442\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u044c PostgreSQL \u0440\u043e\u0441\u043b\u0430 \u043a\u0430\u043a \u043d\u0430 \u0434\u0440\u043e\u0436\u0436\u0430\u0445, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u0432 \u042f\u043d\u0434\u0435\u043a\u0441\u0435. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432\u043e \u0433\u043b\u0430\u0432\u0443 \u0443\u0433\u043b\u0430 \u0431\u044b\u043b\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438, \u0442\u043e \u0440\u0435\u0448\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0435\u0437\u0436\u0430\u0442\u044c \u043d\u0430 Managed Service for PostgreSQL \u0432 Yandex Cloud.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043e\u0431\u0440\u0438\u0441\u0443\u044e\u2026\u00a0<\/p>\n<h3>\u0421\u0442\u0430\u0440\u0442\u043e\u0432\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f<\/h3>\n<ul>\n<li>\n<p>\u041e\u043a\u043e\u043b\u043e 1,5 TiB \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 Oracle, \u043e\u0434\u0438\u043d \u0448\u0430\u0440\u0434, \u0431\u043e\u043b\u0435\u0435 700\u00a0\u0442\u0430\u0431\u043b\u0438\u0446, \u0431\u043e\u043b\u0435\u0435 250\u00a0view, \u043d\u0435\u043c\u043d\u043e\u0436\u043a\u043e stored procedure.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435 \u0432 \u0431\u0443\u0434\u043d\u0438 \u2014 \u0434\u043e 3,5k\u00a0RPS \u0432 API, \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0430\u043a \u0438\u043b\u0438 \u0438\u043d\u0430\u0447\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u043a \u0431\u0430\u0437\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0430\u0440\u0430 \u0441\u043e\u0442\u0435\u043d \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0444\u043e\u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u043d\u043e\u043b\u0438\u0442\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441-\u0434\u0435\u0434\u0443\u0448\u043a\u0430 \u043d\u0430 Spring 5.1.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0430\u0437\u043e\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Spring JDBC, \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e Hibernate.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u043e\u0447\u0435\u043d\u044c \u043d\u0435\u043f\u043b\u043e\u0445\u043e\u0435 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u043c\u0438, \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0438 \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u0430\u043c\u0438 (\u044d\u0442\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043a\u0440\u0430\u0439\u043d\u0435 \u0432\u0430\u0436\u043d\u044b\u043c \u043f\u043e\u0434\u0441\u043f\u043e\u0440\u044c\u0435\u043c).<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u0438\u0437 20 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442 \u043d\u0430\u0432\u0430\u043b\u0438\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0444\u0438\u0447\u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c.<\/p>\n<\/li>\n<li>\n<p>\u042f \u0438 \u043e\u0434\u0438\u043d \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 \u043f\u043e\u043c\u043e\u0449\u044c \u0441\u0442\u0430\u0436\u0451\u0440 \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0435\u0440\u0445\u043d\u0435\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u043e \u0441\u0445\u0435\u043c\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u0430 \u0442\u0430\u043a, \u043d\u0438\u0447\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6fa\/f7a\/a14\/6faf7aa14a315355b3b3b5cbb848d7e2.png\" width=\"2000\" height=\"600\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6fa\/f7a\/a14\/6faf7aa14a315355b3b3b5cbb848d7e2.png\"\/><\/figure>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u043d\u0435 \u0432\u0440\u0443\u0447\u0438\u043b\u0438 \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u043a\u0443 \u043f\u0435\u0440\u0435\u0435\u0437\u0434\u0430, \u0431\u044b\u043b\u0430 \u043d\u0430\u0434\u0435\u0436\u0434\u0430, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u044b \u0438\u00a0\u043f\u0435\u0440\u0435\u0435\u0445\u0430\u0442\u044c \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c \u0437\u0430 \u043c\u043d\u043e\u0433\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439. \u041f\u0440\u043e\u0432\u0435\u043b\u0438 \u0430\u043d\u0430\u043b\u0438\u0437 \u0441\u0432\u044f\u0437\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c, \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0432 \u0433\u0440\u0430\u0444 \u0442\u0430\u0431\u043b\u0438\u0446 \u043f\u043e join \u0438\u0437 \u043b\u043e\u0433\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u0430\u0437\u044b \u0438 \u043f\u043e foreign key \u0438\u0437 \u0441\u0445\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446. \u0418 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u043d\u0430\u043c\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0437\u0430\u043f\u0443\u0442\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0443\u0431\u043e\u043a, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u0441\u0451 \u0437\u0430\u0432\u044f\u0437\u0430\u043d\u043e \u0442\u0440\u0430\u043d\u0437\u0438\u0442\u0438\u0432\u043d\u043e \u043d\u0430 \u0432\u0441\u0451 (\u0437\u0430\u00a0\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c\u0438). \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0438\u0441\u0445\u043e\u0434\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u043e\u043b\u0435\u0435 700\u00a0\u0442\u0430\u0431\u043b\u0438\u0446, \u0430 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043a\u043b\u0443\u0431\u043a\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u043e\u043b\u0435\u0435\u00a0600. \u041a\u043e\u0433\u0434\u0430 \u0432\u0437\u0433\u043b\u044f\u043d\u0443\u043b\u0438 \u043d\u0430 \u044d\u0442\u043e \u0432\u0441\u0451 (\u043d\u0435 \u0431\u0435\u0437 \u0441\u043b\u0451\u0437), \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u043e\u0433\u043e \u0441\u043b\u043e\u043d\u0430 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043c\u043d\u043e\u0433\u043e \u043b\u0435\u0442.<\/p>\n<p>\u0412\u043e\u043f\u0440\u043e\u0441 \u0441 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u043e \u043a\u0443\u0441\u043a\u0430\u043c \u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0438 \u043d\u0430 \u043f\u043e\u043b\u043a\u0443 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u0437\u0430\u0439\u0442\u0438 \u0441 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043a\u043e\u043d\u0446\u0430. \u0421\u0442\u0430\u043b\u0438 \u0434\u0443\u043c\u0430\u0442\u044c, \u043a\u0430\u043a \u0431\u044b \u043c\u044b \u0441\u0442\u0430\u043b\u0438 \u043f\u0435\u0440\u0435\u043b\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0441\u0442\u0430\u0440\u043e\u0439 \u0431\u0430\u0437\u044b \u0432 \u043d\u043e\u0432\u0443\u044e \u2014 \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0440\u0435\u0448\u0430\u0442\u044c. \u041f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0442\u0430\u043a\u0438\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u043a\u043e\u0439-\u0442\u043e \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u0451\u0440\u0433\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043e\u0434\u043d\u043e\u0439 \u0431\u0430\u0437\u044b \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u0434\u0440\u0443\u0433\u0443\u044e. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043e\u0434\u043d\u0430\u0436\u0434\u044b \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0432 \u041c\u0430\u0440\u043a\u0435\u0442\u0435, \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043e\u0434\u043d\u0430\u043a\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u0442\u0430\u043c \u0431\u044b\u043b\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0449\u0435 (\u043d\u0435 \u0431\u044b\u043b\u043e user-facing-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432).<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/laurenz\/oracle_fdw\"><u>oracle_fdw<\/u><\/a>. \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e: live-\u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 Oracle, \u043d\u043e \u0432 PostgreSQL. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 join \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u044d\u0442\u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 <a href=\"https:\/\/github.com\/laurenz\/oracle_fdw\/issues\/171#issuecomment-304862839\"><u>\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b\u043c<\/u><\/a>. \u041d\u0443 \u0438 \u0432\u0441\u0451 \u0436\u0435 \u044d\u0442\u043e \u043d\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043a\u0430\u043a \u0442\u0430\u043a\u043e\u0432\u0430\u044f.\u00a0<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/ora2pg.darold.net\/index.html\"><u>Ora2Pg<\/u><\/a>. \u0412 \u0441\u0432\u043e\u0451\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0430\u0434\u043e. \u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e one-shot-\u0442\u0443\u043b\u0437\u0430, \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c stop the world. \u0410 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043d\u0435\u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u043e.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Change_data_capture\"><u>CDC<\/u><\/a> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Oracle GoldenGate). \u0422\u0443\u0442 \u0443\u0436\u0435 \u0441\u0442\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0439. \u0415\u0441\u043b\u0438 \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043d\u0438\u0437\u043a\u043e\u0433\u043e \u043b\u0430\u0433\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0442\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c in-sync-\u0431\u0430\u0437\u044b, \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u00a0\u0421\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u044d\u0442\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b, \u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442&#8230;<\/p>\n<h3>\u0418\u0434\u0435\u044f<\/h3>\n<p>\u0423 \u043d\u0430\u0441 \u0432\u0435\u0434\u044c \u043f\u043e\u043b\u043d\u043e \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0433\u043e\u043d\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 H2 \u0432 <a href=\"https:\/\/www.h2database.com\/html\/features.html?highlight=oracle#compatibility\"><u>\u0440\u0435\u0436\u0438\u043c\u0435 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441 Oracle<\/u><\/a>. \u0412\u00a0\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a H2 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u0430\u043c\u043e\u043f\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0443 H2. \u0410 \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u0432\u0437\u044f\u0442\u044c CDC, \u043f\u043e\u0445\u043e\u0436\u0443\u044e \u0438\u0434\u0435\u044e \u0441 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u043c, \u0438 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a PostgreSQL \u043d\u0430 \u043b\u0435\u0442\u0443? \u0422\u0435\u0441\u0442\u044b \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u0442\u044c \u2014 \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c?<\/p>\n<p>\u0421\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043b\u0430\u043d:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0438 \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0442\u0430\u0440\u044b\u0435 \u043c\u0443\u0441\u043e\u0440\u043d\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0438 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043b\u044c\u0448\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u043e\u0442\u0441\u0435\u0447\u043a\u0443 \u0431\u043e\u043b\u0435\u0435 10 GiB \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e) \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0443\u0432\u043e\u0437\u0438\u0442\u044c \u0432 \u0434\u0440\u0443\u0433\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u2014 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0438\u043c\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c <a href=\"https:\/\/habr.com\/ru\/companies\/yandex\/articles\/785994\/\"><u>\u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b YTsaurus<\/u><\/a>.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0443 \u0438\u0437 Oracle \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0446\u0435\u043b\u0435\u0432\u0443\u044e \u0441\u0445\u0435\u043c\u0443 \u0432 PostgreSQL.<\/p>\n<\/li>\n<li>\n<p>\u0414\u0435\u043b\u0430\u0435\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 Oracle \u0432 PostgreSQL \u0438\u00a0\u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u043c \u0442\u0435\u0441\u0442\u044b c H2 \u043d\u0430 embedded PostgreSQL.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f CDC, \u043b\u044c\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0441\u0440\u0435\u0434\u0435, \u0447\u0438\u043d\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u043c \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u043c \u0432\u0441\u0435 \u043f\u0443\u043d\u043a\u0442\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430.<\/p>\n<\/li>\n<li>\n<p>Profit?<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043b\u0430\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u043b \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043a\u0435\u043f\u0441\u0438\u0441\u0430 \u0438 \u0441\u043e\u043c\u043d\u0435\u043d\u0438\u0439 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430. \u041d\u043e, \u043a\u0430\u043a \u0432\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442\u0435, \u0440\u0430\u0437 \u0432\u044b \u0447\u0438\u0442\u0430\u0435\u0442\u0435 \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e, \u043e\u043d \u043a\u0430\u043a-\u0442\u043e \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b.<\/p>\n<h2>\u0412\u043e\u043f\u043b\u043e\u0449\u0430\u0435\u043c \u043f\u043b\u0430\u043d \u0432 \u0436\u0438\u0437\u043d\u044c<\/h2>\n<p>\u041f\u043e \u043f\u043b\u0430\u043d\u0443 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0448\u0442\u0443\u043a\u0438 \u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044f\u0442\u0441\u044f \u0438 \u043d\u0435 \u043c\u0435\u0448\u0430\u044e\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443. \u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0430\u0441 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0431\u044b\u043b\u043e \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0437\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0435\u0448\u0438\u043b\u0438 \u0441 \u0447\u0435\u0433\u043e-\u0442\u043e \u043e\u0441\u044f\u0437\u0430\u0435\u043c\u043e\u0433\u043e \u2014 \u0441 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h3>\u0422\u0435\u0441\u0442\u044b \u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440<\/h3>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u0438\u0434\u0435\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043b\u0430 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0442\u043e, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043e\u043d \u0436\u0435\u00a0\u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u043e\u0438\u0442 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u043d\u0430 PostgreSQL \u0432\u043c\u0435\u0441\u0442\u043e H2. \u041d\u0430 \u043d\u0430\u0447\u0430\u043b\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e \u043e\u043a\u043e\u043b\u043e 15 \u0442\u044b\u0441\u044f\u0447 \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0431\u044b\u043b\u0430 \u043f\u043e\u043a\u0440\u044b\u0442\u0430 \u0431\u00f3\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. \u0414\u043b\u044f \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0442\u0430\u043a\u043e\u043c \u043e\u0431\u044a\u0451\u043c\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043c\u043d\u043e\u0433\u043e \u0440\u0443\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u043a\u043e\u0440\u0435 \u043d\u0430\u0448\u043b\u0438\u0441\u044c \u0432\u00a0\u0432\u0438\u0434\u0435 \u0435\u0449\u0451 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0442\u0430\u0436\u0451\u0440\u043e\u0432.<\/p>\n<p>\u0414\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u0432 PostgreSQL \u043c\u044b \u0441\u043f\u0435\u0440\u0432\u0430 \u0441\u0434\u0430\u043c\u043f\u0438\u043b\u0438 \u0441\u0445\u0435\u043c\u044b \u0432\u0441\u0435\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438\u0437 Oracle. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0432\u0441\u0451, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u0434 \u0440\u0443\u043a\u043e\u0439, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 <a href=\"https:\/\/github.com\/darold\/ora2pg\"><u>Ora2Pg<\/u><\/a>, <a href=\"https:\/\/www.jetbrains.com\/datagrip\/\"><u>DataGrip<\/u><\/a>, <a href=\"https:\/\/www.oracle.com\/database\/sqldeveloper\/\"><u>Oracle SQL Developer<\/u><\/a>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u043c\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 \u043d\u0430 Python \u043f\u0440\u0438\u0432\u0435\u043b\u0438 \u0438\u0445 \u0432\u0441\u0435\u0445 \u043a \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e \u00abliquibase \u0432 PostgreSQL \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u043e\u0436\u0435\u0432\u0430\u0442\u044c\u00bb. \u041a\u0441\u0442\u0430\u0442\u0438, \u043f\u0440\u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u0442\u0438\u043f\u043e\u0432 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0433\u043b\u0430 <a href=\"https:\/\/habr.com\/ru\/articles\/335716\/\"><u>\u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445<\/u><\/a> \u0438 <a href=\"https:\/\/www.enterprisedb.com\/blog\/the-complete-oracle-to-postgresql-migration-guide-tutorial-move-convert-database-oracle-alternative\"><u>\u0433\u0430\u0439\u0434 \u043f\u043e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438<\/u><\/a>.\u00a0<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440. \u041f\u043e \u0444\u0430\u043a\u0442\u0443 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u043b\u0435\u0442\u0443. \u0411\u0430\u0437\u043e\u0432\u0430\u044f \u043e\u0431\u0432\u044f\u0437\u043a\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a (\u043a\u043e\u0434 \u0443\u043f\u0440\u043e\u0449\u0451\u043d, \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0443\u0442\u044c):<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@FunctionalInterface public interface Transformer {     String transform(String sql); }  \/** \u042d\u0442\u0438\u043c \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f *\/ public static DataSource wrap(DataSource dataSource, Transformer transformer) {     return new DataSource() {         @Override         public Connection getConnection() throws SQLException {             return wrap(dataSource.getConnection(), transformer);         }          @Override         public Connection getConnection(String username, String password) throws SQLException {             return wrap(dataSource.getConnection(username, password), transformer);         }          \/\/ \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u044b as is...         \/\/ \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438-\u043a\u043b\u0430\u0441\u0441, \u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0438 \u0442\u0430\u043a \u0441\u043e\u0439\u0434\u0451\u0442     }; }  public static Connection wrap(Connection connection, Transformer transformer) {     var handler = new ConnectionProxy(connection, transformer);     return (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), new Class&lt;?>[]{Connection.class}, handler); }  private record ConnectionProxy(Connection proxee, Transformer transformer) implements InvocationHandler {     private static final Set&lt;String> METHODS_FOR_PREPARED_STATEMENT = Set.of(         \"prepareCall\",         \"prepareStatement\"     );     private static final String METHODS_FOR_STATEMENT = \"createStatement\";      @Override     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         if (METHODS_FOR_PREPARED_STATEMENT.contains(method.getName())) {             var sql = args[0].toString();             args[0] = transformer.transform(sql);             return method.invoke(proxee, args);         }         var result = method.invoke(proxee, args);         if (result instanceof Statement statement &amp;&amp; METHODS_FOR_STATEMENT.equals(method.getName())) {             var handler = new StatementProxy(statement, transformer);             return Proxy.newProxyInstance(Statement.class.getClassLoader(), new Class&lt;?>[]{Statement.class}, handler);         }         return result;     } }  private record StatementProxy(Statement proxee, Transformer transformer) implements InvocationHandler {     private static final Set&lt;String> METHODS_WITH_QUERY = Set.of(         \"addBatch\",         \"execute\",         \"executeLargeUpdate\",         \"executeQuery\",         \"executeUpdate\"     );      @Override     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         if (METHODS_WITH_QUERY.contains(method.getName())) {             var sql = args[0].toString();             args[0] = transformer.transform(sql);         }         return method.invoke(proxee, args);     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u043e\u0432\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440 \u0434\u043b\u044f Oracle \u0441\u043f\u0443\u0441\u0442\u044f \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"java\">public enum OracleToPostgresTransformer implements Transformer {     INSTANCE;      \/\/ Map.entry \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a \u043f\u0430\u0440\u0430     private static final List&lt;Map.Entry&lt;Pattern, String>> PATTERNS = Stream.of(         Map.entry(\"\\\\browid\\\\b\", \"ctid\"),         Map.entry(\"\\\\bsys(?:date|timestamp)\\\\b\", \"current_timestamp\"),         Map.entry(\"\\\\bas clob\\\\b\", \"as text\"),         Map.entry(\"\\\\bas number\\\\b\", \"as numeric\"),         Map.entry(\"\\\\bminus\\\\b\", \"except\"), \/\/ select minus select         Map.entry(\"n?varchar2\\\\((?&lt;v1>\\\\d+)(?:\\\\s+char)?\\\\)\", \"varchar(${v1})\"),         Map.entry(\"\\\\blistagg\\\\b\", \"string_agg\"), \/\/ + below         Map.entry(             \"\\\\) within group\\\\s*\\\\(\\\\s*order by (?&lt;v1>[^)]+)\\\\)\", \/\/ listagg(...) within group (order by ...)             \" order by ${v1})\" \/\/ string_agg(... order by ...)         ),         Map.entry(\"(?&lt;seq>[\\\\w.]+)\\\\.nextval\", \"nextval('${seq}')\"),         Map.entry(\"rownum(?: as)? (?&lt;v1>\\\\w+)\", \"row_number() over() as ${v1}\"),         \/\/ ... \u0438 \u0435\u0449\u0451 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0445 \u0434\u043b\u044f \u043d\u0430\u0441 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0439     ).map(e -> Map.entry(makeRegexp(e.getKey()), e.getValue())).toList();      private static Pattern makeRegexp(String regex) {         return Pattern.compile(                 regex.replaceAll(\"\\\\s+\", \"\\\\\\\\s+\"), \/\/ to simplify writing spaces in patterns                 Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.DOTALL         );     }      @Override     public String transform(String sql) {         for (var pattern : PATTERNS) {             sql = pattern.getKey().matcher(sql).replaceAll(pattern.getValue());         }         return sql;     } }<\/code><\/pre>\n<p>\u041f\u043e\u0432\u0435\u0440\u0445 \u0442\u0430\u043a\u0436\u0435 \u0431\u044b\u043b\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 (\u043f\u0440\u043e\u0441\u0442\u043e Guava-\u043a\u044d\u0448), \u043c\u0435\u0442\u0440\u0438\u043a\u0438 (\u0440\u0430\u0437\u043c\u0435\u0440 \u043a\u044d\u0448\u0430, \u0447\u0438\u0441\u043b\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0447\u0438\u0441\u043b\u043e \u043e\u0448\u0438\u0431\u043e\u043a), \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.\u00a0<\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0432 \u0441\u0445\u0435\u043c\u0443 \u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440 \u0441 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438, \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \u043d\u0430 PostgreSQL \u0438 \u043f\u044b\u0442\u0430\u043b\u0438\u0441\u044c \u0438\u0445 \u043e\u0437\u0435\u043b\u0435\u043d\u0438\u0442\u044c. \u041f\u0435\u0440\u0432\u043e\u0439 \u0432 \u0447\u0430\u0442 \u0432\u043b\u0435\u0442\u0435\u043b\u0430 \u043e\u0440\u0430\u043a\u043b\u043e\u0432\u0430\u044f <code>dual<\/code> \u2014 \u0435\u0451 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0442\u0430\u043a: <code>create view dual as select 'x'::varchar as dummy<\/code> (<a href=\"https:\/\/github.com\/orafce\/orafce\/blob\/VERSION_3_0_6\/orafce--3.0.6.sql#L253\"><u>\u043f\u043e\u0434\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0432 Orafce<\/u><\/a>). \u041d\u043e \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u0442\u0435\u0441\u0442\u044b \u0443\u0434\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u043e\u0437\u0435\u043b\u0435\u043d\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e: \u043c\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441, \u043f\u0440\u0438\u0432\u043e\u0434\u044f \u0435\u0433\u043e \u043a \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c\u0443 \u0432\u0438\u0434\u0443 \u0432\u0440\u043e\u0434\u0435 <code>fetch first :limit rows<\/code> \u0432\u043c\u0435\u0441\u0442\u043e <code>where rownum &lt;= :limit<\/code>. \u0418\u043d\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u043b\u0438 \u043d\u043e\u0432\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u00a0\u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440. \u0414\u043b\u044f \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u0447\u0430\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u043e\u043c\u043e\u0433\u043b\u0430 <a href=\"https:\/\/habr.com\/ru\/articles\/216057\/\"><u>\u0445\u043e\u0440\u043e\u0448\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f<\/u><\/a>.\u00a0<\/p>\n<p>\u0421 \u043a\u0430\u0436\u0434\u044b\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c \u043c\u043e\u0433\u043b\u0438 \u0437\u0435\u043b\u0435\u043d\u0435\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0434\u0435\u0441\u044f\u0442\u043a\u0438, \u0430 \u0442\u043e \u0438 \u0441\u043e\u0442\u043d\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u2014 \u044d\u0442\u043e \u0432\u043d\u0443\u0448\u0430\u043b\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u043c. \u0427\u0430\u0441\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u043e\u0441\u044c \u043d\u0438 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c, \u043d\u0438 \u043e\u0431\u043e\u0439\u0442\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0432\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043d\u043e \u043e\u0431 \u044d\u0442\u043e\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<p>\u0421\u043f\u0443\u0441\u0442\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432 (\u0430 \u0432\u044b \u043a\u0430\u043a \u0434\u0443\u043c\u0430\u043b\u0438?) \u0440\u0443\u0442\u0438\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u044b \u043e\u0437\u0435\u043b\u0435\u043d\u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0442\u0435\u0441\u0442. \u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b \u043c\u043e\u043d\u0441\u0442\u0440 \u0424\u0440\u0430\u043d\u043a\u0435\u043d\u0448\u0442\u0435\u0439\u043d\u0430, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043d\u0430 Oracle \u0432 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435 \u0438 \u043d\u0430 PostgreSQL \u0432\u00a0\u0442\u0435\u0441\u0442\u0430\u0445. \u0412\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043e\u043d \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5ad\/f8a\/3e5\/5adf8a3e5a74ba1f3dec8a72362e438c.png\" width=\"1400\" height=\"620\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5ad\/f8a\/3e5\/5adf8a3e5a74ba1f3dec8a72362e438c.png\"\/><\/figure>\n<p>\u041e\u043a, \u0442\u0435\u0441\u0442\u044b \u043f\u043e\u0437\u0435\u043b\u0435\u043d\u0435\u043b\u0438, \u0447\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/p>\n<p>\u041f\u0440\u043e \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0441\u043e\u0431\u043e \u043d\u0435\u0447\u0435\u0433\u043e: \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0437\u043d\u0430\u0442\u043e\u043a\u043e\u0432 \u043a\u043e\u0434\u043e\u0431\u0430\u0437\u044b \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043a\u0438\u043d\u0443\u0442\u044c \u2014 \u0438 \u0432\u044b\u043a\u0438\u043d\u0443\u043b\u0438.<\/p>\n<p>\u041f\u0440\u043e \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446, \u0447\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u0442\u043e\u0436\u0435. \u0418\u0445 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043c\u0430\u043b\u043e, \u0438 \u043e\u043d\u0438 \u0432\u0441\u0435 \u0431\u044b\u043b\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435. \u0420\u0430\u0437\u0432\u0435 \u0447\u0442\u043e \u0435\u0449\u0451 \u0440\u0430\u0437 \u0443\u043f\u043e\u043c\u044f\u043d\u0443 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b YTsaurus: \u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u0445 \u0434\u043b\u044f \u0442\u0435\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u043e\u043d\u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u043e\u0448\u043b\u0438.<\/p>\n<p>\u041f\u0440\u0438\u0448\u043b\u0430 \u043f\u043e\u0440\u0430 \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0432\u043e\u0437\u043a\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h3>\u041b\u044c\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0435<\/h3>\n<p>\u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043b\u0438\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u044b \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0441 CDC. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u0432\u0437\u044f\u043b\u0438 <a href=\"https:\/\/www.oracle.com\/cis\/integration\/goldengate\/\"><u>Oracle GoldenGate<\/u><\/a> (\u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u2014 GG). \u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043b\u0430\u0442\u043d\u044b\u0439, \u043d\u043e \u0443 \u043d\u0435\u0433\u043e \u0431\u044b\u043b \u0434\u0435\u043c\u043e\u0440\u0435\u0436\u0438\u043c, \u0438\u00a0\u043d\u0430\u043c \u0435\u0433\u043e \u0445\u0432\u0430\u0442\u0438\u043b\u043e.<\/p>\n<p>\u0421 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 GG \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0433\u043b\u0438 \u043d\u0430\u0448\u0438 DBA. \u0412 \u0446\u0435\u043b\u043e\u043c \u0443 GG \u043d\u0435\u043f\u043b\u043e\u0445\u0430\u044f <a href=\"https:\/\/docs.oracle.com\/en\/middleware\/goldengate\/core\/19.1\/oracle-db\/index.html\"><u>\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f<\/u><\/a> \u043f\u043e \u0432\u0441\u0435\u043c \u0430\u0441\u043f\u0435\u043a\u0442\u0430\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043f\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c \u0431\u0430\u0437\u044b-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430, \u0431\u0430\u0437\u044b-\u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0430, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u00a0\u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432. \u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043d\u044e\u0430\u043d\u0441\u043e\u0432 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f GG \u043a <a href=\"https:\/\/docs.oracle.com\/en\/middleware\/goldengate\/core\/19.1\/oracle-db\/preparing-database-oracle-goldengate.html#GUID-644099C5-8950-496C-8592-446FB1566AFD\"><u>\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441\u0442\u0440\u043e\u043a<\/u><\/a>. \u041f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0441\u0435\u0432\u0434\u043e\u043a\u043b\u044e\u0447\u0438.<\/p>\n<p>\u0421\u043f\u0443\u0441\u0442\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439 \u0431\u044b\u043b\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u0430 \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b GG \u0432 \u043f\u043b\u0430\u043d\u0435 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>\u041e\u0434\u043d\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0414\u0432\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u2014 Oracle \u0438 PostgreSQL, \u0430 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u043e\u0431\u0449\u0430\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f dirdat \u0434\u043b\u044f trail-\u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0434\u043b\u044f \u043e\u0431\u043e\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c Oracle \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d GG \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 extract.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c PostgreSQL \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d GG \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 replicat.<\/p>\n<\/li>\n<li>\n<p>Oracle GG \u0447\u0438\u0442\u0430\u043b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u0437 Oracle \u0438 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043b \u0432 dirdat \u0441\u0432\u043e\u0438 trail-\u0444\u0430\u0439\u043b\u044b.<\/p>\n<\/li>\n<li>\n<p>PostgreSQL GG \u0447\u0438\u0442\u0430\u043b \u0438\u0437 dirdat trail-\u0444\u0430\u0439\u043b\u044b \u0438 \u043d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u043b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043d\u0430 \u0446\u0435\u043b\u0435\u0432\u0443\u044e PostgreSQL.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0430\u0436\u043d\u044b\u0439 \u043d\u044e\u0430\u043d\u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a PostgreSQL \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438: \u0447\u0442\u043e\u0431\u044b PostgreSQL \u043d\u0435\u00a0\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u043e\u0432\u0430\u043b \u0438 \u043d\u0435 \u0440\u0443\u0433\u0430\u043b\u0441\u044f \u043d\u0430 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u044f foreign key, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f <a href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-client.html#GUC-SESSION-REPLICATION-ROLE\"><u>\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440<\/u><\/a> <code>session_replication_role=replica<\/code>.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043b\u0438\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u043d\u0443\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043d\u0430\u043f\u0448\u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445, \u0437\u0430\u043b\u0438\u0432\u043a\u0443 \u0432\u00a0\u0446\u0435\u043b\u0435\u0432\u0443\u044e \u0431\u0430\u0437\u0443, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u2014 \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0437\u0430 \u0441\u043d\u0430\u043f\u0448\u043e\u0442\u043e\u043c. GG \u0443\u043c\u0435\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u043b\u0438\u0432\u043a\u0443, \u043d\u043e \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043e\u0431\u044a\u0451\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0443\u043f\u0435\u0440\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0439 \u0438\u00a0\u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b\u0439. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u0430\u0437\u043e\u0432\u0451\u043c \u0435\u0433\u043e Copier.<\/p>\n<p>\u0414\u043b\u044f \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c <a href=\"https:\/\/github.com\/laurenz\/oracle_fdw\"><u>oracle_fdw<\/u><\/a>. Copier \u0433\u043e\u0442\u043e\u0432\u0438\u043b foreign-\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0432 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0431\u0430\u0437\u0435 \u0438, \u043f\u043e \u0441\u0443\u0442\u0438, \u0434\u0435\u043b\u0430\u043b <code>insert into t_dst (cols) select cols from t_src<\/code>. \u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0431\u044b\u043b \u0447\u0443\u0442\u044c \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435, \u0441 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u043b\u043e\u043a\u043e\u0432, \u043d\u043e \u0438\u0434\u0435\u0439\u043d\u043e \u2014 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435. \u0412\u00a0\u0442\u0430\u043a\u043e\u0439 \u0441\u0445\u0435\u043c\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043b\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0441\u0440\u0430\u0437\u0443 \u0432 \u0446\u0435\u043b\u0435\u0432\u0443\u044e \u0431\u0430\u0437\u0443 \u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u0438\u0445 \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u043e\u0432.<\/p>\n<p>\u0414\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0432\u044f\u0437\u043a\u043e\u0439 Copier \u0438 GG \u0431\u044b\u043b\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u043f\u0430\u0447\u043a\u0430 bash-\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432, \u0438 \u043d\u0430\u0447\u0430\u043b\u0430\u0441\u044c \u0440\u0430\u0431\u043e\u0442\u0430 \u043f\u043e\u00a0\u043f\u043e\u0434\u0431\u043e\u0440\u0443 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u044f extract \u0438 replicat. \u0421\u0443\u0442\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432 \u043b\u043e\u0431 \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0430 \u0437\u0430\u0445\u043b\u0451\u0431\u044b\u0432\u0430\u0442\u044c\u0441\u044f, \u0437\u0430\u043f\u0438\u043d\u0430\u044f\u0441\u044c \u043e \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u043f\u0435\u0440\u0432\u0430 \u043f\u043e\u0434\u0431\u0438\u0440\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e extract, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u0441\u043f\u0435\u0432\u0430\u043b\u0438 \u0432\u044b\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u0437 Oracle \u0432 trail-\u0444\u0430\u0439\u043b\u044b. \u0410 \u043f\u043e\u0442\u043e\u043c \u043f\u043e\u0434\u0431\u0438\u0440\u0430\u0442\u044c \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e extract \u043d\u0430 replicat, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u0443\u0441\u043f\u0435\u0432\u0430\u043b\u0438 \u043d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u0437 trail-\u0444\u0430\u0439\u043b\u043e\u0432. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043f\u043e\u0434\u0431\u043e\u0440\u0430 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u043f\u0435\u0440\u0435\u043b\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0440\u0430\u0437. \u0411\u0435\u0437 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0437\u0430\u043d\u0438\u043c\u0430\u043b \u043f\u043e\u043d\u0430\u0447\u0430\u043b\u0443 \u0447\u0430\u0441\u044b, \u0430\u00a0\u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 \u2014 \u043c\u0438\u043d\u0443\u0442\u044b.<\/p>\n<p>\u041f\u043e\u043f\u0443\u0442\u043d\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u043e\u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0431\u044a\u0451\u043c\u043e\u0432 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0437\u0430\u043c\u0435\u043d\u0430 <code>update t set c=v where ...<\/code> \u043d\u0430 <code>update t set c=v where ... and c!=v<\/code>. \u0418 \u0435\u0449\u0451, \u0433\u0434\u0435 \u0431\u044b\u043b\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044b\u0432\u0430\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u043e \u0431\u0430\u0442\u0447\u0430\u043c.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0444\u043e\u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u043e\u0431\u044a\u0451\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0447\u0442\u043e \u043d\u0438\u043a\u0430\u043a\u043e\u0439 extract \u0443\u0436\u0435 \u043d\u0435 \u043f\u043e\u0441\u043f\u0435\u0432\u0430\u043b. \u041e\u0431\u044b\u0447\u043d\u043e \u044d\u0442\u043e \u0431\u044b\u043b \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0438\u043c\u043f\u043e\u0440\u0442 \u043a\u0430\u043a\u0438\u0445-\u043d\u0438\u0431\u0443\u0434\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u043a\u043e\u043f\u0438\u0438 \u0437\u0430\u0434\u0430\u0447, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u0440\u0430\u0437\u0443 \u0432 PostgreSQL. \u0418 \u0434\u0430, \u0437\u0430\u0434\u0430\u0447\u0438 \u043c\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438, \u0430\u00a0\u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0435\u043b\u0430\u043b\u0438 \u043a\u043e\u043f\u0438\u044e \u0431\u0438\u043d\u0430 \u0438 \u043d\u0430 \u0432\u0445\u043e\u0434 \u0438\u043d\u0436\u0435\u043a\u0442\u0438\u043b\u0438 DataSource \u0441 \u043f\u0440\u0435\u0441\u043b\u043e\u0432\u0443\u0442\u044b\u043c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u043c.<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043b\u0430\u0433 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 PostgreSQL \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e Oracle \u043d\u0430 \u0442\u0430\u043a\u043e\u0439 \u0441\u0445\u0435\u043c\u0435 \u0433\u0443\u043b\u044f\u043b \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043e\u0442 0\u00a0\u0434\u043e 10\u00a0\u0441\u0435\u043a\u0443\u043d\u0434 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c. \u041f\u043e\u0441\u043b\u0435 \u0432\u0441\u0435\u0445 \u044d\u0442\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u0430 \u0441\u0442\u0430\u043b\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u043e\u0439:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c9e\/bcc\/1a0\/c9ebcc1a07517d75c8455ad7f69c0c13.png\" width=\"1920\" height=\"620\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c9e\/bcc\/1a0\/c9ebcc1a07517d75c8455ad7f69c0c13.png\"\/><\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u0441\u0442\u0430\u043b\u043e \u0435\u0449\u0451 \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u0431\u044b\u043b\u043e \u2014 \u043f\u0440\u0430\u0432\u0434\u0430 \u0436\u0435? \u041d\u0430\u0441\u0442\u0430\u043b\u0430 \u043f\u043e\u0440\u0430 \u0437\u0430\u0444\u0438\u043d\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u0443 \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0438\u00a0\u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043d\u0430 PostgreSQL.<\/p>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044e<\/h3>\n<p>\u0418\u0442\u0430\u043a, \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 PostgreSQL \u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u0431\u00f3\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0435 \u043f\u043e\u043b\u044f\u0436\u0435\u0442 \u0432 \u043e\u0448\u0438\u0431\u043a\u0430\u0445. \u0415\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0441\u0442\u0430\u0432\u0430\u043b\u0438 \u043e\u0442 Oracle \u043d\u0435 \u0431\u043e\u043b\u0435\u0435 10\u00a0\u0441\u0435\u043a\u0443\u043d\u0434. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0434\u043e \u043a\u0430\u043a-\u0442\u043e \u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0438\u0442\u044c \u0441\u0435\u0431\u044f \u043e\u0442 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u043e\u043a\u0440\u044b\u0442\u044b \u0442\u0435\u0441\u0442\u0430\u043c\u0438.<\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0443 \u043d\u0430\u0441 Spring, \u044f \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0430\u043d\u0430\u043b\u043e\u0433 <code>AbstractRoutingDataSource<\/code> \u043d\u0430 \u0441\u0442\u0435\u0440\u043e\u0438\u0434\u0430\u0445. \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u00ab\u043b\u0438\u0431\u043e \u043f\u0435\u0440\u0432\u044b\u0439 DataSource, \u043b\u0438\u0431\u043e \u0432\u0442\u043e\u0440\u043e\u0439\u00bb, \u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u0435\u0436\u0438\u043c\u044b \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0412 \u0438\u0442\u043e\u0433\u0435 \u0441\u043f\u0438\u0441\u043e\u043a \u0436\u0435\u043b\u0430\u0435\u043c\u044b\u0445 \u0440\u0435\u0436\u0438\u043c\u043e\u0432 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code class=\"java\">\/** \u0443\u0440\u043e\u0432\u043d\u0438 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u043e \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u044e \u2014 \u043e\u0442 \u0441\u0430\u043c\u044b\u0445 \u0431\u0435\u0437\u043e\u0431\u0438\u0434\u043d\u044b\u0445 \u0434\u043e \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0432\u0430\u0437\u0438\u0432\u043d\u044b\u0445 *\/ public enum QueryRouting {     \/** \u0445\u043e\u0434\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441 *\/     DISABLED,      \/**      * \u0441\u043f\u0435\u0440\u0432\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u043c \u0432\u0441\u0435 \u0447\u0438\u0442\u0430\u044e\u0449\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441,       * \u043d\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442,      * \u0434\u0430\u043b\u0435\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e      *\/     NOOP_REPEAT,      \/**      * \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u043c \u0432\u0441\u0435 \u0447\u0438\u0442\u0430\u044e\u0449\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0438\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441,       * \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442      * \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043b\u044e\u0431\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u0434\u0435\u043b\u0430\u0435\u043c fallback \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441      *\/     WITH_FALLBACK,      \/**      * \u0445\u043e\u0434\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441      *\/     ENABLED }<\/code><\/pre>\n<p>\u0418\u0434\u0435\u044f \u0431\u044b\u043b\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u0441\u043f\u0435\u0440\u0432\u0430 \u0440\u0435\u0436\u0438\u043c <code>NOOP_REPEAT<\/code>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043d\u0430\u0439\u0442\u0438 \u0438\u00a0\u043f\u043e\u0447\u0438\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u043e\u0448\u0438\u0431\u043a\u0438. \u041f\u043e\u0442\u043e\u043c \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c <code>WITH_FALLBACK<\/code> \u0438 \u043f\u043e\u0447\u0438\u043d\u0438\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u043f\u043b\u044b\u043b\u043e \u0440\u0430\u043d\u044c\u0448\u0435. \u0418\u00a0\u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c <code>ENABLED<\/code> (\u0431\u0438\u043b\u0435\u0442 \u0432 \u043e\u0434\u0438\u043d \u043a\u043e\u043d\u0435\u0446). \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0430\u0447\u043a\u0443 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<ul>\n<li>\n<p><code>OracleToPostgresJdbcTemplate<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u043d\u0430\u0435\u0442 \u043f\u0440\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u0440\u0435\u0436\u0438\u043c\u044b \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430;<\/p>\n<details class=\"spoiler\">\n<summary>OracleToPostgresJdbcTemplate<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">\/**  * JdbcTemplate, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 select\u043e\u0432 \u0432\u043d\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439.  *  * @implNote \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 ThreadLocal-\u043a\u043e\u043f\u0438\u044e \u0444\u043b\u0430\u0433\u0430 \u0441 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430 \u043e\u0434\u0438\u043d \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u0442\u0435\u043c\u043f\u043b\u0435\u0439\u0442  * \u0431\u044b\u043b \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 Supplier. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a JdbcTemplate \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 obtainDataSource,  * \u0430 \u043f\u043e\u0442\u043e\u043c \u0435\u0449\u0451 \u0440\u0430\u0437 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 getDataSource, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.  * &lt;p>  * \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Spring 5.3+, \u0441\u043c. {@link #checkSpringVersion()}  *\/ public class OracleToPostgresJdbcTemplate extends JdbcTemplate {     private static final Logger log = LoggerFactory.getLogger(OracleToPostgresJdbcTemplate.class);     static final ThreadLocal&lt;QueryRouting> ROUTING = new NamedThreadLocal&lt;>(\"routing\");     private static final ThreadLocal&lt;Connection> MANUAL_COMMIT = new NamedThreadLocal&lt;>(\"manualCommit\");     private static final Pattern ROUTING_DESIRED_WORDS = Pattern.compile(             \"\\\\bselect\\\\b\",             Pattern.CASE_INSENSITIVE | Pattern.DOTALL     );     private static final Pattern ROUTING_FORBIDDEN_WORDS = Pattern.compile(             Stream.of(                     \"nextval\", \/\/ select from seq.nextval, etc                     \"create\",                     \"insert\",                     \"update\",                     \"delete\",                     \"drop\",                     \"truncate\",                     \"begin\",                     \"commit\",                     \"function\",                     \"procedure\",                     \"call\",                     \"execute\",                     \"invoke\",                     \"do\"             ).collect(Collectors.joining(\"|\", \"\\\\b(?:\", \")\\\\b\")),             Pattern.CASE_INSENSITIVE     );      private final DataSource newDataSource;     private final Supplier&lt;QueryRouting> dataSourceRouting;     private final AtomicBoolean routingDataSourceExceptionTranslatorRequired = new AtomicBoolean(true);      \/**      * @param oldDataSource     \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439, \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 Oracle      * @param newDataSource     \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 PostgreSQL      * @param dataSourceRouting \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u043c \u043f\u043e\u0434 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438      *                          \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u0441 sql \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c      *                          \u0431\u044b\u0441\u0442\u0440\u043e, \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u0440\u043e\u0447\u0435\u0435 \u2014 \u043d\u0430 \u0432\u0430\u0448\u0435\u0439 \u0441\u043e\u0432\u0435\u0441\u0442\u0438,      *                          \u0432\u0441\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e \u043d\u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f      *\/     public OracleToPostgresJdbcTemplate(             DataSource oldDataSource,             DataSource newDataSource,             Supplier&lt;QueryRouting> dataSourceRouting     ) {         checkSpringVersion();          super.setDataSource(Objects.requireNonNull(oldDataSource, \"regular DataSource\"));         this.newDataSource = Objects.requireNonNull(newDataSource, \"new DataSource\");         Objects.requireNonNull(dataSourceRouting);         this.dataSourceRouting = () -> {             try {                 return dataSourceRouting.get();             } catch (RuntimeException e) {                 log.error(\"Failed to get query routing flag, got {}\", e, e);                 return null;             }         };          \/\/ \u043d\u0430\u043c \u0432\u0430\u0436\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0442\u043e\u0440 \u043e\u0448\u0438\u0431\u043e\u043a \u0441\u043f\u0435\u0440\u0432\u0430 \u043a \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441\u0443,         \/\/ \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0442\u043e\u0440 \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441\u0430         super.setLazyInit(false);     }      \/**      * previously all requests were routed to one of public execute overloads,      * it was changed by addition of queryForStream method      *\/     static void checkSpringVersion() {         Stream.of(JdbcTemplate.class.getDeclaredMethods())                 .filter(m -> \"execute\".equals(m.getName()) &amp;&amp; Modifier.isPrivate(m.getModifiers()))                 .findFirst()                 .ifPresent(m -> {                     throw new UnsupportedOperationException(\"Spring 5.3+ is not supported yet,\" +                             \" JdbcTemplate impl has diverged from expected by this class\");                 });     }      @Override     public final void setLazyInit(boolean lazyInit) {         log.error(\"Setting lazy init is not supported\");         \/\/ do nothing to enforce correct getExceptionTranslator behavior     }      @Override     public final void setExceptionTranslator(SQLExceptionTranslator exceptionTranslator) {         log.error(\"Setting shared translator is usually not what you really want\");         \/\/ do nothing to enforce default SQLErrorCodeSQLExceptionTranslator that is bound to regularDataSource     }      \/**      * @implNote {@link org.springframework.jdbc.support.JdbcAccessor#setExceptionTranslator(SQLExceptionTranslator)} \u0438      * {@link org.springframework.jdbc.support.JdbcAccessor#getExceptionTranslator()} \u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b,      * \u043d\u043e {@link AbstractFallbackSQLExceptionTranslator#setFallbackTranslator(SQLExceptionTranslator)} \u2014 \u043d\u0435\u0442,      * \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0434\u0438\u043d\u043e\u0436\u0434\u044b \u043b\u043e\u0447\u0438\u043c\u0441\u044f \u0440\u0430\u0434\u0438 \u043d\u0435\u0433\u043e, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0447\u0442\u043e\u0431\u044b \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u043d\u0435 \u043f\u043e\u043b\u0435\u0437\u043b\u0438 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0432 \u0431\u0430\u0437\u0443,      * \u043a\u0430\u043a \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 {@link SQLErrorCodeSQLExceptionTranslator#setDataSource(DataSource)}      * @see #setLazyInit(boolean)      *\/     @Nonnull     @Override     public final SQLExceptionTranslator getExceptionTranslator() {         @Nonnull var et = super.getExceptionTranslator();         if (routingDataSourceExceptionTranslatorRequired.get()) {             \/\/ \u0441\u0438\u043d\u043a\u0430\u0435\u043c\u0441\u044f \u043d\u0430 this \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e super.getExceptionTranslator             synchronized (this) {                 \/\/ \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0442\u043e\u0440 \u043e\u0448\u0438\u0431\u043e\u043a \u0435\u0434\u0438\u043d\u043e\u0436\u0434\u044b,                 \/\/ \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a experimentDataSource                 if (routingDataSourceExceptionTranslatorRequired.getAndSet(false)) {                     var etExp = appendExceptionTranslator(et, newDataSource);                     if (etExp != null) {                         super.setExceptionTranslator(etExp);                         et = etExp;                     }                 }             }         }         return et;     }      \/**      * @return {@code null} if current was modified, new translator with fallback to current if not      * @apiNote \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0442\u043e\u0440!      *\/     @Nullable     public static SQLExceptionTranslator appendExceptionTranslator(             @Nonnull SQLExceptionTranslator current,             DataSource additionalDataSource     ) {         var additional = new SQLErrorCodeSQLExceptionTranslator(additionalDataSource);         if (current instanceof AbstractFallbackSQLExceptionTranslator) {             \/\/ \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u0441\u044f \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0443 \u0446\u0435\u043f\u043e\u0447\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0441\u043f\u0435\u0440\u0432\u0430 \u0442\u0440\u0430\u043d\u0441\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u043c \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0442\u043e\u0440\u043e\u043c             var currentFt = (AbstractFallbackSQLExceptionTranslator) current;             var currentFet = currentFt.getFallbackTranslator();             if (currentFet != null) {                 additional.setFallbackTranslator(currentFet);             }             currentFt.setFallbackTranslator(additional);             return null;         } else {             additional.setFallbackTranslator(current);             return additional;         }     }      @Override     public final void setDataSource(DataSource dataSource) {         if (dataSource != super.getDataSource()) {             log.error(\"Setting another datasource (implicitly) is not what you want, only constructor is supported\");         }         \/\/ do nothing to avoid implicit resetting     }      @Override     public final DataSource getDataSource() {         return obtainDataSource();     }      @Nonnull     @Override     protected final DataSource obtainDataSource() {         return isAnyRoutingEnabled()                 ? newDataSource                 : Objects.requireNonNull(super.getDataSource(), \"should be guaranteed by ctor and setter\");     }      \/**      * @see #obtainDataSource()      *\/     private &lt;T> T tryWithRouting(Object sqlProvider, Supplier&lt;T> action) {         var r = ROUTING.get();         UnaryOperator&lt;QueryRouting> rSetter = OracleToPostgresJdbcTemplate::setRouting;         Runnable rRemover = ROUTING::remove;         if (r == null) {             \/\/ \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u0430\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f, \u0442\u043e \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b             \/\/ \u0441 \u0442\u0435\u043c \u0436\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438             var rTx = OracleToPostgresDataSourceTransactionManager.ROUTING.get();             \/\/ \u043d\u0430 \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u0438\u043d \u043f\u043e\u0445\u043e\u0434 \u0437\u0430 \u0444\u043b\u0430\u0433\u043e\u043c             var rFlag = dataSourceRouting.get();             \/\/ \u043f\u0440\u0438 \u043f\u043e\u043b\u043d\u044b\u0445 \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u043f\u043e\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u0445 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0444\u043b\u0430\u0433 \u0432 \u0443\u0449\u0435\u0440\u0431 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, \u0441\u043c DatasourceRouting.FORCE_***             if (rTx == null                     || (rTx == QueryRouting.ENABLED &amp;&amp; rFlag == QueryRouting.DISABLED)                     || (rTx == QueryRouting.DISABLED &amp;&amp; rFlag == QueryRouting.ENABLED)) {                 r = rFlag;             } else {                 r = rTx;             }         } else {             \/\/ \u0435\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0440\u043e\u0443\u0442\u0438\u043d\u0433             rSetter = UnaryOperator.identity();             rRemover = () -> {             };         }         if (r == null) {             r = QueryRouting.DISABLED;         }          \/\/ \u0442\u044e\u043d\u0438\u043c \u0440\u043e\u0443\u0442\u0438\u043d\u0433 \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0432\u0438\u0434\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432         @Nullable var sql = (sqlProvider instanceof SqlProvider)                 ? ((SqlProvider) sqlProvider).getSql()                 : null;         if (r == QueryRouting.WITH_FALLBACK &amp;&amp; isDataConsistencyRequired()) {             \/\/ \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 rw-\u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441, \u043f\u043e\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0435\u0439 \u0438\u043b\u0438 \u043f\u0440\u0438 \u043a\u0435\u0448\u0438\u0440\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445             \/\/ \u0438\u0434\u0443\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043f\u0438\u0435\u0439 \u0432\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u0435 \u043d\u0435\u043a\u043e\u043d\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u0438 \u0438 \u0433\u043e\u043d\u043e\u043a             r = QueryRouting.NOOP_REPEAT;         }         if ((r == QueryRouting.NOOP_REPEAT || r == QueryRouting.WITH_FALLBACK) &amp;&amp; isUnsafeToRepeat(sql)) {             \/\/ \u0432\u0441\u0435 \u043d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043c\u0438\u043c\u043e, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0442\u0438\u043f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441\u0430\u043c\u0430\u044f \u0442\u044f\u0436\u0435\u043b\u0430\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0442\u043e\u0438\u0442 \u0432 \u0441\u0430\u043c\u043e\u043c \u043a\u043e\u043d\u0446\u0435             r = QueryRouting.DISABLED;         }          switch (rSetter.apply(r)) {             case NOOP_REPEAT:                 \/\/ \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441, \u043d\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441\u0430                 try {                     action.get();                 } catch (RuntimeException e) {                     \/\/ \u043f\u0440\u043e\u0441\u0442\u043e \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438                     log.error(\"Failed to execute query [{}], got {}\", sql, e, e);                 } finally {                     rRemover.run();                 }                 return action.get();             case WITH_FALLBACK:                 \/\/ \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441, \u043d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043b\u044e\u0431\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u2014 \u0441\u0440\u0430\u0437\u0443 \u0444\u043e\u043b\u0431\u0435\u043a \u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u044b\u0439                 try {                     return action.get();                 } catch (RuntimeException e) {                     log.error(\"Failed to execute query [{}], got {}\", sql, e, e);                     rRemover.run();                     return action.get();                 } finally {                     rRemover.run();                 }             case ENABLED:             case DISABLED:             default:                 try {                     return action.get();                 } finally {                     rRemover.run();                 }         }     }      private boolean isDataConsistencyRequired() {         \/\/ \u0442\u0443\u0442 \u0431\u044b\u043b\u043e \u0435\u0449\u0451 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0445 \u043d\u0430\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a         return TransactionSynchronizationManager.isActualTransactionActive();     }      private static boolean isUnsafeToRepeat(@Nullable String sql) {         return sql == null \/\/ \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e \u0447\u0442\u043e, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e callback, \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u0442\u0430\u043a\u043e\u0435 \u043e\u043f\u0430\u0441\u043d\u043e                 || !ROUTING_DESIRED_WORDS.matcher(sql).find()                 || ROUTING_FORBIDDEN_WORDS.matcher(sql).find();     }      @Override     public &lt;T> T execute(CallableStatementCreator csc, CallableStatementCallback&lt;T> action) {         return tryWithRouting(csc, () -> super.execute(csc, cs -> handleCustomFetchSize(                 CallableStatement.class,                 cs,                 cs.getConnection(),                 cs.getFetchSize(),                 action::doInCallableStatement         )));     }      @Override     public &lt;T> T execute(ConnectionCallback&lt;T> action) {         return tryWithRouting(action, () -> super.execute((Connection con) -> handleCustomFetchSize(                 null,                 null,                 con,                 getFetchSize(),                 nullStmt -> action.doInConnection(con)         )));     }      @Override     public &lt;T> T execute(PreparedStatementCreator psc, PreparedStatementCallback&lt;T> action) {         return tryWithRouting(psc, () -> super.execute(psc, ps -> handleCustomFetchSize(                 PreparedStatement.class,                 ps,                 ps.getConnection(),                 ps.getFetchSize(),                 action::doInPreparedStatement         )));     }      @Override     public &lt;T> T execute(StatementCallback&lt;T> action) {         return tryWithRouting(action, () -> super.execute((Statement stmt) -> handleCustomFetchSize(                 Statement.class,                 stmt,                 stmt.getConnection(),                 stmt.getFetchSize(),                 action::doInStatement         )));     }      @Override     @Nullable     public &lt;T> T query(String sql, ResultSetExtractor&lt;T> rse) {         return super.query(sql, new RoutingAwareResultSetExtractor&lt;>(rse));     }      @Override     @Nullable     public &lt;T> T query(PreparedStatementCreator psc, @Nullable PreparedStatementSetter pss, ResultSetExtractor&lt;T> rse) {         return super.query(psc, pss, new RoutingAwareResultSetExtractor&lt;>(rse));     }      \/**      * \u0432\u0441\u0435 \u0447\u0438\u0442\u0430\u044e\u0449\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u043d\u043e\u0432\u043e\u043c rw-\u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442,      * \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c, \u043b\u043e\u0432\u0438\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438,      * \u043d\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0440\u0442\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 {@link ResultSetExtractor}, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f stateful      *\/     private static final class RoutingAwareResultSetExtractor&lt;T> implements ResultSetExtractor&lt;T> {         private final ResultSetExtractor&lt;T> proxee;          private RoutingAwareResultSetExtractor(ResultSetExtractor&lt;T> proxee) {             this.proxee = Objects.requireNonNull(proxee, \"result set extractor\");         }          @Override         public T extractData(ResultSet rs) throws SQLException {             if (ROUTING.get() == QueryRouting.NOOP_REPEAT) {                 rs.next();                 return null;             } else {                 return proxee.extractData(rs);             }         }     }      \/**      * handles connection autocommit if custom fetch size is specified as described here      * https:\/\/jdbc.postgresql.org\/documentation\/head\/query.html#query-with-cursor      *      * @apiNote visible for {@link ru.yandex.market.mbi.util.db.DbUtil}      * @see org.postgresql.core.QueryExecutor#QUERY_FORWARD_CURSOR      * @see java.sql.ResultSet#setFetchSize(int)      * @see java.sql.Statement#setFetchSize(int)      * @see JdbcTemplate#setFetchSize(int)      *\/     public static &lt;T, S extends Statement> T handleCustomFetchSize(             @Nullable Class&lt;S> stmtClass,             @Nullable S stmt,             Connection connection,             int fetchSize,             ThrowingJdbcFunction&lt;S, T> action     ) throws SQLException {         try {             if (fetchSize > 0) {                 \/\/ fetch size may be set by eg JdbcTemplate#applyStatementSettings(Statement)                 setManualCommitIfRequired(connection, fetchSize);             } else if (stmt != null) {                 \/\/ fetchSize could be set within action callback,                 \/\/ in this case CustomFetchSizeHandler should handle autoCommit.                 \/\/ additional check is just to avoid creating unnecessary objects                 if (shouldHandleManualCommit(connection)) {                     assert stmtClass != null : \"should be not null when stmt is not null\";                     stmt = stmtClass.cast(Proxy.newProxyInstance(stmtClass.getClassLoader(),                             new Class&lt;?>[]{stmtClass}, new CustomFetchSizeHandler(stmt)));                 }             }             return action.apply(stmt);         } catch (SQLException | RuntimeException e) {             var manualCommit = MANUAL_COMMIT.get();             if (manualCommit == connection) {                 manualCommit.rollback();             }             throw e;         } finally {             var manualCommit = MANUAL_COMMIT.get();             MANUAL_COMMIT.remove();             if (manualCommit == connection) {                 \/\/ this will also implicitly call commit if not yet                 manualCommit.setAutoCommit(true);             }         }     }      \/**      * helps {@link #handleCustomFetchSize} to handle cases when callback sets custom fetch size      *\/     private static class CustomFetchSizeHandler implements InvocationHandler {         private static final String METHOD = \"setFetchSize\";         private final Statement proxee;          CustomFetchSizeHandler(Statement proxee) {             this.proxee = proxee;         }          @Override         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {             if (METHOD.equals(method.getName())) {                 setManualCommitIfRequired(proxee.getConnection(), (Integer) args[0]);             }             try {                 return method.invoke(proxee, args);             } catch (InvocationTargetException ex) {                 throw ex.getCause();             }         }     }      \/**      * @apiNote visible for {@link ru.yandex.market.mbi.util.db.DbUtil}      *\/     @FunctionalInterface     public interface ThrowingJdbcFunction&lt;S, T> {         @Nullable         T apply(@Nullable S s) throws SQLException;     }      private static void setManualCommitIfRequired(Connection connection, int fetchSize) throws SQLException {         if (fetchSize > 0 &amp;&amp; shouldHandleManualCommit(connection)) {             connection.setAutoCommit(false); \/\/ may fail so call before storing             MANUAL_COMMIT.set(connection);             \/\/ we store connection to avoid nested connection issues             \/\/ eg if somebody opens another connecton within running callback             \/\/ then we won't apply manual commit\/rollback to it         }     }      private static boolean shouldHandleManualCommit(Connection connection) throws SQLException {         \/\/ don't check for isAnyRoutingEnabled, all this stuff is only for pg         if (MANUAL_COMMIT.get() != null || !connection.getAutoCommit()) {             return false;         }         try {             return \"PostgreSQL\".equals(connection.getMetaData().getDatabaseProductName());         } catch (SQLException e) {             throw new UncategorizedSQLException(\"DatabaseType::of\", null, e);         }     }      private static boolean isAnyRoutingEnabled() {         var r = ROUTING.get();         return r != null &amp;&amp; r != QueryRouting.DISABLED;     }      @Nonnull     private static QueryRouting setRouting(QueryRouting r) {         ROUTING.set(Objects.requireNonNull(r, \"routing flag should always be defined before request\"));         return r;     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<\/li>\n<li>\n<p><code>OracleToPostgresDataSourceTransactionManager<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043f\u0430\u0440\u0435 \u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0438\u00a0\u0432\u00a0\u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0435\u0434\u0438\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430;<\/p>\n<details class=\"spoiler\">\n<summary>OracleToPostgresDataSourceTransactionManager<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">\/**  * TransactionManager, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 select\u043e\u0432 \u0432\u043d\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439.  *  * @implNote \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 ThreadLocal-\u043a\u043e\u043f\u0438\u044e \u0444\u043b\u0430\u0433\u0430 \u0441 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430 \u043e\u0434\u0438\u043d \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u0442\u0435\u043c\u043f\u043b\u0435\u0439\u0442  * \u0431\u044b\u043b \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 Supplier. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a JdbcTemplate \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 obtainDataSource,  * \u0430 \u043f\u043e\u0442\u043e\u043c \u0435\u0449\u0451 \u0440\u0430\u0437 getDataSource, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.  * &lt;p>  * \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Spring 5.3+, \u0441\u043c {@link OracleToPostgresJdbcTemplate},  * \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c \u0432 \u0441\u0432\u044f\u0437\u043a\u0435.  * &lt;p>  * \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 {@link CallbackPreferringPlatformTransactionManager}, \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043b\u044e\u0431\u044b\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u043c {@link TransactionTemplate}  *\/ public class OracleToPostgresDataSourceTransactionManager         extends DataSourceTransactionManager         implements CallbackPreferringPlatformTransactionManager {     private static final Logger log = LoggerFactory.getLogger(OracleToPostgresDataSourceTransactionManager.class);     static final ThreadLocal&lt;QueryRouting> ROUTING = new NamedThreadLocal&lt;>(\"routing\");     private final DataSource newDataSource;     private final Supplier&lt;QueryRouting> dataSourceRouting;      \/**      * @param oldDataSource     \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439, \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 Oracle      * @param newDataSource     \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 PostgreSQL      * @param dataSourceRouting \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u043c \u043f\u043e\u0434 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438      *                          \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u0441 sql \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c      *                          \u0431\u044b\u0441\u0442\u0440\u043e, \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u0440\u043e\u0447\u0435\u0435 \u2014 \u043d\u0430 \u0432\u0430\u0448\u0435\u0439 \u0441\u043e\u0432\u0435\u0441\u0442\u0438,      *                          \u0432\u0441\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e \u043d\u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f      *\/     public OracleToPostgresDataSourceTransactionManager(             DataSource oldDataSource,             DataSource newDataSource,             Supplier&lt;QueryRouting> dataSourceRouting     ) {         OracleToPostgresJdbcTemplate.checkSpringVersion();          super.setDataSource(Objects.requireNonNull(oldDataSource, \"regular DataSource\"));         this.newDataSource = Objects.requireNonNull(newDataSource, \"new DataSource\");         Objects.requireNonNull(dataSourceRouting);         this.dataSourceRouting = () -> {             try {                 return dataSourceRouting.get();             } catch (RuntimeException e) {                 log.error(\"Failed to get query routing flag, got {}\", e, e);                 return null;             }         };     }      @Override     public final void setDataSource(DataSource dataSource) {         if (dataSource != super.getDataSource()) {             log.error(\"Setting another datasource (implicitly) is not what you wanted, only constructor is supported\");         }         \/\/ do nothing to avoid implicit resetting     }      @Override     public final DataSource getDataSource() {         return obtainDataSource();     }      @Nonnull     @Override     protected final DataSource obtainDataSource() {         return ROUTING.get() == QueryRouting.ENABLED                 ? newDataSource                 : Objects.requireNonNull(super.getDataSource(), \"should be guaranteed by ctor and setter\");     }      @Override     public &lt;T> T execute(             TransactionDefinition definition,             TransactionCallback&lt;T> callback     ) throws TransactionException {         var r = ROUTING.get();         if (r == null) {             \/\/ \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441, \u0442\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e             \/\/ \u0441 \u0442\u0435\u043c \u0436\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438             \/\/ \u044d\u0442\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0440\u0430\u043d\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u0438 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e-\u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443 \u0431\u044b\u0442\u044c \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e,             \/\/ \u043d\u043e \u0448\u0430\u043b\u043e\u0432\u043b\u0438\u0432\u044b\u0435 \u0440\u0443\u0447\u043a\u0438 \u0434\u0435\u0432\u0435\u043b\u043e\u043f\u0435\u0440\u043e\u0432 \u043c\u043e\u0433\u0443\u0442 \u0438 \u043d\u0435 \u0442\u0430\u043a\u043e\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0443\u0442 \u0437\u0430\u0449\u0438\u0442\u0430 \u043e\u0442 \u0434\u0443\u0440\u0430\u043a\u0430             r = OracleToPostgresJdbcTemplate.ROUTING.get();         } else {             \/\/ \u0435\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u0430\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0440\u043e\u0443\u0442\u0438\u043d\u0433             return doExecute(definition, callback);         }         if (r == null) {             \/\/ \u043d\u0430 \u043e\u0434\u043d\u0443 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u0438\u043d \u043f\u043e\u0445\u043e\u0434 \u0437\u0430 \u0444\u043b\u0430\u0433             r = dataSourceRouting.get();         }         if (r == null) {             \/\/ \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0440\u043e\u0443\u0442\u0438\u043d\u0433 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435 \u043d\u0430\u0447\u0430\u043b\u0438 \u0445\u043e\u0434\u0438\u0442\u044c \u043a\u0443\u0434\u0430 \u043f\u043e\u043f\u0430\u043b\u043e             r = QueryRouting.DISABLED;         }          ROUTING.set(Objects.requireNonNull(r, \"routing flag should always be defined before request\"));         try {             return doExecute(definition, callback);         } finally {             ROUTING.remove();         }     }      \/**      * @see TransactionTemplate#execute      *\/     private &lt;T> T doExecute(             TransactionDefinition definition,             TransactionCallback&lt;T> callback     ) throws TransactionException {         TransactionStatus status = getTransaction(definition);         T result;         try {             result = callback.doInTransaction(status);         } catch (RuntimeException | Error ex) {             doRollbackOnException(status, ex);             throw ex;         } catch (Throwable ex) {             doRollbackOnException(status, ex);             throw new UndeclaredThrowableException(ex, \"TransactionCallback threw undeclared checked exception\");         }         commit(status);         return result;     }      \/**      * @see TransactionTemplate#rollbackOnException      *\/     private void doRollbackOnException(             TransactionStatus status,             Throwable ex     ) throws TransactionException {         try {             rollback(status);         } catch (TransactionSystemException ex2) {             log.error(\"Application exception overridden by rollback exception\", ex);             ex2.initApplicationException(ex);             throw ex2;         } catch (RuntimeException | Error ex2) {             log.error(\"Application exception overridden by rollback exception\", ex);             throw ex2;         }     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<\/li>\n<li>\n<p><code>OracleToPostgresLobHandler<\/code> \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 <code>PreparedStatement.setString<\/code> \u0434\u043b\u044f PostgreSQL \u0432\u043c\u0435\u0441\u0442\u043e <code>setClobAsString<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 PostgreSQL \u0432\u043c\u0435\u0441\u0442\u043e CLOB-\u043a\u043e\u043b\u043e\u043d\u043e\u043a \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 text-\u043a\u043e\u043b\u043e\u043d\u043a\u0438;<\/p>\n<details class=\"spoiler\">\n<summary>OracleToPostgresLobHandler<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">\/**  * \u041f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f {@link #getClobAsString} \u0438 {@link LobCreator#setClobAsString}  * \u0438 \u0438\u0445 \u0435\u0434\u0438\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430\u043c\u0438 \u0434\u043b\u044f oracle \u0438 pg.  *\/ @Immutable public final class OracleToPostgresLobHandler extends DefaultLobHandler {     \/**      * \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0438\u043f\u0430 varchar2      * https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/19\/refrn\/datatype-limits.html      *\/     private static final int ORACLE_MAX_VARCHAR_SIZE_BYTES = 4000;      public OracleToPostgresLobHandler() {         \/\/ \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043e\u0440\u0430\u043a\u043b\u043e\u0432\u044b\u0439 \u0434\u0440\u0430\u0439\u0432\u0435\u0440,         \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u041d\u0415 TemporaryLobCreator,         \/\/ \u043e\u0447\u0438\u0441\u0442\u043a\u043e\u0439 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0441\u0430\u043c \u043e\u0440\u0430\u043a\u043b\u043e\u0432\u044b\u0439 \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 PreparedStatement         setCreateTemporaryLob(false);         setStreamAsLob(true);     }      @Override     public LobCreator getLobCreator() {         return new DefaultLobCreator() {             @Override             public void setClobAsString(                     @Nonnull PreparedStatement ps,                     int paramIndex,                     @Nullable String content             ) throws SQLException {                 if (content == null                         \/\/ \u0431\u0435\u0440\u0451\u043c \u043f\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c\u0443 (\u043f\u043e 4 \u0431\u0430\u0439\u0442\u0430) \u043d\u0430 \u0441\u0438\u043c\u0432\u043e\u043b \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438                         || content.length() &lt;= ORACLE_MAX_VARCHAR_SIZE_BYTES >> 2                         \/\/ \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u043c\u0430\u043f\u0438\u043c \u043e\u0440\u0430\u043a\u043b\u043e\u0432\u044b\u0435 clob-\u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u043d\u0430 text, \u043d\u0435 \u043d\u0430 oid                         || \"PostgreSQL\".equals(ps.getConnection().getMetaData().getDatabaseProductName())                         \/\/ \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432                         || content.getBytes(StandardCharsets.UTF_8).length &lt;= ORACLE_MAX_VARCHAR_SIZE_BYTES                 ) {                     \/\/ \u043e\u0440\u0430\u043a\u043b\u043e\u0432\u044b\u0439 \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0441\u0442\u0440\u043e\u043a \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 clob-\u043a\u043e\u043b\u043e\u043d\u043a\u0443 \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u0443\u044e                     ps.setString(paramIndex, content);                 } else {                     super.setClobAsString(ps, paramIndex, content);                 }             }         };     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<\/li>\n<li>\n<p><code>OracleToPostgresSql<\/code> \u0434\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0431\u0430\u0437\u044b (\u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 \u0443\u0434\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a\u00a0\u0435\u0434\u0438\u043d\u043e\u043c\u0443 \u0432\u0438\u0434\u0443) \u2014 \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u043c\u043e\u0433\u0430\u043b \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0438, \u043a\u043e\u0433\u0434\u0430 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430 \u043d\u0435\u00a0\u0445\u0432\u0430\u0442\u0430\u043b\u043e;<\/p>\n<details class=\"spoiler\">\n<summary>OracleToPostgresSql<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@ThreadSafe public final class OracleToPostgresSql implements PreparedStatementCreator, SqlProvider {     private static final ThreadLocal&lt;String> LAST_DB_TYPE = new NamedThreadLocal&lt;>(\"db type\");     private final String sqlOracle;     private final String sqlPg;      public OracleToPostgresSql(             String sqlOracle,             String sqlPg     ) {         this.sqlOracle = Objects.requireNonNull(sqlOracle);         this.sqlPg = Objects.requireNonNull(sqlPg);     }      @Override     public PreparedStatement createPreparedStatement(Connection con) throws SQLException {         LAST_DB_TYPE.set(con.getMetaData().getDatabaseProductName());         return con.prepareStatement(getSql());     }      @Override     public String getSql() {         return \"PostgreSQL\".equals(LAST_DB_TYPE.get())                 ? sqlPg                 : sqlOracle;     }      \/**      * uses {@link PreparedStatementCreator} instead of sql string      *      * @see JdbcOperations#batchUpdate(String, List)      *\/     public int[] batchUpdate(             JdbcOperations jdbcTemplate,             List&lt;Object[]> batchArgs     ) throws DataAccessException {         return batchUpdate(jdbcTemplate, batchArgs, new int[0]);     }      \/**      * uses {@link PreparedStatementCreator} instead of sql string      *      * @see JdbcOperations#batchUpdate(String, List, int[])      *\/     public int[] batchUpdate(             JdbcOperations jdbcTemplate,             List&lt;Object[]> batchArgs,             int[] argTypes     ) throws DataAccessException {         if (batchArgs.isEmpty()) {             return new int[0];         }         return batchUpdate(jdbcTemplate, new BatchPreparedStatementSetter() {             @Override             public void setValues(PreparedStatement ps, int i) throws SQLException {                 Object[] values = batchArgs.get(i);                 int colIndex = 0;                 for (Object value : values) {                     colIndex++;                     if (value instanceof SqlParameterValue) {                         SqlParameterValue paramValue = (SqlParameterValue) value;                         StatementCreatorUtils.setParameterValue(ps, colIndex, paramValue, paramValue.getValue());                     } else {                         int colType;                         if (argTypes.length &lt; colIndex) {                             colType = SqlTypeValue.TYPE_UNKNOWN;                         } else {                             colType = argTypes[colIndex - 1];                         }                         StatementCreatorUtils.setParameterValue(ps, colIndex, colType, value);                     }                 }             }              @Override             public int getBatchSize() {                 return batchArgs.size();             }         });     }      \/**      * uses {@link PreparedStatementCreator} instead of sql string      *      * @see JdbcOperations#batchUpdate(String, BatchPreparedStatementSetter)      *\/     public int[] batchUpdate(             JdbcOperations jdbcTemplate,             BatchPreparedStatementSetter pss     ) throws DataAccessException {         return Objects.requireNonNull(jdbcTemplate.execute(this, ps -> {             try {                 int batchSize = pss.getBatchSize();                 var ipss = pss instanceof InterruptibleBatchPreparedStatementSetter                         ? (InterruptibleBatchPreparedStatementSetter) pss                         : null;                 if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) {                     for (int i = 0; i &lt; batchSize; i++) {                         pss.setValues(ps, i);                         if (ipss != null &amp;&amp; ipss.isBatchExhausted(i)) {                             break;                         }                         ps.addBatch();                     }                     return ps.executeBatch();                 } else {                     List&lt;Integer> rowsAffected = new ArrayList&lt;>(batchSize);                     for (int i = 0; i &lt; batchSize; i++) {                         pss.setValues(ps, i);                         if (ipss != null &amp;&amp; ipss.isBatchExhausted(i)) {                             break;                         }                         rowsAffected.add(ps.executeUpdate());                     }                     int[] rowsAffectedArray = new int[rowsAffected.size()];                     for (int i = 0; i &lt; rowsAffectedArray.length; i++) {                         rowsAffectedArray[i] = rowsAffected.get(i);                     }                     return rowsAffectedArray;                 }             } finally {                 if (pss instanceof ParameterDisposer) {                     ((ParameterDisposer) pss).cleanupParameters();                 }             }         }));     }      \/**      * uses {@link PreparedStatementCreator} instead of sql string      *      * @see JdbcOperations#batchUpdate(String, Collection, int, ParameterizedPreparedStatementSetter)      *\/     public &lt;T> int[][] batchUpdate(             JdbcOperations jdbcTemplate,             Collection&lt;T> batchArgs,             int batchSize,             ParameterizedPreparedStatementSetter&lt;T> pss     ) throws DataAccessException {         return Objects.requireNonNull(jdbcTemplate.execute(this, ps -> {             try {                 boolean batchSupported = JdbcUtils.supportsBatchUpdates(ps.getConnection());                 List&lt;int[]> rowsAffected = new ArrayList&lt;>(batchSupported                         ? Math.min(batchArgs.size(), (batchArgs.size() \/ batchSize) + 1)                         : batchArgs.size());                 int n = 0;                 for (T obj : batchArgs) {                     pss.setValues(ps, obj);                     n++;                     if (batchSupported) {                         ps.addBatch();                         if (n % batchSize == 0 || n == batchArgs.size()) {                             rowsAffected.add(ps.executeBatch());                         }                     } else {                         int i = ps.executeUpdate();                         rowsAffected.add(new int[]{i});                     }                 }                 int[][] result1 = new int[rowsAffected.size()][];                 for (int i = 0; i &lt; result1.length; i++) {                     result1[i] = rowsAffected.get(i);                 }                 return result1;             } finally {                 if (pss instanceof ParameterDisposer) {                     ((ParameterDisposer) pss).cleanupParameters();                 }             }         }));     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<\/li>\n<li>\n<p>\u0440\u0430\u043d\u0442\u0430\u0439\u043c-\u0444\u043b\u0430\u0436\u043e\u043a \u0434\u043b\u044f <code>QueryRouting<\/code> \u0441 \u0444\u043e\u043d\u043e\u0432\u044b\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u043c (\u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0438\u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b), \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 (\u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0435\u0441\u043b\u0438 \u044f\u0432\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043d\u0435 \u0431\u044b\u043b\u043e).<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u0441\u0430\u043c\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 jdbc template \u0438 tx manager. \u0421\u043a\u0430\u0436\u0443 \u0442\u0430\u043a: \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u043c\u0430\u043b\u043e\u0432\u0430\u0442\u043e \u0442\u0435\u0441\u0442\u043e\u0432, \u2014 \u0432\u0430\u043c \u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u043f\u0438\u0448\u0438\u0442\u0435 \u0435\u0449\u0451. \u041b\u0438\u0448\u044c \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u043a\u0440\u044b\u043b\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043c\u0438 (\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c), \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044e.<\/p>\n<p>\u041a \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u0441\u0445\u0435\u043c\u0430 \u0441\u0442\u0430\u043b\u0430 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/057\/253\/11f\/05725311f6e2661e1fa4563ef16d4bb0.png\" width=\"2060\" height=\"620\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/057\/253\/11f\/05725311f6e2661e1fa4563ef16d4bb0.png\"\/><\/figure>\n<h3>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435. \u0422\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043c\u0430\u0440\u0442\u0430 2022 \u0433\u043e\u0434\u0430 \u043d\u0430\u0441\u0442\u0430\u043b \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438. \u0425\u043e\u0442\u044f \u043e\u043d\u043e \u0438 \u0434\u0430\u043b\u0435\u043a\u043e\u0432\u0430\u0442\u043e \u043e\u0442 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u043d\u043e \u0432\u0441\u0435 \u0444\u043e\u043d\u043e\u0432\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0442\u0430\u043c \u0442\u0430\u043a\u0438\u0435 \u0436\u0435, \u043a\u0430\u043a \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435, \u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u043f\u043e\u043a\u0440\u044b\u0442\u043e \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438, \u0430 \u0435\u0449\u0451 \u0440\u0443\u0447\u043d\u044b\u043c\u0438 \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438. \u0412 \u043e\u0431\u0449\u0435\u043c, \u043d\u0435\u0434\u043e\u0432\u043e\u043b\u044c\u043d\u044b\u043c\u0438 \u043c\u043e\u0433\u043b\u0438 \u043e\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u043b\u0438\u0448\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0438, \u043d\u043e \u0438\u043c \u043d\u0435 \u043f\u0440\u0438\u0432\u044b\u043a\u0430\u0442\u044c.<\/p>\n<p>\u041a\u043e\u0440\u043e\u0447\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u043c\u044b \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u043b\u0438\u0441\u044c \u043d\u0430 <code>NOOP_REPEAT<\/code> \u0438 \u0441\u0442\u0430\u043b\u0438 \u0436\u0434\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043e\u043d\u0438 \u043d\u0435\u00a0\u0437\u0430\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0441\u0435\u0431\u044f \u0436\u0434\u0430\u0442\u044c. \u041e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442\u043b\u0430\u0432\u043b\u0438\u0432\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/sentry.io\"><u>Sentry<\/u> (<\/a>\u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u0443\u0436\u0435 \u0431\u044b\u043b, \u0430 \u0442\u0430\u043a \u0432\u043c\u0435\u0441\u0442\u043e Sentry \u043c\u043e\u0433 \u0431\u044b\u0442\u044c ELK \u0438 \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441\u0431\u043e\u0440\u0430 \u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043b\u043e\u0433\u043e\u0432, <code>tail -f<\/code> \u0442\u043e\u0436\u0435 \u0441\u043e\u0439\u0434\u0451\u0442): \u0432\u0431\u0438\u043b\u0438 \u0444\u0438\u043b\u044c\u0442\u0440 \u043f\u043e \u043a\u043b\u0430\u0441\u0441\u0443 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0438 \u0432 \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u0447\u0438\u043d\u0438\u043b\u0438 \u0432\u0441\u0451, \u0447\u0442\u043e \u043d\u0430\u0448\u043b\u043e\u0441\u044c.\u00a0<\/p>\n<p>\u041e\u0448\u0438\u0431\u043a\u0438 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438, \u043d\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u043c \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u0440\u043c\u043e\u0437\u043e\u0432. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0435 \u0441\u0445\u0435\u043c\u044b \u0432 PostgreSQL \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 \u0440\u043e\u0432\u043d\u043e \u0442\u0435 \u0436\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u044b, \u043a\u0430\u043a \u0438 \u0432 Oracle, \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u043b\u0438, \u0447\u0442\u043e performance \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c\u044b\u043c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u0434\u0443\u043c\u0430\u043b\u0438, \u0447\u0442\u043e \u0442\u0430\u0439\u043c\u0438\u043d\u0433\u0438 \u043f\u0440\u0438 shadow-\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 x2. \u041d\u043e \u0443 PostgreSQL \u0441\u0432\u043e\u0451 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0432 \u0441\u0440\u043e\u0447\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u043c\u0438\u0440 \u0442\u044e\u043d\u0438\u043d\u0433\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u043e\u0434 PostgreSQL.<\/p>\n<p>\u0423\u0447\u0438\u0442\u044b\u0432\u0430\u044f, \u0447\u0442\u043e \u043d\u0430 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u043f\u044b\u0442\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 PostgreSQL \u0443 \u043c\u0435\u043d\u044f \u0431\u044b\u043b\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043d\u043e\u043b\u044c, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0441\u043a\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0447\u0442\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0435 \u0437\u0430\u043d\u044f\u043b\u043e \u0431\u044b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0434\u0435\u043b\u044c. \u0418 \u044f \u0435\u0451 \u043d\u0430\u0448\u0451\u043b. \u041f\u043e\u0434 \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u043e\u043c \u0441\u0441\u044b\u043b\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0441\u0442\u0430\u043b\u0438\u0441\u044c \u0432 \u0437\u0430\u043a\u0440\u043e\u043c\u0430\u0445 \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u043b\u0438 \u043b\u0438\u0447\u043d\u043e \u043c\u043d\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043f\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p><a href=\"https:\/\/postgrespro.com\/blog\/pgsql\/5968054\"><u>\u0410 deep dive into PostgreSQL query optimizations<\/u><\/a> (\u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u043b\u0430\u0441\u044c \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043a \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438)<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/pgday.ru\/files\/pgmaster14\/max.boguk.query.optimization.pdf\"><u>\u041d\u0435\u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0440\u0438\u0451\u043c\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.postgresql.eu\/events\/pgconfde2019\/sessions\/session\/2414\/slides\/188\/P-DBI-20190402-001-PostgreSQLTuningforOracleDBA.pdf\"><u>PostgreSQL tuning for Oracle DBAs<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/postgrespro\/articles\/326096\/\"><u>\u0418\u043d\u0434\u0435\u043a\u0441\u044b \u0432 PostgreSQL<\/u><\/a> (\u0432\u0441\u044f \u0441\u0435\u0440\u0438\u044f)<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/use-the-index-luke.com\/sql\/table-of-contents\"><u>What every developer should know about SQL performance<\/u><\/a> (\u0432\u0435\u0441\u044c \u0441\u0430\u0439\u0442)<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/wiki.postgresql.org\/wiki\/OptimizerHintsDiscussion\"><u>Optimizer Hints Discussion<\/u><\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u0421\u043f\u0443\u0441\u0442\u044f \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u0448\u043e\u0440\u0442-\u043b\u0438\u0441\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439:<\/p>\n<ol>\n<li>\n<p>\u0412\u044b\u043a\u0438\u043d\u0443\u0442\u044c \u0438\u0437 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432\u0441\u0451 \u043b\u0438\u0448\u043d\u0435\u0435 (join, \u043f\u043e\u043b\u044f \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u043b\u043e\u0447\u0438 \u2014 Oracle \u044d\u0442\u043e \u043f\u0440\u043e\u0449\u0430\u043b).<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 (\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u043b\u0441\u044f \u0434\u0430\u0436\u0435 <a href=\"https:\/\/www.postgresql.org\/docs\/current\/brin-intro.html\">brin<\/a>).<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0440\u044f\u0434\u043e\u043a join. \u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u0438\u0445 \u043c\u043d\u043e\u0433\u043e (\u043d\u0430 \u044d\u0442\u043e \u0442\u0430\u043a\u0436\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043b\u0438\u044f\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <a href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-query.html#GUC-JOIN-COLLAPSE-LIMIT\"><u>join_collapse_limit<\/u><\/a>, \u043d\u043e \u043c\u044b \u0435\u0433\u043e \u043d\u0435 \u043c\u0435\u043d\u044f\u043b\u0438).<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c join \u043d\u0430 <code>where [not] exists(...)<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c <code>row_number over as rn ... where rn = 1<\/code> \u043d\u0430 <code>select distinct on (columns) order by<\/code> \u2014 \u044d\u0442\u043e \u043a\u0440\u0443\u0442\u0430\u044f PostgreSQL-specific-\u0444\u0438\u0447\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043b\u0435\u0433\u0447\u0435 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u0435\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0445\u043e\u0447\u0435\u0442\u0441\u044f nested loop \u0434\u043b\u044f join, \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c PostgreSQL-specific <code>join lateral<\/code>. \u041f\u0440\u0430\u0432\u0434\u0430, \u043d\u0430\u043c \u043e\u043d \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u043b\u0441\u044f \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437.\u00a0<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043d\u044f\u0442\u044c <code>work_mem<\/code> \u043d\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 PostgreSQL. \u041f\u0440\u0438 16 MiB \u043c\u044b \u0443\u043f\u0438\u0440\u0430\u043b\u0438\u0441\u044c \u0432 IO, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0434\u043d\u044f\u043b\u0438 \u0434\u043e 32 MiB (\u0435\u0441\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b).<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043d\u044f\u0442\u044c <code>lock_timeout<\/code>. \u0414\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u043c.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u043e \u043a \u044d\u0442\u043e\u043c\u0443 \u0441\u043f\u0438\u0441\u043a\u0443 \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043d\u0435 \u0441\u0440\u0430\u0437\u0443. \u0412\u043e\u0442, \u0447\u0442\u043e \u043c\u044b \u0435\u0449\u0451 \u0443\u0441\u043f\u0435\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u0432 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a, \u00ab\u043a\u0430\u043a \u0432 Oracle\u00bb:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0438\u0433\u0440\u0430\u043b\u0438\u0441\u044c \u0441 <a href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-query.html\"><u>cost-\u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438<\/u><\/a>. \u0412 \u0438\u0442\u043e\u0433\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u0443 \u043d\u0430\u0441 <code>cpu_tuple_cost=0.01<\/code>, <code>cpu_index_tuple_cost=0.001<\/code>, <code>cpu_operator_cost = 0.0005<\/code>, \u043d\u043e \u044d\u0442\u0438 \u0447\u0438\u0441\u0435\u043b\u043a\u0438 \u0431\u044b\u043b\u0438 \u0432\u0437\u044f\u0442\u044b \u0433\u0434\u0435-\u0442\u043e \u043f\u043e \u0441\u043e\u0432\u0435\u0442\u0443 \u0430\u0433\u0435\u043d\u0442\u0441\u0442\u0432\u0430 \u041e\u0411\u0421, \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432\u043b\u0438\u044f\u043d\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e ?<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u043c\u0435\u043d\u044f\u0442\u044c <a href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-query.html\"><u>join_collapse_limit<\/u><\/a> \u2014 \u043d\u0435 \u043f\u043e\u043c\u043e\u0433\u043b\u043e, \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u044c <a href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-query.html\"><u>enable_seqscan<\/u><\/a> \u2014 \u043d\u0435 \u043f\u043e\u043c\u043e\u0433\u043b\u043e, \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 <a href=\"https:\/\/github.com\/ossc-db\/pg_hint_plan\"><u>pg_hint_plan<\/u><\/a> \u2014 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0445\u0438\u043d\u0442\u0430\u043c\u0438 Oracle \u0438\u00a0\u0441\u043c\u0430\u0445\u0438\u0432\u0430\u0435\u0442 \u043d\u0430 \u043a\u043e\u0441\u0442\u044b\u043b\u0438, \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c. \u0412 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u043d\u0430 Oracle \u0431\u044b\u043b\u0430 \u043a\u0443\u0447\u0430 \u0445\u0438\u043d\u0442\u043e\u0432, \u0430 \u0434\u043b\u044f PostgreSQL \u0432 \u0438\u0442\u043e\u0433\u0435 \u0445\u0432\u0430\u0442\u0438\u043b\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0442\u043e\u0433\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0431\u044b\u043b\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e 94 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0438\u043b\u0438 \u043b\u043e\u0433\u0438\u043a\u043e\u0439, \u0430 \u0435\u0449\u0451 27 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 performance.<\/p>\n<p>\u041f\u043b\u0430\u043d \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<ol>\n<li>\n<p>\u0412 \u0447\u0430\u0441 \u0427 \u043e\u0442\u0431\u0438\u0440\u0430\u0435\u043c \u0443 Oracle \u043f\u0440\u0430\u0432\u0430 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c.<\/p>\n<\/li>\n<li>\n<p>\u0416\u0434\u0451\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 10 \u0441\u0435\u043a\u0443\u043d\u0434, \u043f\u0440\u0438\u0431\u0438\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0437\u0430\u0432\u0438\u0441\u0448\u0438\u0435 \u0434\u043e\u043b\u0433\u0438\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 Oracle.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u0441\u044f \u043d\u0443\u043b\u0435\u0432\u043e\u0433\u043e \u043b\u0430\u0433\u0430 \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e \u043d\u0430\u0448\u0438\u043c \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0442\u0430\u043c.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044e.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043d\u0430 PostgreSQL \u0433\u0440\u0430\u043d\u0442\u044b, \u0434\u0430\u0451\u043c \u043f\u0440\u0430\u0432\u0430 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u0438 \u043e\u0442\u0431\u0438\u0440\u0430\u0435\u043c \u0438\u0445 \u0443 GG.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0432 PostgreSQL.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0434\u0451\u043c \u0447\u0438\u043d\u0438\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0432\u044b\u043b\u0435\u0437\u0435\u0442.<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043b\u0430\u043d \u0431\u044b\u043b \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u0432 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043c\u0430\u0440\u0442\u0430 2022 \u0433\u043e\u0434\u0430. \u041e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043d\u0430 \u0443\u0440\u0430 (\u043f\u0440\u0430\u0432\u0434\u0430, \u0441\u0440\u0430\u0437\u0443 \u0432\u0441\u043f\u043b\u044b\u043b\u043e, \u0447\u0442\u043e \u043c\u044b \u0437\u0430\u0431\u044b\u043b\u0438 \u0441\u0434\u0432\u0438\u043d\u0443\u0442\u044c sequences \u0432 PostgreSQL ?). \u0412 \u044d\u0442\u043e\u0442 \u0434\u0435\u043d\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0431\u044f\u0442 \u0432\u044b\u0437\u0432\u0430\u043b\u0438\u0441\u044c \u043f\u043e\u043c\u043e\u0447\u044c \u0431\u044b\u0441\u0442\u0440\u0435\u043d\u044c\u043a\u043e \u0440\u0430\u0437\u0433\u0440\u0435\u0441\u0442\u0438 \u0432\u0441\u043f\u043b\u044b\u0432\u0448\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043b\u0438 \u0432\u0441\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u0438\u044f.\u00a0<\/p>\n<p>\u041a \u0432\u0435\u0447\u0435\u0440\u0443 \u044d\u0442\u043e\u0433\u043e \u0436\u0435 \u0434\u043d\u044f \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u043d\u0433\u0430 \u0432\u0441\u0451 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u043e\u0441\u044c, \u0432\u043f\u0435\u0440\u0435\u0434\u0438 \u043c\u0430\u044f\u0447\u0438\u043b \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d.<\/p>\n<h3>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u2014 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d<\/h3>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430 \u043c\u044b \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u043b\u0438 \u0432\u0441\u0435 \u0442\u0435 \u0436\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u043e\u0432\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0437\u0430 \u0434\u0432\u0435 \u043d\u0435\u0434\u0435\u043b\u0438 \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c 51 \u043e\u0448\u0438\u0431\u043a\u0443 \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0438 \u043b\u043e\u0433\u0438\u043a\u0435 \u0438 25 \u043e\u0448\u0438\u0431\u043e\u043a \u0432\u00a0performance. \u0421 \u0443\u0447\u0451\u0442\u043e\u043c \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0441\u043d\u043e\u0432\u0430 \u0431\u044b\u043b \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043f\u043e\u043c\u0438\u043d\u0443\u0442\u043d\u044b\u0439 \u043f\u043b\u0430\u043d \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u2014 \u0438 \u0432 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u043f\u0440\u043e sequences \u043d\u0435 \u0437\u0430\u0431\u044b\u043b\u0438 ?.<\/p>\n<p>\u0418 \u0432\u043e\u0442 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u043b \u0434\u0435\u043d\u044c \u0414, \u0447\u0430\u0441 \u0427. \u0417\u043d\u0430\u0435\u0442\u0435 \u0442\u043e \u0447\u0443\u0432\u0441\u0442\u0432\u043e, \u043a\u043e\u0433\u0434\u0430 \u043b\u0430\u0434\u043e\u0448\u043a\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043f\u043e\u0442\u043d\u044b\u043c\u0438 \u0438 \u043f\u0443\u043b\u044c\u0441 \u043f\u043e\u0434\u0441\u043a\u0430\u043a\u0438\u0432\u0430\u0435\u0442? \u0412\u043e\u0442 \u0435\u0433\u043e \u044f \u0438 \u0438\u0441\u043f\u044b\u0442\u0430\u043b. \u041a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0431\u044b\u043b\u0438 \u0433\u043e\u0442\u043e\u0432\u044b, \u044f \u0434\u0430\u043b \u043e\u0442\u043c\u0430\u0448\u043a\u0443 \u043a \u043d\u0430\u0447\u0430\u043b\u0443.<\/p>\n<p>\u0418 \u043e\u043d\u043e \u0441\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u0418 \u043e\u043d\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e. \u0421\u043d\u0430\u0447\u0430\u043b\u0430, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0431\u044b\u043b\u0430 \u0442\u0438\u0448\u0438\u043d\u0430 \u0438 \u0440\u0435\u0434\u043a\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b: \u00ab\u0410 \u043c\u044b \u0443\u0436\u0435 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u043b\u0438\u0441\u044c?\u00bb \u041d\u043e \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u0438\u0448\u043b\u043e \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u0438\u0435 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e. \u0410 \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438. \u0412\u0441\u0435 \u043f\u0440\u043e\u0448\u043b\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0442\u0438\u0445\u043e \u0438 \u0433\u043b\u0430\u0434\u043a\u043e \u2014 \u0440\u0430\u0437\u0432\u0435 \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u044b\u0445 \u043f\u044f\u0442\u0438\u0441\u043e\u0442\u043e\u043a.<\/p>\n<p>\u0420\u0435\u0434\u043a\u0438\u0435 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u043c\u044b \u043f\u043e\u0447\u0438\u043d\u0438\u043b\u0438 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043f\u0430\u0440\u044b \u0447\u0430\u0441\u043e\u0432. \u0423\u0441\u0442\u0430\u0432\u0448\u0438\u0435, \u043d\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0440\u0430\u0437\u043e\u0448\u043b\u0438\u0441\u044c \u043f\u043e \u0434\u043e\u043c\u0430\u043c.<\/p>\n<p>\u0421\u0445\u0435\u043c\u0430 \u0441\u0442\u0430\u043b\u0430 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/422\/1e5\/9b7\/4221e59b74ba4ebb517d02d194db3d2a.png\" width=\"1450\" height=\"610\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/422\/1e5\/9b7\/4221e59b74ba4ebb517d02d194db3d2a.png\"\/><\/figure>\n<h2>\u042d\u043f\u0438\u043b\u043e\u0433<\/h2>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u043f\u043e\u0434\u0445\u043e\u0434 \u0432 \u0434\u0443\u0445\u0435 <a href=\"https:\/\/polotnos.cdnbro.com\/posts\/0095096-kak-narisovat-mem-5.jpg\"><u>\u00ab\u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0443\u00bb<\/u><\/a>, \u043d\u043e \u043e\u043d \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u0445\u043e\u0442\u044f \u0432 \u043d\u0435\u0433\u043e \u043f\u043e\u043d\u0430\u0447\u0430\u043b\u0443 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0432\u0435\u0440\u0438\u043b\u0438. \u041f\u0440\u0438\u0447\u0451\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u0448\u0435\u043b \u0434\u0430\u0436\u0435 \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u043b\u0438 \u0432\u043d\u0430\u0447\u0430\u043b\u0435. \u041c\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0431\u0430\u0437\u043e\u0439, \u043f\u043e\u043b\u0443\u0447\u0438\u0432 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u0447\u0442\u043e \u0432\u0438\u0434\u043d\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u0439 \u043f\u0435\u0440\u0432\u043e\u043c \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>\u042d\u0442\u043e\u0442 \u0436\u0435 \u043f\u043e\u0434\u0445\u043e\u0434, \u043d\u043e \u0432 \u0441\u0438\u043b\u044c\u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0438\u0445 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430\u0445 \u043c\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b\u0438 \u0435\u0449\u0451 \u0440\u0430\u0437 \u0432 \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0435: \u0442\u0435 \u0436\u0435 \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0437\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430, \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0434\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u044b, \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u043e \u043f\u0443\u0442\u0438 \u2014 \u0438\u00a0\u0434\u0435\u043b\u043e \u0433\u043e\u0442\u043e\u0432\u043e.<\/p>\n<p>\u041d\u0443 \u0438 \u043d\u0430\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a: \u0442\u0435\u0441\u0442\u044b \u2014 \u043d\u0430\u0448\u0435 \u0432\u0441\u0451. \u0418\u043c\u0435\u043d\u043d\u043e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0442\u0435\u0441\u0442\u0430\u043c \u043c\u044b \u0431\u044b\u043b\u0438 \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u043d\u0435 \u0443\u0440\u043e\u043d\u0438\u043c \u0432\u0441\u0451 \u0438 \u0441\u0440\u0430\u0437\u0443. \u0422\u0435\u0441\u0442\u043e\u0432 \u043c\u043d\u043e\u0433\u043e \u043d\u0435 \u0431\u044b\u0432\u0430\u0435\u0442.<\/p>\n<details class=\"spoiler\">\n<summary>\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0441\u0441\u044b\u043b\u043e\u043a \u043f\u043e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p><a href=\"https:\/\/wiki.postgresql.org\/wiki\/Oracle_to_Postgres_Conversion\"><u>Oracle to Postgres Conversion<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/335716\/\"><u>\u0421\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 Oracle \u0441 PostgreSQL<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/216057\/\"><u>\u0418\u0437 Oracle \u0434\u0430 \u0432 Postgres<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=GoOri7fOHLg\"><u>Top 10 Mistakes When Migrating From Oracle to PostgreSQL<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.enterprisedb.com\/blog\/the-complete-oracle-to-postgresql-migration-guide-tutorial-move-convert-database-oracle-alternative\"><u>The Complete Oracle to Postgres Migration Guide: Move and Convert Schema, Applications and Data<\/u><\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/801415\/\"> https:\/\/habr.com\/ru\/articles\/801415\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\">\n<div><figcaption>\u0413\u0440\u0430\u0444\u0438\u043a 99-\u0433\u043e \u043f\u0435\u0440\u0446\u0435\u043d\u0442\u0438\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e user-facing-\u0441\u0435\u0440\u0432\u0438\u0441\u0430: \u0436\u0438\u0437\u043d\u044c \u0434\u043e, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0435\u0437\u0434\u0430. \u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0430\u043b\u043e \u043b\u0443\u0447\u0448\u0435!<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u042f \u0421\u0435\u0440\u0433\u0435\u0439, \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 B2B-\u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u042f\u043d\u0434\u0435\u043a\u0441 \u041c\u0430\u0440\u043a\u0435\u0442\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 3,5\u00a0\u0433\u043e\u0434\u0430. \u041a\u0430\u043a \u0443\u0436\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430, \u0441\u0435\u0439\u0447\u0430\u0441 \u044f \u0432\u0430\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e yet-another-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u0431\u0430\u0437\u044b \u043d\u0430 \u0431\u0430\u0437\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u0447\u0430\u043b\u0430\u0441\u044c \u0432 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 2021 \u0433\u043e\u0434\u0430 \u0438 \u0437\u0430\u043d\u044f\u043b\u0430 \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0434. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u043c\u0435\u043c\u0443\u0430\u0440\u044b.<\/p>\n<p>\u0412\u0430\u0441 \u0436\u0434\u0451\u0442 \u0440\u0430\u0441\u0441\u043a\u0430\u0437 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u044b:<\/p>\n<ul>\n<li>\n<p>\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0441\u044f\u0446\u0435\u0432 \u0447\u0438\u043d\u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \u0438 \u0434\u0435\u043b\u0430\u043b\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440;<\/p>\n<\/li>\n<li>\n<p>\u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0440\u0430\u0437 \u043f\u0435\u0440\u0435\u043b\u0438\u0432\u0430\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435;<\/p>\n<\/li>\n<li>\n<p>\u0447\u0438\u043d\u0438\u043b\u0438 \u0431\u0430\u0433\u0438 \u043d\u0435\u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0437\u0430\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 PostgreSQL \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043d\u0430 Oracle.<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h2>\u0427\u0442\u043e \u0431\u044b\u043b\u043e \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435<\/h2>\n<p>\u0415\u0441\u0442\u044c \u0432 \u042f\u043d\u0434\u0435\u043a\u0441 \u041c\u0430\u0440\u043a\u0435\u0442\u0435 \u043e\u0434\u0438\u043d \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043f\u0430\u0440\u0442\u043d\u0451\u0440\u0430\u043c\u0438 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u0440\u043e\u0434\u0430\u0432\u0446\u0430\u043c\u0438 \u0438\u043b\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430\u043c\u0438. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f, \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0430\u0441\u0441\u043e\u0440\u0442\u0438\u043c\u0435\u043d\u0442\u043e\u043c, \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u043a\u0430\u0437\u043e\u0432 \u2014 \u0432 \u043e\u0431\u0449\u0435\u043c, \u0432 \u043d\u0451\u043c \u0441\u043e\u0431\u0440\u0430\u043d\u043e \u0432\u0441\u0451, \u0441 \u0447\u0435\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0430\u0440\u0442\u043d\u0451\u0440\u0430\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c.\u00a0<\/p>\n<p>\u041f\u043e \u0441\u0443\u0442\u0438 \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u0445 API (\u0431\u044d\u043a \u0434\u043b\u044f \u043f\u0430\u0440\u0442\u043d\u0451\u0440\u0441\u043a\u043e\u0433\u043e UI, API \u0434\u043b\u044f \u043f\u0430\u0440\u0442\u043d\u0451\u0440\u043e\u0432, API \u0434\u043b\u044f \u0441\u043c\u0435\u0436\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c), \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0434\u043b\u044f \u0444\u043e\u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 (\u0432\u0441\u044f\u043a\u0438\u0435 \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u0435 \u0440\u0430\u0441\u0447\u0451\u0442\u044b, \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u0447\u0451\u0442\u043e\u0432, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441\u043e \u0441\u043c\u0435\u0436\u043d\u044b\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438) \u0438 \u0430\u0434\u043c\u0438\u043d\u043a\u0430. \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u044d\u0442\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0436\u0438\u0432\u0451\u0442 \u043d\u0430 \u043e\u0431\u0449\u0435\u0439 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0441\u0432\u043e\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0422\u0430\u043a \u0438\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043b\u043e\u0436\u0438\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0431\u044b\u043b Oracle. \u041f\u043e\u0447\u0435\u043c\u0443? \u041f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u0437\u0430\u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043e\u043d \u0443\u0436\u0435 \u0431\u044b\u043b \u043a\u0443\u043f\u043b\u0435\u043d, \u0430 \u043c\u044b \u0432\u0437\u044f\u043b\u0438 \u0442\u043e, \u0447\u0442\u043e \u0431\u044b\u043b\u043e. \u0421\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 Oracle \u2014 \u044d\u0442\u043e \u043c\u043e\u0449\u043d\u0430\u044f \u0431\u0430\u0437\u0430. \u0412 \u044d\u0442\u043e\u043c \u043f\u043b\u0430\u043d\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u043d\u0435\u0439 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0436\u0438\u0442\u044c \u043d\u0430 \u043d\u0435\u0439 \u0438 \u0434\u0430\u043b\u044c\u0448\u0435, \u0435\u0441\u043b\u0438 \u0431\u044b \u043d\u0435 \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u2014 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438.<\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, Oracle \u0436\u0438\u043b \u043d\u0430 \u0434\u043e\u0440\u043e\u0433\u0438\u0445 \u0436\u0435\u043b\u0435\u0437\u043d\u044b\u0445 \u0442\u0430\u0447\u043a\u0430\u0445, \u0431\u0435\u0437 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, Oracle DBA \u2014 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0440\u043e\u0433\u0438\u0435 \u0440\u0435\u0431\u044f\u0442\u0430 \u0438 \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043d\u0430 \u0432\u0441\u044e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044e \u0438\u0445 \u0441\u0442\u0430\u043b\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0442\u044c. \u041d\u0443 \u0438 \u0432-\u0442\u0440\u0435\u0442\u044c\u0438\u0445, \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u043b\u0430\u0442\u043d\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 Oracle, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0451\u043d\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438, \u0441\u043e\u00a0\u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0441\u0442\u0430\u043b\u0430 \u043e\u0433\u0440\u043e\u043c\u043d\u0430.<\/p>\n<p>\u0412\u043e\u043f\u0440\u043e\u0441 \u043f\u0435\u0440\u0435\u0435\u0437\u0434\u0430 \u0441 Oracle \u0432\u0441\u0442\u0430\u043b \u0440\u0435\u0431\u0440\u043e\u043c.<\/p>\n<p>\u0410 \u0442\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u044c PostgreSQL \u0440\u043e\u0441\u043b\u0430 \u043a\u0430\u043a \u043d\u0430 \u0434\u0440\u043e\u0436\u0436\u0430\u0445, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u0432 \u042f\u043d\u0434\u0435\u043a\u0441\u0435. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432\u043e \u0433\u043b\u0430\u0432\u0443 \u0443\u0433\u043b\u0430 \u0431\u044b\u043b\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438, \u0442\u043e \u0440\u0435\u0448\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0435\u0437\u0436\u0430\u0442\u044c \u043d\u0430 Managed Service for PostgreSQL \u0432 Yandex Cloud.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043e\u0431\u0440\u0438\u0441\u0443\u044e\u2026\u00a0<\/p>\n<h3>\u0421\u0442\u0430\u0440\u0442\u043e\u0432\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f<\/h3>\n<ul>\n<li>\n<p>\u041e\u043a\u043e\u043b\u043e 1,5 TiB \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 Oracle, \u043e\u0434\u0438\u043d \u0448\u0430\u0440\u0434, \u0431\u043e\u043b\u0435\u0435 700\u00a0\u0442\u0430\u0431\u043b\u0438\u0446, \u0431\u043e\u043b\u0435\u0435 250\u00a0view, \u043d\u0435\u043c\u043d\u043e\u0436\u043a\u043e stored procedure.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435 \u0432 \u0431\u0443\u0434\u043d\u0438 \u2014 \u0434\u043e 3,5k\u00a0RPS \u0432 API, \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0430\u043a \u0438\u043b\u0438 \u0438\u043d\u0430\u0447\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u043a \u0431\u0430\u0437\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0430\u0440\u0430 \u0441\u043e\u0442\u0435\u043d \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0444\u043e\u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u043d\u043e\u043b\u0438\u0442\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441-\u0434\u0435\u0434\u0443\u0448\u043a\u0430 \u043d\u0430 Spring 5.1.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0430\u0437\u043e\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Spring JDBC, \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e Hibernate.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u043e\u0447\u0435\u043d\u044c \u043d\u0435\u043f\u043b\u043e\u0445\u043e\u0435 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u043c\u0438, \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0438 \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u0430\u043c\u0438 (\u044d\u0442\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043a\u0440\u0430\u0439\u043d\u0435 \u0432\u0430\u0436\u043d\u044b\u043c \u043f\u043e\u0434\u0441\u043f\u043e\u0440\u044c\u0435\u043c).<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u0438\u0437 20 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442 \u043d\u0430\u0432\u0430\u043b\u0438\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0444\u0438\u0447\u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0434\u0435\u043d\u044c.<\/p>\n<\/li>\n<li>\n<p>\u042f \u0438 \u043e\u0434\u0438\u043d \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 \u043f\u043e\u043c\u043e\u0449\u044c \u0441\u0442\u0430\u0436\u0451\u0440 \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0435\u0440\u0445\u043d\u0435\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u043e \u0441\u0445\u0435\u043c\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u0430 \u0442\u0430\u043a, \u043d\u0438\u0447\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u043d\u0435 \u0432\u0440\u0443\u0447\u0438\u043b\u0438 \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u043a\u0443 \u043f\u0435\u0440\u0435\u0435\u0437\u0434\u0430, \u0431\u044b\u043b\u0430 \u043d\u0430\u0434\u0435\u0436\u0434\u0430, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u044b \u0438\u00a0\u043f\u0435\u0440\u0435\u0435\u0445\u0430\u0442\u044c \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c \u0437\u0430 \u043c\u043d\u043e\u0433\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439. \u041f\u0440\u043e\u0432\u0435\u043b\u0438 \u0430\u043d\u0430\u043b\u0438\u0437 \u0441\u0432\u044f\u0437\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c, \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0432 \u0433\u0440\u0430\u0444 \u0442\u0430\u0431\u043b\u0438\u0446 \u043f\u043e join \u0438\u0437 \u043b\u043e\u0433\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u0430\u0437\u044b \u0438 \u043f\u043e foreign key \u0438\u0437 \u0441\u0445\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446. \u0418 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u043d\u0430\u043c\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0437\u0430\u043f\u0443\u0442\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0443\u0431\u043e\u043a, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u0441\u0451 \u0437\u0430\u0432\u044f\u0437\u0430\u043d\u043e \u0442\u0440\u0430\u043d\u0437\u0438\u0442\u0438\u0432\u043d\u043e \u043d\u0430 \u0432\u0441\u0451 (\u0437\u0430\u00a0\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c\u0438). \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0438\u0441\u0445\u043e\u0434\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u043e\u043b\u0435\u0435 700\u00a0\u0442\u0430\u0431\u043b\u0438\u0446, \u0430 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043a\u043b\u0443\u0431\u043a\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u043e\u043b\u0435\u0435\u00a0600. \u041a\u043e\u0433\u0434\u0430 \u0432\u0437\u0433\u043b\u044f\u043d\u0443\u043b\u0438 \u043d\u0430 \u044d\u0442\u043e \u0432\u0441\u0451 (\u043d\u0435 \u0431\u0435\u0437 \u0441\u043b\u0451\u0437), \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u043e\u0433\u043e \u0441\u043b\u043e\u043d\u0430 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043c\u043d\u043e\u0433\u043e \u043b\u0435\u0442.<\/p>\n<p>\u0412\u043e\u043f\u0440\u043e\u0441 \u0441 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u043e \u043a\u0443\u0441\u043a\u0430\u043c \u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0438 \u043d\u0430 \u043f\u043e\u043b\u043a\u0443 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u0437\u0430\u0439\u0442\u0438 \u0441 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043a\u043e\u043d\u0446\u0430. \u0421\u0442\u0430\u043b\u0438 \u0434\u0443\u043c\u0430\u0442\u044c, \u043a\u0430\u043a \u0431\u044b \u043c\u044b \u0441\u0442\u0430\u043b\u0438 \u043f\u0435\u0440\u0435\u043b\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0441\u0442\u0430\u0440\u043e\u0439 \u0431\u0430\u0437\u044b \u0432 \u043d\u043e\u0432\u0443\u044e \u2014 \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0440\u0435\u0448\u0430\u0442\u044c. \u041f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0442\u0430\u043a\u0438\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u043a\u043e\u0439-\u0442\u043e \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u0451\u0440\u0433\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043e\u0434\u043d\u043e\u0439 \u0431\u0430\u0437\u044b \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u0434\u0440\u0443\u0433\u0443\u044e. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043e\u0434\u043d\u0430\u0436\u0434\u044b \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0432 \u041c\u0430\u0440\u043a\u0435\u0442\u0435, \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043e\u0434\u043d\u0430\u043a\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u0442\u0430\u043c \u0431\u044b\u043b\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0449\u0435 (\u043d\u0435 \u0431\u044b\u043b\u043e user-facing-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432).<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/laurenz\/oracle_fdw\"><u>oracle_fdw<\/u><\/a>. \u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e: live-\u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 Oracle, \u043d\u043e \u0432 PostgreSQL. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 join \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u044d\u0442\u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 <a href=\"https:\/\/github.com\/laurenz\/oracle_fdw\/issues\/171#issuecomment-304862839\"><u>\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b\u043c<\/u><\/a>. \u041d\u0443 \u0438 \u0432\u0441\u0451 \u0436\u0435 \u044d\u0442\u043e \u043d\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043a\u0430\u043a \u0442\u0430\u043a\u043e\u0432\u0430\u044f.\u00a0<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/ora2pg.darold.net\/index.html\"><u>Ora2Pg<\/u><\/a>. \u0412 \u0441\u0432\u043e\u0451\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0430\u0434\u043e. \u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e one-shot-\u0442\u0443\u043b\u0437\u0430, \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c stop the world. \u0410 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043d\u0435\u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u043e.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Change_data_capture\"><u>CDC<\/u><\/a> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Oracle GoldenGate). \u0422\u0443\u0442 \u0443\u0436\u0435 \u0441\u0442\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0439. \u0415\u0441\u043b\u0438 \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043d\u0438\u0437\u043a\u043e\u0433\u043e \u043b\u0430\u0433\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0442\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c in-sync-\u0431\u0430\u0437\u044b, \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u00a0\u0421\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u044d\u0442\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b, \u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442&#8230;<\/p>\n<h3>\u0418\u0434\u0435\u044f<\/h3>\n<p>\u0423 \u043d\u0430\u0441 \u0432\u0435\u0434\u044c \u043f\u043e\u043b\u043d\u043e \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0433\u043e\u043d\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 H2 \u0432 <a href=\"https:\/\/www.h2database.com\/html\/features.html?highlight=oracle#compatibility\"><u>\u0440\u0435\u0436\u0438\u043c\u0435 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441 Oracle<\/u><\/a>. \u0412\u00a0\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a H2 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u0430\u043c\u043e\u043f\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0443 H2. \u0410 \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u0432\u0437\u044f\u0442\u044c CDC, \u043f\u043e\u0445\u043e\u0436\u0443\u044e \u0438\u0434\u0435\u044e \u0441 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u043e\u043c, \u0438 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a PostgreSQL \u043d\u0430 \u043b\u0435\u0442\u0443? \u0422\u0435\u0441\u0442\u044b \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u0442\u044c \u2014 \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c?<\/p>\n<p>\u0421\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043b\u0430\u043d:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0438 \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0442\u0430\u0440\u044b\u0435 \u043c\u0443\u0441\u043e\u0440\u043d\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0438 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043b\u044c\u0448\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u043e\u0442\u0441\u0435\u0447\u043a\u0443 \u0431\u043e\u043b\u0435\u0435 10 GiB \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e) \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0443\u0432\u043e\u0437\u0438\u0442\u044c \u0432 \u0434\u0440\u0443\u0433\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u2014 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0438\u043c\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c <a href=\"https:\/\/habr.com\/ru\/companies\/yandex\/articles\/785994\/\"><u>\u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b YTsaurus<\/u><\/a>.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0443 \u0438\u0437 Oracle \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0446\u0435\u043b\u0435\u0432\u0443\u044e \u0441\u0445\u0435\u043c\u0443 \u0432 PostgreSQL.<\/p>\n<\/li>\n<li>\n<p>\u0414\u0435\u043b\u0430\u0435\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 Oracle \u0432 PostgreSQL \u0438\u00a0\u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u043c \u0442\u0435\u0441\u0442\u044b c H2 \u043d\u0430 embedded PostgreSQL.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f CDC, \u043b\u044c\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0441\u0440\u0435\u0434\u0435, \u0447\u0438\u043d\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u043c \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u043c \u0432\u0441\u0435 \u043f\u0443\u043d\u043a\u0442\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430.<\/p>\n<\/li>\n<li>\n<p>Profit?<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043b\u0430\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u043b \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043a\u0435\u043f\u0441\u0438\u0441\u0430 \u0438 \u0441\u043e\u043c\u043d\u0435\u043d\u0438\u0439 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430. \u041d\u043e, \u043a\u0430\u043a \u0432\u044b \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442\u0435, \u0440\u0430\u0437 \u0432\u044b \u0447\u0438\u0442\u0430\u0435\u0442\u0435 \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e, \u043e\u043d \u043a\u0430\u043a-\u0442\u043e \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b.<\/p>\n<h2>\u0412\u043e\u043f\u043b\u043e\u0449\u0430\u0435\u043c \u043f\u043b\u0430\u043d \u0432 \u0436\u0438\u0437\u043d\u044c<\/h2>\n<p>\u041f\u043e \u043f\u043b\u0430\u043d\u0443 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0448\u0442\u0443\u043a\u0438 \u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044f\u0442\u0441\u044f \u0438 \u043d\u0435 \u043c\u0435\u0448\u0430\u044e\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443. \u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0430\u0441 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0431\u044b\u043b\u043e \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0437\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0435\u0448\u0438\u043b\u0438 \u0441 \u0447\u0435\u0433\u043e-\u0442\u043e \u043e\u0441\u044f\u0437\u0430\u0435\u043c\u043e\u0433\u043e \u2014 \u0441 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h3>\u0422\u0435\u0441\u0442\u044b \u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440<\/h3>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u0438\u0434\u0435\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043b\u0430 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0442\u043e, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043e\u043d \u0436\u0435\u00a0\u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u043e\u0438\u0442 \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u043d\u0430 PostgreSQL \u0432\u043c\u0435\u0441\u0442\u043e H2. \u041d\u0430 \u043d\u0430\u0447\u0430\u043b\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u043e \u043e\u043a\u043e\u043b\u043e 15 \u0442\u044b\u0441\u044f\u0447 \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0431\u044b\u043b\u0430 \u043f\u043e\u043a\u0440\u044b\u0442\u0430 \u0431\u00f3\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. \u0414\u043b\u044f \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0442\u0430\u043a\u043e\u043c \u043e\u0431\u044a\u0451\u043c\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043c\u043d\u043e\u0433\u043e \u0440\u0443\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u043a\u043e\u0440\u0435 \u043d\u0430\u0448\u043b\u0438\u0441\u044c \u0432\u00a0\u0432\u0438\u0434\u0435 \u0435\u0449\u0451 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0442\u0430\u0436\u0451\u0440\u043e\u0432.<\/p>\n<p>\u0414\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u0432 PostgreSQL \u043c\u044b \u0441\u043f\u0435\u0440\u0432\u0430 \u0441\u0434\u0430\u043c\u043f\u0438\u043b\u0438 \u0441\u0445\u0435\u043c\u044b \u0432\u0441\u0435\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438\u0437 Oracle. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0432\u0441\u0451, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u0434 \u0440\u0443\u043a\u043e\u0439, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 <a href=\"https:\/\/github.com\/darold\/ora2pg\"><u>Ora2Pg<\/u><\/a>, <a href=\"https:\/\/www.jetbrains.com\/datagrip\/\"><u>DataGrip<\/u><\/a>, <a href=\"https:\/\/www.oracle.com\/database\/sqldeveloper\/\"><u>Oracle SQL Developer<\/u><\/a>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u043c\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 \u043d\u0430 Python \u043f\u0440\u0438\u0432\u0435\u043b\u0438 \u0438\u0445 \u0432\u0441\u0435\u0445 \u043a \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e \u00abliquibase \u0432 PostgreSQL \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u043e\u0436\u0435\u0432\u0430\u0442\u044c\u00bb. \u041a\u0441\u0442\u0430\u0442\u0438, \u043f\u0440\u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u0442\u0438\u043f\u043e\u0432 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0433\u043b\u0430 <a href=\"https:\/\/habr.com\/ru\/articles\/335716\/\"><u>\u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445<\/u><\/a> \u0438 <a href=\"https:\/\/www.enterprisedb.com\/blog\/the-complete-oracle-to-postgresql-migration-guide-tutorial-move-convert-database-oracle-alternative\"><u>\u0433\u0430\u0439\u0434 \u043f\u043e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438<\/u><\/a>.\u00a0<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440. \u041f\u043e \u0444\u0430\u043a\u0442\u0443 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u043b\u0435\u0442\u0443. \u0411\u0430\u0437\u043e\u0432\u0430\u044f \u043e\u0431\u0432\u044f\u0437\u043a\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a (\u043a\u043e\u0434 \u0443\u043f\u0440\u043e\u0449\u0451\u043d, \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u0443\u0442\u044c):<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@FunctionalInterface public interface Transformer {     String transform(String sql); }  \/** \u042d\u0442\u0438\u043c \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0434\u0430\u0442\u0430\u0441\u043e\u0440\u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f *\/ public static DataSource wrap(DataSource dataSource, Transformer transformer) {     return new DataSource() {         @Override         public Connection getConnection() throws SQLException {             return wrap(dataSource.getConnection(), transformer);         }          @Override         public Connection getConnection(String username, String password) throws SQLException {             return wrap(dataSource.getConnection(username, password), transformer);         }          \/\/ \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u044b as is...         \/\/ \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438-\u043a\u043b\u0430\u0441\u0441, \u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0438 \u0442\u0430\u043a \u0441\u043e\u0439\u0434\u0451\u0442     }; }  public static Connection wrap(Connection connection, Transformer transformer) {     var handler = new ConnectionProxy(connection, transformer);     return (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), new Class&lt;?>[]{Connection.class}, handler); }  private record ConnectionProxy(Connection proxee, Transformer transformer) implements InvocationHandler {     private static final Set&lt;String> METHODS_FOR_PREPARED_STATEMENT = Set.of(         \"prepareCall\",         \"prepareStatement\"     );     private static final String METHODS_FOR_STATEMENT = \"createStatement\";      @Override     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         if (METHODS_FOR_PREPARED_STATEMENT.contains(method.getName())) {             var sql = args[0].toString();             args[0] = transformer.transform(sql);             return method.invoke(proxee, args);         }         var result = method.invoke(proxee, args);         if (result instanceof Statement statement &amp;&amp; METHODS_FOR_STATEMENT.equals(method.getName())) {             var handler = new StatementProxy(statement, transformer);             return Proxy.newProxyInstance(Statement.class.getClassLoader(), new Class&lt;?>[]{Statement.class}, handler);         }         return result;     } }  private record StatementProxy(Statement proxee, Transformer transformer) implements InvocationHandler {     private static final Set&lt;String> METHODS_WITH_QUERY = Set.of(         \"addBatch\",         \"execute\",         \"executeLargeUpdate\",         \"executeQuery\",         \"executeUpdate\"     );      @Override     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         if (METHODS_WITH_QUERY.contains(method.getName())) {             var sql = args[0].toString();             args[0] = transformer.transform(sql);         }         return method.invoke(proxee, args);     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u043e\u0432\u044b\u0439 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440 \u0434\u043b\u044f Oracle \u0441\u043f\u0443\u0441\u0442\u044f \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"java\">public enum OracleToPostgresTransformer implements Transformer {     INSTANCE;      \/\/ Map.entry \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0430\u043a \u043f\u0430\u0440\u0430     private static final List&lt;Map.Entry&lt;Pattern, String>> PATTERNS = Stream.of(         Map.entry(\"\\\\browid\\\\b\", \"ctid\"),<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-371257","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/371257","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=371257"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/371257\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=371257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=371257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=371257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}