{"id":479931,"date":"2026-05-16T06:44:27","date_gmt":"2026-05-16T06:44:27","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=479931"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=479931","title":{"rendered":"manage.py migrate \u0432 \u043f\u044f\u0442\u043d\u0438\u0446\u0443 \u0432 17:30 \u043d\u0430 \u043f\u0440\u043e\u0434\u0435 \u0441 3K RPS \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439 200\u041c \u0441\u0442\u0440\u043e\u043a"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041c\u0430\u043a\u0441, \u044f Lead Backend \u0438 \u0430\u0432\u0442\u043e\u0440 YouTube-\u043a\u0430\u043d\u0430\u043b\u0430\u00a0<a href=\"https:\/\/www.youtube.com\/channel\/UCru5FZQN_Xa0tKfrBqUIcng\" rel=\"noopener noreferrer nofollow\">PyLounge<\/a>.\u00a0<\/p>\n<p>\u042d\u0442\u043e \u0442\u0440\u0435\u0442\u044c\u044f \u0447\u0430\u0441\u0442\u044c \u043c\u0438\u043d\u0438-\u0441\u0435\u0440\u0438\u0438 \u043e Django-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f\u0445. \u0412\u00a0<a href=\"https:\/\/habr.com\/ru\/companies\/idaproject\/articles\/861386\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438<\/a>\u00a0\u043c\u044b \u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u043a \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f\u043c \u0438 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438\u0441\u044c \u0441 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0430\u043c\u0438, \u0432\u043e\u00a0<a href=\"https:\/\/habr.com\/ru\/companies\/idaproject\/articles\/865036\/\" rel=\"noopener noreferrer nofollow\">\u0432\u0442\u043e\u0440\u043e\u0439<\/a>\u00a0\u0447\u0438\u043d\u0438\u043b\u0438 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438. \u0415\u0441\u043b\u0438 \u0438\u0445 \u043d\u0435 \u0447\u0438\u0442\u0430\u043b\u0438, \u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043d\u0430\u0447\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0441 \u043d\u0438\u0445, \u0430 \u0437\u0430\u0442\u0435\u043c \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u0441\u044e\u0434\u0430.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0436\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0435 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0441\u0430\u043c\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c: \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u043a\u043e\u0433\u0434\u0430\u00a0<code>python <\/code><a href=\"http:\/\/manage.py\" rel=\"noopener noreferrer nofollow\"><code>manage.py<\/code><\/a><code> migrate<\/code>\u00a0\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 17:30 \u0432 \u043f\u044f\u0442\u043d\u0438\u0446\u0443 \u043d\u0430 \u043f\u0440\u043e\u0434\u0435, \u043f\u043e\u0434 3k RPS \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439 \u0432 200 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a.\u00a0<\/p>\n<p>\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043a\u0430\u043a\u0438\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0432 PostgreSQL \u0431\u0435\u0440\u0451\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f Django, \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438\u00a0<code>atomic = False<\/code>, \u043a\u0430\u043a \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u00a0<strong>expand &#8212; migrate &#8212; contract<\/strong>, \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u00a0<code>AddIndexConcurrently<\/code>,\u00a0<code>AddConstraintNotValid<\/code>,\u00a0<code>SeparateDatabaseAndState<\/code>\u00a0\u0438 \u043a\u0430\u043a \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445.<\/p>\n<p>P.S. \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u044b, \u0447\u0442\u043e\u0431\u044b \u0432\u043b\u0435\u0437\u043b\u0438 \u0432 \u0441\u0442\u0430\u0442\u044c\u044e \u0438 \u043d\u0435 \u0437\u0430\u0434\u0443\u0448\u0438\u043b\u0438. \u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0436\u0438\u0437\u043d\u0438 \u0432\u0441\u0451 \u0435\u0449\u0451 \u0445\u0443\u0436\u0435 &#8212; \u043d\u043e \u0448\u0430\u0433\u0438 \u0442\u0435 \u0436\u0435.<\/p>\n<p>P.S.S. \u041f\u0440\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043d\u0438 \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0434\u043e\u0432\u0430\u044f \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043f\u043e\u0441\u0442\u0440\u0430\u0434\u0430\u043b\u0430.\u00a0<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f46\/86b\/7c4\/f4686b7c4c56ba4b99dfa37f685f8189.jpg\" width=\"1280\" height=\"720\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f46\/86b\/7c4\/f4686b7c4c56ba4b99dfa37f685f8189.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f46\/86b\/7c4\/f4686b7c4c56ba4b99dfa37f685f8189.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443\u00a0migrate\u00a0\u0432 \u043f\u0440\u043e\u0434\u0435 \u044d\u0442\u043e \u043d\u0435 &#171;\u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430&#187;<\/h3>\n<p>\u0423 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0435\u0441\u0442\u044c \u0442\u0440\u0438 <s>\u0441\u0442\u0443\u043b\u0430<\/s> \u0441\u043b\u043e\u044f, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043f\u0430\u0434\u0435\u043d\u0438\u044e \u043f\u0440\u043e\u0434\u0430:<\/p>\n<ol>\n<li>\n<p><strong>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 SQL.<\/strong>\u00a0\u0418\u043d\u043e\u0433\u0434\u0430 \u043d\u0435 \u0442\u0430\u043a\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u044b \u043e\u0436\u0438\u0434\u0430\u043b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0<code>AlterField(max_length=64)<\/code>\u0434\u043b\u044f\u00a0<code>CharField(max_length=32)<\/code>\u00a0&#8212; \u044d\u0442\u043e\u00a0<code>ALTER TABLE ... ALTER COLUMN TYPE varchar(64)<\/code>, \u0438, \u0434\u0430, \u043d\u0430 PostgreSQL \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e.\u00a0<\/p>\n<\/li>\n<\/ol>\n<p>\u0410 \u0432\u043e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044e \u0432\u0441\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b (table rewrite), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0<code>text -&gt; integer<\/code>,\u00a0<code>varchar -&gt; numeric<\/code>,\u00a0<code>json -&gt; jsonb<\/code>\u00a0\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0435\u0431\u0438\u043d\u0430\u0440\u043d\u043e-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u041f\u0440\u0438 \u044d\u0442\u043e\u043c\u00a0<code>varchar(n) -&gt; text<\/code>\u00a0\u0432 PostgreSQL rewrite \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 &#8212; \u044d\u0442\u043e binary-compatible \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0438 \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a metadata-only \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f.<\/p>\n<ol start=\"2\">\n<li>\n<p><strong>\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438<\/strong>. PostgreSQL \u043c\u043e\u0436\u0435\u0442 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0442\u0430\u043a, \u0447\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u0442 \u0434\u0430\u0436\u0435\u00a0<code>SELECT<\/code>. \u041e\u0447\u0435\u0440\u0435\u0434\u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0432 PostgreSQL &#8212; \u044d\u0442\u043e FIFO. \u0422\u043e \u0435\u0441\u0442\u044c \u0442\u0432\u043e\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0436\u0434\u0435\u0442 \u0434\u043e\u043b\u0433\u0443\u044e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e \u043f\u044f\u0442\u044c \u043c\u0438\u043d\u0443\u0442, \u0430 \u0437\u0430 \u043d\u0435\u0439 \u043c\u043e\u043b\u0447\u0430 \u0441\u0442\u043e\u044f\u0442 \u0435\u0449\u0451 200 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041d\u0438\u043a\u0442\u043e \u043d\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442. \u041f\u0440\u043e\u0434 R.I.P.<\/p>\n<\/li>\n<li>\n<p><strong>Python-\u043a\u043e\u0434 \u0432\u00a0<\/strong><code><strong>RunPython<\/strong><\/code>. \u041e\u043d \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u044f\u043c\u043e \u0432 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 (\u0435\u0441\u043b\u0438\u00a0<code>atomic = True<\/code>, \u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e) \u0438 \u0434\u0435\u0440\u0436\u0438\u0442 \u0435\u0451 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.\u00a0<code>Developer.objects.all().update(...)<\/code>\u00a0\u043d\u0430 50 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a &#8212; R.I.P.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0437 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 (\u0432\u0441\u0435 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0438 \u0438 \u0447\u0438\u0441\u043b\u0430 \u0432\u044b\u0434\u0443\u043c\u0430\u043d\u044b, \u044f \u0430\u043a\u0442\u0435\u0440, \u044d\u0442\u043e \u0432\u0441\u0435 \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430):<\/p>\n<ul>\n<li>\n<p><strong>\u041a\u0435\u0439\u0441 1<\/strong>. \u0421\u043b\u0430\u0432\u0438\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043f\u043e\u043b\u0435\u00a0<code>is_archived =models.BooleanField(default=False)<\/code>\u00a0<br \/>\u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441 80 000 000 \u0441\u0442\u0440\u043e\u043a \u043d\u0430 PostgreSQL 13. \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u0437\u0430 14 \u043c\u0438\u043d\u0443\u0442. \u0412\u0441\u0451 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0431\u044b\u043b\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c. \u041f\u0440\u043e\u0434 \u043b\u0435\u0436\u0430\u043b, \u0432\u0435\u0441\u044c \u0430\u0432\u0442\u043e\u0431\u0443\u0441 \u043f\u043b\u0430\u043a\u0430\u043b.\u00a0<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0435\u0439\u0441 2<\/strong>. \u0412\u043b\u0430\u0434\u0438\u0441\u043b\u0430\u0432 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u00a0<code>models.Index(fields=['created_at'])<\/code>\u00a0\u0432\u00a0<code>Meta<\/code>\u00a0\u043c\u043e\u0434\u0435\u043b\u0438\u00a0<code>Order<\/code>.\u00a0\u00a0<code>CREATE INDEX<\/code>\u00a0\u0431\u0435\u0437\u00a0<code>CONCURRENTLY<\/code>\u0432\u0437\u044f\u043b\u00a0<code>SHARE<\/code>\u00a0\u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 &#8212; \u0432\u0441\u0435 \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0437\u0430\u043a\u0430\u0437\u043e\u0432 \u0432\u0441\u0442\u0430\u043b\u0438 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u044c \u043c\u0438\u043d\u0443\u0442.\u00a0<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0435\u0439\u0441 3<\/strong>. \u0412\u0430\u0441\u044f\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u043b data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0431\u044d\u043a\u0444\u0438\u043b\u043b\u0430 \u043d\u0430 20M \u0441\u0442\u0440\u043e\u043a \u0447\u0435\u0440\u0435\u0437\u00a0<code>Order.objects.filter(...).update(...)<\/code>. \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0431\u044b\u043b\u0430 \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u043e\u0439 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u041e\u0434\u0438\u043d \u0431\u043e\u043b\u044c\u0448\u043e\u0439\u00a0<code>UPDATE<\/code>\u00a0\u0441\u0433\u0435\u043d\u0435\u0440\u0438\u043b \u0433\u0438\u0433\u0430\u043d\u0442\u0441\u043a\u0438\u0439 WAL, \u0440\u0435\u043f\u043b\u0438\u043a\u0438 \u0437\u0430\u043b\u0430\u0433\u0430\u043b\u0438 &#8212; R.I.P \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435 \u0442\u0440\u0438 \u0441\u043b\u0443\u0447\u0430\u044f \u043b\u0435\u0447\u0430\u0442\u0441\u044f \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e &#8212; \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u0442\u0432\u043e\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 PostgreSQL.<\/p>\n<h3>\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u0442\u0435\u043e\u0440\u0438\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0432 PostgreSQL<\/h3>\n<p>PostgreSQL \u0438\u043c\u0435\u0435\u0442 8 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a. \u0417\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e &#8212; \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c\u00a0<em>&#171;\u043b\u0435\u0441\u0442\u043d\u0438\u0446\u0443&#187;<\/em>: \u0447\u0435\u043c \u0432\u044b\u0448\u0435 \u0443\u0440\u043e\u0432\u0435\u043d\u044c, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043e\u043d \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442. \u0423\u0440\u043e\u0432\u043d\u0438 \u0432 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 (\u043e\u0442 \u0441\u043b\u0430\u0431\u043e\u0433\u043e \u043a \u0441\u0438\u043b\u044c\u043d\u043e\u043c\u0443):<\/p>\n<p><strong>1. ACCESS SHARE<\/strong>\u00a0&#8212; \u0431\u0435\u0440\u0435\u0442\u00a0<code>SELECT<\/code>. \u0421\u0430\u043c\u0430\u044f \u0441\u043b\u0430\u0431\u0430\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430: \u043e\u0431\u044b\u0447\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u0438 \u043d\u0438\u043a\u043e\u043c\u0443 \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u0438 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 ACCESS EXCLUSIVE.<\/p>\n<ol start=\"4\">\n<li>\n<p><strong>ROW SHARE<\/strong>\u00a0&#8212;\u00a0<code>SELECT FOR UPDATE\/SHARE<\/code>. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438; \u0447\u0443\u0442\u044c \u0441\u0442\u0440\u043e\u0436\u0435 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>ROW EXCLUSIVE<\/strong>\u00a0&#8212;\u00a0<code>INSERT<\/code>,\u00a0<code>UPDATE<\/code>,\u00a0<code>DELETE<\/code>. \u042d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f DML-\u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430: \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e, \u043f\u043e\u043a\u0430 \u043d\u0435\u0442 \u00ab\u0442\u044f\u0436\u0451\u043b\u043e\u0433\u043e\u00bb DDL. \u0422\u043e \u0435\u0441\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435 DML-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u0435 \u043c\u0435\u0448\u0430\u044e\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443, \u043d\u043e \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043c\u043e\u0433\u0443\u0442 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u043b\u0438 \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 (<code>REINDEX<\/code>,\u00a0<code>ALTER TABLE ... TYPE<\/code>,\u00a0<code>ALTER TABLE ... ADD COLUMN<\/code>\u00a0\u0438 \u0442.\u0434.).<\/p>\n<\/li>\n<li>\n<p><strong>SHARE UPDATE EXCLUSIVE<\/strong>\u00a0&#8212;\u00a0<code>VACUUM<\/code>\u00a0(\u0431\u0435\u0437 FULL),\u00a0<code>ANALYZE<\/code>,\u00a0<code>CREATE INDEX CONCURRENTLY<\/code>,\u00a0<code>ALTER TABLE VALIDATE CONSTRAINT<\/code>,\u00a0<code>REINDEX CONCURRENTLY<\/code>. \u041d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u0440\u0438\u0430\u043b\u0442\u0430\u0439\u043c-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u043c\u0435\u043d\u044f\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>SHARE<\/strong>\u00a0&#8212;\u00a0<code>CREATE INDEX<\/code>\u00a0(\u0431\u0435\u0437 CONCURRENTLY). \u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \u0447\u0442\u0435\u043d\u0438\u0435, \u043d\u043e \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u00a0<code>INSERT\/UPDATE\/DELETE<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u043a\u043e\u043d\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>SHARE ROW EXCLUSIVE<\/strong>\u00a0&#8212;\u00a0<code>CREATE TRIGGER<\/code>, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435\u00a0<code>ALTER TABLE<\/code>. \u0411\u043e\u043b\u0435\u0435 \u0436\u0451\u0441\u0442\u043a\u0438\u0439 DDL-\u0440\u0435\u0436\u0438\u043c: PostgreSQL \u0437\u0430\u0449\u0438\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043e\u0442 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>EXCLUSIVE<\/strong>\u00a0&#8212;\u00a0<code>REFRESH MATERIALIZED VIEW CONCURRENTLY<\/code>. \u041f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u043d\u0430\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430: \u0447\u0438\u0442\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u043b\u044e\u0431\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>ACCESS EXCLUSIVE &#8212;<\/strong>\u00a0<code>DROP TABLE<\/code>,\u00a0<code>TRUNCATE<\/code>, \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e\u00a0<code>ALTER TABLE<\/code>,\u00a0<code>REINDEX<\/code>. \u0421\u0430\u043c\u0430\u044f \u0441\u0438\u043b\u044c\u043d\u0430\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430: \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0451, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u0439\u00a0<code>SELECT<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 \u043d\u0430\u0441 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0432\u043e\u043b\u043d\u0443\u0435\u0442 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443\u00a0<strong>CONCURRENTLY-\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c\u0438<\/strong>\u00a0(SHARE UPDATE EXCLUSIVE &#8212; \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e \u0441 DML) \u0438 \u043e\u0431\u044b\u0447\u043d\u044b\u043c\u0438 DDL (SHARE \/ ACCESS EXCLUSIVE &#8212; \u041d\u0415 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e \u0441 DML).<\/p>\n<h4>\u0412\u0435\u043b\u0438\u043a\u0438\u0439 \u0438 \u0443\u0436\u0430\u0441\u043d\u044b\u0439 &#8212; ACCESS EXCLUSIVE<\/h4>\n<p>\u042d\u0442\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u0431\u0435\u0440\u0435\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p><code>ALTER TABLE ... ADD COLUMN<\/code>\u00a0(\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e).<\/p>\n<\/li>\n<li>\n<p><code>ALTER TABLE ... DROP COLUMN<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>ALTER TABLE ... ALTER COLUMN TYPE<\/code>\u00a0(\u0434\u0430\u0436\u0435 \u0431\u0435\u0437\u00a0<code>REWRITE<\/code>).<\/p>\n<\/li>\n<li>\n<p><code>ALTER TABLE ... ADD CONSTRAINT<\/code>\u00a0(\u0431\u0435\u0437\u00a0<code>NOT VALID<\/code>).<\/p>\n<\/li>\n<li>\n<p><code>CREATE INDEX<\/code>\u00a0(\u0431\u0435\u0437\u00a0<code>CONCURRENTLY<\/code>) &#8212; \u0431\u0435\u0440\u0451\u0442 SHARE, \u0447\u0442\u043e \u043d\u0435\u00a0<em>\u043f\u043e\u043b\u043d\u044b\u0439<\/em>\u00a0ACCESS EXCLUSIVE, \u043d\u043e \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 write.<\/p>\n<\/li>\n<li>\n<p><code>DROP INDEX<\/code>\u00a0(\u0431\u0435\u0437\u00a0<code>CONCURRENTLY<\/code>).<\/p>\n<\/li>\n<li>\n<p><code>ALTER TABLE ... RENAME<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>DROP TABLE<\/code>,\u00a0<code>TRUNCATE<\/code>,\u00a0<code>CLUSTER<\/code>,\u00a0<code>VACUUM FULL<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>ACCESS EXCLUSIVE \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u0435\u043d,\u00a0<strong>\u0435\u0441\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438\u043b\u0438 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u043e\u043a<\/strong>. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0<code>ADD COLUMN<\/code>\u00a0\u0431\u0435\u0437 default &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u00a0<code>pg_attribute<\/code>, \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u041d\u043e \u0434\u0430\u0436\u0435 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u0430\u044f ACCESS EXCLUSIVE \u043c\u043e\u0436\u0435\u0442 \u0443\u0440\u043e\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0434 \u0438\u0437-\u0437\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a.<\/p>\n<h4>\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u043e\u043d\u0430 \u043e\u043f\u0430\u0441\u043d\u0430<\/h4>\n<p>PostgreSQL \u0441\u0442\u0430\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u0438\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438\u00a0<strong>\u0436\u0434\u0443\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0434\u043e\u043b\u0433\u043e<\/strong>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438\u00a0<code>ALTER TABLE<\/code>\u00a0\u0443\u0436\u0435 \u0436\u0434\u0451\u0442\u00a0<code>ACCESS EXCLUSIVE<\/code>, \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 lock&#8217;\u0430\u043c\u0438, \u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u0447\u0430\u0442\u044c \u0432\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430 \u043d\u0438\u043c.<\/p>\n<p>\u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a &#8212; \u043e\u0434\u043d\u0430 \u043e\u0436\u0438\u0434\u0430\u044e\u0449\u0430\u044f DDL-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0442\u043e\u0440\u043c\u043e\u0437\u0438\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u043e\u0442\u043e\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0442\u0430\u0431\u043b\u0438\u0446\u0435.<\/p>\n<p>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439:<\/p>\n<pre><code>T0: \u0410\u043d\u0430\u043b\u0438\u0442\u0438\u043a \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b SELECT pg_dump \u0442\u0430\u0431\u043b\u0438\u0446\u044b users \u2192 \u0431\u0435\u0440\u0451\u0442 ACCESS SHARE \u043d\u0430 5 \u043c\u0438\u043d\u0443\u0442.T1: \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f ALTER TABLE users ADD COLUMN foo    -&gt; \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u0437\u044f\u0442\u044c ACCESS EXCLUSIVE -&gt; \u0436\u0434\u0451\u0442.T2: \u041f\u0440\u0438\u0448\u0451\u043b API-\u0437\u0430\u043f\u0440\u043e\u0441: SELECT * FROM users WHERE id = 42    -&gt; \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u0437\u044f\u0442\u044c ACCESS SHARE -&gt; \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0443 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430,       \u041d\u041e \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0416\u0414\u0401\u0422 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f -&gt; \u0432\u0441\u0442\u0430\u0451\u0442 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c.T3: \u0415\u0449\u0451 200 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 -&gt; \u0432\u0441\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438.T4: \u0410\u043d\u0430\u043b\u0438\u0442\u0438\u043a \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b.T5: \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u0437\u0430 5 \u043c\u0441.T6: \u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0440\u0430\u0441\u0441\u0430\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f.<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u0435\u0436\u0434\u0443 T1 \u0438 T5 \u043f\u0440\u043e\u0448\u043b\u043e 5 \u043c\u0438\u043d\u0443\u0442 \u043f\u043e\u043b\u043d\u043e\u0439 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u0437\u0430 5 \u043c\u0441.<\/p>\n<p>\u041b\u0435\u0447\u0435\u043d\u0438\u0435 &#8212;\u00a0<code>lock_timeout<\/code>. \u042d\u0442\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PostgreSQL, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u00a0<em>&#171;\u0435\u0441\u043b\u0438 \u043d\u0435 \u043c\u043e\u0433\u0443 \u0432\u0437\u044f\u0442\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443 \u0437\u0430 N \u0441\u0435\u043a\u0443\u043d\u0434 &#8212; \u0443\u043f\u0430\u0434\u0438&#187;<\/em>. \u041b\u0443\u0447\u0448\u0435 \u0443\u043f\u0430\u0441\u0442\u044c \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430 \u0447\u0435\u0440\u0435\u0437 \u043c\u0438\u043d\u0443\u0442\u0443, \u0447\u0435\u043c \u0441\u0442\u043e\u044f\u0442\u044c \u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0434:<\/p>\n<pre><code class=\"python\"># 0042_safe_alter.pyfrom django.db import migrationsclass Migration(migrations.Migration):    atomic = False    dependencies = [...]    operations = [        migrations.RunSQL(            sql=\"SET lock_timeout = '3s'; SET statement_timeout = '5min';\",            reverse_sql=migrations.RunSQL.noop,        ),        # ... \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>lock_timeout<\/code>\u00a0\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u0435\u0441\u0441\u0438\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0442\u0440\u043e\u043a\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c\u00a0<strong>\u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u043e\u0439 \u0436\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438\/\u0441\u0435\u0441\u0441\u0438\u0438<\/strong>, \u0447\u0442\u043e \u0438 \u043e\u043f\u0430\u0441\u043d\u044b\u0439 ALTER.\u00a0<\/p>\n<p>\u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f timeout&#8217;\u043e\u0432 \u0441\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442\u00a0<strong><em>\u0432\u0430\u0448\u0435\u0439 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438.<\/em><\/strong><\/p>\n<p>\u0414\u043b\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c 3 \u0441. \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0430\u0433\u0440\u0435\u0441\u0441\u0438\u0432\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0438 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u043c \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0430\u043c.<\/p>\n<p>Timeout&#8217;\u044b \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0434\u0431\u0438\u0440\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437:<\/p>\n<ul>\n<li>\n<p>\u0441\u0440\u0435\u0434\u043d\u0435\u0439 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>maintenance window;<\/p>\n<\/li>\n<li>\n<p>replication lag;<\/p>\n<\/li>\n<li>\n<p>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.<\/p>\n<\/li>\n<\/ul>\n<p><code>statement_timeout<\/code>\u00a0&#8212; \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0439 \u043f\u0440\u0435\u0434\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435\u043b\u044c &#8212;\u00a0<em>&#171;\u0435\u0441\u043b\u0438 \u0441\u0430\u043c SQL-\u0441\u0442\u0435\u0439\u0442\u043c\u0435\u043d\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u043b\u044c\u0448\u0435 N &#8212; \u0443\u043f\u0430\u0434\u0438&#187;<\/em>.<\/p>\n<p><strong>\u0412 PostgreSQL 17<\/strong>\u00a0\u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0443\u0440\u043e\u0432\u0435\u043d\u044c &#8212;\u00a0<code>transaction_timeout<\/code>. \u041e\u043d \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u0432\u0441\u0435\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430.<\/p>\n<pre><code class=\"python\">migrations.RunSQL(    sql=(        \"SET lock_timeout = '3s'; \"        \"SET statement_timeout = '5min'; \"        \"SET transaction_timeout = '10min';\"  # PG 17+    ),    reverse_sql=migrations.RunSQL.noop,),<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>sqlmigrate\u00a0&#8212; \u0442\u0432\u043e\u0439 \u043b\u0443\u0447\u0448\u0438\u0439 \u0434\u0440\u0443\u0433 \u043f\u0435\u0440\u0435\u0434\u00a0migrate<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u043d\u0430\u043a\u0430\u0442\u043e\u043c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u0440\u043e\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c:<\/p>\n<pre><code class=\"bash\">python manage.py sqlmigrate developers 0042<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u0447\u0438\u0442\u0430\u0435\u043c\u00a0<strong><em>\u0433\u043b\u0430\u0437\u0430\u043c\u0438<\/em><\/strong>. \u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 SQL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Django \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442,\u00a0<strong>\u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044f \u0435\u0433\u043e<\/strong>. \u042d\u0442\u043e \u043f\u0435\u0440\u0432\u0430\u044f \u0438 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430. \u041f\u043e \u043d\u0435\u043c\u0443 \u0442\u044b \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u0438\u0448\u044c:<\/p>\n<ul>\n<li>\n<p>\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u043b\u0438\u00a0<code>ALTER TABLE ... ALTER COLUMN TYPE<\/code>\u00a0(\u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u00a0<code>REWRITE<\/code>);<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u043b\u0438\u00a0<code>CREATE INDEX<\/code>\u00a0\u0431\u0435\u0437\u00a0<code>CONCURRENTLY<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u043b\u0438\u00a0<code>ADD CONSTRAINT<\/code>\u00a0\u0431\u0435\u0437\u00a0<code>NOT VALID<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0437\u0430\u0432\u0435\u0440\u043d\u0435\u0442 \u043b\u0438 Django \u0432\u0441\u0435 \u0432\u00a0<code>BEGIN ... COMMIT<\/code>\u00a0(\u0435\u0441\u043b\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u0430\u044f).<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u00a0<em>&#171;\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e&#187;<\/em>\u00a0\u0432\u044b\u0432\u043e\u0434\u0430:<\/p>\n<pre><code class=\"sql\">BEGIN;---- Alter field rating on developer--ALTER TABLE \"developers_developer\" ALTER COLUMN \"rating\" TYPE numeric(10, 2)    USING \"rating\"::numeric(10, 2);COMMIT;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>ALTER COLUMN ... TYPE ... USING ...<\/code>\u00a0&#8212; \u044d\u0442\u043e REWRITE \u043d\u0430 \u0432\u0441\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043f\u043e\u0434 ACCESS EXCLUSIVE. \u041d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0432 50\u041c \u0441\u0442\u0440\u043e\u043a \u044d\u0442\u043e \u0447\u0430\u0441\u044b \u043f\u0440\u043e\u0441\u0442\u043e\u044f.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u00a0<em>&#171;\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e&#187;<\/em>:<\/p>\n<pre><code class=\"sql\">BEGIN;---- Add field nickname to developer--ALTER TABLE \"developers_developer\" ADD COLUMN \"nickname\" varchar(64) NULL;COMMIT;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>ACCESS EXCLUSIVE, \u043d\u043e \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u044b\u0439 (\u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435). \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c\u00a0<code>lock_timeout<\/code>.<\/p>\n<h3>\u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0445 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c<\/h3>\n<p>\u0428\u043f\u0430\u0440\u0433\u0430\u043b\u043a\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e +-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f.\u00a0<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f Django<\/p>\n<\/th>\n<th>\n<p align=\"left\">SQL<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0412\u0440\u0435\u043c\u044f<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430?<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>CreateModel<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>CREATE TABLE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2014<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>DeleteModel<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>DROP TABLE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u26a0\ufe0f \u043b\u043e\u043c\u0430\u0435\u0442 \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AddField<\/code> (nullable, \u0431\u0435\u0437 default)<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ADD COLUMN NULL<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AddField<\/code> (NOT NULL + constant default)<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ADD COLUMN NOT NULL DEFAULT 'x'<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043f\u043e\u0447\u0442\u0438 \u0431\u044b\u0441\u0442\u0440\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u26a0\ufe0f, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u044e\u0430\u043d\u0441\u044b \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c\u0438<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AddField<\/code> (NOT NULL + volatile default: <code>uuid4<\/code>, <code>now()<\/code>)<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ADD COLUMN<\/code> + UPDATE \u0441\u0442\u0440\u043e\u043a<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0434\u043e\u043b\u0433\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AddField<\/code> (FK)<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ADD COLUMN<\/code> + <code>ADD CONSTRAINT FK<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code> + \u043f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0430\u043d<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0434\u043e\u043b\u0433\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u26a0\ufe0f<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>RemoveField<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>DROP COLUMN<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u26a0\ufe0f \u043b\u043e\u043c\u0430\u0435\u0442 \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AlterField<\/code>: \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 <code>max_length<\/code> \u0434\u043b\u044f varchar<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ALTER COLUMN TYPE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code>, \u0431\u0435\u0437 <code>REWRITE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AlterField<\/code>: \u0441\u0443\u0436\u0435\u043d\u0438\u0435 \/ \u0441\u043c\u0435\u043d\u0430 \u0442\u0438\u043f\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ALTER COLUMN TYPE<\/code> \u0441 <code>REWRITE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AlterField<\/code>: \u0441\u043c\u0435\u043d\u0430 <code>null=True \u2192 null=False<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ALTER COLUMN SET NOT NULL<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code> + \u043f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0430\u043d (PG 12+ \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0440\u0438 <code>CHECK<\/code>)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0434\u043e\u043b\u0433\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AlterField<\/code>: \u0441\u043c\u0435\u043d\u0430 <code>default=<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ALTER COLUMN SET DEFAULT<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u2705<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AddIndex<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>CREATE INDEX<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>SHARE<\/code> (\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 write)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043e\u0442 \u0441\u0435\u043a\u0443\u043d\u0434 \u0434\u043e \u0447\u0430\u0441\u043e\u0432<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c \u2192 <code>AddIndexConcurrently<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>RemoveIndex<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>DROP INDEX<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">lock \u043d\u0430 index + \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 table locks<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u26a0\ufe0f \u2192 <code>RemoveIndexConcurrently<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AddConstraint<\/code> (<code>CheckConstraint<\/code>)<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ADD CONSTRAINT CHECK<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code> + \u043f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0430\u043d<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0434\u043e\u043b\u0433\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c \u2192 <code>NOT VALID<\/code> + <code>VALIDATE<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>AddConstraint<\/code> (<code>UniqueConstraint<\/code>)<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ADD CONSTRAINT UNIQUE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>SHARE<\/code> \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0434\u043e\u043b\u0433\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c \u2192 <code>SeparateDatabaseAndState<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>RenameField<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ALTER TABLE RENAME COLUMN<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u26a0\ufe0f \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434 \u0443\u043f\u0430\u0434\u0451\u0442<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>RenameModel<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ALTER TABLE RENAME<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ACCESS EXCLUSIVE<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u26a0\ufe0f \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434 \u0443\u043f\u0430\u0434\u0451\u0442<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>RunPython<\/code> (UPDATE \u0431\u0435\u0437 \u0431\u0430\u0442\u0447\u0435\u0439)<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>UPDATE ...<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ROW EXCLUSIVE<\/code> \u043d\u0430 \u043a\u0443\u0447\u0435 \u0441\u0442\u0440\u043e\u043a<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u274c \u2192 \u0431\u0430\u0442\u0447\u0438<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>P.S. \u041d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u0433\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439, \u044d\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0448\u043f\u0430\u0440\u0433\u0430\u043b\u043a\u0430 \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u044f. \u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u0433\u043e\u043b\u043e\u0432\u0435.\u00a0<\/p>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435.<\/p>\n<h4>AddField\u00a0+ DEFAULT \u043d\u0430 PostgreSQL 14+<\/h4>\n<pre><code class=\"python\"># PG 14+ (\u0438 \u0434\u0430\u0436\u0435 11+), \u0411\u0415\u0417\u041e\u041f\u0410\u0421\u041d\u041e:migrations.AddField(    model_name='developer',    name='is_archived',    field=models.BooleanField(default=False),),<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u0430 \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435. ACCESS EXCLUSIVE \u0431\u0435\u0440\u0451\u0442\u0441\u044f, \u043d\u043e \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b.<\/p>\n<p>\u041d\u043e! \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f\u00a0<strong>\u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043d\u044b\u0445<\/strong>\u00a0default. \u0415\u0441\u043b\u0438 default &#8212; \u044d\u0442\u043e callable, \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f PG \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"python\"># \u041e\u041f\u0410\u0421\u041d\u041e \u043d\u0430 \u043b\u044e\u0431\u043e\u043c PG:migrations.AddField(    model_name='developer',    name='external_id',    field=models.UUIDField(default=uuid.uuid4),),<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041b\u0435\u0447\u0435\u043d\u0438\u0435 &#8212; \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 \u044d\u0442\u0430\u043f\u044b:<\/p>\n<ol>\n<li>\n<p><code>AddField(null=True)<\/code>\u00a0&#8212; \u0431\u0435\u0437 default.<\/p>\n<\/li>\n<li>\n<p><code>RunPython(backfill_uuid)<\/code>\u00a0\u0447\u0430\u043d\u043a\u0430\u043c\u0438 \u0441\u00a0<code>atomic=False<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>AlterField(null=False)<\/code>\u00a0&#8212; \u0447\u0435\u0440\u0435\u0437\u00a0<code>AddConstraintNotValid<\/code>\u00a0+\u00a0<code>ValidateConstraint<\/code>\u00a0(\u0441\u043c. \u043d\u0438\u0436\u0435).<\/p>\n<\/li>\n<\/ol>\n<h4>AddField\u00a0+ FK \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435<\/h4>\n<p><code>ADD CONSTRAINT FOREIGN KEY<\/code>\u00a0\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0434\u043e\u043b\u0433\u043e \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0437\u0434\u0435\u0441\u044c &#8212; \u043d\u0435 \u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c validation scan \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445. \u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 PostgreSQL \u0431\u0435\u0440\u0451\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e lock&#8217;\u043e\u0432 \u043d\u0430 referencing\/referenced tables, \u0430 \u0441\u0430\u043c\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u0434\u0442\u0438 \u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u043e \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u0445 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a. \u041d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0432 100M \u0441\u0442\u0440\u043e\u043a \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u0447\u0430\u0441\u044b.<\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 &#8212;\u00a0<code>NOT VALID<\/code>\u00a0+\u00a0<code>VALIDATE CONSTRAINT<\/code>. Django \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043b\u044f FK \u0441 NOT VALID, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0435\u043b\u0430\u0435\u043c \u0440\u0443\u043a\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437\u00a0<code>RunSQL<\/code>\u00a0+\u00a0<code>SeparateDatabaseAndState<\/code>:<\/p>\n<pre><code class=\"python\">class Migration(migrations.Migration):    atomic = False    dependencies = [...]    operations = [        # 1. \u041a\u043e\u043b\u043e\u043d\u043a\u0430 nullable, \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e.        migrations.AddField(            model_name='order',            name='customer',            field=models.ForeignKey(                'customers.Customer', null=True,                on_delete=models.PROTECT, db_constraint=False,            ),        ),        # 2. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c FK \u043a\u0430\u043a NOT VALID - \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e (\u0431\u0435\u0440\u0451\u0442 ACCESS EXCLUSIVE,        #    \u043d\u043e \u043d\u0435 \u0441\u043a\u0430\u043d\u0438\u0440\u0443\u0435\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u0443).        migrations.RunSQL(            sql=(                'ALTER TABLE \"orders_order\" '                'ADD CONSTRAINT \"orders_order_customer_fk\" '                'FOREIGN KEY (\"customer_id\") '                'REFERENCES \"customers_customer\" (\"id\") NOT VALID;'            ),            reverse_sql=(                'ALTER TABLE \"orders_order\" DROP CONSTRAINT \"orders_order_customer_fk\";'            ),        ),        # 3. \u0412\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u043c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 - SHARE UPDATE EXCLUSIVE,        #    \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e \u0441 DML, \u043c\u043e\u0436\u0435\u0442 \u0438\u0434\u0442\u0438 \u0434\u043e\u043b\u0433\u043e, \u043d\u043e \u043f\u0440\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.        migrations.RunSQL(            sql='ALTER TABLE \"orders_order\" VALIDATE CONSTRAINT \"orders_order_customer_fk\";',            reverse_sql=migrations.RunSQL.noop,        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>VALIDATE CONSTRAINT<\/code>\u00a0\u043e\u0431\u044b\u0447\u043d\u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 \u043e\u0431\u044b\u0447\u043d\u044b\u043c DML \u0438 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0435\u0435 \u043f\u0440\u044f\u043c\u043e\u0433\u043e\u00a0<code>ADD CONSTRAINT<\/code>.<\/p>\n<p>\u041d\u043e \u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u0433\u043e\u0440\u044f\u0447\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445 validation \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0437\u0430\u043c\u0435\u0442\u043d\u0443\u044e IO-\u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0438 \u0432\u043b\u0438\u044f\u0442\u044c \u043d\u0430 latency.<\/p>\n<p><code>db_constraint=False<\/code>\u00a0\u0432\u00a0<code>ForeignKey<\/code>. \u042d\u0442\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 Django &#8212; \u0432 \u0411\u0414 constraint \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0439, \u044f \u0435\u0433\u043e \u0441\u0434\u0435\u043b\u0430\u044e \u0440\u0443\u043a\u0430\u043c\u0438.<\/p>\n<h4>AlterConstraint\u00a0&#8212; \u043f\u043e\u0434\u0430\u0440\u043e\u043a \u043e\u0442 Django 5.2<\/h4>\n<p>\u042d\u0442\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0430\u044f, \u043d\u043e \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u0430\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430 \u0444\u0438\u0447\u0430. \u0420\u0430\u043d\u044c\u0448\u0435 \u043b\u044e\u0431\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 constraint &#8212; \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u00a0<code>violation_error_message<\/code>\u00a0\u0434\u043b\u044f \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u044e\u0437\u0435\u0440\u0443 \u043f\u0440\u0438 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0438 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 &#8212; \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b\u043e \u043a \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0432\u0438\u0434\u0430 \u00abDROP CONSTRAINT + ADD CONSTRAINT\u00bb. \u041d\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u044d\u0442\u043e DROP INDEX + CREATE INDEX = \u0431\u043e\u043b\u044c.<\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 Django 5.2:<\/p>\n<pre><code class=\"python\"># \u0411\u044b\u043b\u043e \u0432 \u043c\u043e\u0434\u0435\u043b\u0438:class Meta:    constraints = [        models.UniqueConstraint(fields=['email'], name='user_email_uniq'),    ]# \u0421\u0442\u0430\u043b\u043e:class Meta:    constraints = [        models.UniqueConstraint(            fields=['email'], name='user_email_uniq',            violation_error_message='Email \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442',        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 Django 5.1 \u0438 \u0440\u0430\u043d\u0435\u0435\u00a0<code>makemigrations<\/code>\u00a0\u0441\u0433\u0435\u043d\u0435\u0440\u0438\u043b \u0431\u044b\u00a0<code>RemoveConstraint<\/code>\u00a0+\u00a0<code>AddConstraint<\/code>\u00a0\u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c DROP\/CREATE \u0432 \u0411\u0414. \u0412 Django 5.2 &#8212;\u00a0<code>AlterConstraint<\/code>\u00a0(no-op \u0434\u043b\u044f \u0411\u0414, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e in-memory state):<\/p>\n<pre><code class=\"python\"># Django 5.2 makemigrations:operations = [    migrations.AlterConstraint(        model_name='user',        name='user_email_uniq',        constraint=models.UniqueConstraint(            fields=['email'], name='user_email_uniq',            violation_error_message='Email \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442',        ),    ),]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0438\u043a\u0430\u043a\u043e\u0433\u043e\u00a0<code>ALTER TABLE<\/code>. \u041f\u0440\u043e\u0441\u0442\u043e Django \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435. \u041c\u0438\u043d\u0443\u0441 \u043e\u0434\u043d\u0430 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0433\u0430\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f &#8212; \u044d\u0442\u043e \u0437\u0434\u043e\u0440\u043e\u0432\u043e.<\/p>\n<h3>\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d: Expand &#8212; Migrate &#8212; Contract<\/h3>\n<blockquote>\n<p><strong>\u041f\u0440\u0438\u043d\u0446\u0438\u043f 1<\/strong>: \u0421\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u043e\u0432\u043e\u0439 \u0441\u0445\u0435\u043c\u043e\u0439.\u00a0<br \/><strong>\u041f\u0440\u0438\u043d\u0446\u0438\u043f 2<\/strong>: \u041d\u043e\u0432\u044b\u0439 \u043a\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e \u0441\u0442\u0430\u0440\u043e\u0439 \u0441\u0445\u0435\u043c\u043e\u0439.\u00a0<br \/><strong>\u041f\u0440\u0438\u043d\u0446\u0438\u043f 3<\/strong>: \u041c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 &#8212; \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0448\u0430\u0433\u0438 \u043f\u043e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/blockquote>\n<p>\u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u043b\u044e\u0431\u043e\u0435 &#171;\u043e\u043f\u0430\u0441\u043d\u043e\u0435&#187; \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0445\u0435\u043c\u044b &#8212; \u044d\u0442\u043e \u043d\u0435 \u043e\u0434\u043d\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0438 \u043d\u0435 \u043e\u0434\u0438\u043d \u0434\u0435\u043f\u043b\u043e\u0439. \u042d\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438\u0437 3+ \u0440\u0435\u043b\u0438\u0437\u043e\u0432:<\/p>\n<ol start=\"4\">\n<li>\n<p><strong>Expand<\/strong>. \u0420\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c \u0441\u0445\u0435\u043c\u0443 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c (\u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f nullable, \u043d\u043e\u0432\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f, \u0441\u0442\u0430\u0440\u044b\u0435 \u043f\u043e\u043b\u044f \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f).<\/p>\n<\/li>\n<li>\n<p><strong>Migrate<\/strong>. \u041f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u043d\u043e\u0432\u0443\u044e \u0441\u0445\u0435\u043c\u0443. \u041e\u0431\u044b\u0447\u043d\u043e &#8212; \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u044d\u0442\u0430\u043f\u043e\u0432 \u0441 \u043a\u043e\u0434-\u0440\u0435\u043b\u0438\u0437\u0430\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>Contract<\/strong>. \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0441\u0442\u0430\u0440\u043e\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u041c\u0435\u0436\u0434\u0443 \u044d\u0442\u0438\u043c\u0438 \u044d\u0442\u0430\u043f\u0430\u043c\u0438 &#8212; \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0435\u043f\u043b\u043e\u0438 \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.\u00a0<strong>\u041d\u0438\u043a\u043e\u0433\u0434\u0430<\/strong>\u00a0\u043d\u0435 \u043f\u044b\u0442\u0430\u0439\u0441\u044f \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u0432 \u043e\u0434\u0438\u043d PR.<\/p>\n<h4>\u0421\u043a\u0432\u043e\u0437\u043d\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440: \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435\u00a0Developer.title\u00a0\u0432\u00a0Developer.name<\/h4>\n<p>\u042d\u0442\u043e \u0442\u0430 \u0436\u0435 \u043c\u043e\u0434\u0435\u043b\u044c, \u0447\u0442\u043e \u0432 \u043f\u0435\u0440\u0432\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438, \u0447\u0442\u043e\u00a0<code>title<\/code>\u00a0&#8212; \u043f\u043b\u043e\u0445\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u0438\u043c\u0435\u043d\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0432\u00a0<code>name<\/code>. \u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u043b\u043e\u0431 \u0447\u0435\u0440\u0435\u0437\u00a0<code>RenameField<\/code>\u00a0\u0437\u043d\u0430\u0447\u0438\u0442:<\/p>\n<ul>\n<li>\n<p>\u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 PG:\u00a0<code>ALTER TABLE RENAME COLUMN<\/code>\u00a0&#8212; \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e, ACCESS EXCLUSIVE.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u043c\u0435\u0436\u0434\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b\u0430\u0441\u044c, \u0438 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u0434\u0435\u043f\u043b\u043e\u0438\u043b\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u0434,\u00a0<strong>\u0441\u0442\u0430\u0440\u044b\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/strong>\u00a0\u0445\u043e\u0434\u044f\u0442 \u0432 \u0411\u0414 \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c\u00a0<code>SELECT title FROM developers_developer<\/code>\u00a0\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u043e\u0448\u0438\u0431\u043a\u0443\u00a0<code>column \"title\" does not exist<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 rolling deploy \u044d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0435\u0441\u0435\u043b\u043e: \u043f\u043e\u043a\u0430 \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u0434\u044b \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f, \u0441\u0442\u0430\u0440\u044b\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e\u0442 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c 500-\u043a\u0438.<\/p>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0447\u0435\u0440\u0435\u0437 3 \u0440\u0435\u043b\u0438\u0437\u0430:<\/p>\n<p><strong>\u0420\u0435\u043b\u0438\u0437 1 (Expand): \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c\u00a0<\/strong><code><strong>name<\/strong><\/code><strong>, \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u00a0<\/strong><code><strong>title<\/strong><\/code><strong>.<\/strong><\/p>\n<pre><code class=\"python\"># developers\/models.pyclass Developer(models.Model):    title = models.CharField(max_length=64)           # \u0441\u0442\u0430\u0440\u043e\u0435 \u043f\u043e\u043b\u0435    name = models.CharField(max_length=64, null=True) # \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435    @property    def display_name(self):        return self.name or self.title<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f 1 &#8212; schema:<\/p>\n<pre><code class=\"python\">class Migration(migrations.Migration):    dependencies = [('developers', '0041_previous')]    operations = [        migrations.AddField(            model_name='developer',            name='name',            field=models.CharField(max_length=64, null=True),        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f 2 &#8212; data (\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0435\u0439, \u043d\u0435 \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435!):<\/p>\n<pre><code class=\"python\">def copy_title_to_name(apps, schema_editor):    Developer = apps.get_model('developers', 'Developer')    db_alias = schema_editor.connection.alias    from django.db.models import F    BATCH_SIZE = 5000    last_pk = 0    while True:        # \u0417\u0430\u0431\u0438\u0440\u0430\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0431\u043b\u043e\u043a \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439, \u0441\u0442\u0440\u043e\u0433\u043e pk &gt; last_pk        chunk = list(            Developer.objects.using(db_alias)            .filter(name__isnull=True, pk__gt=last_pk)            .order_by('pk')            .values_list('pk', flat=True)[:BATCH_SIZE]        )        if not chunk:            break        # \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0440\u043e\u0432\u043d\u043e \u044d\u0442\u043e\u0442 \u0431\u043b\u043e\u043a        (            Developer.objects.using(db_alias)            .filter(pk__in=chunk)            .update(name=F('title'))        )        # \u0414\u0432\u0438\u0433\u0430\u0435\u043c \u043a\u0443\u0440\u0441\u043e\u0440        last_pk = chunk[-1]class Migration(migrations.Migration):    atomic = False  # \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u2014 \u0431\u0430\u0442\u0447\u0438 \u043a\u043e\u043c\u043c\u0438\u0442\u044f\u0442\u0441\u044f \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e    dependencies = [('developers', '0042_add_name_field')]    operations = [        migrations.RunPython(            copy_title_to_name,            reverse_code=migrations.RunPython.noop,            elidable=True,  # \u043f\u0440\u0438 squash \u0443\u0434\u0430\u043b\u0438\u0442\u0441\u044f \u2014 \u044d\u0442\u043e \u0440\u0430\u0437\u043e\u0432\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0439 PK \u0432\u0441\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0432 Python-\u0441\u043f\u0438\u0441\u043e\u043a (<code>list(qs.values_list(...))<\/code>) \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u0445 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u043c\u0443 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044e \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0435\u0435 keyset pagination (<code>pk &gt; last_pk<\/code>) \u0438\u043b\u0438 cursor-based batching.<\/p>\n<p><code>order_by('pk') + pk__gt=last_pk<\/code>\u00a0\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e \u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0447\u0430\u043d\u043a\u0430\u043c\u0438 \u0431\u0435\u0437 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0441\u0435\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u0441\u0442\u0440\u043e\u043a \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 Python-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430.<\/p>\n<blockquote>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0434\u0430\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u044b\u0448\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c<\/p>\n<\/blockquote>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u00a0<strong>\u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0447\u0438\u0442\u0430\u0442\u044c\u00a0<\/strong><code><strong>title<\/strong><\/code>, \u043d\u043e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438\/\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043f\u0438\u0448\u0435\u043c \u0432 \u043e\u0431\u0430 \u043f\u043e\u043b\u044f:<\/p>\n<pre><code class=\"python\">def update_developer(developer: Developer, new_title: str) -&gt; None:    developer.title = new_title    developer.name = new_title    developer.save(update_fields=['title', 'name'])<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u0442\u0430\u0440\u044b\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430\u043c \u0447\u0438\u0442\u0430\u0442\u044c\u00a0<code>title<\/code>, \u0430 \u043d\u043e\u0432\u044b\u043c &#8212;\u00a0<code>name<\/code>. \u0411\u044d\u043a\u0444\u0438\u043b\u043b \u0437\u0430\u043a\u0440\u043e\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<p><strong>\u0420\u0435\u043b\u0438\u0437 2 (Migrate): \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0447\u0442\u0435\u043d\u0438\u0435 \u043d\u0430\u00a0<\/strong><code><strong>name<\/strong><\/code><strong>.<\/strong><\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0440\u0435\u043b\u0438\u0437 1 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u0441\u044f \u0438 \u0431\u044d\u043a\u0444\u0438\u043b\u043b \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 &#8212; \u0432 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"python\">class Developer(models.Model):    title = models.CharField(max_length=64)    name = models.CharField(max_length=64, null=True)    @property    def display_name(self):        return self.name  # \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 fallback \u043d\u0430 title<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0438\u0448\u0435\u043c \u0432 \u043e\u0431\u0430 \u043f\u043e\u043b\u044f (\u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 \u043e\u0442\u043a\u0430\u0442\u0430), \u0447\u0438\u0442\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437\u00a0<code>name<\/code>.<\/p>\n<p><strong>\u0420\u0435\u043b\u0438\u0437 3 (Contract): \u0443\u0434\u0430\u043b\u044f\u0435\u043c\u00a0<\/strong><code><strong>title<\/strong><\/code><strong>.<\/strong><\/p>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u0443\u0431\u0438\u0440\u0430\u0435\u043c\u00a0<code>title<\/code>\u00a0\u0441\u043e\u0432\u0441\u0435\u043c. \u0414\u0435\u043b\u0430\u0435\u043c\u00a0<code>name<\/code>\u00a0\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c.<\/p>\n<pre><code class=\"python\">class Developer(models.Model):    name = models.CharField(max_length=64)  # \u0442\u0435\u043f\u0435\u0440\u044c NOT NULL<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"python\">operations = [    # \u041d\u0430 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 100% \u0441\u0442\u0440\u043e\u043a \u0438\u043c\u0435\u044e\u0442 name, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c CHECK NOT VALID + VALIDATE.    AddConstraintNotValid(...),    ValidateConstraint(...),    migrations.AlterField(        model_name='developer',        name='name',        field=models.CharField(max_length=64),  # null=False    ),    migrations.RemoveField(        model_name='developer',        name='title',    ),]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u0430, \u0442\u0440\u0438 \u0440\u0435\u043b\u0438\u0437\u0430 \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0434\u043d\u043e\u0433\u043e. \u0417\u0430\u0442\u043e 0 \u043c\u0438\u043d\u0443\u0442 \u0434\u0430\u0443\u043d\u0442\u0430\u0439\u043c\u0430.<\/p>\n<h4>\u0410\u043d\u0442\u0438\u043f\u0430\u0442\u0442\u0435\u0440\u043d: \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u0442\u043e RenameField<\/h4>\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u0441\u043e\u0431\u043b\u0430\u0437\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"python\">operations = [    migrations.RenameField(        model_name='developer',        old_name='title',        new_name='name',    ),]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>makemigrations<\/code>\u00a0\u0434\u0430\u0436\u0435 \u0441\u043f\u0440\u043e\u0441\u0438\u0442: &#171;It looked like you renamed\u00a0<code>title<\/code>\u00a0to\u00a0<code>name<\/code>. Is that correct?&#187; &#8212; yes.\u00a0<\/p>\n<p>\u0414\u043b\u044f rolling deploy \u0438 distributed environments \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043e\u043f\u0430\u0441\u0435\u043d \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438. \u0412 controlled deployment \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u0445 (<code>blue-green deploy<\/code>)\u00a0<code>RenameField<\/code>\u00a0\u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c.<\/p>\n<h3>PostgreSQL-\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 Django<\/h3>\n<p>\u0412\u00a0<code>django.contrib.postgres.operations<\/code>\u00a0\u043b\u0435\u0436\u0438\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439, \u043d\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f Django\u00a0<strong>\u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442 \u0441\u0430\u043c\u0430<\/strong>. \u0418\u0445 \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0440\u0443\u043a\u0430\u043c\u0438.<\/p>\n<h4>AddIndexConcurrently\u00a0\u0438\u00a0RemoveIndexConcurrently<\/h4>\n<p><code>CREATE INDEX<\/code>\u00a0\u0431\u0435\u0437\u00a0<code>CONCURRENTLY<\/code>\u00a0\u0431\u0435\u0440\u0451\u0442\u00a0<code>SHARE<\/code>\u00a0\u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 &#8212; \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e\u00a0<code>INSERT\/UPDATE\/DELETE<\/code>\u00a0\u0432\u0441\u0442\u0430\u044e\u0442 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c. \u041d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0438\u0448\u0443\u0442, \u0442\u0430\u043a\u043e\u0439\u00a0<code>AddIndex<\/code>\u00a0= \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442.<\/p>\n<p><code>CONCURRENTLY<\/code>\u00a0\u043e\u0431\u0445\u043e\u0434\u0438\u0442 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443, \u0447\u0438\u0442\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u043e\u0432. \u0426\u0435\u043d\u0430: \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0432 2-3 \u0440\u0430\u0437\u0430 \u0434\u043e\u043b\u044c\u0448\u0435 \u0438\u00a0<strong>\u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438<\/strong>.<\/p>\n<pre><code class=\"python\">from django.contrib.postgres.operations import (    AddIndexConcurrently, RemoveIndexConcurrently,)from django.db import migrations, modelsclass Migration(migrations.Migration):    atomic = False  # \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u2014 CONCURRENTLY \u0432\u043d\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438    dependencies = [('developers', '0044_some_migration')]    operations = [        AddIndexConcurrently(            model_name='developer',            index=models.Index(                fields=['rating'],                name='developer_rating_idx',            ),        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0434\u0432\u043e\u0445: \u0435\u0441\u043b\u0438\u00a0<code>CREATE INDEX CONCURRENTLY<\/code>\u00a0\u0443\u043f\u0430\u0434\u0451\u0442 \u043f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u00a0<code>lock_timeout<\/code>\u00a0\u0438\u043b\u0438 \u0438\u0437-\u0437\u0430 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u0430 \u0432 unique-\u0438\u043d\u0434\u0435\u043a\u0441\u0435), \u0438\u043d\u0434\u0435\u043a\u0441 \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0432 \u0411\u0414 \u0441\u043e \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u043c\u00a0<code>INVALID<\/code>. \u041e\u043d\u00a0<strong>\u0432\u0438\u0434\u0435\u043d<\/strong>\u00a0\u0432\u00a0<code>\\d table<\/code>\u00a0\u0438\u00a0<code>pg_indexes<\/code>, \u043d\u043e \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u043c. Django \u043e\u0431 \u044d\u0442\u043e\u043c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442.<\/p>\n<p>\u041b\u0435\u0447\u0435\u043d\u0438\u0435 &#8212; \u043f\u0435\u0440\u0435\u0434 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u043c \u043d\u0430\u043a\u0430\u0442\u043e\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c:<\/p>\n<pre><code class=\"sql\">-- \u041d\u0430\u0439\u0442\u0438 INVALID-\u0438\u043d\u0434\u0435\u043a\u0441\u044b:SELECT indexrelid::regclass AS index_name, indrelid::regclass AS table_nameFROM pg_indexWHERE indisvalid = false;-- \u0423\u0434\u0430\u043b\u0438\u0442\u044c:DROP INDEX CONCURRENTLY IF EXISTS developer_rating_idx;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e.<\/p>\n<h4>AddConstraintNotValid\u00a0+\u00a0ValidateConstraint<\/h4>\n<p>\u041f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0432 Django 4.0 \u0434\u043b\u044f PostgreSQL. \u0422\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f\u00a0<code>CheckConstraint<\/code>\u00a0(\u0434\u043b\u044f FK &#8212; \u0440\u0443\u043a\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437\u00a0<code>RunSQL<\/code>, \u043a\u0430\u043a \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u0432\u044b\u0448\u0435).<\/p>\n<p>\u041e\u0431\u044b\u0447\u043d\u044b\u0439\u00a0<code>ADD CONSTRAINT ... CHECK<\/code>\u00a0\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043f\u043e\u0434 ACCESS EXCLUSIVE \u0438 \u0441\u043a\u0430\u043d\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438. \u041d\u0430 50M \u0441\u0442\u0440\u043e\u043a \u044d\u0442\u043e \u043d\u0430\u0434\u043e\u043b\u0433\u043e.<\/p>\n<p><code>NOT VALID<\/code>\u00a0\u0433\u043e\u0432\u043e\u0440\u0438\u0442: \u043d\u0435 \u0441\u043a\u0430\u043d\u0438\u0440\u0443\u0439 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435 INSERT\/UPDATE. \u0411\u0435\u0440\u0451\u0442 ACCESS EXCLUSIVE, \u043d\u043e \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e. \u041f\u043e\u0442\u043e\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u043c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 &#8212; \u044d\u0442\u043e \u0438\u0434\u0451\u0442 \u043f\u043e\u0434 SHARE UPDATE EXCLUSIVE (\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e \u0441 DML).<\/p>\n<pre><code class=\"python\">from django.contrib.postgres.operations import AddConstraintNotValid, ValidateConstraintfrom django.db import migrations, models# \u0424\u0430\u0439\u043b 0045_add_rating_constraint_not_valid.pyclass Migration(migrations.Migration):    dependencies = [('developers', '0044_previous')]    operations = [        AddConstraintNotValid(            model_name='developer',            constraint=models.CheckConstraint(                condition=models.Q(rating__gte=0),  # \u0412\u0410\u0416\u041d\u041e                name='developer_rating_non_negative',            ),        ),    ]# \u041e\u0422\u0414\u0415\u041b\u042c\u041d\u042b\u0419 \u0444\u0430\u0439\u043b 0046_validate_rating_constraint.pyclass Migration(migrations.Migration):    atomic = False  # VALIDATE \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u043b\u0433\u0438\u043c    dependencies = [('developers', '0045_add_rating_constraint_not_valid')]    operations = [        ValidateConstraint(            model_name='developer',            name='developer_rating_non_negative',        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0412\u0430\u0436\u043d\u043e \u043f\u0440\u043e\u00a0<\/strong><code><strong>CheckConstraint<\/strong><\/code>: \u0432 Django 5.1+ \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0441\u0442\u0430\u043b \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f\u00a0<code><strong>condition<\/strong><\/code>\u00a0\u0432\u043c\u0435\u0441\u0442\u043e\u00a0<code>check<\/code>\u00a0(\u0441\u0442\u0430\u0440\u043e\u0435 \u0438\u043c\u044f deprecated, \u0432 6.0 \u0435\u0449\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 warning, \u043d\u043e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0443\u0434\u0430\u043b\u044f\u0442).\u00a0<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u043e \u043f\u0440\u043e \u0434\u0432\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438<\/strong>: \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 \u043e\u0434\u043d\u0443, \u0442\u043e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f \u0432\u043e\u043a\u0440\u0443\u0433 \u043d\u0438\u0445 (<code>atomic = True<\/code>\u00a0\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e) \u0441\u0432\u0435\u0434\u0451\u0442 \u0432\u0441\u044e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u0430 \u043d\u0435\u0442.<\/p>\n<h4>UniqueConstraint CONCURRENTLY: \u043b\u0430\u0439\u0444\u0445\u0430\u043a \u0447\u0435\u0440\u0435\u0437\u00a0SeparateDatabaseAndState<\/h4>\n<p>Django \u043d\u0435 \u0438\u043c\u0435\u0435\u0442\u00a0<code>AddConstraintConcurrently<\/code>. \u0415\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0432\u0435\u0441\u0438\u0442\u044c UNIQUE \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u043e\u0431\u044b\u0447\u043d\u044b\u0439\u00a0<code>AddConstraint(UniqueConstraint(...))<\/code>\u00a0\u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0438\u043d\u0434\u0435\u043a\u0441 \u043f\u043e\u0434 SHARE &#8212; \u0430 \u044d\u0442\u043e write-\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430.<\/p>\n<p>\u041e\u0431\u0445\u043e\u0434: \u0441\u043e\u0437\u0434\u0430\u0442\u044c UNIQUE INDEX CONCURRENTLY \u0440\u0443\u043a\u0430\u043c\u0438, \u0430 Django \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0447\u0438\u0442\u0430\u0439, \u0447\u0442\u043e constraint \u0443 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u0447\u0435\u0440\u0435\u0437\u00a0<code>SeparateDatabaseAndState<\/code>:<\/p>\n<pre><code class=\"python\">from django.db import migrations, modelsclass Migration(migrations.Migration):    atomic = False    dependencies = [('developers', '0046_previous')]    operations = [        migrations.SeparateDatabaseAndState(            database_operations=[                migrations.RunSQL(                    sql=(                        'CREATE UNIQUE INDEX CONCURRENTLY \"developer_inn_uniq\" '                        'ON \"developers_developer\" (\"inn\");'                    ),                    reverse_sql=(                        'DROP INDEX CONCURRENTLY IF EXISTS \"developer_inn_uniq\";'                    ),                ),            ],            state_operations=[                migrations.AddConstraint(                    model_name='developer',                    constraint=models.UniqueConstraint(                        fields=['inn'],                        name='developer_inn_uniq',                    ),                ),            ],        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>database_operations<\/code>\u00a0\u0438\u0434\u0443\u0442 \u0432 \u0411\u0414 (\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u043d\u0434\u0435\u043a\u0441 CONCURRENTLY),\u00a0<code>state_operations<\/code>\u00a0\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442 in-memory \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Django (autodetector \u0434\u0443\u043c\u0430\u0435\u0442, \u0447\u0442\u043e constraint \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0438 \u043d\u0435 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u043d\u043e\u0432\u0430).<\/p>\n<p>PostgreSQL \u0443\u043c\u0435\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c unique-\u0438\u043d\u0434\u0435\u043a\u0441 \u043a\u0430\u043a backing \u0434\u043b\u044f constraint \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0435\u043d \u0438 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0438.<\/p>\n<h3>SeparateDatabaseAndState<\/h3>\n<p>SDAS &#8212; \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0442\u043e\u043d\u043a\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b, \u043a\u043e\u0433\u0434\u0430 \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f Django \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043f\u043e \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0435, \u043d\u043e \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u043f\u0435\u0440\u0444\u043e\u0440\u043c\u0430\u043d\u0441\u0443. \u0415\u0449\u0451 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u0435\u0439\u0441\u043e\u0432, \u0433\u0434\u0435 \u043e\u043d \u043d\u0443\u0436\u0435\u043d.<\/p>\n<h4>\u041a\u0435\u0439\u0441 1: \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u0441\u00a0index_together\u00a0\u043d\u0430\u00a0Meta.indexes<\/h4>\n<p><code>index_together<\/code>\u00a0deprecated \u0432 Django 4.2 \u0438 \u0443\u0434\u0430\u043b\u0451\u043d \u0432 5.1. \u041f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0432\u00a0<code>indexes<\/code>\u00a0\u043d\u0435\u043b\u044c\u0437\u044f &#8212; Django \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f\u00a0<strong>\u043f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0438\u043d\u0434\u0435\u043a\u0441<\/strong>: DROP + CREATE. \u041d\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043b\u043e\u0445\u043e.<\/p>\n<p>\u0425\u0438\u0442\u0440\u043e\u0441\u0442\u044c: \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u043d\u0434\u0435\u043a\u0441 \u0432 \u0411\u0414, \u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c Django, \u0447\u0442\u043e \u043c\u044b\u00a0<em>&#171;\u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043b\u0438&#187;<\/em>\u00a0\u0435\u0433\u043e \u0432 state:<\/p>\n<pre><code class=\"python\"># \u041d\u0430\u0439\u0442\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0438\u043c\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0432 \u0411\u0414:# \\d+ developers_developer \u0432 psql# \u0418\u043b\u0438: SELECT indexname FROM pg_indexes WHERE tablename='developers_developer';# \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0431\u044b\u043b\u043e developers_dev_a_b_idx.# \u0412 Meta \u043c\u043e\u0434\u0435\u043b\u0438:class Meta:    indexes = [        models.Index(fields=['a', 'b'], name='developers_dev_a_b_idx'),    ]# \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f:operations = [    migrations.SeparateDatabaseAndState(        database_operations=[],  # \u0432 \u0411\u0414 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c        state_operations=[            migrations.AlterIndexTogether(                name='developer',                index_together=set(),            ),            migrations.AddIndex(                model_name='developer',                index=models.Index(                    fields=['a', 'b'],                    name='developers_dev_a_b_idx',                ),            ),        ],    ),]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0435 &#8212; \u0443\u043a\u0430\u0437\u0430\u0442\u044c\u00a0<strong>\u0442\u043e \u0436\u0435 \u0438\u043c\u044f<\/strong>, \u0447\u0442\u043e \u0443 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0432 \u0411\u0414. \u0422\u043e\u0433\u0434\u0430 Django \u0441\u0447\u0438\u0442\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0441\u0451 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0438\u043d\u0434\u0435\u043a\u0441 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u043b\u0441\u044f.<\/p>\n<h4>\u041a\u0435\u0439\u0441 2: \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0447\u0435\u0440\u0435\u0437\u00a0db_column<\/h4>\n<p>\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 expand\/contract \u0434\u043b\u044f \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u0438\u043b\u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u043e\u0432: \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c\u00a0<strong>\u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043a\u043e\u0434\u0435 Python<\/strong>, \u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0438\u043c\u044f \u043a\u043e\u043b\u043e\u043d\u043a\u0438.<\/p>\n<pre><code class=\"python\">class Developer(models.Model):    # \u0412 \u043a\u043e\u0434\u0435 \u2014 name, \u0432 \u0411\u0414 \u2014 title    name = models.CharField(max_length=64, db_column='title')<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f:<\/p>\n<pre><code class=\"python\">operations = [    migrations.SeparateDatabaseAndState(        database_operations=[],        state_operations=[            migrations.RenameField(                model_name='developer',                old_name='title',                new_name='name',            ),            migrations.AlterField(                model_name='developer',                name='name',                field=models.CharField(max_length=64, db_column='title'),            ),        ],    ),]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>\u041a\u0435\u0439\u0441 3: \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 M2M \u0432 \u044f\u0432\u043d\u0443\u044e through-\u043c\u043e\u0434\u0435\u043b\u044c<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043a\u00a0<code>ManyToManyField<\/code>\u00a0\u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0<code>created_at<\/code>,\u00a0<code>created_by<\/code>), \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430\u00a0<code>through<\/code>. Django \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u2014 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f.<\/p>\n<p>\u0427\u0435\u0440\u0435\u0437\u00a0<code>SeparateDatabaseAndState<\/code>\u00a0\u043c\u044b \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0432 \u0411\u0414, \u043d\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u043c Django &#8212; \u0432\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e \u0442\u0432\u043e\u044f through-\u043c\u043e\u0434\u0435\u043b\u044c:<\/p>\n<pre><code class=\"python\"># \u0412 models.py \u2014 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c through:class Project(models.Model):    developers = models.ManyToManyField(        'developers.Developer',        through='ProjectDeveloper',    )class ProjectDeveloper(models.Model):    project = models.ForeignKey('Project', on_delete=models.CASCADE)    developer = models.ForeignKey(        'developers.Developer', on_delete=models.CASCADE,    )    class Meta:        db_table = 'projects_project_developers'  # \u0438\u043c\u044f \u0430\u0432\u0442\u043e-\u0442\u0430\u0431\u043b\u0438\u0446\u044b M2M<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>SeparateDatabaseAndState<\/code>\u00a0&#8212; \u043e\u0447\u0435\u043d\u044c \u043c\u043e\u0449\u043d\u044b\u0439, \u043d\u043e \u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442.<\/p>\n<p>\u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442\u00a0<em>&#171;\u0440\u0430\u0437\u0432\u043e\u0434\u0438\u0442\u044c&#187;:<\/em><\/p>\n<ul>\n<li>\n<p>\u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0411\u0414;<\/p>\n<\/li>\n<li>\n<p>migration state Django.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438 \u043d\u0435\u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a state drift, \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u043c auto-generated migrations \u0438 \u0442\u0440\u0443\u0434\u043d\u043e\u043e\u0442\u043b\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c \u0432 \u0433\u0440\u0430\u0444\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439.<\/p>\n<p>\u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 SDAS \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0442\u0435\u043c \u0432\u0430\u0436\u043d\u0435\u0435 \u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u0430 \u0432\u043e\u043a\u0440\u0443\u0433 \u0440\u0435\u0432\u044c\u044e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439.<\/p>\n<h3>atomic = False<\/h3>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043a\u0430\u0436\u0434\u0430\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f Django \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e (<code>BEGIN ... COMMIT<\/code>). \u042d\u0442\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439: \u0443\u043f\u0430\u043b\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f &#8212; \u0411\u0414 \u043e\u0442\u043a\u0430\u0442\u0438\u043b\u0430\u0441\u044c \u043a \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e.<\/p>\n<p>\u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u043e\u0441\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u0430 \u0438 \u0434\u0430\u0436\u0435 \u0432\u0440\u0435\u0434\u0438\u0442:<\/p>\n<ul>\n<li>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u00a0<code>CONCURRENTLY<\/code>\u00a0\u0432\u043e\u043e\u0431\u0449\u0435 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043b\u0433\u0438\u0439 \u0431\u044d\u043a\u0444\u0438\u043b\u043b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 = ROW EXCLUSIVE \u043d\u0430 \u043a\u0443\u0447\u0435 \u0441\u0442\u0440\u043e\u043a \u043d\u0430\u0434\u043e\u043b\u0433\u043e + \u0440\u0430\u0437\u0434\u0443\u0442\u044b\u0439 WAL.<\/p>\n<\/li>\n<li>\n<p><code>AddConstraintNotValid<\/code>\u00a0+\u00a0<code>VALIDATE<\/code>\u00a0\u0445\u043e\u0442\u0438\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e, \u0447\u0442\u043e\u0431\u044b VALIDATE \u043c\u043e\u0433 \u0438\u0434\u0442\u0438 \u043d\u0430 \u043f\u0440\u043e\u0434\u0435 \u0431\u0435\u0437 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0441\u0442\u0430\u0432\u0438\u043c:<\/p>\n<pre><code class=\"python\">class Migration(migrations.Migration):    atomic = False    # ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>\u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438 \u0441\u0431\u043e\u0435 \u0432 non-atomic \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438<\/h4>\n<p>\u0422\u043e\u043d\u043a\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. \u0412 \u043e\u0431\u044b\u0447\u043d\u043e\u0439 (atomic) \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u043e\u0448\u0438\u0431\u043a\u0435 Django \u0434\u0435\u043b\u0430\u0435\u0442 ROLLBACK &#8212; \u0411\u0414 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0432\u00a0<code>django_migrations<\/code>\u00a0\u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f. \u041c\u043e\u0436\u043d\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c.<\/p>\n<p>\u0412 non-atomic \u043f\u0440\u0438 \u043e\u0448\u0438\u0431\u043a\u0435:<\/p>\n<ol start=\"7\">\n<li>\n<p>SQL, \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0435 \u0434\u043e \u043c\u0435\u0441\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0438,\u00a0<strong>\u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u043c\u0438 \u0432 \u0411\u0414<\/strong>\u00a0(Django \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 transaction scopes, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0447\u0430\u0441\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043c\u043e\u0436\u0435\u0442 \u0443\u0441\u043f\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f \u0434\u043e \u043c\u0435\u0441\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0438)<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0438\u0441\u044c \u0432\u00a0<code>django_migrations<\/code>\u00a0<strong>\u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f<\/strong>\u00a0&#8212; Django \u043d\u0435 \u0437\u043d\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0430 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 Django \u043d\u0430\u0447\u043d\u0451\u0442 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u0438 \u0443\u043f\u0430\u0434\u0451\u0442 \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u0439 \u0436\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u00a0<code>column already exists<\/code>\u00a0\/\u00a0<code>index already exists<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u041a\u0430\u043a \u043b\u0435\u0447\u0438\u0442\u044c:<\/p>\n<p><strong>\u0412\u0430\u0440\u0438\u0430\u043d\u0442 1: \u043f\u0438\u0441\u0430\u0442\u044c \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u044b\u0435 SQL \u0440\u0443\u043a\u0430\u043c\u0438<\/strong>. \u042d\u0442\u043e \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f\u00a0<code>RunSQL<\/code>:<\/p>\n<pre><code class=\"python\">migrations.RunSQL(    sql='ALTER TABLE foo ADD COLUMN IF NOT EXISTS bar integer;',    reverse_sql='ALTER TABLE foo DROP COLUMN IF EXISTS bar;',),<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, Django-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (<code>AddField<\/code>,\u00a0<code>AddIndex<\/code>) \u043d\u0435 \u0443\u043c\u0435\u044e\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c\u00a0<code>IF NOT EXISTS<\/code>\u00a0&#8212; \u0434\u043b\u044f \u043d\u0438\u0445 \u044d\u0442\u043e\u0442 \u0442\u0440\u044e\u043a \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<p><strong>\u0412\u0430\u0440\u0438\u0430\u043d\u0442 2: \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0442\u044c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u043d\u0430 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043c\u0435\u043b\u043a\u0438\u0435 \u0448\u0430\u0433\u0438<\/strong>. \u0415\u0441\u043b\u0438 \u0443\u043f\u0430\u0434\u0451\u0442 &#8212; \u0443\u043f\u0430\u0434\u0451\u0442 \u043d\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c \u0448\u0430\u0433\u0435, \u0438 \u0440\u0443\u043a\u0430\u043c\u0438 \u043b\u0435\u0433\u0447\u0435 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b\u043e\u0441\u044c, \u0430 \u0447\u0442\u043e \u043d\u0435\u0442.<\/p>\n<p><strong>\u0412\u0430\u0440\u0438\u0430\u043d\u0442 3: \u0440\u0443\u0447\u043d\u0430\u044f \u043e\u0447\u0438\u0441\u0442\u043a\u0430 \u043f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c<\/strong>. \u0417\u0430\u0448\u0451\u043b \u0432\u00a0<code>psql<\/code>, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u00a0<code>\\d table<\/code>, \u0443\u0434\u0430\u043b\u0438\u043b \u043b\u0438\u0448\u043d\u0435\u0435, \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u043b \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e.<\/p>\n<p><strong>\u0412\u0430\u0440\u0438\u0430\u043d\u0442 4:\u00a0<\/strong><code><strong>--fake<\/strong><\/code><strong>\u00a0\u043f\u043e\u0441\u043b\u0435 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f<\/strong>. \u0415\u0441\u043b\u0438 \u0442\u044b \u0440\u0443\u043a\u0430\u043c\u0438 \u0434\u043e\u043a\u0430\u0442\u0438\u043b \u0432\u0441\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0441\u043a\u0430\u0436\u0438 Django\u00a0<em>&#171;\u0441\u0447\u0438\u0442\u0430\u0439, \u0447\u0442\u043e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0430&#187;<\/em>:<\/p>\n<pre><code class=\"bash\">python manage.py migrate developers 0045 --fake<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>(<code>--fake<\/code>\u00a0\u043c\u044b \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435)<\/p>\n<h3>Batch updates: data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445<\/h3>\n<p>\u041e\u0434\u0438\u043d UPDATE \u043d\u0430 50M \u0441\u0442\u0440\u043e\u043a \u044d\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>ROW EXCLUSIVE \u043d\u0430 \u043a\u0443\u0447\u0435 \u0441\u0442\u0440\u043e\u043a \u043d\u0430\u0434\u043e\u043b\u0433\u043e;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 WAL &#8212; \u0440\u0435\u043f\u043b\u0438\u043a\u0438 \u0437\u0430\u043b\u0430\u0433\u0430\u044e\u0442;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u043b\u0438 \u0432\u00a0<code>atomic = True<\/code>\u00a0= \u043e\u0434\u043d\u0430 \u0433\u0438\u0433\u0430\u043d\u0442\u0441\u043a\u0430\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f, \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 shared buffers, autovacuum \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0431\u0435\u0437 \u043e\u0442\u043a\u0430\u0442\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>PostgreSQL 17 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u044f\u0434 \u0437\u0430\u043c\u0435\u0442\u043d\u044b\u0445 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0439 \u0432\u043e\u043a\u0440\u0443\u0433 vacuum\/WAL \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u043d\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0432\u044b\u0438\u0433\u0440\u044b\u0448 \u0441\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u044d\u0442\u043e\u0439 \u0441\u0430\u043c\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0422\u043e \u0435\u0441\u0442\u044c \u044d\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435 \u0434\u0443\u043c\u0430\u0442\u044c \u043f\u0440\u043e \u0431\u0430\u0442\u0447\u0438 &#8212; \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u044f \u0442\u0432\u043e\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u0440\u043e\u0449\u0435 \u043f\u0435\u0440\u0435\u0436\u0438\u0442\u044c. \u041d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043d\u0430\u0434\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.<\/p>\n<p>\u041b\u0435\u0447\u0435\u043d\u0438\u0435 &#8212; \u0431\u0430\u0442\u0447\u0438 \u0441\u00a0<code>atomic = False<\/code>:<\/p>\n<pre><code class=\"python\">from django.db import migrationsdef backfill_status(apps, schema_editor):    Developer = apps.get_model('developers', 'Developer')    db_alias = schema_editor.connection.alias    BATCH_SIZE = 10_000    qs = (        Developer.objects.using(db_alias)        .filter(status__isnull=True)    )    last_pk = 0    while True:        batch_qs = (            qs.filter(pk__gt=last_pk)               .order_by('pk')        )        # \u0431\u0435\u0440\u0451\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u0443 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430        batch = list(            batch_qs.values_list('pk', flat=True)[:BATCH_SIZE]        )        if not batch:            break        start = batch[0]        end = batch[-1]        Developer.objects.using(db_alias).filter(            pk__gte=start,            pk__lte=end,            status__isnull=True        ).update(status='active')        last_pk = endclass Migration(migrations.Migration):    atomic = False    dependencies = [('developers', '0050_add_status_field')]    operations = [        migrations.RunPython(            backfill_status,            reverse_code=migrations.RunPython.noop,            elidable=True,        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u044d\u0442\u043e\u043c \u043a\u043e\u0434\u0435:<\/p>\n<ol start=\"10\">\n<li>\n<p><code><strong>apps.get_model(...)<\/strong><\/code><strong>, \u0430 \u043d\u0435 \u043f\u0440\u044f\u043c\u043e\u0439 \u0438\u043c\u043f\u043e\u0440\u0442 \u043c\u043e\u0434\u0435\u043b\u0438<\/strong>. \u041c\u044b \u044d\u0442\u043e \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u043b\u0438 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c &#8212; \u044d\u0442\u043e &#171;\u0442\u0435\u043a\u0443\u0449\u0430\u044f&#187; \u0432\u0435\u0440\u0441\u0438\u044f \u0438\u0437\u00a0<a href=\"http:\/\/models.py\" rel=\"noopener noreferrer nofollow\"><code>models.py<\/code><\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u044f, \u0435\u0449\u0451 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0432 \u0411\u0414.\u00a0<code>apps.get_model<\/code>\u00a0\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 &#171;\u0438\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0443\u044e&#187; \u043c\u043e\u0434\u0435\u043b\u044c &#8212; \u0440\u043e\u0432\u043d\u043e \u0442\u0430\u043a\u0443\u044e, \u043a\u0430\u043a\u043e\u0439 \u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u044d\u0442\u043e\u0439 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><code><strong>using(db_alias)<\/strong><\/code>. \u041d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 multi-db\u00a0<code>schema_editor.connection.alias<\/code>\u00a0\u043e\u0442\u0434\u0430\u0441\u0442 \u043d\u0443\u0436\u043d\u043e\u0435 \u0438\u043c\u044f \u0411\u0414. \u0415\u0441\u043b\u0438 \u0437\u0430\u0431\u044b\u0442\u044c &#8212;\u00a0<code>update()<\/code>\u043f\u043e\u0439\u0434\u0451\u0442 \u0432 default-\u0431\u0430\u0437\u0443.<\/p>\n<\/li>\n<li>\n<p><code><strong>reverse_code=migrations.RunPython.noop<\/strong><\/code>. \u0425\u043e\u0440\u043e\u0448\u043e \u0431\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u044d\u043a\u0444\u0438\u043b\u043b\u0430 \u044d\u0442\u043e \u0447\u0430\u0441\u0442\u043e \u0431\u0435\u0441\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u043e (\u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f &#171;\u0431\u0435\u0437 \u0441\u0442\u0430\u0442\u0443\u0441\u0430&#187; \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438).\u00a0<code>noop<\/code>\u00a0\u0433\u043e\u0432\u043e\u0440\u0438\u0442 Django: &#171;\u043c\u043e\u0436\u0435\u0448\u044c \u043e\u0442\u043a\u0430\u0442\u0438\u0442\u044c, \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e&#187;.<\/p>\n<\/li>\n<li>\n<p><code><strong>elidable=True<\/strong><\/code>. \u0411\u044d\u043a\u0444\u0438\u043b\u043b &#8212; \u0440\u0430\u0437\u043e\u0432\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f. \u041f\u0440\u0438\u00a0<code>squashmigrations<\/code>\u00a0Django \u0443\u0434\u0430\u043b\u0438\u0442 \u0435\u0451 \u0438\u0437 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0451\u043d\u043d\u043e\u0439 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><code><strong>atomic = False<\/strong><\/code>\u00a0\u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Migration. \u0411\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u043a\u0430\u0436\u0434\u044b\u0439\u00a0<code>.update()<\/code>\u00a0\u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0431\u044b\u043b \u0431\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u0449\u0435\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 &#8212; \u0442\u043e \u0435\u0441\u0442\u044c \u043c\u044b \u0431\u044b \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u0430.<\/p>\n<\/li>\n<\/ol>\n<h4>\u041a\u043e\u0433\u0434\u0430 \u043b\u0443\u0447\u0448\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0430, \u0430 \u043d\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f<\/h4>\n<p>\u0414\u043b\u044f \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0431\u044d\u043a\u0444\u0438\u043b\u043b\u043e\u0432 (&gt;10M \u0441\u0442\u0440\u043e\u043a, \u0447\u0430\u0441\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f) data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f &#8212; \u043f\u043b\u043e\u0445\u043e\u0439 \u0432\u044b\u0431\u043e\u0440:<\/p>\n<ul>\n<li>\n<p>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0432\u044b\u043a\u0430\u0442\u043a\u0443. \u0415\u0441\u043b\u0438 \u0431\u044d\u043a\u0444\u0438\u043b\u043b \u0438\u0434\u0451\u0442 6 \u0447\u0430\u0441\u043e\u0432, \u0440\u0435\u043b\u0438\u0437\u044b \u0441\u0442\u043e\u044f\u0442.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0430 \u043f\u0430\u0443\u0437\u0443, \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c, \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442 \u0435\u0451 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e (<code>migrate<\/code>\u00a0\u0438\u0434\u0451\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0434\u043e\u043b\u0433\u043e)<\/p>\n<\/li>\n<\/ul>\n<p>\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 &#8212;\u00a0<code>BaseCommand<\/code>:<\/p>\n<pre><code class=\"python\"># developers\/management\/commands\/backfill_developer_status.pyfrom django.core.management.base import BaseCommandfrom django.db import transactionfrom developers.models import Developerclass Command(BaseCommand):    help = 'Backfill Developer.status'    def add_arguments(self, parser):        parser.add_argument('--batch-size', type=int, default=5000)        parser.add_argument('--sleep', type=float, default=0.0)    def handle(self, *args, batch_size, sleep, **options):        import time        qs = Developer.objects.filter(status__isnull=True)        total = qs.count()        self.stdout.write(f'To backfill: {total}')        done = 0        while True:            pks = list(                qs.order_by('pk').values_list('pk', flat=True)[:batch_size]            )            if not pks:                break            with transaction.atomic():                Developer.objects.filter(pk__in=pks).update(status='active')            done += len(pks)            self.stdout.write(f'Done: {done}\/{total}')            if sleep:                time.sleep(sleep)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c:<\/p>\n<pre><code class=\"bash\">python manage.py backfill_developer_status --batch-size 2000 --sleep 0.5<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043b\u044e\u0441\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<ul>\n<li>\n<p>\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0448\u044c \u0440\u0443\u043a\u0430\u043c\u0438, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043d\u0438\u0436\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0436\u0435\u0448\u044c \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c\u00a0<code>Ctrl+C<\/code>\u00a0\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u043f\u043e\u0437\u0436\u0435 (\u043e\u043d\u0430 \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u0430 &#8212; \u0431\u0435\u0440\u0451\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a\u0438 \u0441\u00a0<code>status IS NULL<\/code>);<\/p>\n<\/li>\n<li>\n<p>\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b (batch_size, sleep) \u043d\u0430 \u043b\u0435\u0442\u0443;<\/p>\n<\/li>\n<li>\n<p>\u043b\u0435\u0433\u043a\u043e \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u0442\u044c &#8212; \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043b\u043e\u0433.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0438\u043d\u0443\u0441: \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0440\u0443\u043a\u0430\u043c\u0438.<\/p>\n<h3>NOT NULL \u0431\u0435\u0437 \u0434\u0430\u0443\u043d\u0442\u0430\u0439\u043c\u0430: \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439<\/h3>\n<p>\u0412\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438, \u043a\u0430\u043a \u043f\u0440\u043e\u0439\u0442\u0438 \u043e\u0448\u0438\u0431\u043a\u0443 &#171;You are trying to add a non-nullable field&#187; \u043f\u0440\u0438\u00a0<code>makemigrations<\/code>. \u0421\u0435\u0439\u0447\u0430\u0441 \u0442\u043e\u0442 \u0436\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0432 production-\u0440\u0430\u0437\u0440\u0435\u0437\u0435.<\/p>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430: \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435\u00a0<code>Developer.status<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 nullable, \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c.<\/p>\n<p>\u041d\u0430\u0438\u0432\u043d\u044b\u0439 \u043f\u0443\u0442\u044c:<\/p>\n<pre><code class=\"python\">operations = [    migrations.AlterField(        model_name='developer',        name='status',        field=models.CharField(max_length=16),  # null=False    ),]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e Django \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0442:<\/p>\n<pre><code class=\"sql\">ALTER TABLE \"developers_developer\" ALTER COLUMN \"status\" SET NOT NULL;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u0430 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0431\u0435\u0440\u0451\u0442 ACCESS EXCLUSIVE \u0438\u00a0<strong>\u0441\u043a\u0430\u043d\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443<\/strong>\u00a0\u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0447\u0442\u043e \u043d\u0435\u0442 NULL. \u041d\u0430 50M \u0441\u0442\u0440\u043e\u043a = \u043c\u0438\u043d\u0443\u0442\u044b \u043f\u0440\u043e\u0441\u0442\u043e\u044f.<\/p>\n<p>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u2014 4 \u0448\u0430\u0433\u0430:<\/p>\n<p><strong>\u0428\u0430\u0433 1: \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u2014 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c\u00a0<\/strong><code><strong>CHECK (status IS NOT NULL) NOT VALID<\/strong><\/code><strong>.<\/strong><\/p>\n<pre><code class=\"python\">from django.contrib.postgres.operations import AddConstraintNotValidfrom django.db import migrations, modelsclass Migration(migrations.Migration):    dependencies = [('developers', '0050_previous')]    operations = [        AddConstraintNotValid(            model_name='developer',            constraint=models.CheckConstraint(                condition=models.Q(status__isnull=False),                name='developer_status_not_null',            ),        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0439 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438\u00a0<strong>\u043d\u043e\u0432\u044b\u0435<\/strong>\u00a0\u0441\u0442\u0440\u043e\u043a\u0438 \u0443\u0436\u0435 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c\u00a0<code>NULL<\/code>\u00a0\u0432\u00a0<code>status<\/code>. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 &#8212; \u043f\u043e\u043a\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c NULL, \u043c\u044b \u0438\u0445 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u0435\u043c.<\/p>\n<p><strong>\u0428\u0430\u0433 2: \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u0438\u0448\u0435\u0442 \u0432\u00a0<\/strong><code><strong>status<\/strong><\/code><strong>\u00a0\u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.<\/strong><\/p>\n<p>\u0414\u0435\u043f\u043b\u043e\u0438\u043c \u0440\u0435\u043b\u0438\u0437. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0442\u043e\u043a \u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0447\u0438\u0441\u0442.<\/p>\n<p><strong>\u0428\u0430\u0433 3: data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f &#8212; \u0431\u044d\u043a\u0444\u0438\u043b\u043b\u0438\u043c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438.<\/strong><\/p>\n<pre><code class=\"python\">def backfill_status(apps, schema_editor):    # \u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0440\u0430\u043d\u0435\u0435class Migration(migrations.Migration):    atomic = False    dependencies = [('developers', '0051_check_status_not_null')]    operations = [        migrations.RunPython(            backfill_status,            reverse_code=migrations.RunPython.noop,            elidable=True,        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>\u0428\u0430\u0433 4: \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u2014 VALIDATE CONSTRAINT + AlterField.<\/strong><\/p>\n<pre><code class=\"python\">from django.contrib.postgres.operations import ValidateConstraintfrom django.db import migrations, modelsclass Migration(migrations.Migration):    atomic = False  # VALIDATE \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u043b\u0433\u0438\u043c    dependencies = [('developers', '0052_backfill_status')]    operations = [        # 1. \u0412\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u043c CHECK \u2014 SHARE UPDATE EXCLUSIVE, \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e \u0441 DML.        ValidateConstraint(            model_name='developer',            name='developer_status_not_null',        ),        # 2. \u041c\u0435\u043d\u044f\u0435\u043c \u043a\u043e\u043b\u043e\u043d\u043a\u0443 \u043d\u0430 NOT NULL.        # \u041d\u0430 PG 12+ \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0433\u043e CHECK NOT NULL \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u0430:        # PG \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 CHECK \u043a\u0430\u043a \u0434\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e.        migrations.AlterField(            model_name='developer',            name='status',            field=models.CharField(max_length=16),        ),        # 3. CHECK \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d (\u0435\u0433\u043e \u0440\u043e\u043b\u044c \u0442\u0435\u043f\u0435\u0440\u044c \u0443 NOT NULL constraint).        migrations.RemoveConstraint(            model_name='developer',            name='developer_status_not_null',        ),    ]<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Django \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0442 \u0442\u0430\u043a\u0443\u044e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0430\u043c.\u00a0<code>makemigrations<\/code>\u00a0\u0434\u043b\u044f \u0441\u043c\u0435\u043d\u044b\u00a0<code>null=True \u2192 null=False<\/code>\u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0439\u00a0<code>AlterField<\/code>. \u0428\u0430\u0433\u0438 1, 3, 4 \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0443\u043a\u0430\u043c\u0438; \u0448\u0430\u0433 2 &#8212; \u043e\u0431\u044b\u0447\u043d\u0430\u044f code-only data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f.<\/p>\n<h4>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439<\/h4>\n<p>Data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 &#8212; \u044d\u0442\u043e \u043a\u043e\u0434. \u041a\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0442\u0435\u0441\u0442\u044b. \u0411\u0435\u0437 \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f, \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0432\u0448\u0430\u044f \u043d\u0430 12 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 \u043d\u0430 dev, \u043c\u043e\u0436\u0435\u0442 \u0440\u0443\u0445\u043d\u0443\u0442\u044c \u043d\u0430 100M \u0441\u0442\u0440\u043e\u043a \u043d\u0430 \u043f\u0440\u043e\u0434\u0435.<\/p>\n<p>\u041f\u0430\u043a\u0435\u0442\u00a0<code>django-test-migrations<\/code>\u00a0\u043e\u0442\u00a0<a href=\"https:\/\/github.com\/wemake-services\" rel=\"noopener noreferrer nofollow\">wemake-services\u00a0<\/a>\u0434\u0430\u0451\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 API:<\/p>\n<pre><code class=\"python\">from django_test_migrations.migrator import Migratordef test_backfill_status_fills_existing_rows(transactional_db):    migrator = Migrator(database='default')    # 1. \u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \"\u0414\u041e\" \u043d\u0430\u0448\u0435\u0439 data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438.    old_state = migrator.apply_initial_migration(        ('developers', '0050_add_status_field'),    )    Developer = old_state.apps.get_model('developers', 'Developer')    # 2. \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u2014 \u043a\u0430\u043a \u043e\u043d\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u0438 \u0434\u043e \u0431\u044d\u043a\u0444\u0438\u043b\u043b\u0430.    Developer.objects.create(title='Alice', status=None)    Developer.objects.create(title='Bob', status=None)    Developer.objects.create(title='Charlie', status='admin')    # 3. \u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u043d\u0430\u0448\u0443 data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e.    new_state = migrator.apply_tested_migration(        ('developers', '0052_backfill_status'),    )    Developer = new_state.apps.get_model('developers', 'Developer')    # 4. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.    assert Developer.objects.filter(status='unknown').count() == 2    assert Developer.objects.filter(status='admin').count() == 1    assert Developer.objects.filter(status__isnull=True).count() == 0    migrator.reset()<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0433\u043e:<\/p>\n<ul>\n<li>\n<p>\u0422\u0435\u0441\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u0442 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u043f\u0440\u043e\u0442\u0438\u0432 \u0411\u0414, \u0430 \u043d\u0435 \u043c\u043e\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c reverse: \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b A &#8212; \u0441\u043e\u0437\u0434\u0430\u043b \u0434\u0430\u043d\u043d\u044b\u0435 &#8212; \u043e\u0442\u043a\u0430\u0442\u0438\u043b\u0441\u044f \u0434\u043e B &#8212; \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0430\u0434\u0435\u043a\u0432\u0430\u0442\u043d\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 pytest-django (\u0444\u0438\u043a\u0441\u0442\u0443\u0440\u0430\u00a0<code>transactional_db<\/code>).<\/p>\n<\/li>\n<\/ul>\n<h4>CI-\u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0434\u043b\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 (\u0447\u0435\u043a-\u043b\u0438\u0441\u0442)<\/h4>\n<p>\u0412 \u043a\u0430\u0436\u0434\u043e\u043c PR:<\/p>\n<ol start=\"15\">\n<li>\n<p><code>python <\/code><a href=\"http:\/\/manage.py\" rel=\"noopener noreferrer nofollow\"><code>manage.py<\/code><\/a><code> makemigrations --check --dry-run<\/code>\u00a0&#8212; \u0435\u0441\u0442\u044c \u043b\u0438 \u043d\u0435\u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0432 \u043a\u043e\u0434\u0435? \u0415\u0441\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043f\u043e\u043c\u0435\u043d\u044f\u043b \u043c\u043e\u0434\u0435\u043b\u0438, \u043d\u043e \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u00a0<code>makemigrations<\/code>, \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0432 \u043f\u0440\u043e\u0434\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p><code>python <\/code><a href=\"http:\/\/manage.py\" rel=\"noopener noreferrer nofollow\"><code>manage.py<\/code><\/a><code> migrate --plan<\/code>\u00a0&#8212; \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u0435\u0434\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u044b \u043d\u0430 data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 (<code>django-test-migrations<\/code>).<\/p>\n<\/li>\n<li>\n<p>(\u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e, \u0434\u043b\u044f \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432) &#8212;\u00a0<code>python <\/code><a href=\"http:\/\/manage.py\" rel=\"noopener noreferrer nofollow\"><code>manage.py<\/code><\/a><code> sqlmigrate &lt;app&gt; &lt;migration&gt;<\/code>\u00a0\u0432 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 CI: \u0440\u0435\u0432\u044c\u044e\u0432\u0435\u0440\u0430\u043c \u0443\u0434\u043e\u0431\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0443\u0432\u0438\u0434\u0435\u0442\u044c SQL \u0431\u0435\u0437 \u043f\u043e\u0434\u043d\u044f\u0442\u0438\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ol>\n<h3>\u0427\u0435\u043a-\u043b\u0438\u0441\u0442 \u043f\u0435\u0440\u0435\u0434 \u043d\u0430\u043a\u0430\u0442\u043e\u043c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u0440\u043e\u0434<\/h3>\n<p>\u0411\u0443\u043c\u0430\u0436\u043a\u0430 \u043d\u0430\u0434 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u043e\u043c. \u041f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u043e\u0439 production-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0435\u0439:<\/p>\n<ol start=\"19\">\n<li>\n<p><strong>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u00a0<\/strong><code><strong>sqlmigrate<\/strong><\/code>, \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043b SQL \u0433\u043b\u0430\u0437\u0430\u043c\u0438. \u041d\u0435 \u0441\u043c\u043e\u0433 \u043f\u043e\u043d\u044f\u0442\u044c \u0433\u043b\u0430\u0437\u0430\u043c\u0438 &#8212; \u043f\u0440\u043e\u0433\u043d\u0430\u043b \u043d\u0435\u0439\u0440\u043e\u043d\u043a\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u043d\u0438\u043c\u0430\u044e<\/strong>, \u043a\u0430\u043a\u0443\u044e \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443 \u0432\u043e\u0437\u044c\u043c\u0451\u0442 PostgreSQL \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u0415\u0441\u043b\u0438 ACCESS EXCLUSIVE \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435<\/strong>\u00a0&#8212; \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0430 \u043d\u0430 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0435 \u0448\u0430\u0433\u0438 (NOT VALID + VALIDATE, CONCURRENTLY, expand\/contract).<\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u043e\u043b\u0433\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438<\/strong>\u00a0\u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0441\u00a0<code>atomic = False<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>\u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0441\u043e\u043c\u043d\u0435\u043d\u0438\u044f &#8212; \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u043d\u0430\u0434<\/strong>\u00a0<code>lock_timeout<\/code>\u00a0\u0438\u00a0<code>statement_timeout<\/code><\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b<\/strong>: \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043d\u043e\u0432\u043e\u0439 \u0441\u0445\u0435\u043c\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u0415\u0441\u0442\u044c \u043f\u043b\u0430\u043d \u043e\u0442\u043a\u0430\u0442\u0430<\/strong>: \u0435\u0441\u043b\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0441\u043b\u043e\u043c\u0430\u043b\u0430 \u043f\u0440\u043e\u0434, \u0447\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c? (\u041e\u0442\u043a\u0430\u0442\u0438\u0442\u044c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e? \u041e\u0442\u043a\u0430\u0442\u0438\u0442\u044c \u043a\u043e\u0434? \u0418 \u0442\u043e \u0438 \u0434\u0440\u0443\u0433\u043e\u0435?)<\/p>\n<\/li>\n<li>\n<p><strong>\u0415\u0441\u0442\u044c \u0431\u044d\u043a\u0430\u043f<\/strong>\u00a0\u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0411\u0414, \u0438\u043b\u0438 \u044d\u0442\u043e slave \u0441 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u043c lag.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0430 staging<\/strong>\u00a0\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0433\u043d\u0430\u043b\u0430\u0441\u044c \u043f\u0440\u043e\u0442\u0438\u0432 \u0434\u0430\u043c\u043f\u0430 prod-\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u0438\u0445 \u043e\u0431\u044a\u0451\u043c\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0440\u0435\u043c\u044f \u043d\u0430\u043a\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f<\/strong>\u00a0&#8212; \u043d\u0435 \u043f\u044f\u0442\u043d\u0438\u0446\u0430 \u0432\u0435\u0447\u0435\u0440. \u041d\u0435 &#171;\u0432\u043e\u0442 \u0441\u0435\u0439\u0447\u0430\u0441 \u0440\u0435\u043b\u0438\u0437, \u0438 \u0441\u0440\u0430\u0437\u0443 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0432 \u043f\u0438\u043a\u043e\u0432\u044b\u0439 \u0442\u0440\u0430\u0444\u0438\u043a&#187;.<\/p>\n<\/li>\n<\/ol>\n<p>\u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u044c \u043e\u0434\u0438\u043d \u043f\u0443\u043d\u043a\u0442 \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0442 &#8212; \u043b\u0443\u0447\u0448\u0435 \u043f\u0435\u0440\u0435\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430\u043a\u0430\u0442 \u0438\u043b\u0438 \u043f\u043e\u043c\u043e\u043b\u0438\u0442\u044c\u0441\u044f.<\/p>\n<h3>\u042d\u043a\u0441\u0442\u0440\u0430<\/h3>\n<p>\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0432\u043f\u0438\u0441\u0430\u043b\u0438\u0441\u044c \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435, \u043d\u043e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u0441\u0442\u0440\u0435\u043b\u044f\u044e\u0442:<\/p>\n<ul>\n<li>\n<p><strong>FK \u0441 CASCADE<\/strong>.\u00a0<code>ON DELETE CASCADE<\/code>\u00a0\u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442. \u041d\u043e\u00a0<code>DELETE<\/code>\u00a0\u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0431\u0435\u0440\u0451\u0442 ROW EXCLUSIVE \u043d\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 &#8212; \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445 \u044d\u0442\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e.\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u00a0<code>choices<\/code>\u00a0\u0432 Django \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a\u00a0<code>AlterField<\/code>\u00a0\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0441\u0445\u0435\u043c\u0430 \u0411\u0414 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f. \u041d\u0430 PostgreSQL \u043b\u0438\u0448\u043d\u0438\u0435\u00a0<code>ALTER TABLE<\/code>\u00a0\u043c\u043e\u0433\u0443\u0442 \u0431\u0440\u0430\u0442\u044c \u0441\u0438\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u0447\u0430\u0441\u0442\u043e \u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0445\u0441\u044f choices \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c callable choices (Django 5.0+) \u043b\u0438\u0431\u043e state-only \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437\u00a0<code>SeparateDatabaseAndState<\/code>.<\/p>\n<\/li>\n<li>\n<p><code><strong>max_length<\/strong><\/code><strong>\u00a0\u0434\u043b\u044f varchar<\/strong>. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e. \u0421\u0443\u0436\u0435\u043d\u0438\u0435 &#8212; REWRITE.\u00a0<\/p>\n<\/li>\n<li>\n<p><code><strong>AlterField<\/strong><\/code><strong>\u00a0\u0434\u043b\u044f\u00a0<\/strong><code><strong>default<\/strong><\/code>. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u00a0<code>default=...<\/code>\u00a0\u0432 Python-\u043a\u043e\u0434\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044e default \u0432 \u0411\u0414 &#8212; Django \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 default \u043f\u0440\u0438 INSERT \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 Python. \u041d\u043e\u00a0<code>makemigrations<\/code>\u00a0\u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0442\u00a0<code>AlterField<\/code>. \u042d\u0442\u043e no-op \u0434\u043b\u044f \u0411\u0414, \u043d\u043e \u043b\u0438\u0448\u043d\u0438\u0439\u00a0<code>ALTER TABLE<\/code>\u00a0(\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u044b\u0439, \u043d\u043e ACCESS EXCLUSIVE).<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0435\u0439\u0441 \u0441\u00a0<\/strong><code><strong>migrate --fake<\/strong><\/code><strong>\u00a0\u043f\u043e\u0441\u043b\u0435 non-atomic \u043a\u0440\u0430\u0445\u0430<\/strong>. \u0415\u0441\u043b\u0438 \u0442\u044b \u0440\u0443\u043a\u0430\u043c\u0438 \u0434\u043e\u043a\u0430\u0442\u0438\u043b \u0447\u0430\u0441\u0442\u044c SQL, \u043f\u043e\u043c\u043d\u0438:\u00a0<code>--fake<\/code>\u00a0\u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u0432\u00a0<code>django_migrations<\/code>, \u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u044b \u0432\u0441\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. \u041e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0437\u0430 \u043a\u043e\u043d\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u044c &#8212; \u043d\u0430 \u0442\u0435\u0431\u0435. \u041b\u0443\u0447\u0448\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c checklist \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 PR: &#171;\u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b \u0440\u0443\u043a\u0430\u043c\u0438: ALTER TABLE X, CREATE INDEX Y; \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e migrate &#8212;fake&#187;.<\/p>\n<\/li>\n<li>\n<p><strong>Reverse data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439<\/strong>. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u0442\u0430\u0432\u0438\u043c\u00a0<code>reverse_code=migrations.RunPython.noop<\/code>\u00a0&#8212; \u043d\u0430 reverse \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442. \u042d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0431\u044d\u043a\u0444\u0438\u043b\u043b\u043e\u0432: \u0441\u043c\u044b\u0441\u043b\u0430 \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435\u0442. \u0414\u043b\u044f \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u044b\u0445 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 enum) &#8212; \u043f\u0438\u0448\u0438\u043c \u044f\u0432\u043d\u044b\u0439 reverse. \u041d\u0435 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u00a0<code>RunPython<\/code>\u00a0\u0431\u0435\u0437 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430: Django \u0432\u044b\u0434\u0430\u0441\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043e\u0442\u043a\u0430\u0442\u0438\u0442\u044c.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0413\u043b\u0430\u0432\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u043e\u0438\u0442 \u0443\u043d\u0435\u0441\u0442\u0438 \u0441 \u0441\u043e\u0431\u043e\u0439:<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u0435\u0440\u0435\u0434\u00a0<\/strong><code><strong>migrate<\/strong><\/code><strong>\u00a0&#8212;\u00a0<\/strong><code><strong>sqlmigrate<\/strong><\/code>. \u0412\u0441\u0435\u0433\u0434\u0430. \u041d\u0430 \u043b\u044e\u0431\u043e\u0439 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0432 \u043b\u044e\u0431\u043e\u0439 \u0432\u0435\u0442\u043a\u0435. \u042d\u0442\u043e \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e \u0438 \u0441\u043f\u0430\u0441\u0430\u0435\u0442 \u043e\u0442 90% \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>\u041c\u0430\u043b\u044b\u0435 \u0448\u0430\u0433\u0438, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438<\/strong>. \u0412 \u0438\u0434\u0435\u0430\u043b\u0435 \u043e\u0434\u043d\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f &#8212; \u043e\u0434\u043d\u0430 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f. NOT NULL &#8212; \u044d\u0442\u043e \u0447\u0435\u0442\u044b\u0440\u0435 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438, \u0430 \u043d\u0435 \u043e\u0434\u043d\u0430. \u0414\u0430, \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 \u0441\u0442\u0430\u043d\u0435\u0442 \u043c\u043d\u043e\u0433\u043e, \u043d\u043e \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u0432\u043e\u0448\u043d\u0443\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>Expand &#8212; Migrate &#8212; Contract<\/strong>. \u041b\u044e\u0431\u043e\u0435 \u0437\u043d\u0430\u0447\u0438\u043c\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0445\u0435\u043c\u044b &#8212; \u044d\u0442\u043e \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0442\u0440\u0438 \u0440\u0435\u043b\u0438\u0437\u0430. \u0421\u0442\u0430\u0440\u044b\u0439 \u0438 \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u0434 \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u043c\u0435\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043e\u0434\u043d\u043e\u0439 \u0438 \u0442\u043e\u0439 \u0436\u0435 \u0411\u0414.<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f Django &#8212; \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u044f \u0442\u043e\u0447\u043a\u0430, \u043d\u0435 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f<\/strong>. \u041d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445 \u0435\u0451 \u043d\u0430\u0434\u043e \u043f\u0440\u0430\u0432\u0438\u0442\u044c:\u00a0<code>SeparateDatabaseAndState<\/code>,\u00a0<code>AddIndexConcurrently<\/code>,\u00a0<code>AddConstraintNotValid<\/code>,\u00a0<code>atomic = False<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b-\u043c\u0438\u043d\u0438\u043c\u0443\u043c<\/strong>:\u00a0<code>sqlmigrate<\/code>\u00a0+ \u0442\u0435\u0441\u0442\u044b data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435\u00a0\u00a0<\/strong><code><strong>lock_timeout<\/strong><\/code><strong>\u00a0+\u00a0<\/strong><code><strong>statement_timeout<\/strong><\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u0430\u0442\u044f\u0442\u0441\u044f \u043f\u043e\u0434 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 &#8212; \u044d\u0442\u043e \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430, \u0430 \u043d\u0435 \u043e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430. \u0427\u0435\u043c \u0440\u0430\u043d\u044c\u0448\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043e\u0441\u043e\u0437\u043d\u0430\u0435\u0442 \u044d\u0442\u043e, \u0442\u0435\u043c \u043c\u0435\u043d\u044c\u0448\u0435 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442.<\/p>\n<p>\u0411\u0443\u0434\u0443 \u0440\u0430\u0434 \u0444\u0438\u0434\u0431\u0435\u043a\u0443 \u0438 \u043a\u0435\u0439\u0441\u0430\u043c \u0438\u0437 \u0432\u0430\u0448\u0435\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445. \u0410 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f\u043c \u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u043c \u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e, \u044f \u043c\u043e\u0433 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \ud83d\ude42<\/p>\n<h3>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h3>\n<p><strong>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f PostgreSQL<\/strong>:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.postgresql.org\/docs\/current\/explicit-locking.html\" rel=\"noopener noreferrer nofollow\">Explicit Locking<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.postgresql.org\/docs\/current\/sql-altertable.html\" rel=\"noopener noreferrer nofollow\">ALTER TABLE<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.postgresql.org\/docs\/current\/sql-createindex.html#SQL-CREATEINDEX-CONCURRENTLY\" rel=\"noopener noreferrer nofollow\">CREATE INDEX CONCURRENTLY<\/a><\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0430\u043a\u0435\u0442\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/wemake-services\/django-test-migrations\" rel=\"noopener noreferrer nofollow\">django-test-migrations<\/a><\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0421\u0442\u0430\u0442\u044c\u0438 \u043d\u0430 \u0442\u0435\u043c\u0443<\/strong>:<\/p>\n<ul>\n<li>\n<p>Vinta:\u00a0<a href=\"https:\/\/www.vintasoftware.com\/blog\/django-zero-downtime-guide\" rel=\"noopener noreferrer nofollow\">Django zero-downtime migrations guide<\/a><\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438 \u0441\u0435\u0440\u0438\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/idaproject\/articles\/861386\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 1: \u0413\u043e\u0442\u043e\u0432\u0438\u043c\u0441\u044f \u043a \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f\u043c \u0438 \u0438\u0437\u0431\u0435\u0433\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/idaproject\/articles\/865036\/\" rel=\"noopener noreferrer nofollow\">\u0427\u0430\u0441\u0442\u044c 2: \u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u043e\u0432\u0435\u0442\u044b \u0438 \u043e\u0431\u0445\u043e\u0434 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0445 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u0435\u0439<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<p>\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\/1035830\/\">https:\/\/habr.com\/ru\/articles\/1035830\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041c\u0430\u043a\u0441, \u044f Lead Backend \u0438 \u0430\u0432\u0442\u043e\u0440 YouTube-\u043a\u0430\u043d\u0430\u043b\u0430\u00a0PyLounge.\u00a0\u042d\u0442\u043e \u0442\u0440\u0435\u0442\u044c\u044f \u0447\u0430\u0441\u0442\u044c \u043c\u0438\u043d\u0438-\u0441\u0435\u0440\u0438\u0438 \u043e Django-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f\u0445. \u0412\u00a0\u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438\u00a0\u043c\u044b \u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u043a \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f\u043c \u0438 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u043b\u0438\u0441\u044c \u0441 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0430\u043c\u0438, \u0432\u043e\u00a0\u0432\u0442\u043e\u0440\u043e\u0439\u00a0\u0447\u0438\u043d\u0438\u043b\u0438 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438. \u0415\u0441\u043b\u0438 \u0438\u0445 \u043d\u0435 \u0447\u0438\u0442\u0430\u043b\u0438, \u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043d\u0430\u0447\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0441 \u043d\u0438\u0445, \u0430 \u0437\u0430\u0442\u0435\u043c \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u0441\u044e\u0434\u0430.\u0412 \u044d\u0442\u043e\u043c \u0436\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0435 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e \u0441\u0430\u043c\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c: \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u043a\u043e\u0433\u0434\u0430\u00a0python manage.py migrate\u00a0\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 17:30 \u0432 \u043f\u044f\u0442\u043d\u0438\u0446\u0443 \u043d\u0430 \u043f\u0440\u043e\u0434\u0435, \u043f\u043e\u0434 3k RPS \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439 \u0432 200 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a.\u00a0\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043a\u0430\u043a\u0438\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0432 PostgreSQL \u0431\u0435\u0440\u0451\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f Django, \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438\u00a0atomic = False, \u043a\u0430\u043a \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u00a0expand &#8212; migrate &#8212; contract, \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u00a0AddIndexConcurrently,\u00a0AddConstraintNotValid,\u00a0SeparateDatabaseAndState\u00a0\u0438 \u043a\u0430\u043a \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445.P.S. \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u044b, \u0447\u0442\u043e\u0431\u044b \u0432\u043b\u0435\u0437\u043b\u0438 \u0432 \u0441\u0442\u0430\u0442\u044c\u044e \u0438 \u043d\u0435 \u0437\u0430\u0434\u0443\u0448\u0438\u043b\u0438. \u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0436\u0438\u0437\u043d\u0438 \u0432\u0441\u0451 \u0435\u0449\u0451 \u0445\u0443\u0436\u0435 &#8212; \u043d\u043e \u0448\u0430\u0433\u0438 \u0442\u0435 \u0436\u0435.P.S.S. \u041f\u0440\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043d\u0438 \u043e\u0434\u043d\u0430 \u043f\u0440\u043e\u0434\u043e\u0432\u0430\u044f \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043f\u043e\u0441\u0442\u0440\u0430\u0434\u0430\u043b\u0430.\u00a0\u041f\u043e\u0447\u0435\u043c\u0443\u00a0migrate\u00a0\u0432 \u043f\u0440\u043e\u0434\u0435 \u044d\u0442\u043e \u043d\u0435 &#171;\u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430&#187;\u0423 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u0441\u0442\u0443\u043b\u0430 \u0441\u043b\u043e\u044f, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043f\u0430\u0434\u0435\u043d\u0438\u044e \u043f\u0440\u043e\u0434\u0430:\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 SQL.\u00a0\u0418\u043d\u043e\u0433\u0434\u0430 \u043d\u0435 \u0442\u0430\u043a\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u044b \u043e\u0436\u0438\u0434\u0430\u043b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0AlterField(max_length=64)\u0434\u043b\u044f\u00a0CharField(max_length=32)\u00a0&#8212; \u044d\u0442\u043e\u00a0ALTER TABLE &#8230; ALTER COLUMN TYPE varchar(64), \u0438, \u0434\u0430, \u043d\u0430 PostgreSQL \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e.\u00a0\u0410 \u0432\u043e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044e \u0432\u0441\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b (table rewrite), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0text -&gt; integer,\u00a0varchar -&gt; numeric,\u00a0json -&gt; jsonb\u00a0\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0435\u0431\u0438\u043d\u0430\u0440\u043d\u043e-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.\u041f\u0440\u0438 \u044d\u0442\u043e\u043c\u00a0varchar(n) -&gt; text\u00a0\u0432 PostgreSQL rewrite \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 &#8212; \u044d\u0442\u043e binary-compatible \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0438 \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a metadata-only \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f.\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438. PostgreSQL \u043c\u043e\u0436\u0435\u0442 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0442\u0430\u043a, \u0447\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u0442 \u0434\u0430\u0436\u0435\u00a0SELECT. \u041e\u0447\u0435\u0440\u0435\u0434\u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0432 PostgreSQL &#8212; \u044d\u0442\u043e FIFO. \u0422\u043e \u0435\u0441\u0442\u044c \u0442\u0432\u043e\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0436\u0434\u0435\u0442 \u0434\u043e\u043b\u0433\u0443\u044e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e \u043f\u044f\u0442\u044c \u043c\u0438\u043d\u0443\u0442, \u0430 \u0437\u0430 \u043d\u0435\u0439 \u043c\u043e\u043b\u0447\u0430 \u0441\u0442\u043e\u044f\u0442 \u0435\u0449\u0451 200 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041d\u0438\u043a\u0442\u043e \u043d\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442. \u041f\u0440\u043e\u0434 R.I.P.Python-\u043a\u043e\u0434 \u0432\u00a0RunPython. \u041e\u043d \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u044f\u043c\u043e \u0432 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 (\u0435\u0441\u043b\u0438\u00a0atomic = True, \u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e) \u0438 \u0434\u0435\u0440\u0436\u0438\u0442 \u0435\u0451 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.\u00a0Developer.objects.all().update(&#8230;)\u00a0\u043d\u0430 50 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a &#8212; R.I.P.\u0418\u0437 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 (\u0432\u0441\u0435 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0438 \u0438 \u0447\u0438\u0441\u043b\u0430 \u0432\u044b\u0434\u0443\u043c\u0430\u043d\u044b, \u044f \u0430\u043a\u0442\u0435\u0440, \u044d\u0442\u043e \u0432\u0441\u0435 \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430):\u041a\u0435\u0439\u0441 1. \u0421\u043b\u0430\u0432\u0438\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043f\u043e\u043b\u0435\u00a0is_archived =models.BooleanField(default=False)\u00a0\u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441 80 000 000 \u0441\u0442\u0440\u043e\u043a \u043d\u0430 PostgreSQL 13. \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u0437\u0430 14 \u043c\u0438\u043d\u0443\u0442. \u0412\u0441\u0451 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0431\u044b\u043b\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c. \u041f\u0440\u043e\u0434 \u043b\u0435\u0436\u0430\u043b, \u0432\u0435\u0441\u044c \u0430\u0432\u0442\u043e\u0431\u0443\u0441 \u043f\u043b\u0430\u043a\u0430\u043b.\u00a0\u041a\u0435\u0439\u0441 2. \u0412\u043b\u0430\u0434\u0438\u0441\u043b\u0430\u0432 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u00a0models.Index(fields=[&#8216;created_at&#8217;])\u00a0\u0432\u00a0Meta\u00a0\u043c\u043e\u0434\u0435\u043b\u0438\u00a0Order.\u00a0\u00a0CREATE INDEX\u00a0\u0431\u0435\u0437\u00a0CONCURRENTLY\u0432\u0437\u044f\u043b\u00a0SHARE\u00a0\u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 &#8212; \u0432\u0441\u0435 \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0437\u0430\u043a\u0430\u0437\u043e\u0432 \u0432\u0441\u0442\u0430\u043b\u0438 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430 \u0434\u0435\u0441\u044f\u0442\u044c \u043c\u0438\u043d\u0443\u0442.\u00a0\u041a\u0435\u0439\u0441 3. \u0412\u0430\u0441\u044f\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u043b data-\u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0431\u044d\u043a\u0444\u0438\u043b\u043b\u0430 \u043d\u0430 20M \u0441\u0442\u0440\u043e\u043a \u0447\u0435\u0440\u0435\u0437\u00a0Order.objects.filter(&#8230;).update(&#8230;). \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0431\u044b\u043b\u0430 \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u043e\u0439 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. \u041e\u0434\u0438\u043d \u0431\u043e\u043b\u044c\u0448\u043e\u0439\u00a0UPDATE\u00a0\u0441\u0433\u0435\u043d\u0435\u0440\u0438\u043b \u0433\u0438\u0433\u0430\u043d\u0442\u0441\u043a\u0438\u0439 WAL, \u0440\u0435\u043f\u043b\u0438\u043a\u0438 \u0437\u0430\u043b\u0430\u0433\u0430\u043b\u0438 &#8212; R.I.P \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445.\u0412\u0441\u0435 \u0442\u0440\u0438 \u0441\u043b\u0443\u0447\u0430\u044f \u043b\u0435\u0447\u0430\u0442\u0441\u044f \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e &#8212; \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u0442\u0432\u043e\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 PostgreSQL.\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u0442\u0435\u043e\u0440\u0438\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0432 PostgreSQLPostgreSQL \u0438\u043c\u0435\u0435\u0442 8 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a. \u0417\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e &#8212; \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c\u00a0&#171;\u043b\u0435\u0441\u0442\u043d\u0438\u0446\u0443&#187;: \u0447\u0435\u043c \u0432\u044b\u0448\u0435 \u0443\u0440\u043e\u0432\u0435\u043d\u044c, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043e\u043d \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442. \u0423\u0440\u043e\u0432\u043d\u0438 \u0432 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 (\u043e\u0442 \u0441\u043b\u0430\u0431\u043e\u0433\u043e \u043a \u0441\u0438\u043b\u044c\u043d\u043e\u043c\u0443):1. ACCESS SHARE\u00a0&#8212; \u0431\u0435\u0440\u0435\u0442\u00a0SELECT. \u0421\u0430\u043c\u0430\u044f \u0441\u043b\u0430\u0431\u0430\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430: \u043e\u0431\u044b\u0447\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u0438 \u043d\u0438\u043a\u043e\u043c\u0443 \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u0438 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 ACCESS EXCLUSIVE.ROW SHARE\u00a0&#8212;\u00a0SELECT FOR UPDATE\/SHARE. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438; \u0447\u0443\u0442\u044c \u0441\u0442\u0440\u043e\u0436\u0435 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f.ROW EXCLUSIVE\u00a0&#8212;\u00a0INSERT,\u00a0UPDATE,\u00a0DELETE. \u042d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f DML-\u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430: \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e, \u043f\u043e\u043a\u0430 \u043d\u0435\u0442 \u00ab\u0442\u044f\u0436\u0451\u043b\u043e\u0433\u043e\u00bb DDL. \u0422\u043e \u0435\u0441\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435 DML-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u0435 \u043c\u0435\u0448\u0430\u044e\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443, \u043d\u043e \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043c\u043e\u0433\u0443\u0442 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u043b\u0438 \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 (REINDEX,\u00a0ALTER TABLE &#8230; TYPE,\u00a0ALTER TABLE &#8230; ADD COLUMN\u00a0\u0438 \u0442.\u0434.).SHARE UPDATE EXCLUSIVE\u00a0&#8212;\u00a0VACUUM\u00a0(\u0431\u0435\u0437 FULL),\u00a0ANALYZE,\u00a0CREATE INDEX CONCURRENTLY,\u00a0ALTER TABLE VALIDATE CONSTRAINT,\u00a0REINDEX CONCURRENTLY. \u041d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u0440\u0438\u0430\u043b\u0442\u0430\u0439\u043c-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u044f: \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u043c\u0435\u043d\u044f\u0442\u044c.SHARE\u00a0&#8212;\u00a0CREATE INDEX\u00a0(\u0431\u0435\u0437 CONCURRENTLY). \u0420\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \u0447\u0442\u0435\u043d\u0438\u0435, \u043d\u043e \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u00a0INSERT\/UPDATE\/DELETE, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u043c \u043a\u043e\u043d\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438.SHARE ROW EXCLUSIVE\u00a0&#8212;\u00a0CREATE TRIGGER, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435\u00a0ALTER TABLE. \u0411\u043e\u043b\u0435\u0435 \u0436\u0451\u0441\u0442\u043a\u0438\u0439 DDL-\u0440\u0435\u0436\u0438\u043c: PostgreSQL \u0437\u0430\u0449\u0438\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043e\u0442 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.EXCLUSIVE\u00a0&#8212;\u00a0REFRESH MATERIALIZED VIEW CONCURRENTLY. \u041f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u043d\u0430\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430: \u0447\u0438\u0442\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u043b\u044e\u0431\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u044b.ACCESS EXCLUSIVE &#8212;\u00a0DROP TABLE,\u00a0TRUNCATE, \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e\u00a0ALTER TABLE,\u00a0REINDEX. \u0421\u0430\u043c\u0430\u044f \u0441\u0438\u043b\u044c\u043d\u0430\u044f \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430: \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0451, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u0439\u00a0SELECT.\u0414\u043b\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439 \u043d\u0430\u0441 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0432\u043e\u043b\u043d\u0443\u0435\u0442 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443\u00a0CONCURRENTLY-\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c\u0438\u00a0(SHARE UPDATE EXCLUSIVE &#8212; \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e \u0441 DML) \u0438 \u043e\u0431\u044b\u0447\u043d\u044b\u043c\u0438 DDL (SHARE \/ ACCESS EXCLUSIVE &#8212; \u041d\u0415 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e \u0441 DML).\u0412\u0435\u043b\u0438\u043a\u0438\u0439 \u0438 \u0443\u0436\u0430\u0441\u043d\u044b\u0439 &#8212; ACCESS EXCLUSIVE\u042d\u0442\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u0431\u0435\u0440\u0435\u0442\u0441\u044f:ALTER TABLE &#8230; ADD COLUMN\u00a0(\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e).ALTER TABLE &#8230; DROP COLUMN.ALTER TABLE &#8230; ALTER COLUMN TYPE\u00a0(\u0434\u0430\u0436\u0435 \u0431\u0435\u0437\u00a0REWRITE).ALTER TABLE &#8230; ADD CONSTRAINT\u00a0(\u0431\u0435\u0437\u00a0NOT VALID).CREATE INDEX\u00a0(\u0431\u0435\u0437\u00a0CONCURRENTLY) &#8212; \u0431\u0435\u0440\u0451\u0442 SHARE, \u0447\u0442\u043e \u043d\u0435\u00a0\u043f\u043e\u043b\u043d\u044b\u0439\u00a0ACCESS EXCLUSIVE, \u043d\u043e \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 write.DROP INDEX\u00a0(\u0431\u0435\u0437\u00a0CONCURRENTLY).ALTER TABLE &#8230; RENAME.DROP TABLE,\u00a0TRUNCATE,\u00a0CLUSTER,\u00a0VACUUM FULL.ACCESS EXCLUSIVE \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u0435\u043d,\u00a0\u0435\u0441\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438\u043b\u0438 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u043e\u043a. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,\u00a0ADD COLUMN\u00a0\u0431\u0435\u0437 default &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u00a0pg_attribute, \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u041d\u043e \u0434\u0430\u0436\u0435 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u0430\u044f ACCESS EXCLUSIVE \u043c\u043e\u0436\u0435\u0442 \u0443\u0440\u043e\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0434 \u0438\u0437-\u0437\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a.\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u043e\u043d\u0430 \u043e\u043f\u0430\u0441\u043d\u0430PostgreSQL \u0441\u0442\u0430\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u0438\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438\u00a0\u0436\u0434\u0443\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0434\u043e\u043b\u0433\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438\u00a0ALTER TABLE\u00a0\u0443\u0436\u0435 \u0436\u0434\u0451\u0442\u00a0ACCESS EXCLUSIVE, \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 lock&#8217;\u0430\u043c\u0438, \u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u0447\u0430\u0442\u044c \u0432\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430 \u043d\u0438\u043c.\u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a &#8212; \u043e\u0434\u043d\u0430 \u043e\u0436\u0438\u0434\u0430\u044e\u0449\u0430\u044f DDL-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0442\u043e\u0440\u043c\u043e\u0437\u0438\u0442\u044c \u0432\u0435\u0441\u044c \u043f\u043e\u0442\u043e\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0442\u0430\u0431\u043b\u0438\u0446\u0435.\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439:T0: \u0410\u043d\u0430\u043b\u0438\u0442\u0438\u043a \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b SELECT pg_dump \u0442\u0430\u0431\u043b\u0438\u0446\u044b users \u2192 \u0431\u0435\u0440\u0451\u0442 ACCESS SHARE \u043d\u0430 5 \u043c\u0438\u043d\u0443\u0442.T1: \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f ALTER TABLE users ADD COLUMN foo    -&gt; \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u0437\u044f\u0442\u044c ACCESS EXCLUSIVE -&gt; \u0436\u0434\u0451\u0442.T2: \u041f\u0440\u0438\u0448\u0451\u043b API-\u0437\u0430\u043f\u0440\u043e\u0441: SELECT * FROM users WHERE id = 42    -&gt; \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u0437\u044f\u0442\u044c ACCESS SHARE -&gt; \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0443 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430,       \u041d\u041e \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0416\u0414\u0401\u0422 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f -&gt; \u0432\u0441\u0442\u0430\u0451\u0442 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c.T3: \u0415\u0449\u0451 200 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 -&gt; \u0432\u0441\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438.T4: \u0410\u043d\u0430\u043b\u0438\u0442\u0438\u043a \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b.T5: \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u0437\u0430 5 \u043c\u0441.T6: \u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0440\u0430\u0441\u0441\u0430\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f.\u041c\u0435\u0436\u0434\u0443 T1 \u0438 T5 \u043f\u0440\u043e\u0448\u043b\u043e 5 \u043c\u0438\u043d\u0443\u0442 \u043f\u043e\u043b\u043d\u043e\u0439 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u0437\u0430 5 \u043c\u0441.\u041b\u0435\u0447\u0435\u043d\u0438\u0435 &#8212;\u00a0lock_timeout. \u042d\u0442\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PostgreSQL, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u00a0&#171;\u0435\u0441\u043b\u0438 \u043d\u0435 \u043c\u043e\u0433\u0443 \u0432\u0437\u044f\u0442\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443 \u0437\u0430 N \u0441\u0435\u043a\u0443\u043d\u0434 &#8212; \u0443\u043f\u0430\u0434\u0438&#187;. \u041b\u0443\u0447\u0448\u0435 \u0443\u043f\u0430\u0441\u0442\u044c \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430 \u0447\u0435\u0440\u0435\u0437 \u043c\u0438\u043d\u0443\u0442\u0443, \u0447\u0435\u043c \u0441\u0442\u043e\u044f\u0442\u044c \u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0434:# 0042_safe_alter.pyfrom django.db import migrationsclass Migration(migrations.Migration):    atomic = False    dependencies = [&#8230;]    operations = [        migrations.RunSQL(            sql=&#187;SET lock_timeout = &#8216;3s&#8217;; SET statement_timeout = &#8216;5min&#8217;;&#187;,            reverse_sql=migrations.RunSQL.noop,        ),        # &#8230; \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438    ]lock_timeout\u00a0\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u0435\u0441\u0441\u0438\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0442\u0440\u043e\u043a\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c\u00a0\u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u043e\u0439 \u0436\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438\/\u0441\u0435\u0441\u0441\u0438\u0438, \u0447\u0442\u043e \u0438 \u043e\u043f\u0430\u0441\u043d\u044b\u0439 ALTER.\u00a0\u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f timeout&#8217;\u043e\u0432 \u0441\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442\u00a0\u0432\u0430\u0448\u0435\u0439 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438.\u0414\u043b\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c 3 \u0441. \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0430\u0433\u0440\u0435\u0441\u0441\u0438\u0432\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0438 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u043c \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0430\u043c.Timeout&#8217;\u044b \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0434\u0431\u0438\u0440\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437:\u0441\u0440\u0435\u0434\u043d\u0435\u0439 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439;\u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438;maintenance window;replication lag;\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.statement_timeout\u00a0&#8212; \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0439 \u043f\u0440\u0435\u0434\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435\u043b\u044c &#8212;\u00a0&#171;\u0435\u0441\u043b\u0438 \u0441\u0430\u043c SQL-\u0441\u0442\u0435\u0439\u0442\u043c\u0435\u043d\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u043b\u044c\u0448\u0435 N &#8212; \u0443\u043f\u0430\u0434\u0438&#187;.\u0412 PostgreSQL 17\u00a0\u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0443\u0440\u043e\u0432\u0435\u043d\u044c &#8212;\u00a0transaction_timeout. \u041e\u043d \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u0432\u0441\u0435\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430.migrations.RunSQL(    sql=(        &#171;SET lock_timeout = &#8216;3s&#8217;; &#187;        &#171;SET statement_timeout = &#8216;5min&#8217;; &#187;        &#171;SET transaction_timeout = &#8217;10min&#8217;;&#187;  # PG 17+    ),    reverse_sql=migrations.RunSQL.noop,),sqlmigrate\u00a0&#8212; \u0442\u0432\u043e\u0439 \u043b\u0443\u0447\u0448\u0438\u0439 \u0434\u0440\u0443\u0433 \u043f\u0435\u0440\u0435\u0434\u00a0migrate\u041f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u043d\u0430\u043a\u0430\u0442\u043e\u043c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u0440\u043e\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c:python manage.py sqlmigrate developers 0042\u0418 \u0447\u0438\u0442\u0430\u0435\u043c\u00a0\u0433\u043b\u0430\u0437\u0430\u043c\u0438. \u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 SQL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Django \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442,\u00a0\u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044f \u0435\u0433\u043e. \u042d\u0442\u043e \u043f\u0435\u0440\u0432\u0430\u044f \u0438 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430. \u041f\u043e \u043d\u0435\u043c\u0443 \u0442\u044b \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u0438\u0448\u044c:\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e;\u0435\u0441\u0442\u044c \u043b\u0438\u00a0ALTER TABLE &#8230; ALTER COLUMN TYPE\u00a0(\u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u00a0REWRITE);\u0435\u0441\u0442\u044c \u043b\u0438\u00a0CREATE INDEX\u00a0\u0431\u0435\u0437\u00a0CONCURRENTLY;\u0435\u0441\u0442\u044c \u043b\u0438\u00a0ADD CONSTRAINT\u00a0\u0431\u0435\u0437\u00a0NOT VALID;\u0437\u0430\u0432\u0435\u0440\u043d\u0435\u0442 \u043b\u0438 Django \u0432\u0441\u0435 \u0432\u00a0BEGIN &#8230; COMMIT\u00a0(\u0435\u0441\u043b\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044f \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u0430\u044f).\u041f\u0440\u0438\u043c\u0435\u0440\u00a0&#171;\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e&#187;\u00a0\u0432\u044b\u0432\u043e\u0434\u0430:BEGIN;&#8212;- Alter field rating on developer&#8212;ALTER TABLE &#171;developers_developer&#187; ALTER COLUMN &#171;rating&#187; TYPE numeric(10, 2)    USING &#171;rating&#187;::numeric(10, 2);COMMIT;ALTER COLUMN &#8230; TYPE &#8230; USING &#8230;\u00a0&#8212; \u044d\u0442\u043e REWRITE \u043d\u0430 \u0432\u0441\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043f\u043e\u0434 ACCESS EXCLUSIVE. \u041d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0432 50\u041c \u0441\u0442\u0440\u043e\u043a \u044d\u0442\u043e \u0447\u0430\u0441\u044b \u043f\u0440\u043e\u0441\u0442\u043e\u044f.\u041f\u0440\u0438\u043c\u0435\u0440\u00a0&#171;\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e&#187;:BEGIN;&#8212;- Add field nickname to developer&#8212;ALTER TABLE &#171;developers_developer&#187; ADD COLUMN &#171;nickname&#187; varchar(64) NULL;COMMIT;ACCESS EXCLUSIVE, \u043d\u043e \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u044b\u0439 (\u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435). \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c\u00a0lock_timeout.\u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0445 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\u0428\u043f\u0430\u0440\u0433\u0430\u043b\u043a\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e +-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f.\u00a0\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f DjangoSQL\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430\u0412\u0440\u0435\u043c\u044f\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430?CreateModelCREATE TABLE\u2014\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u2705DeleteModelDROP TABLEACCESS EXCLUSIVE\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u26a0\ufe0f \u043b\u043e\u043c\u0430\u0435\u0442 \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434AddField (nullable, \u0431\u0435\u0437 default)ADD COLUMN NULLACCESS EXCLUSIVE\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u2705AddField (NOT NULL + constant default)ADD COLUMN NOT NULL DEFAULT &#8216;x&#8217;ACCESS EXCLUSIVE\u043f\u043e\u0447\u0442\u0438 \u0431\u044b\u0441\u0442\u0440\u043e\u26a0\ufe0f, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u044e\u0430\u043d\u0441\u044b \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c\u0438AddField (NOT NULL + volatile default: uuid4, now())ADD COLUMN + UPDATE \u0441\u0442\u0440\u043e\u043aACCESS EXCLUSIVE\u0434\u043e\u043b\u0433\u043e\u274cAddField (FK)ADD COLUMN + ADD CONSTRAINT FKACCESS EXCLUSIVE + \u043f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0430\u043d\u0434\u043e\u043b\u0433\u043e\u26a0\ufe0fRemoveFieldDROP COLUMNACCESS EXCLUSIVE\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u26a0\ufe0f \u043b\u043e\u043c\u0430\u0435\u0442 \u0441\u0442\u0430\u0440\u044b\u0439 \u043a\u043e\u0434AlterField: \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 max_length \u0434\u043b\u044f varcharALTER COLUMN TYPEACCESS EXCLUSIVE, \u0431\u0435\u0437 REWRITE\u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u2705AlterField: \u0441\u0443\u0436\u0435\u043d\u0438\u0435 \/ \u0441\u043c\u0435\u043d\u0430 \u0442\u0438\u043f\u0430ALTER COLUMN TYPE \u0441&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-479931","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/479931","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=479931"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/479931\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=479931"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=479931"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=479931"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}