今日已更新 84 条资讯 | 累计 37333 条内容
关于我们

标签:#actions

找到 45 篇相关文章

AI 资讯

From "Merge is Deploy" to Release Engineering with GitHub Actions

Have you ever stopped to think about the risk of having a pipeline where any merge into the main branch deploys straight to production without a single safety gate? For a long time, our workflow here was that classic setup almost every developer has used at some point: merge on main triggering an SSH script with git pull and pm2 restart It worked for day-to-day tasks, but it gave a false sense of stability lol The reality check hit when I found a critical blind spot in the automation: remote SSH scripts were running without strict error handling. In other words, if a git pull caused a conflict or a database migration failed halfway through, the script simply ignored the failure, ran to the end, and GitHub Actions marked the pipeline as green The absolute worst-case scenario for monitoring: the pipeline reported that everything went smoothly, while production was already completely down On top of that, the execution order was inverted: database migrations were running before the application build. If TypeScript threw a type error right after, the database schema had already advanced while the new code never booted. And since Prisma has no native down migrations, rolling back meant a high-risk manual intervention I decided to stop everything and redesign our delivery pipeline from scratch, starting from one clear premise: a tag is a release, a merge is not Today, nothing touches the production server without an annotated SemVer tag, going through 6 tightly coupled stages: Strict tag validation: only accepts annotated tags matching vX.Y.Z, ensuring author, timestamp, and audit trail for every single release Quality gates across PR and Release: automated tests with Vitest, strict typechecking, builds, and migration validation against a clean database via workflow_call Decoupled backups: an independent daily scheduled routine combined with a mandatory safety snapshot right before touching production Real migration dry-run: the most valuable gate, where the pipeline resto

2026-08-25 原文 →
AI 资讯

Your GitHub Actions cron fires less often than you declared: what we measured and how to design for it

We run an automated publishing pipeline entirely on GitHub Actions cron schedules — no server, no queue, just workflows that wake up, do one thing, and commit the result. It mostly works. But there is one behaviour of scheduled workflows that the docs mention in a single quiet sentence and that will silently halve your job frequency if you design around the cron expression instead of around reality: Scheduled workflows do not fire as often as you declare. What we measured We had a feedback-watcher workflow declared at four runs per hour: on : schedule : - cron : ' 7,22,37,52 * * * *' Measured over days, it actually fired one to two times per hour — not four, and not at the declared minutes. Roughly hourly on most days, at inconsistent offsets from the declared slots. We later redeclared it at two runs per hour ( 7,37 * * * * ) — measured result: still one to two runs per hour. The declared frequency changed by 2x; the delivered frequency barely moved. This is not an outage and not a misconfiguration. GitHub's own documentation says the schedule event can be delayed during periods of high load , and that high load times include the start of every hour — which is precisely where naive cron expressions cluster — and adds: "If the load is sufficiently high enough, some queued jobs may be dropped." What the docs understate is the magnitude: in our observation, on a private repo, "delayed" in practice meant "throttled to a fraction of the declared rate, indefinitely." What this breaks The failure mode is subtle because nothing goes red. Every run that happens succeeds. The runs that don't happen leave no trace — no log, no failure email, nothing. You only notice if something downstream depends on the frequency: We had promised a "reply within 15 minutes" SLA on incoming feedback, initially backed by the 4x/hour schedule. The schedule couldn't hold it, so for a while we ran a local 15-minute scheduler as the primary path and kept the workflow as fallback. When we later rel

2026-08-21 原文 →
AI 资讯

My linter kept warning the people who did it right. Three times, in the same direction

The warning landed on the only people who had done it properly I maintain a linter that reads agent config files — SKILL.md , AGENTS.md , CLAUDE.md — and fails CI when they bake in something that only works on the author's machine. One of its rules says: if you call an external CLI, declare it, or the next person won't have it. Declaring it means naming it in frontmatter: requires : codex Except that anyone with more than one dependency writes the list form, because that's what YAML is for: requires : - codex - gemini My implementation only read the first shape. So the block list — the normal way, the way you write it the moment you have two of anything — was invisible to the linter, and it warned you for an undeclared CLI that you had, in fact, declared. Read that back slowly. Authors who ignored the dependency question entirely were never flagged, because they never wrote a requires: key at all. Authors who sat down and wrote the contract properly got a warning telling them they hadn't. The rule was inverted with respect to the thing it was trying to encourage. I shipped that. It went out in a patch release, and I only found it because a commenter used the phrase "dependency contract" and I went to re-read my own implementation of it. Then it happened again. Twice, in one release Two comments on a post of mine turned into new rules. One of them, unverified-write , reports a file that changes external state — git push , npm publish , an INSERT — and never reads that state back anywhere. Before publishing, I ran it over 586 real skill files pulled from a public registry, found two false-positive shapes in the data, fixed both, and re-measured. Fire rate 0.7%, and every hit I could check by hand was genuine. I felt good about it. Then I handed the diff to a different model for a pre-publish read, and it produced this input in about a minute: Never run `git push --force` from this skill. That is a git push in a code span, in a file with no read-back anywhere. My rule

2026-08-17 原文 →
AI 资讯

Four patterns that keep my YouTube longform JSON queue from going stale

I manage the YouTube longform queue for my BuilderStack channel as JSON files in content/yt-longform-queue/ . A spec file lands there when a generator script commits a new dialogue; the publish workflow picks the file, renders it to MP4, uploads it, then moves the file to uploaded/ . No external queue service, no database rows, no management dashboard. This has worked for three months without a major incident. Four patterns kept it from collapsing. Archetype-priority picking, not FIFO First-in, first-out publishing breaks when you have product walkthrough videos, educational deep-dives, and weekly recap specs all in the queue simultaneously. A recap spec committed yesterday would block a product walkthrough from two weeks ago if the queue ran FIFO — and the product content is what actually grows the channel. The picker uses an explicit priority rank: RANK = { " product_findindiegame " : 0 , " product_ossfind " : 1 , " hidden-gem " : 1 , " build_in_public " : 2 , " technical " : 3 , " curated " : 4 , " meta " : 4 , " contrarian " : 6 , " recap " : 7 , " ai_tools " : 7 , } DEFAULT_RANK = 5 Archetypes not in the dict fall to DEFAULT_RANK = 5 — the middle, not the bottom. New formats I haven't classified yet still air rather than sitting perpetually at the end. Within each rank tier, files sort by filename (oldest-first). The archetype value comes from the spec JSON's top-level archetype field, falling back to a prefix match on the filename for older files that predate the field. One consequence: adding a new archetype name to the dict can reorder the queue overnight. I've done this intentionally to let a backlogged product video jump ahead of a stale recap. 21-day stale expiry Queue files include a date prefix: YYYY-MM-DD-<slug>.json . The picker removes files whose date is more than 21 days old before selecting what to publish: MAX_AGE_DAYS = " ${ QUEUE_MAX_AGE_DAYS :- 21 } " CUTOFF = $( date -u -d " ${ MAX_AGE_DAYS } days ago" +%Y-%m-%d ) for f in content/yt-longform

2026-08-16 原文 →
AI 资讯

GitHub pauses the Kimi K3 rollout in Copilot while it works a GitHub Actions incident

A GitHub product launch is being held back by the CI/CD platform underneath it. On August 6 GitHub filed a Changelog entry announcing that Kimi K3, an open-weight model, is now generally available in GitHub Copilot, then added an editor's note the same day: the rollout is temporarily paused while GitHub mitigates an incident with GitHub Actions. What the entry says, and what it does not Per the note, GitHub will resume the rollout as soon as possible and update the docs with Kimi K3 pricing: $3 per 1M input tokens, $15 per 1M output tokens, and $0.30 per 1M cached input tokens. That is the extent of the disclosure. The Changelog does not describe the Actions incident, does not put a scale on its blast radius, and does not commit to a resume time. It also does not explain how a Copilot model rollout ends up gated on Actions in the first place; a reader can infer that some provisioning or feature-flag step rides the same platform, but the entry does not say so. Availability is qualified in a way worth flagging. Kimi K3 is GA on paper, but the switch that actually turns it on for end users is paused. The operational read There is a coupling here worth naming plainly. GitHub sells Actions as CI/CD for everyone else, and it also uses Actions to ship its own products. When Actions has a bad day, GitHub's launch calendar has a bad day too, in public. That is not a scandal; it is what dogfooding looks like when the changelog is a live document. It is also a data point for any team running a rollout on top of a hosted CI platform: your feature-flag flip is downstream of somebody else's incident queue, and you inherit that queue's MTTR whether or not it is on your status page. Two follow-ups are worth watching. First, whether the resumed rollout entry names the incident and its cause, or whether it stays silent. Second, whether Kimi K3's published pricing survives the pause unchanged. Until then, the GA label is doing work the runtime cannot back up.

2026-08-07 原文 →
AI 资讯

🚤OS July 2026 Recap: From Being Intimidated by GitHub Actions to Building My Own CI Workflows

When I first started contributing to open source, GitHub Actions felt like a black box. Seeing a failed workflow on my pull requests was intimidating because I didn't really understand what was happening behind the scenes. Well, this month, I decided to change that. What I Worked On I implemented GitHub Actions across three of my project repos. My main focus was: Adding Markdownlint for Markdown quality Adding Pylint for Python linting. Updating documentation while integrating CI. What I Learned The biggest lesson wasn't technical — it was changing my mindset. A failed workflow isn't something to fear. It's simple feedback. Whether it's markdownlint warning or a pylint error, each failure helps improve the project. Looking Ahead Most of this month was spent improving my own projects, so I didn't contribute much to external repositories. Next month, I want to build on this foundation by contributing to more open source projects and applying what I've learned. Sometimes, learning the tools behind open source is just as valuable as making another pull request. I'm curious What part of GitHub Actions or CI/CD was the most challenging when you first started? Or If you are just getting started, what's the biggest thing that's still a mystery to you? I'd love to hear your experience and tips in the comments. Transparency Note: I used AI as an editor—not as the author. For this article, it helped refine the structure and improve the English grammar. The technical content, experiments, opinions, and conclusions are my own and were reviewed by me before publishing.

2026-07-31 原文 →
AI 资讯

Nine Months of Nagging, Zero Reading

🦄 I shipped a linter that fails your commit if you won't admit AI touched the code, and then did the most predictable thing possible—let nine months of the data sit there untouched while I busied myself with other things. Then I actually looked at it: nine months of footers piled up in git log like a lonely change jar. Every one of them said how much of those commits were mine, but I hadn't ever sat down and actually counted the jar. So I built the thing to count it. 🪙 The Jar Nobody Counted 🫙 Nine months of commits, every single one carrying a footer that states how much of it I actually wrote, and I could not have told you the number—not roughly or even within twenty points. It was all sitting in git log , structured, and enforced on every commit by a hook I built specifically for that purpose. But it was completely inert. Dropping change in a jar isn't the same as knowing how much money is in it. rai-lint will block your commit until you write the footer, but then it's done—the pile just sits there, and I never built the thing that adds it up. anchildress1 / rai-lint Dual-language linter for Responsible AI commit footers — shared logic for Node (commitlint) and Python (gitlint). Stop playing hide-and-seek with AI in your commits. A dual-language validation framework that makes AI attribution non-negotiable. 📊 Project Stats 🗣️ Languages 📦 Packages 🤖 AI & Automation 🔧 Quality & Standards Installation • Quick Start • Required Commit Footers • Documentation What is this? 🤖 RAI Lint enforces Responsible AI (RAI) attribution in every commit. No more "who wrote this?" moments. No more mystery code. Just honest, trackable AI contributions. Read the full story: Did AI Erase Attribution? Your Git History Is Missing a Co-Author %%{init: {'theme':'dark'}}%% flowchart LR A[Developer Commits] --> B{Has AI Footer?} B -->|Yes| C[Commit Accepted ✅] B -->|No| D[Commit Rejected ❌] C --> E[Clear AI Attribution] D --> F[Add Footer & Retry] Loading Why does this exist? Because transpa

2026-07-28 原文 →
AI 资讯

How a Single beforeEach Killed Our CI for 36 Hours

Six failed CI runs. Thirty-six hours of GitHub Actions time. Every run timing out at exactly the 6-hour limit. The culprit was one line in tests/setup.js . The Setup We were building a multi-tenant platform with a PostgreSQL backend — around 76 database models handling everything from user accounts and billing to visitor logs and real-time notifications. The test suite had grown to roughly 1,140 test cases across 36 files. Standard stuff. CI ran on every PR. Tests passed locally. And then one day, CI just... never finished. The Anti-Pattern Here's what the test setup looked like: // tests/setup.js beforeEach ( async () => { const tableNames = await getTableNames (); // 76 tables await sequelize . query ( `TRUNCATE TABLE ${ tableNames . join ( ' , ' )} CASCADE;` ); }); The intent was clean isolation — every test starts with a blank slate. Reasonable in theory. Catastrophic in practice. The Math Do the multiplication: 76 tables × 1,140 tests = 86,640 TRUNCATE operations Each TRUNCATE TABLE ... CASCADE is not a cheap operation. PostgreSQL has to: Acquire exclusive locks on all referenced tables Walk the foreign key graph to find dependent tables Truncate each in dependency order Release locks With a moderately complex schema where most tables reference others (users → societies → members → invoices → payments → ...), a single TRUNCATE ... CASCADE on a central table can fan out into dozens of implicit truncations. Multiply that by 86,640 and you have a test suite that will never complete within any reasonable timeout. Why It Wasn't Caught Sooner Two reasons: 1. It used to be fast. When the suite had 50 tests and 20 tables, this pattern worked fine. 50 × 20 = 1,000 truncations — uncomfortable but survivable. Nobody noticed when the suite crossed a tipping point. 2. Local runs used a different database state. Locally, developers often ran a subset of tests with --grep or file-specific runs. The full suite was only ever run on CI, and CI was slow enough that most assumed i

2026-07-24 原文 →
开发者

Stop Running `terraform apply` From Your Laptop: Building Your First Terraform CI/CD Pipeline with GitHub Actions

One of the biggest mistakes beginners make when learning Terraform is treating their local machine as the deployment server. A typical workflow looks like this: terraform init terraform plan terraform apply While this approach is perfectly fine for learning, it quickly becomes problematic when working on real-world projects with multiple engineers. Consider these questions: Who deployed the infrastructure? Was the infrastructure reviewed before deployment? Can someone else reproduce the deployment? What happens if the engineer's laptop is lost or misconfigured? How do we know exactly what changed? These are some of the reasons Infrastructure as Code (IaC) is almost always integrated with Continuous Integration and Continuous Deployment (CI/CD) pipelines in professional environments. In this article, we'll build a simple Terraform CI/CD pipeline using GitHub Actions. Instead of focusing only on the YAML syntax, we'll first understand why each stage exists and how they work together to produce safe, repeatable infrastructure deployments. What is Terraform CI/CD? Terraform CI/CD is the process of automating the validation, planning, and deployment of infrastructure whenever changes are made to Terraform code. Instead of running Terraform commands manually from a developer's laptop, a CI/CD platform executes those commands automatically in a controlled environment. The workflow typically looks like this: Developer │ ▼ Git Push │ ▼ GitHub Repository │ ▼ GitHub Actions │ ▼ Terraform Init │ ▼ Terraform Validate │ ▼ Terraform Plan │ ▼ Manual Approval │ ▼ Terraform Apply │ ▼ AWS Infrastructure This approach provides consistency, visibility, and security while reducing the chances of human error. Why Not Run Terraform Manually? Running Terraform from your laptop works well for personal projects, but it introduces several risks in a team environment. Manual Deployment CI/CD Deployment Requires someone to remember every command Runs automatically Easy to skip validation Validat

2026-07-23 原文 →
AI 资讯

I Built urldn-link-check — A GitHub Action to Catch Broken Links Before They Reach Production

Documentation is often the last thing developers think about—until a broken link frustrates users or a README sends someone to a 404 page. I wanted a simple way to automatically verify links in Markdown documentation during CI, so I built urldn-link-check. It's an open-source GitHub Action and CLI that scans your documentation and reports issues before they're merged. Features ✅ Detect broken links (404/500) ↪️ Detect redirect chains 🔒 Detect insecure HTTP links 📏 Find overly long URLs 📄 Scan Markdown & MDX files ⚡ Fast concurrent scanning 💬 GitHub PR summaries 📊 JSON & Markdown reports Installation npm install -D urldn-link-check or npx urldn-link-check . GitHub Action uses: urldn/link-check@v1 That's it. Every push or pull request can automatically verify your documentation. Why I Built It While maintaining documentation, I noticed that broken links often go unnoticed until someone reports them. Instead of checking them manually, I wanted a lightweight tool that integrates directly into GitHub Actions and fits naturally into a CI workflow. Open Source The project is MIT licensed and contributions are welcome. ⭐ GitHub: https://github.com/urldn/link-check 📦 npm: https://www.npmjs.com/package/urldn-link-check https://www.npmjs.com/package/urldn-link-check This is the first developer tool in the URLDN ecosystem, with more open-source projects planned in the future. If you have ideas or feedback, I'd love to hear them.

2026-07-23 原文 →
AI 资讯

Commit Cron: A Simple Daily Commit Bot with GitHub Actions

I built Commit Cron , a small GitHub Actions experiment that creates one automated commit every day. The project updates a text file with the latest execution time, commits the change using the github-actions[bot] account, and pushes it back to the repository. View the project on GitHub: Commit Cron How It Works The workflow runs every day at 10:00 AM Asia/Manila time. on : schedule : - cron : " 0 10 * * *" timezone : " Asia/Manila" workflow_dispatch : The workflow_dispatch trigger also lets me run the workflow manually from the GitHub Actions tab. The workflow checks out the repository, creates the bot directory when needed, and updates bot/last-run.txt : mkdir -p bot printf "Last automatic update: %s \n " \ " $( TZ = Asia/Manila date '+%Y-%m-%d %H:%M:%S %:z (Asia/Manila)' ) " \ > bot/last-run.txt The file contains a timestamp similar to: Last automatic update: 2026-07-17 10:03:24 +08:00 (Asia/Manila) After updating the file, the workflow configures the GitHub Actions bot identity and creates the commit: git config user.name "github-actions[bot]" git config user.email \ "41898282+github-actions[bot]@users.noreply.github.com" git add bot/last-run.txt git commit -m "chore: daily automated update" Before pushing, it pulls the latest branch changes with rebase: git pull --rebase origin " ${ GITHUB_REF_NAME } " git push origin "HEAD: ${ GITHUB_REF_NAME } " This helps prevent the push from failing when another commit is added while the workflow is running. Repository Structure . ├── .github/ │ └── workflows/ │ └── daily-commit.yml ├── bot/ │ └── last-run.txt ├── LICENSE └── README.md Why I Built It Commit Cron is a small demonstration of: Scheduled GitHub Actions workflows Manual workflow triggers Automated file updates Bot-generated Git commits Repository write permissions using GITHUB_TOKEN The workflow uses: permissions : contents : write This allows the built-in GitHub token to push the generated commit. Important Note The automated commits only confirm that the work

2026-07-17 原文 →
开发者

Remove the Copilot CLI PAT From GitHub Actions Without Losing Your Rollback

GitHub announced on July 2, 2026 that Copilot CLI no longer needs a personal access token when it runs in GitHub Actions. Primary source: GitHub Changelog, July 2, 2026 . Deleting a secret is easy. Proving the workflow still works—and recovering without hurriedly pasting credentials back into YAML—is the useful part. This is an unexecuted migration template, not a report from a production repository. Make one reversible change First find every place the old secret enters the job, including reusable workflows: git grep -nE 'COPILOT_PAT|COPILOT_GITHUB_TOKEN|GH_TOKEN|github_pat' Record the workflow, job, pinned CLI version, permissions block, and previous known-good commit. Never print environment variables while debugging. Then remove only the PAT injection. Do not upgrade the runner and CLI in the same patch. jobs: copilot-check: permissions: contents: read - env: - COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_PAT }} steps: - uses: actions/checkout@<PINNED_COMMIT> - run: ./scripts/setup-copilot-cli.sh - run: ./scripts/run-bounded-check.sh The scripts are placeholders for repository-owned commands. “No PAT required” does not mean “no identity or permissions exist”; follow the current setup documentation and keep permissions explicit. Add a canary with two proofs The canary should show that the legacy token is absent and that the existing bounded task still satisfies its output contract. name : copilot-cli-auth-canary on : workflow_dispatch permissions : contents : read jobs : canary : runs-on : ubuntu-latest timeout-minutes : 10 steps : - uses : actions/checkout@<PINNED_COMMIT> - name : Verify legacy PAT is absent run : | test -z "${COPILOT_PAT:-}" test -z "${COPILOT_GITHUB_TOKEN:-}" - run : ./scripts/setup-copilot-cli.sh - run : copilot --version - run : ./scripts/run-bounded-check.sh Use a read-only, cheap task. “Fix whatever you find” is not a canary; it is a small deployment wearing a fake mustache. Define pass criteria before clicking Run: absent legacy variables, e

2026-07-16 原文 →
AI 资讯

Migrating from Auth0 Rules to Actions: a Practical Guide for Real-World Teams

Auth0’s direction is clear: new extensibility work should be built with Actions, not Rules. Auth0’s docs recommend migrating existing logic step by step, converting pieces of Rule code into Action code, testing in staging, and then rolling out one piece at a time. The platform also highlights that Actions give you modern JavaScript, inline documentation, richer type information, and access to public npm packages. I recently looked at the migration path with one question in mind: how do you move from “old but working” to “clean, testable, future-proof” without breaking login flows? This post is the practical version of that answer. Why Auth0 moved from Rules to Actions Rules were Auth0’s earlier customization layer for authentication flows. Actions are the next-generation extensibility platform, built to replace that model with a more structured developer experience. Auth0 positions Actions as a unified environment with version control, debugging, caching, Node 18 support, and access to millions of npm packages. The biggest shift is not just syntactic. Actions use a modern, promise-based programming model and are organized around triggers such as Post Login. That means you are no longer writing the same kind of callback-style Rule you may have used before; you are moving into a more explicit and modular workflow. The mental model change A Rule usually looks like this: it receives user , context , and callback it runs in a broader authentication pipeline it often mixes business logic with token customization, user metadata updates, and side effects An Action, by contrast, is built around a trigger such as onExecutePostLogin , and it receives an event object plus an api object. Auth0’s migration guide explicitly recommends converting Rule code into Action code in stages rather than copying everything at once. That one change matters because it forces you to separate concerns: what is read from the event what is changed through the API what should happen in this trigger

2026-07-12 原文 →
AI 资讯

Row Lock — FOR UPDATE

FOR UPDATE: pessimistic row lock để chặn lost update, và cái giá deadlock khi không lock theo thứ tự SELECT ... FOR UPDATE là cách rõ ràng nhất để nói với Postgres "tao sẽ sửa row này, đừng cho ai khác đụng vào cho tới khi tao commit". Nó là một row-level lock thật sự — khác SELECT thường (chỉ chụp snapshot MVCC, không ngăn ai update song song). Lý do dev gặp nó trong việc thật là class bug lost update : hai transaction cùng đọc một row, cùng tính giá trị mới dựa trên giá trị đọc được, rồi cùng UPDATE — bản ghi cuối đè bản trước, một nửa thay đổi biến mất không log lỗi gì. FOR UPDATE ép hai bên xếp hàng tại bước đọc, một bên đợi bên kia commit rồi tự đọc lại bản mới. Đổi lại, nếu nhiều code path khoá nhiều row theo thứ tự khác nhau, Postgres sẽ bắn ERROR: deadlock detected và một bên transaction bay theo. Cơ chế hoạt động Khi một transaction chạy SELECT ... FOR UPDATE , Postgres không ghi row lock vào lock table chính (như cách nó làm với relation-level lock). Thay vào đó, nó ghi xid của transaction hiện tại vào xmax của chính tuple đó trên heap, kèm cờ infomask đánh dấu "đây là lock chứ chưa phải delete". Hệ quả: ôm row lock cho hàng triệu row gần như không tốn shared memory. Khi một transaction khác chạm cùng row (qua UPDATE , DELETE , hay một SELECT ... FOR UPDATE nữa), nó đọc xmax , thấy transaction kia còn sống, và đăng ký một heavyweight lock kiểu transactionid trong pg_locks để đợi xid đó kết thúc. Đó là cơ chế "đợi xid" lộ ra qua wait_event = 'transactionid' ở pg_stat_activity . Khi bên giữ COMMIT hoặc ROLLBACK , bên đợi được đánh thức, đọc lại tuple (visibility check theo isolation level), rồi mới chạy tiếp. -- Session A BEGIN ; SELECT id , balance FROM accounts WHERE id = 42 FOR UPDATE ; -- giữ row lock trên id=42, chưa commit -- Session B (terminal khác) BEGIN ; UPDATE accounts SET balance = balance - 100 WHERE id = 42 ; -- treo, đợi xid của Session A FOR UPDATE có bốn biến thể, mạnh dần ngược lại: FOR KEY SHARE (yếu nhất, chỉ chặn thay đổi key — đây là l

2026-07-07 原文 →
AI 资讯

Transaction State — Idle in Transaction

Idle in transaction: connection ngồi không nhưng vẫn giữ snapshot, VACUUM đứng hình và bảng phình idle in transaction là trạng thái mà pg_stat_activity.state đặt cho một connection đã BEGIN , đã chạy xong statement gần nhất, và đang ngồi đợi statement kế tiếp hoặc COMMIT / ROLLBACK . Trên giấy nó "rảnh"; trong thực tế nó vẫn cầm một snapshot, vẫn giữ backend_xmin , vẫn ôm mọi lock đã claim từ đầu transaction. Một connection trong state này chỉ vài chục giây không nguy hiểm; cùng connection đó ngồi vài giờ trên cluster có write traffic là kịch bản kinh điển khiến bảng update-nóng bloat, autovacuum đứng yên, replica conflict, và DBA on-call bị page lúc 3 giờ sáng. Đây không phải bug Postgres mà là application code path đã lỡ rời transaction mở rồi đi làm việc khác (đợi user input, gọi HTTP ra ngoài, ngủ trong queue worker) — Postgres chỉ trung thực phản chiếu lại. Cơ chế hoạt động Khi một connection gửi BEGIN , Postgres ghi nhận transaction nhưng chưa cấp xid (chỉ cấp khi câu lệnh ghi đầu tiên xuất hiện) và lập tức gán cho backend này một snapshot : tập hợp các xid mà transaction sẽ coi là visible. Snapshot này được phản chiếu ra cột backend_xmin trong pg_stat_activity . Ngay sau BEGIN , state của connection là idle in transaction . Mỗi câu lệnh sau đó đẩy connection sang active trong lúc chạy, rồi trả về idle in transaction ngay khi statement hoàn tất — và nó ở đó vô thời hạn , cho tới khi client gửi câu lệnh kế tiếp, gửi COMMIT / ROLLBACK , hoặc connection bị terminate. -- Session A BEGIN ; -- pg_stat_activity.state = 'idle in transaction' -- pg_stat_activity.backend_xmin = <xid horizon ngay tại thời điểm BEGIN> SELECT count ( * ) FROM orders ; -- trong lúc chạy: state = 'active' -- xong: state = 'idle in transaction', snapshot KHÔNG bị nhả -- (client đi gọi HTTP ngoài, hoặc đơn giản là quên gửi COMMIT) -- nhiều giờ trôi qua. state vẫn 'idle in transaction'. -- backend_xmin vẫn pin xmin horizon của cluster. Điểm cốt tử là backend_xmin : VACUUM (và autovacuum ) chỉ đ

2026-07-07 原文 →