Hỏi về thư viện backup database Postgresql cho Python

Chào cả nhà,
Mình đang cải thiện ứng dụng của mình, cụ thể là mình thêm tính năng sao lưu khôi phục database. Hiện tại mình đang dùng python call command pg_dump và pg_restore. Hiện mình làm ổn rồi, mọi chức năng đã chạy bình thường nhưng mình vẫn chưa thấy nó ok lắm. Cụ thể là máy người dùng phải cài postgresql để có thể sử dụng được pg_dump và pg_restore. Cực kỳ bất tiện nếu người dùng sử dụng database cloud.
Không biết có thư viện hay hướng nào xử lý hay hơn không nhờ mọi người góp ý.
Chân thành cảm ơn cả nhà.


Bổ sung thêm:
Xin lỗi cả nhà mình viết không rõ nên gây rối.
Ý mình đặt câu hỏi là mình đang đứng ở server nhé. Lúc này có vài trường trường hợp:

  • Họ sử dụng luôn docker image của mình, cái này mình cài sẵn database PostgresSql nên ok.
  • Họ lấy app của mình về dùng: lúc này do bên backend của mình là đang làm theo kiểu dùng python call command pg_dump và pg_restore nên nếu trên cái máy khách hàng làm server không cài postgresql thì tính năng này sẽ tèo. Mình đang nghĩ cho case mà người ta sài db cloud hoặc đơn giản hơn là start cái docker container postgresql thì cái tính năng này của mình cũng tèo.
    Mình thấy cài thêm thì cũng quan trọng lắm nhưng mà thấy cảm cài cả 1 cái bự để sài 2 cái nhỏ nghe nó “cấn cấn”

Bạn có thể mô ta về ngữ cảnh của tính năng này không? Database đang open ra internet? User có cả thông tin kết nối, thậm chí là có quyền restore? Là sử dụng nội bộ hay…

Cách thì có, và thậm chí là có thể giải quyết các vấn đề ở trên, tuy nhiên mình không rõ ngữ cảnh của cái “tính năng kì lạ” này, nên mình muốn xác nhận lại

5 Likes

Ứng dụng nếu sử dụng mô hình client - server thì luôn có một phần chạy trên server, một phần chạy trên client, 2 phần này có thể gần như 2 phần mềm riêng biệt nhưng có giao tiếp với nhau. Việc backup thực hiện ở phần chạy trên server, phần client chỉ gửi lệnh lên thôi, chứ làm gì có chuyện từ client mà đi thực hiện mấy việc kia để rồi phải cài công cụ dành cho quản trị vào client bao giờ?

Mình chưa làm Python nhưng ngày xưa triển khai phần mềm .NET thì thấy đa phần phần trên server cũng chạy các lệnh do cơ sở dữ liệu cung cấp, được viết đóng gói thành module của phần chạy trên server, khi người dùng ở client thực hiện thì đơn giản là nó gọi lên phần server thực hiện rồi thông báo về cho phần client kết quả. Phần client không có “quyền năng” để tác động trực tiếp vào database, bài này có bàn về vấn đề đó.

4 Likes

nếu db 1 người sử dụng thì xài sqlite cho khỏe.

5 Likes

Xin lỗi cả nhà mình viết không rõ nên gây rối.
Ý mình đặt câu hỏi là mình đang đứng ở server nhé. Lúc này có vài trường trường hợp:

  • Họ sử dụng luôn docker image của mình, cái này mình cài sẵn database PostgresSql nên ok.
  • Họ lấy app của mình về dùng: lúc này do bên backend của mình là đang làm theo kiểu dùng python call command pg_dump và pg_restore nên nếu trên cái máy khách hàng làm server không cài postgresql thì tính năng này sẽ tèo. Mình đang nghĩ cho case mà người ta sài db cloud hoặc đơn giản hơn là start cái docker container postgresql thì cái tính năng này của mình cũng tèo.

Mình thấy cài thêm thì cũng quan trọng lắm nhưng mà thấy cảm cài cả 1 cái bự để sài 2 cái nhỏ nghe nó “cấn cấn”

1 Like

Bây giờ bỏ qua chuyện kỹ thuật, bàn đến sau khi đã làm rõ: đối tượng khách hàng là như thế nào? Và bạn định làm:

  1. Phần mềm dạng đóng gói hoàn chỉnh: khách hàng đơn giản là cài đặt với các nút bấm Next để cài đặt là xong mọi thứ, bạn đóng gói tất cả những gì cần thiết để hoạt động ở mức tốt nhất theo ý đồ của bạn. Trên server không có GUI cũng làm được, dùng text-based giống như khi cài MySQL vậy.

  2. Phần mềm dạng phải có triển khai: khách hàng phải đọc tài liệu (và/ hoặc khoá đào tạo cho những ai muốn dùng phần mềm bên bạn) để làm theo, tức là phải có 1 người biết triển khai phần mềm làm hoặc dưới sự hỗ trợ của bạn thì mới hoàn chỉnh được.

  3. Phát hành dạng nguồn mở với tài liệu do cộng đồng đóng góp và chỉ bảo nhau, khách hàng muốn sử dụng hoàn hảo thì thuê dịch vụ đào tạo, triển khai, tuỳ chỉnh của bên bạn.

Vì không biết phần mềm bạn viết dạng Desktop Software hay Web App nên không thể nói rõ hơn vì nó có khác biệt chút ít. Tuy nhiên, cứ thử kiếm vài phần mềm nguồn mở giống giống của bạn, viết bằng Python càng tốt, hoặc bằng Java, PHP nếu là chạy trên nền web. Khi cài sẽ luôn có 2 phần: phần xử lý ở dòng lệnh gõ trên server trước, phần cài đặt trên giao diện web sau. Nếu viết được script chạy trên server có đối đáp cho phần cài bên server với các tuỳ chọn thì quá tốt, người cài sẽ có tuỳ chọn tự quyết định là có đóng gói cái pg_dump và pg_restore hay không lúc cài.

Không nên đứng ở tư duy của người làm kỹ thuật đơn thuần rồi lại nghĩ thay khách hàng - dễ dẫn đến “chân đi hai hàng”. Học hỏi cách làm quản lý tính tiền phòng game của VNG, thử tải cái đó về cài đặt và sử dụng như một khách hàng để hình dung một phần mềm có kèm CSDL trong thực tế là như thế nào.

Với khách hàng thì sử dụng được, yêu thích, chọn dùng hoặc sử dụng kém và từ bỏ. Họ không quan tâm kỹ thuật. Ngày trước mình đi triển khai, thấy kể cả mấy ông kỹ sư bên khách hàng cũng chẳng quan tâm phần mềm bên dưới có cái gì hết, miễn nó thân thiện, dễ sử dụng là được, ít các bước lằng ngoằng càng tốt. Cho nên lúc đó toàn viết batch (sau này là PowerShell) để làm các việc liên quan đến backup vì linh hoạt hơn là viết cứng code vô trong phần mềm <- vừa khó, vừa không linh hoạt bởi phần mềm hỗ trợ nhiều loại cơ sở dữ liệu/ phiên bản khác nhau. Khi nâng phiên bản cũng hiếm khi viết lại những file này vì test kỹ.

3 Likes

Cảm ơn bác đã nói kỹ như vậy. Mình xin phép trả lời câu hỏi của bác để cùng thảo luận:

  • Mình làm web app cụ thể là flask
  • App mình đang làm theo cả dạng 1 và 2 như bác nói, mình có phát hành docker image nên chỉ cần chạy là… xong, mình phát hành thêm source code để khách hàng có thể tự deploy trên hệ thống có sẵn của họ.

Mình làm api, requirement là làm api backup và cho phép download file backup database đó về, cùng với đó là 1 api cho phép upload file backup lên để restore.

Hiện tại cả 2 tính năng mình đều đã hoàn thành. Nhưng nó vướng vì mình dùng pg_dump và pg_restore nên thiếu nó cái tính năng này của ứng dụng của mình nó cũng tèo. Mình muốn cải thiện hơn để nó không bị phụ thuộc nữa.

Mình cũng đang hiểu vấn đề bạn đề cập, cực kỳ xúc tích và dễ hiểu. Mình cũng muốn nhấn mạnh vế “dễ dùng dễ sử dụng”, mình muốn cải thiện theo hướng đó thay vì viết cái doc cho khách hàng ngồi cài hay là cần sự hỗ trợ từ bất kỳ ai

Viết script cũng ok nhưng nó k nằm trong requirement của khách hàng, mình cũng đã đề cập rồi nhưng họ lắc đầu nên well, khách hàng là thượng đế.

1 Like

docker của bạn chứa những gì?
app python chạy trên docker hay trên máy thật?
database chạy trên docker hay trên máy thật?

theo như mô tả của bạn bây giờ, thì rất khác có với post #1 của bạn
#1 của bạn làm mình nghĩ user chạy pg dump để lấy được cục data, và lại chạy pg restore để restore lại
bài post sau của bạn thì pg dump đó là chạy trên server, user gọi api để remove cho python gọi

mình muốn biết là app flask này phục vụ cho 1 hay nhiều user?

3 Likes

Đúng rồi cái bài đầu mình ghi hơi rối nên mình mới update post sau. App cho nhiều người dùng. Người dùng call api backup, server chạy pg_dump để tạo bản sao lưu rồi trả file backup về cho người dùng.
Rất xin lỗi vì cách hành văn và mô tả vấn đề của mình.

vậy mô hình này là cài cho một server và nhiều người dùng dùng thông qua ui web
như vậy, máy dùng làm server cài các command của postgres thì cũng đâu có vấn đề gì đâu, bạn đã yêu cầu người dùng cài docker trên máy server đó thì postres có là gì nữa đâu

mà bạn chưa trả lời, docker dùng cho việc gì
nếu python và postgres chạy trong docker thì bạn cho docker đó cài sẵn pg dump & pg restore luôn

4 Likes

Cần phải hiểu: người dùng ở đây có tới 2 nhóm, và không nhập nhèm với nhau được.

Nhóm 1: người dùng chính là cái ông/ nhóm quản trị server ấy, và ông/ nhóm ấy phải cài được cái phần cơ sở dữ liệu PosgreSQL, Python, Flask lên lên server hoặc cái gọi là requirements mà phần mềm bạn đòi hỏi phải đáp ứng (ví dụ như mail server, hệ thống xác thực LDAP hay gì đó nếu không dùng login bằng web thông thường, PostScript để in ấn,… blah blah )

Nhóm 2: người dùng cuối, tức mấy người làm nghiệp vụ chỉ xài giao diện web mà thôi. Họ đăng nhập vào và cứ thế làm việc, hoàn toàn là trang web, họ chẳng thèm quan tâm gì đến web bằng Python hay cái gì back-end cả, họ chỉ nhập liệu và thao tác trên giao diện web hoàn toàn, kể cả việc backup thì có khi là thấy xuất hiện và bảo chờ gì đó, rồi sau dó có 1 dòng chứa file có ngày tháng/ tên để phân biệt với file cũ. Rồi học click vào đó và tải về cất (theo như mấy ông quản trị hệ thống báo lại nếu mấy ông đó không chịu làm việc đó).

Rất may mắn khi Python không phải chỉ là ngôn ngữ lập trình web. Do đó, mấy cái việc chạy trên server nó mạnh mẽ hơn so với PHP nhiều. Việc Flask giao tiếp với code Python (compile sẵn luôn khi xài cho nhanh) làm mấy việc backup nào đó trên server là hoàn toàn thông suốt, không bị vướng mắc hoặc khó như PHP.

Vậy thì sao? Việc quan tâm chỉ còn là viết được mã Python làm được việc backup, thậm chí compile thành .exe nếu trên Windows server hoặc binary cho Linux. Rồi Flask sẽ gọi tới function đó để thực hiện việc backup, sau đó cái function đó trả về kết quả cho Flask để Flask hiện lên web cho người dùng tải về.

Việc cài đặt phần mềm thì quản trị hệ thống làm theo tài liệu của bạn hướng dẫn, buộc phải vậy mà thôi, bạn yêu cầu họ cài Docker thì họ cài Docker, PosgreSQL gì đó hoặc bất cứ cái gì để phần mềm có thể thì họ đều phải đáp ứng nếu muốn phần mềm chạy, và việc cài đó là chỉ làm một lần mà thôi, thì ta không phải lăn tăn làm gì họ không làm được nếu ta đã làm và viết lại các bước (làm cả video clip thao tác step by step có kèm thuyết minh bằng giọng nói) cho họ làm theo.

Nếu quá phức tạp thì buộc phải training cho họ hoặc ta phải thuê người có kỹ năng viết tốt để người khác hiểu nếu ta viết kém. Ngày trước mình triển khai thì mỗi ngày liên tục phải tập dượt cài đặt, chỉnh chọc với các bạn dev, trong team, rồi viết tài liệu, rà soát phiên bản để phổ biến đến khách hàng, cũng luôn chỉnh sửa để hoàn thiện, dễ hiểu. Lâu dần thì mình cũng biết viết code để làm những việc mà dev làm quá rối rắm hoặc họ làm mang tính chỉ cho server dev, không chạy ngay được trên môi trường triển khai thực tế để khi đi đến nơi triển khai, hỗ trợ khách hàng được nhanh hơn.

Còn nếu lo sợ khách hàng không làm được việc cài đặt lên server, thì cứ làm tất cả các bước đó rồi đóng gói trong một gói cài đặt viết bằng Python, người ta cứ gõ python setup.py rồi trả lời vài thứ nó cài tất cả, giống như cài các gói binary như Deb, RPM cho Linux vậy đó. Hay là bạn chưa tự tin viết Python để làm mấy việc không phải là lập trình web? (mà là Python nói chung).

Vấn đề lằng ngoằng cần giải quyết ở đây: viết phần mềm Python chạy được trên server có khả năng đóng gói tất cả lại thay vì để ngổn ngang rồi lo sợ thế nọ thế kia. Và Docker chính là đã rất tiện cho việc này rồi. Ta làm xong, cứ phát hành Docker, họ pull về và chạy nó thôi. Viết cho họ bài hướng dẫn như kiểu này là người ta (mấy ông quản trị server) làm được, mấy ông đó không làm được thì xem ra họ nên bỏ tiền ra để được hỗ trợ hoặc ta nên đi tìm khách hàng khác :smiley:

4 Likes

Đúng rồi

Docker mình đóng gói ứng dụng của mình thôi, full ứng dụng

Đúng, hiện tại mình phát hành docker image thì đã đóng gói toàn bộ, chỉ start là dùng nhưng như mình đã đề cập. NHƯNG mình muốn cải tiến ứng dụng của mình nếu ở đây để:

  • Nếu có tồn tại một cách để sao lưu khôi phục database khác mà cá nhân mình chưa biết và nó không phụ thuộc vào việc có pg_dump hay pg_restore, nó sẽ giúp ứng dụng của mình có thể sử dụng độc lập hơn
  • Nó cũng sẽ giúp cho image của mình nhẹ hơn vì không có postgresql (trong trường hợp người sử dụng họ sài database cloud)
  • Tiện hơn nữa mình sẽ có 2 tuỳ chọn khi phát hành, 1 image có sẵn database và một image không. Nó sẽ rất tiện cho người dùng chọn bản phù hợp với yêu cầu của họ.

@superthin @kisuluoibieng
Cảm ơn 2 bác đã nêu cực kỳ rõ ràng về cách để giải quyết vấn đề và cách các nhà phát hành lớn nhỏ triển khai phần mềm của họ. Mình đã đọc rất kỹ và cũng đã hiểu vấn đề mà các bác muốn truyền tải và mình một lần nữa chân thành cảm ơn hai bác cực nhiều.
Nhưng như ở trên , mình chỉ muốn ứng dụng của mình nhẹ nhàng và độc lập hơn thôi. Có chăng có cách nào khác để sao lưu khôi phục database khác tiện dụng hơn mà mình không biết chẳng hạn. Như @superthin có đề cập, viết doc, viết script… thì ứng dụng của mình nó vẫn bị phụ thuộc. Mình muốn tìm cách cải thiện vấn đề này thôi.

1 Like

Bác chắc chắn tuổi nghề cao hơn em cực nhiều vì cái ngày em đang coi anh Đạt dạy C++ thì bác đã đi giải đáp giúp đỡ mọi người rồi nên chắc bác thừa biết khi làm công ty khách hàng nó còn lâu mới bỏ tiền ra để “để được hỗ trợ hoặc ta nên đi tìm khách hàng khác”, họ chỉ đưa requirement và… hết. Việc còn lại là mình và khách hàng, mình không làm được thì người khác làm, mình chim cút. Tìm khách hàng khác? Có lẽ bác đang làm ở trên level cao hoặc trực tiếp với khách hàng nên có góc nhìn khác. Còn với em, dev quèn, nope, chuyển cty thì đúng hơn.

Mình cảm thấy ứng dụng của bạn đã rất độc lập

Bạn không muốn docker của bạn sử dung pg dump và restore nhưng lại muốn dùng một cái lib python nào đó.
Vậy bạn lại phụ thuộc thêm 1 lib python, mình chưa biết có hay không, cứ coi là có, thì sao?
Về dung lượng, mình nghĩ nó không nhẹ hơn một tool binary như pg cung cấp đâu
Về độ tin cậy, khỏi phải bàn, khi bạn xài hàng chính chủ
Về hiệu năng, python cũng không chơi lại binary đã được buid

Nếu bạn vẫn không chịu dùng tool đó, thì có thể zip thư mục data của postgres lại, chỉ cần gọi lệnh zip mà thôi, zip cũng chỉ vài mb (mà pg dump, restore cũng chỉ có thế)
Đối với cloud, thì backup là việc của dịch vụ cloud, mình không nên quản

Suy nghĩ tối ưu là một chuyện tốt, nhưng nếu như sự tốt ưu không mang lại ý nghĩa gì thì nên xem xét lại
Dont be mad!

6 Likes

Bài này có lẽ là 1 ví dụ cho việc bạn viết chưa đặt nhiều năng lượng để đặt câu hỏi và người trả lời không thật sự hiểu câu hỏi mà vẫn cố trả lời. Có lẽ DNH cần có đội ngũ mod chặt chẽ hơn hoặc quy trình tốt hơn - ví dụ như template cho câu hỏi chẳng hạn!

Theo ý câu hỏi mình hiểu bạn là 1 nhà cung cấp phần mềm theo dạng SaaS + on-premise subscription và bạn nghĩ người sử dụng có thể dùng sản phẩm của bạn + database của 1 provider khác ngoài cài đặt sẵn có (Flask+Postgresql)? Theo kinh nghiệm của mình, trước hết bạn cần làm rõ:

  • Điều đó có thực sự cần thiết không, hay b chỉ đang suy đoán khách hàng muốn gì?
  • Điểm quan trọng của sản phẩm của bạn là gì? Nếu backup+restore là 1 trong những killer feature của bạn, thì không vội trông chờ vào mấy ông tướng trên này, b có thể hỏi ý kiến sếp để thuê 1 dịch vụ của 1 bên chuyên nghiệp nào đó, nếu tính theo giờ thì cũng ko quá đắt đâu, rẻ hơn so với việc bạn ko chắc chắn!

Về technical, do đây là diễn đàn miễn phí và mình cũng không có nhiều thời gian nên chỉ có thể khuyên bạn:

Không biết có thư viện hay hướng nào xử lý hay hơn không nhờ mọi người góp ý.

Ngoài sử dụng pg_dump/pg_restore (bắt buộc sử dụng postgresql), bạn có thể giải quyết 1 trong 2 trường hợp sau:

  • Cách tốt nhất là tạo 1 service đọc connection string và tạo các adapter tương ứng. Ví dụ, nếu connection string có tham số db là mysql thì sử dụng adapter: mysqldump, sqlite thì dùng copyfile,…

  • Dùng ORM: Việc backup đơn giản hơn restore, nhưng cũng phụ thuộc nhiều vào cấu trúc CSDL của bạn. Thông thường, khi bạn backup thì bạn serialize database object và khi restore thì deserialize object tương ứng. Hiểu đơn giản giống như mỗi model bạn dump sang 1 file csv và khi restore thì thêm vào database của model tương ứng. Cách này phải thông qua 1 layer trung gian là ORM nên các extensions của Postgresql bạn sẽ mất (views, materialized views, triggers,…). SQLAlchemy dùng hàm dumps [0] (sử dụng pickle để serialize objects) hoặc bạn có thể dùng thư viện AlchemyDumps [1]

P/S:

Đây chắc là 1 trong những atti-pattern mình hay gặp nhất, bạn ko nên đóng gói toàn bộ flask+postgres vào 1 docker image. Trừ trường hợp bất khả kháng (process monitoring, workers, etc.) thì 1 container = 1 process - trừ khi bạn hiểu rõ bạn đang quản lý process nào!

[0] https://github.com/sqlalchemy/sqlalchemy/blob/main/lib/sqlalchemy/ext/serializer.py#L164
[1] https://github.com/cuducos/alchemydumps

4 Likes

Đọc bài này thì mình có thêm góc nhìn mới, có thể phỏng đoán của bạn chính xác hơn, bởi vì các bạn trẻ bây giờ hay áp dụng những “công nghệ” mới. Còn mình thì khi xem câu hỏi đọc được bao nhiêu thông tin biết/ hiểu vấn đề chừng đó. Và cũng chỉ có thể bàn đến dựa trên cách thức tổng quát mà mình biết.

Hơn nữa, Python là một ngôn ngữ lập trình không phải chỉ để riêng làm web, thì nếu không muốn phụ thuộc cái nọ cái kia, chi bằng nhóm lập trình viết luôn phần phải phụ thuộc đó bằng Python, kể cả viết luôn cơ sở dữ liệu :smiley: mà không dùng CSDL có sẵn, rồi compile ra một gói. Lúc đó cloud hay không cloud thì cũng dựa trên mô hình client - server.

4 Likes

Chân thành cảm ơn bác, cũng từ bài viết này mình cũng học hỏi thêm được nhiều thứ, cả về những cái liên quan tới câu hỏi và không. Tuổi trẻ mà va vấp chút mới khôn lên được, học hỏi đàn anh để cải thiện bản thân, chân thành cảm ơn bác rất nhiều.

1 Like

Ý bác là sao nhỉ?

  • Trình đủ không ?
  • Khách hàng có đồng ý chấp nhận bỏ thêm tiền để thêm thời gian làm hay không ?
  • Độ tin cậy khách hàng có chịu không ?
  • Có vẻ nó hơi ngược với câu nói: “đứng trên vai người khổng lồ”. Tạm bỏ qua giới hạn kiến thức, cứ cho là mình cùng team có àm được, nhưng ngược lại liệu nó có đáng không ?

Mình đang muốn cải thiện, cho ứng dụng bớt phụ thuộc, muốn sài 2 cái lib mà phải cài cả postgresql. Mình đã không muốn cài cả cái ô tô nhưng dùng mỗi tiến, lùi rồi, đây bác lại khuyên đi chế cái ô tô mới đi thì cũng thấy hơi bất hợp lý.

Điều bác ấy nói không phải là viễn vông đâu bạn.
Tình trạng của bạn, chỉ có bạn hiểu rõ, tự bạn quyết định phương hướng giải quyết.
Mỗi góp ý ở đây là để đóng góp một góc nhìn, chỉ có tác dụng tham khảo, bạn không cần thiết phải chỉ ra rõ ràng là ý kiến đó đúng hay không.

Suy cho cùng, trước khi trở thành người khổng lồ, họ cũng chỉ là những đứa trẻ mà thôi.
Nếu công việc của bạn không cần người khổng lồ, mà trẻ sơ sinh cũng làm được, thì tự tạo ra đứa trẻ cũng là một cách :sweat_smile:

Trường ĐH KHTN TPHCM ngày xưa, trong môn Hệ quản trị CSDL, nghe đồn là sinh viên phải tự viết mới một hệ quản trị CSDL từ A-Z. Sau này thì bỏ rồi.
Một số chức năng như import/export CSV chẳng hạn, bây giờ cũng có nhiều người tự viết chứ không dùng thư viện.

3 Likes

Well, mình đâu có nói là viển vông?
Mình hiểu cách góp ý của bác ấy, mình hiểu mình ở đâu và bác ấy như thế nào. Như đã nói, đây là tranh luận và trao đổi. Phải nói cái mình đang nghĩ ra để sai người ta còn sửa còn biết mình sai ở đâu chứ bạn. Diễn đàn trao đổi mà. Không hỏi thì giấu dốt sao tiến bộ được.
Như bạn nói mỗi người có góc nhìn và quan điểm khác nhau, mình là lần đầu trải sẽ khác với mọi người đã nhẵn nhụi rồi.
Mình cũng hiểu code là tự làm nó sẽ giúp bản thân tiến bộ hơn nhưng cũng còn tuỳ cái tuỳ trường hợp đâu thể cứ cứng nhắc được đúng chứ.
Một job được giao trong 3 ngày mình không nghĩ là mình có thể build cả một CSDL và làm các tính năng cho nó, nên, well, như bạn đã nói, “tình trạng của mình, mình hiểu rõ và tự mình quyết định phương hướng giải quyết”. Và mình cũng đã trình bày hướng giải quyết của mình và mình ở đây là để xin lời khuyên ý kiến cải thiện, không phải ở đây để xin code.

3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?